-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPosition_of_motor
218 lines (200 loc) · 7.76 KB
/
Position_of_motor
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*Code for position control of motor*/
#define in1 5 //D5
#define in2 4 //D4
#define pwm_pin 6 //D6
#define md_vcc 12 //5v supply to motor driver
#define interrupt0 2 //D2 for Channel A
#define channel_b 3 //D3
#include <avr/io.h>
#include <avr/interrupt.h>
void Ext_interrupt_Init();
void anti_clockwise();
void clockwise();
void stop_motion();
volatile int counter = 0; //counter will count pulses obtained from encoder
int counter_angle = 0;
int angle = 0; //angle variable will store the reading of Robot Arm angle
int set_angle = 180; //assign the required angle to this variable
uint8_t pwm = 0; //assign the base pwm value (initial value) to this variable
float Kp = 1.4160; //proportional constant max can be 1.416 i.e 255/180. 1.0055 is good. 1.4160, 1.8000 is also fine. 2.5000 is faster and has possibility of overshoot.
float Ki = 0.06789; //integral constant
int error = 0;
int integral = 0; //integral will store the area of error curve used to reduce the steady state error (offset)
int correction = 0;
int accuracy = 2;
int check = 0; //used once in program to gradually increase pwm of motor from 0 to required (Kp*error)
void setup()
{
pinMode(md_vcc,OUTPUT); //md_vcc pin is for 5v supply to motor driver
digitalWrite(md_vcc,HIGH); //5v VCC to L298 Motor driver given from pin 12
pinMode(in1,OUTPUT); //In1 pin of L298 Motor Driver
pinMode(in2,OUTPUT); //In2 pin of L298 Motor Driver
pinMode(pwm_pin,OUTPUT); //pwm pin of cytron
// DDRD&=(0<<PD2)&(0<<PD3); //PD2(D2)(used as INT0) for Channel A and PD3(D3)(used as digital) for Channel B of encoder
// PORTD&=(0<<PD2)&(0<<PD3); //pull down INT0 and Channel B pin to read exact pulses
pinMode(interrupt0,INPUT); //External INT0 pin declared as input for Channel A
pinMode(channel_b,INPUT); //D3 declared as input for Channel B
digitalWrite(interrupt0,HIGH);
digitalWrite(channel_b,HIGH);
sei(); //global interrupt enabled
Ext_interrupt_Init(); //initialising External INT0 to trigger flag at rising edge
Serial.begin(9600);
}
void loop()
{
counter_angle = counter;
angle = counter_angle * 3/5; //angle is counter * 360 / 600
if (angle > 360) //angle value must be between 0 to 360. Hence if angle is greater than 360, it is set to 360
angle = 360;
else if (angle < 0) //if angle is calculated less than 0, it is assigned 0
angle = 0;
Serial.print("\nangle = ");
Serial.print(angle);
Serial.print(" error = ");
Serial.print(error);
Serial.print(" correction = ");
Serial.print(correction);
if ( check == 0 )
{
if (angle < set_angle - accuracy) //method to define direction of motion of robotic arm, clockwise or anticlockwise
{
error = set_angle - angle;
if (error > 180)
{
error = 360 - error;
anti_clockwise();
correction = pwm + Kp*error;
if ( correction < 30 )
correction = 30;
else if ( correction > 255 )
correction = 255;
analogWrite(pwm_pin , correction); //proportional control method used. Kp is proportional constant.
}
else if (error < 180)
{
clockwise();
correction = pwm + Kp*error;
if ( correction < 30 )
correction = 30;
else if ( correction > 255 )
correction = 255;
analogWrite(pwm_pin , correction); //proportional control method used. Kp is proportional constant.
}
}
else if (angle > set_angle + accuracy)
{
error = angle - set_angle;
if (error > 180)
{
error = 360 - error;
clockwise();
correction = pwm + Kp*error;
if ( correction < 30 )
correction = 30;
else if ( correction > 255 )
correction = 255;
analogWrite(pwm_pin , correction); //proportional control method used. Kp is proportional constant.
}
else if (error < 180)
{
anti_clockwise();
correction = pwm + Kp*error;
if ( correction < 30 )
correction = 30;
else if ( correction > 255 )
correction = 255;
analogWrite(pwm_pin , correction); //proportional control method used. Kp is proportional constant.
}
}
// else if ((set_angle - accuracy < angle) && (angle < set_angle + accuracy))
// {
// if (set_angle > angle)
// {
// error = set_angle - angle;
// integral = integral + error;
// anti_clockwise();
// correction = pwm + Ki*integral;
// if ( correction < 26 )
// correction = 26;
// else if ( correction > 255 )
// correction = 255;
// analogWrite(pwm_pin , correction); //proportional control method used. Kp is proportional constant.
// }
// else if (set_angle < angle)
// {
// error = angle - set_angle;
// integral = integral + error;
// clockwise();
// correction = pwm + Ki*integral;
// if ( correction < 26 )
// correction = 26;
// else if ( correction > 255 )
// correction = 255;
// analogWrite(pwm_pin , correction); //proportional control method used. Kp is proportional constant.
// }
else if ((set_angle - accuracy < angle) && (angle < set_angle + accuracy))
{
stop_motion();
}
}
}
void clockwise()
{
digitalWrite(in1,HIGH);
digitalWrite(in2,LOW);
// if (check==0)
// {
// for (int i = 0 ; i < Kp*error ; i+=2)
// {
// analogWrite(pwm_pin,i);
// delay(2);
// }
// check++;
// }
}
void anti_clockwise()
{
digitalWrite(in1,LOW);
digitalWrite(in2,HIGH);
// if (check==0)
// {
// for (int i = 0 ; i < Kp*error ; i+=2)
// {
// analogWrite(pwm_pin,i);
// delay(2);
// }
// check++;
// }
}
void stop_motion()
{
integral = 0;
error = 0;
angle = set_angle;
correction = 0;
check++;
digitalWrite(in1,LOW);
digitalWrite(in2,LOW);
analogWrite(pwm_pin,correction);
}
void Ext_interrupt_Init()
{
EICRA|=(1<<ISC01)|(1<<ISC00); //Interrupt0 will trigger at rising edge.
EIMSK|=(1<<INT0); //ext interrupt 0 enabled
sei(); //global interrupt enabled
}
ISR(INT0_vect)
{
if (digitalRead(channel_b)==LOW)
{
counter++;
if (counter > 600)
counter = counter - 600; //if value of counter becomes more than 600 then it is updated to quantize between 0 to 600
}
else if (digitalRead(channel_b)==HIGH)
{
counter--;
if (counter < 0)
counter = 600 + counter; //if value of counter becomes less than 0 then it is updated to quantize between 0 to 600
}
}