-
Notifications
You must be signed in to change notification settings - Fork 0
/
nxtpid.nxc
110 lines (91 loc) · 3.23 KB
/
nxtpid.nxc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*---------------------------------------------------------------
LEGO NXT PID Line Follower
by Robin Messenger
This is a program written for a LEGO NXT. The goal is to follow a
line using downward-facing light sensor. I am using a Proportional
Integral Derivative (PID) controller to keep the robot on the edge
of a line on the ground. It is written in a c-style language called
nxc designed specifically for the NXT. The compiler can be found at
http://bricxcc.sourceforge.net/nbc/
------------------------------------------------------------------*/
//PARAMETERS
#define SIDEOFLINE 1
#define KP 11000
#define KI 190
#define KD 11000
#define INTEGRALDECAY 990
#define MAXEI 500
#define SETPOINT 38
#define POWER 55
#define LEFT_WHEEL OUT_A
#define RIGHT_WHEEL OUT_B
#define BOTH_WHEELS OUT_AB
#define LIGHT_SENSOR S1
/* This function takes a parameter rb which refers to the right bias of the
robots steering. A value of zero indicates travel straight ahead, whereas
a positive value steers right, and a negative value left. It sets the power
to the motor powering each wheel based on this value */
inline void drive(int rb)
{
//restrict "right bias" to an appropriate range: the motor
//control functions take values between 0-100
if (rb>(100+POWER))
rb=100+POWER;
else if (rb<(-100-POWER))
rb=-100-POWER;
if (rb>0) //positive "right bias" (turn right)
{
// slow or reverse right wheel
if (POWER-rb<0)
OnRev(RIGHT_WHEEL,-POWER+rb);
else
OnFwd(RIGHT_WHEEL,POWER-rb);
//full power to right wheel
OnFwd(LEFT_WHEEL,POWER);
}
else //negative "right bias" (turn left)
{
//full power to right wheel
OnFwd(RIGHT_WHEEL,POWER);
//slow or reverse left wheel
if (POWER+rb<0)
OnRev(LEFT_WHEEL,-POWER-rb);
else
OnFwd(LEFT_WHEEL,POWER+rb);
}
}
/* The main "task" (the NXT has build-in multitasking, this keyword defines
an independant task, this program only uses one) */
task main()
{
//initialize the light sensor
SetSensorLight(LIGHT_SENSOR);
//initialize the PID controller variables
int e=0; //error
int ei=0; //integral
int ed=0; //derivative
int eOld=0; //previous error
int u; //control variable
while (true)
{
//MAIN LOOP--------------------------------------------------
//set the error to the light sensor value minus the set point
e=Sensor(LIGHT_SENSOR)-SETPOINT;
//add current error to integral term, multiplying existing
//value by a decay factor to account for integral wind-up
ei=ei*INTEGRALDECAY/1000+e;
//clear the integral term if we pass the set point
if (e*eOld<0)
ei=0;
//derivative factor is the current minus the previous error
ed=e-eOld;
//record old error
eOld=e;
//calculate control variable
u=(KP*e+KI*ei+KD*ed+500)/1000;
//acount for which side of the line we're following
u*=SIDEOFLINE;
drive(u); //drive with calculated steering correction
//-----------------------------------------------------------
}
}