-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathpicontrol.ino
110 lines (101 loc) · 2.96 KB
/
picontrol.ino
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
// Pin sssignment
int channelA = 2; // Channel A of the encoder
int channelB = 3; // Channel B of the encoder
int en = 5; // Enable pin of the H-bridge
int pina = 11; // Input 1(a) of the H-bridge
int pinb = 13; // Input 2(b) of the H-bridge
// Controller gains
float Kp = 10; // Proportional gain
float Ki = 20; // Integral gain
// Control law variables
float Ts = 1000; // Sample time in microseconds. Recalculated on each sample.
float reference = 0;
float error = 0;
float controllaw = 0;
float integrat = 0;
// Encoder variables
long encoderval = 0;
float mspeed = 0;
// Previous sample data
float previntegrat = 0;
float preverror = 0;
unsigned long prevtime = 0;
long prevencoderval = 0;
// Calculated PWM
unsigned char pwm;
// Serial port variables
int availablebytes = 0;
char readreference[5] = {'0','0','0','0','0'};
void setup()
{
attachInterrupt(0, encoderInt, RISING); // Interrupt 0 is on pin 2
pinMode(channelB, INPUT);
pinMode(en, OUTPUT);
pinMode(pina, OUTPUT);
pinMode(pinb, OUTPUT);
digitalWrite(pina, HIGH);
digitalWrite(pinb, LOW);
Serial.begin(115200); // A lower serial port speed can affect controller performance
}
void loop()
{
availablebytes = Serial.available();
if(availablebytes > 0)
{
readreference[0] = 0;
readreference[1] = 0;
readreference[2] = 0;
readreference[3] = 0;
Serial.readBytes(readreference, 5);
reference = atof(readreference);
encoderval = 0;
prevencoderval = 0;
}
//Measuring motor speed
mspeed = (float)(encoderval - prevencoderval);
prevencoderval = encoderval;
// This encoder produces 2000 pulses per round.
// And sample time is in micro seconds.
// Thus, mspeed is in rounds/sec units.
// The original formula was: mspeed = mspeed * 1000000 / (2000 * Ts)
mspeed = mspeed * 1000 / (2 * Ts);
error = reference - mspeed;
// Dividing by 1000000 as Ts is in microseconds
integrat = previntegrat + (preverror / 1000000) * Ts;
previntegrat = integrat;
preverror = error;
controllaw = error * Kp + Ki * integrat;
// Applying saturation operation
if(controllaw > 12)
{
controllaw = 12;
}
if(controllaw < -12)
{
controllaw = -12;
}
// Setting direction with H-bridge
if(controllaw > 0)
{
digitalWrite(pina, HIGH);
digitalWrite(pinb, LOW);
}
if(controllaw < 0)
{
digitalWrite(pina, LOW);
digitalWrite(pinb, HIGH);
}
// Updating motor speed
Serial.println(mspeed);
controllaw = abs(controllaw);
pwm = (controllaw / 12) * 255;
analogWrite(en, pwm);
// Measuring sample time
Ts = micros() - prevtime;
prevtime = micros();
}
void encoderInt()
{
if(digitalRead(channelB) == HIGH){encoderval++;}
else if(digitalRead(channelB) == LOW){encoderval--;}
}