2. Maqueen module
The
maqueen
module is required to control the Maqueen buggy.Download the python file
maqueen.py module
.Place it in the mu_code folder: C:\Users\username\mu_code
The file needs to be copied onto the microbit.
In Mu editor, with the microbit attached by USB, click the Files icon.
Files on the microbit are shown on the left.
Files in the mu_code folder are listed on the right.
Click and drag the maqueen.py file from the right window to the left window to copy it to the microbit.
The images below are for the maqueen, but illustrate the idea.
Before copying:
After copying:
2.1. Use Maqueen library
To use the maqueen module, import it via:
import maqueen
.from microbit import *
import maqueen
2.2. Maqueen code
The Maqueen module is shown below.
1# maqueen module for motors, line following and distance sensing
2# requires microbit v2
3# GMC-code; 2022-4
4# The MIT License (MIT)
5# motor uses i2c
6# motor speeds from 0,1,2,3,4,5
7# turn tightness from 5,4,3,2,1
8# 5 being tightest without spinning by reversing other wheel
9
10from microbit import *
11import machine
12import utime
13from neopixel import NeoPixel as leds
14
15
16CHIP_ADDR = 0x10
17LEFT_MOTOR = 0x00
18RIGHT_MOTOR = 0x02
19FORWARD = 0x00
20BACKWARD = 0x01
21SERVO_ONE = 0x14
22SERVO_TWO = 0x15
23
24TRIGGER_PIN = pin1
25ECHO_PIN = pin2
26LEFT_HEADLIGHT_PIN = pin8
27RIGHT_HEADLIGHT_PIN = pin12
28LEFT_LINE_SENSOR_PIN = pin13
29RIGHT_LINE_SENSOR_PIN = pin14
30IR_PIN = pin16
31
32MOTOR_SPEEDS = [0, 20, 25, 30, 60, 255]
33MPC = len(MOTOR_SPEEDS) - 1 # Motor speed count used for tightness of turns
34
35
36class MaqueenMotors:
37
38 def stop_left(self):
39 buffer = bytearray(3)
40 buffer[0] = LEFT_MOTOR
41 buffer[1] = FORWARD
42 buffer[2] = 0
43 i2c.write(CHIP_ADDR, buffer, False)
44
45 def stop_right(self):
46 buffer = bytearray(3)
47 buffer[0] = RIGHT_MOTOR
48 buffer[1] = FORWARD
49 buffer[2] = 0
50 i2c.write(CHIP_ADDR, buffer, False)
51
52 def stop(self):
53 self.stop_left()
54 self.stop_right()
55
56 @staticmethod
57 def _analog_speed(self, speed):
58 if speed < -MPC:
59 return -MOTOR_SPEEDS[MPC]
60 elif speed < 0 and speed >= -MPC:
61 return -MOTOR_SPEEDS[abs(int(speed))]
62 elif speed > 0 and speed <= MPC:
63 return MOTOR_SPEEDS[int(speed)]
64 elif speed > MPC:
65 return MOTOR_SPEEDS[MPC]
66 else:
67 return 0
68
69 def left_motor(self, speed=1, duration=None):
70 buffer = bytearray(3)
71 buffer[0] = LEFT_MOTOR
72 if (speed > 0):
73 buffer[1] = FORWARD
74 else:
75 buffer[1] = BACKWARD
76 buffer[2] = abs(self._analog_speed(self, speed))
77 i2c.write(CHIP_ADDR, buffer, False)
78 if duration is not None:
79 utime.sleep_ms(duration)
80 self.stop_left()
81
82 def right_motor(self, speed=1, duration=None):
83 buffer = bytearray(3)
84 buffer[0] = RIGHT_MOTOR
85 if (speed > 0):
86 buffer[1] = FORWARD
87 else:
88 buffer[1] = BACKWARD
89 buffer[2] = abs(self._analog_speed(self, speed))
90 i2c.write(CHIP_ADDR, buffer, False)
91 if duration is not None:
92 utime.sleep_ms(duration)
93 self.stop_right()
94
95 def backwards(self, speed=1, duration=None):
96 analog_speed = abs(self._analog_speed(self, speed))
97 buffer = bytearray(3)
98 buffer[0] = LEFT_MOTOR
99 buffer[1] = BACKWARD
100 buffer[2] = analog_speed
101 i2c.write(CHIP_ADDR, buffer, False)
102 buffer = bytearray(3)
103 buffer[0] = RIGHT_MOTOR
104 buffer[1] = BACKWARD
105 buffer[2] = analog_speed
106 i2c.write(CHIP_ADDR, buffer, False)
107 if duration is not None:
108 utime.sleep_ms(duration)
109 self.stop()
110
111 def forwards(self, speed=1, duration=None):
112 analog_speed = abs(self._analog_speed(self, speed))
113 buffer = bytearray(3)
114 buffer[0] = LEFT_MOTOR
115 buffer[1] = FORWARD
116 buffer[2] = analog_speed
117 i2c.write(CHIP_ADDR, buffer, False)
118 buffer = bytearray(3)
119 buffer[0] = RIGHT_MOTOR
120 buffer[1] = FORWARD
121 buffer[2] = analog_speed
122 i2c.write(CHIP_ADDR, buffer, False)
123 if duration is not None:
124 utime.sleep_ms(duration)
125 self.stop()
126
127 @staticmethod
128 def _inner_turn_speed(self, tightness=MPC):
129 return MOTOR_SPEEDS[MPC - tightness]
130
131 def left(self, tightness=MPC, duration=None):
132 # right motor faster than left
133 inner_turn_speed = self._inner_turn_speed(self, tightness)
134 buffer = bytearray(3)
135 buffer[0] = LEFT_MOTOR
136 buffer[1] = FORWARD
137 buffer[2] = inner_turn_speed
138 i2c.write(CHIP_ADDR, buffer, False)
139 utime.sleep_ms(2)
140 buffer = bytearray(3)
141 buffer[0] = RIGHT_MOTOR
142 buffer[1] = FORWARD
143 buffer[2] = 255
144 i2c.write(CHIP_ADDR, buffer, False)
145 if duration is not None:
146 utime.sleep_ms(duration)
147 self.stop()
148
149 def right(self, tightness=MPC, duration=None):
150 # left motor faster than right
151 inner_turn_speed = self._inner_turn_speed(self, tightness)
152 buffer = bytearray(3)
153 buffer[0] = LEFT_MOTOR
154 buffer[1] = FORWARD
155 buffer[2] = 255
156 i2c.write(CHIP_ADDR, buffer, False)
157 utime.sleep_ms(2)
158 buffer = bytearray(3)
159 buffer[0] = RIGHT_MOTOR
160 buffer[1] = FORWARD
161 buffer[2] = inner_turn_speed
162 i2c.write(CHIP_ADDR, buffer, False)
163 if duration is not None:
164 utime.sleep_ms(duration)
165 self.stop()
166
167 def spin_left(self, speed=1, duration=None):
168 analog_speed = abs(self._analog_speed(self, speed))
169 buffer = bytearray(3)
170 buffer[0] = LEFT_MOTOR
171 buffer[1] = BACKWARD
172 buffer[2] = analog_speed
173 i2c.write(CHIP_ADDR, buffer, False)
174 buffer[0] = RIGHT_MOTOR
175 buffer[1] = FORWARD
176 buffer[2] = analog_speed
177 i2c.write(CHIP_ADDR, buffer, False)
178 if duration is not None:
179 utime.sleep_ms(duration)
180 self.stop()
181
182 def spin_right(self, speed=1, duration=None):
183 analog_speed = abs(self._analog_speed(self, speed))
184 buffer = bytearray(3)
185 buffer[0] = LEFT_MOTOR
186 buffer[1] = FORWARD
187 buffer[2] = analog_speed
188 i2c.write(CHIP_ADDR, buffer, False)
189 buffer[0] = RIGHT_MOTOR
190 buffer[1] = BACKWARD
191 buffer[2] = analog_speed
192 i2c.write(CHIP_ADDR, buffer, False)
193 if duration is not None:
194 utime.sleep_ms(duration)
195 self.stop()
196
197 # angle: {0-180}
198 def servo_one(self, angle=0):
199 buffer = bytearray(2)
200 buffer[0] = SERVO_ONE
201 buffer[1] = angle
202 i2c.write(CHIP_ADDR, buffer, False)
203
204 # angle: {0-180}
205 def servo_two(self, angle=0):
206 buffer = bytearray(2)
207 buffer[0] = SERVO_TWO
208 buffer[1] = angle
209 i2c.write(CHIP_ADDR, buffer, False)
210
211
212class MaqueenLineSensors:
213
214 def line_sensor_read(self, sensor):
215 if sensor == 'left':
216 return LEFT_LINE_SENSOR_PIN.read_digital()
217 elif sensor == 'right':
218 return RIGHT_LINE_SENSOR_PIN.read_digital()
219
220
221class MaqueenDistanceSensor:
222
223 def distance(self):
224 ECHO_PIN.set_pull(ECHO_PIN.NO_PULL)
225 TRIGGER_PIN.write_digital(0)
226 utime.sleep_us(2)
227 TRIGGER_PIN.write_digital(1)
228 utime.sleep_us(10)
229 TRIGGER_PIN.write_digital(0)
230 distance = machine.time_pulse_us(ECHO_PIN, 1, 1160000)
231 if distance > 0:
232 # distance in cm
233 return round(distance/58)
234 else:
235 return 0
236
237
238class MaqueenIR:
239
240 def get_IR(self):
241 IR_PIN.set_pull(IR_PIN.PullUp)
242
243
244class MaqueenHeadLights:
245
246 def set_headlight(self, headlight='left', on=1):
247 # value = 1 for on and 0 for off
248 if headlight == 'left':
249 if on == 1:
250 LEFT_HEADLIGHT_PIN.write_digital(1)
251 else:
252 LEFT_HEADLIGHT_PIN.write_digital(0)
253 elif headlight == 'right':
254 if on == 1:
255 RIGHT_HEADLIGHT_PIN .write_digital(1)
256 else:
257 RIGHT_HEADLIGHT_PIN .write_digital(0)
258
259 def set_headlights(self, left=1, right=1):
260 # value = 1 for on and 0 for off
261 LEFT_HEADLIGHT_PIN.write_digital(left)
262 RIGHT_HEADLIGHT_PIN .write_digital(right)
263
264
265class MaqueenNeoPixels:
266
267 def __init__(self, front=(20, 20, 20), indicator=(35, 25, 0), rear=(20, 0, 0)):
268 self.np = leds(pin15, 4)
269 self.front = front
270 self.indicator = indicator
271 self.rear = rear
272
273 # rgb: (red: {0-255}, green: {0-255}, blue: {0-255})
274 # front left = 0; rear left = 1; rear right = 2; front right = 3
275
276 def set_front(self, rgb=(20, 20, 20)):
277 self.front = rgb
278
279 def set_indicator(self, rgb=(35, 25, 0)):
280 self.indicator = rgb
281
282 def set_rear(self, rgb=(20, 0, 0)):
283 self.rear = rgb
284
285 def set_led(self, led_number, rgb=(20, 20, 20)):
286 self.np[led_number] = rgb
287 self.np.show()
288
289 def set_leds(self, rgb=(20, 20, 20)):
290 for led_number in range(4):
291 self.np[led_number] = rgb
292 self.np.show()
293
294 def rear_lights(self):
295 self.np[1] = self.rear
296 self.np[2] = self.rear
297
298 def all_lights(self, left, right):
299 self.np[0] = left
300 self.np[3] = right
301 self.rear_lights()
302 self.np.show()
303
304 def front_lights(self):
305 self.all_lights(self.front, self.front)
306
307 def left_indicator(self):
308 self.all_lights(self.indicator, self.front)
309
310 def right_indicator(self):
311 self.all_lights(self.front, self.indicator)
312
313 def both_indicators(self):
314 self.all_lights(self.indicator, self.indicator)
315