19
19
20
20
import os
21
21
import time
22
+ import threading
22
23
import pigpio
23
24
import config
24
25
import logging
40
41
PIN_SONAR_2_ECHO = 8
41
42
PIN_SONAR_3_TRIGGER = 18
42
43
PIN_SONAR_3_ECHO = 23
43
- PIN_ENCODER_LEFT = 14
44
- PIN_ENCODER_RIGHT = 15
44
+ PIN_ENCODER_LEFT = 15
45
+ PIN_ENCODER_RIGHT = 14
45
46
46
47
PWM_FREQUENCY = 100 #Hz
47
48
PWM_RANGE = 100 #0-100
@@ -82,7 +83,11 @@ def __init__(self, servo=False, motor_trim_factor=1.0):
82
83
self ._encoder_cur_right = 0
83
84
self ._encoder_target_left = - 1
84
85
self ._encoder_target_right = - 1
85
- self ._ag = mpu .AccelGyro ()
86
+ self ._encoder_k_s_1 = 20
87
+ self ._encoder_k_v_1 = 80
88
+ self ._encoder_sem = threading .Condition ()
89
+
90
+ #self._ag = mpu.AccelGyro()
86
91
87
92
the_bot = None
88
93
@@ -99,11 +104,13 @@ def get_instance(cls, servo=False, motor_trim_factor=1.0):
99
104
cls .the_bot = CoderBot (servo , motor_trim_factor )
100
105
return cls .the_bot
101
106
102
- def move (self , speed = 100 , elapse = - 1 ):
103
- self .motor_control (speed_left = min (100 , max (- 100 , speed * self ._motor_trim_factor )), speed_right = min (100 , max (- 100 , speed / self ._motor_trim_factor )), elapse = elapse )
107
+ def move (self , speed = 100 , elapse = - 1 , steps_left = - 1 , steps_right = - 1 ):
108
+ self .motor_control (speed_left = min (100 , max (- 100 , speed * self ._motor_trim_factor )), speed_right = min (100 , max (- 100 , speed / self ._motor_trim_factor )), elapse = elapse , steps_left = steps_left , steps_right = steps_right )
104
109
105
- def turn (self , speed = 100 , elapse = - 1 ):
106
- self .motor_control (speed_left = min (100 , max (- 100 , speed / self ._motor_trim_factor )), speed_right = - min (100 , max (- 100 , speed * self ._motor_trim_factor )), elapse = elapse )
110
+ def turn (self , speed = 100 , elapse = - 1 , steps = - 1 ):
111
+ steps_left = steps
112
+ steps_right = - steps if steps > 0 else - 1
113
+ self .motor_control (speed_left = min (100 , max (- 100 , speed / self ._motor_trim_factor )), speed_right = - min (100 , max (- 100 , speed * self ._motor_trim_factor )), elapse = elapse , steps_left = steps_left , steps_right = steps_right )
107
114
108
115
def turn_angle (self , speed = 100 , angle = 0 ):
109
116
z = self ._ag .get_gyro_data ()['z' ]
@@ -139,7 +146,17 @@ def _dc_motor(self, speed_left=100, speed_right=100, elapse=-1, steps_left=-1, s
139
146
self ._encoder_cur_right = 0
140
147
self ._encoder_target_left = steps_left
141
148
self ._encoder_target_right = steps_right
142
-
149
+ self ._encoder_dir_left = cmp (speed_left , 0 )
150
+ self ._encoder_dir_right = cmp (speed_right , 0 )
151
+ self ._encoder_last_tick_time_left = 0
152
+ self ._encoder_last_tick_time_right = 0
153
+ self ._encoder_motor_stopping_left = False
154
+ self ._encoder_motor_stopping_right = False
155
+ self ._encoder_motor_stopped_left = False
156
+ self ._encoder_motor_stopped_right = False
157
+ if steps_left > 0 or steps_right > 0 :
158
+ self ._encoder_sem .acquire ()
159
+
143
160
self ._is_moving = True
144
161
if speed_left < 0 :
145
162
speed_left = abs (speed_left )
@@ -162,7 +179,11 @@ def _dc_motor(self, speed_left=100, speed_right=100, elapse=-1, steps_left=-1, s
162
179
time .sleep (elapse )
163
180
self .stop ()
164
181
165
- def _servo_motor (self , speed_left = 100 , speed_right = 100 , elapse = - 1 ):
182
+ if steps_left > 0 or steps_right > 0 :
183
+ self ._encoder_sem .wait ()
184
+ self ._encoder_sem .release ()
185
+
186
+ def _servo_motor (self , speed_left = 100 , speed_right = 100 , elapse = - 1 , steps_left = - 1 , steps_right = - 1 ):
166
187
self ._is_moving = True
167
188
speed_left = - speed_left
168
189
@@ -206,16 +227,56 @@ def set_callback(self, gpio, callback, elapse):
206
227
self ._cb_last_tick [gpio ] = 0
207
228
208
229
def callback (self , gpio , level , tick ):
209
- if gpio == PIN_ENCODER_LEFT :
230
+ if gpio == PIN_ENCODER_LEFT and self . _encoder_target_left >= 0 :
210
231
self ._encoder_cur_left += 1
211
- if self ._encoder_target_left >= self ._encoder_cur_left :
232
+ delta_ticks_left = tick - self ._encoder_last_tick_time_left if tick > self ._encoder_last_tick_time_left else tick - self ._encoder_last_tick_time_left + 4294967295
233
+ self ._encoder_last_tick_time_left = tick
234
+ self ._encoder_speed_left = 1000000.0 / delta_ticks_left #convert speed in steps per second
235
+ delta_s = self ._encoder_speed_left / self ._encoder_k_s_1 #delta_s is the delta (in steps)before the target to reverse the motor in order to arrive at target
236
+ if (self ._encoder_cur_left >= self ._encoder_target_left - delta_s and
237
+ not self ._encoder_motor_stopping_left ):
238
+ self ._encoder_motor_stopping_left = True
239
+ if self ._encoder_dir_left > 0 :
240
+ self .pi .write (PIN_LEFT_FORWARD , 0 )
241
+ self .pi .set_PWM_dutycycle (PIN_LEFT_BACKWARD , 100 )
242
+ else :
243
+ self .pi .set_PWM_dutycycle (PIN_LEFT_FORWARD , 100 )
244
+ self .pi .write (PIN_LEFT_BACKWARD , 0 )
245
+ elif (self ._encoder_motor_stopped_left == False and
246
+ ((self ._encoder_motor_stopping_left and
247
+ self ._encoder_speed_left < self ._encoder_k_v_1 ) or
248
+ (self ._encoder_motor_stopping_left and
249
+ self ._encoder_cur_left >= self ._encoder_target_left ))):
212
250
self .pi .write (PIN_LEFT_FORWARD , 0 )
213
- self .pi .write (PIN_LEFT_BACKWARD , 0 )
214
- elif gpio == PIN_ENCODER_RIGHT :
251
+ self .pi .write (PIN_LEFT_BACKWARD , 0 )
252
+ self ._encoder_motor_stopped_left = True
253
+ self ._encoder_check_stopped_and_notify ()
254
+ print "LEFT: " + str (self ._encoder_cur_left ) + " speed: " + str (self ._encoder_speed_left )
255
+ elif gpio == PIN_ENCODER_RIGHT and self ._encoder_target_right >= 0 :
215
256
self ._encoder_cur_right += 1
216
- if self ._encoder_target_right >= self ._encoder_cur_right :
257
+ delta_ticks_right = tick - self ._encoder_last_tick_time_right if tick > self ._encoder_last_tick_time_right else tick - self ._encoder_last_tick_time_right + 4294967295
258
+ self ._encoder_last_tick_time_right = tick
259
+ self ._encoder_speed_right = 1000000.0 / delta_ticks_right #convert speed in steps per second
260
+ delta_s = self ._encoder_speed_right / self ._encoder_k_s_1 #delta_s is the delta (in steps)before the target to reverse the motor in order to arrive at target
261
+ if (self ._encoder_cur_right >= self ._encoder_target_right - delta_s and
262
+ not self ._encoder_motor_stopping_right ):
263
+ self ._encoder_motor_stopping_right = True
264
+ if self ._encoder_dir_right > 0 :
265
+ self .pi .write (PIN_RIGHT_FORWARD , 0 )
266
+ self .pi .set_PWM_dutycycle (PIN_RIGHT_BACKWARD , 100 )
267
+ else :
268
+ self .pi .set_PWM_dutycycle (PIN_RIGHT_FORWARD , 100 )
269
+ self .pi .write (PIN_RIGHT_BACKWARD , 0 )
270
+ elif (self ._encoder_motor_stopped_right == False and
271
+ ((self ._encoder_motor_stopping_right and
272
+ self ._encoder_speed_right < self ._encoder_k_v_1 ) or
273
+ (self ._encoder_motor_stopping_right and
274
+ self ._encoder_cur_right >= self ._encoder_target_right ))):
217
275
self .pi .write (PIN_RIGHT_FORWARD , 0 )
218
- self .pi .write (PIN_RIGHT_BACKWARD , 0 )
276
+ self .pi .write (PIN_RIGHT_BACKWARD , 0 )
277
+ self ._encoder_motor_stopped_right = True
278
+ self ._encoder_check_stopped_and_notify ()
279
+ print "RIGHT: " + str (self ._encoder_cur_right ) + " speed: " + str (self ._encoder_speed_right )
219
280
else :
220
281
cb = self ._cb .get (gpio )
221
282
if cb :
@@ -226,6 +287,12 @@ def callback(self, gpio, level, tick):
226
287
self ._cb_last_tick [gpio ] = tick
227
288
print "pushed: " , level , tick
228
289
cb ()
290
+
291
+ def _encoder_check_stopped_and_notify (self ):
292
+ if self ._encoder_motor_stopped_left and self ._encoder_motor_stopped_right :
293
+ self ._encoder_sem .acquire ()
294
+ self ._encoder_sem .notify ()
295
+ self ._encoder_sem .release ()
229
296
230
297
def halt (self ):
231
298
os .system ('sudo halt' )
0 commit comments