@tigerpython/robotics-libraries 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG +68 -0
  2. package/LICENSE +373 -0
  3. package/README.md +81 -0
  4. package/calliope/README.md +15 -0
  5. package/calliope/callibot.py +176 -0
  6. package/calliope/callibotmot.py +46 -0
  7. package/calliope/callimk.py +143 -0
  8. package/calliope/cbalarm.py +14 -0
  9. package/calliope/cpglow.py +76 -0
  10. package/calliope/cpmike.py +16 -0
  11. package/calliope/cprover.py +33 -0
  12. package/calliope/cputils.py +23 -0
  13. package/calliope/libraries.json +10 -0
  14. package/calliope/libraries.raw.json +10 -0
  15. package/calliope/min/callibot.py +97 -0
  16. package/calliope/min/callibotmot.py +23 -0
  17. package/calliope/min/callimk.py +47 -0
  18. package/calliope/min/cbalarm.py +6 -0
  19. package/calliope/min/cpglow.py +29 -0
  20. package/calliope/min/cpmike.py +8 -0
  21. package/calliope/min/cprover.py +9 -0
  22. package/calliope/min/cputils.py +7 -0
  23. package/dist/index.d.mts +124 -0
  24. package/dist/index.d.ts +124 -0
  25. package/dist/index.js +2896 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/index.mjs +2862 -0
  28. package/dist/index.mjs.map +1 -0
  29. package/microbit/README.md +48 -0
  30. package/microbit/controller.py +212 -0
  31. package/microbit/huskylens.py +479 -0
  32. package/microbit/libraries.json +19 -0
  33. package/microbit/libraries.raw.json +19 -0
  34. package/microbit/mbalarm.py +15 -0
  35. package/microbit/mbbitbot.py +127 -0
  36. package/microbit/mbglow.py +77 -0
  37. package/microbit/mbled.py +56 -0
  38. package/microbit/mbmarsrover.py +216 -0
  39. package/microbit/mbminibit.py +139 -0
  40. package/microbit/mbrobot.py +401 -0
  41. package/microbit/mbrobot_legacy.py +90 -0
  42. package/microbit/mbrobot_plus.py +179 -0
  43. package/microbit/mbrobot_plusV2.py +490 -0
  44. package/microbit/mbrobot_plusV3.py +427 -0
  45. package/microbit/mbrobotmot.py +49 -0
  46. package/microbit/mbthetabot.py +167 -0
  47. package/microbit/mbwait.py +50 -0
  48. package/microbit/mbxgo.py +173 -0
  49. package/microbit/min/controller.py +42 -0
  50. package/microbit/min/huskylens.py +145 -0
  51. package/microbit/min/mbalarm.py +6 -0
  52. package/microbit/min/mbbitbot.py +40 -0
  53. package/microbit/min/mbglow.py +29 -0
  54. package/microbit/min/mbled.py +18 -0
  55. package/microbit/min/mbmarsrover.py +62 -0
  56. package/microbit/min/mbminibit.py +50 -0
  57. package/microbit/min/mbrobot.py +82 -0
  58. package/microbit/min/mbrobot_legacy.py +45 -0
  59. package/microbit/min/mbrobot_plus.py +75 -0
  60. package/microbit/min/mbrobot_plusV2.py +102 -0
  61. package/microbit/min/mbrobot_plusV3.py +194 -0
  62. package/microbit/min/mbrobotmot.py +25 -0
  63. package/microbit/min/mbthetabot.py +47 -0
  64. package/microbit/min/mbwait.py +23 -0
  65. package/microbit/min/mbxgo.py +37 -0
  66. package/package.json +54 -0
@@ -0,0 +1,401 @@
1
+ # mbrobot.py
2
+ # Date 10/09/24
3
+
4
+ from microbit import i2c, pin1, pin2, pin8, pin12, pin13, pin14, pin15, sleep
5
+ import gc
6
+ import machine
7
+ import music
8
+ import neopixel
9
+
10
+ # Motor state
11
+ _speedPercent = 50
12
+ _powerByteL = 40
13
+ _powerByteR = 40
14
+ _motorState = bytearray(5)
15
+ _servoBytes = bytearray(2)
16
+ _powerBytesLUT = bytes(b'\x00\x0b\x0b\x0c\x0c\x0d\x0d\x0d\x0e\x0e\x0f\x0f\x0f\x10\x10\x11\x11\x11\x12\x12\x13\x13\x13\x14\x14\x15\x15\x15\x16\x16\x17\x17\x17\x18\x19\x1a\x1b\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x36\x38\x3a\x3c\x3f\x41\x44\x46\x49\x4c\x4f\x53\x56\x5a\x5e\x62\x67\x6b\x70\x75\x7b\x81\x87\x8d\x94\x9b\xa3\xab\xb4\xbd\xc6\xd0\xdb\xe6\xf2\xff')
17
+
18
+ # Calibration data
19
+ _powerOffset = 0
20
+ _powerDifferential = 0
21
+ _arcScaling = 0
22
+
23
+ # signaling objects
24
+ _underglowNP = neopixel.NeoPixel(pin15, 4)
25
+ np_rgb_pixels = _underglowNP
26
+ _alarmSequence = ['c5:1', 'r', 'c5:1', 'r:3']
27
+
28
+ _UNCONNECTEDERRORMSG = "Please connect to Maqueen robot and switch it on."
29
+
30
+ # Utility functions
31
+
32
+
33
+ def _setMotors(dirL, powerL, dirR, powerR):
34
+ # """Write Motor State via i2c
35
+
36
+ # Parameters:
37
+ # dirL (0/1): Direction of left Wheel. 0=forward, 1=backward
38
+ # powerL (int): Power of left Wheel in range [0,255].
39
+ # dirR (0/1): Direction of right Wheel. 0=forward, 1=backward
40
+ # powerR (int): Power of right Wheel in range [0,255].
41
+ #
42
+ # raises:
43
+ # RuntimeError: if Robot is switched off or unconnected. (replaces ENODEV error)
44
+ # """
45
+ global _motorState
46
+ _motorState[1] = dirL
47
+ _motorState[2] = powerL
48
+ _motorState[3] = dirR
49
+ _motorState[4] = powerR
50
+ try:
51
+ i2c.write(0x10, _motorState)
52
+ except:
53
+ raise RuntimeError(_UNCONNECTEDERRORMSG)
54
+
55
+
56
+ def _setSingleMotor(side, dir, power):
57
+ # """Write Motor State of a single Motor via i2c
58
+
59
+ # Parameters:
60
+ # side (0/2): Selection of the Wheel. 0=left, 2=right
61
+ # dir (0/1): Direction for that Wheel. 0=forward, 1=backward
62
+ # power (int): Power for that Wheel in range [0,255].
63
+ #
64
+ # raises:
65
+ # RuntimeError: if Robot is switched off or unconnected. (replaces ENODEV error)
66
+ # """
67
+ global _motorState
68
+ _motorState[1 + side] = dir
69
+ _motorState[2 + side] = power
70
+ try:
71
+ i2c.write(0x10, _motorState)
72
+ except:
73
+ raise RuntimeError(_UNCONNECTEDERRORMSG)
74
+
75
+ # _getPowerByte was used to create LookUpTable (_powerBytesLUT) used in _getPowerByteLUT to reduce Memory Leaks.
76
+ # def _getPowerByte(speed, offset):
77
+ # # """Computes the power value for a given speed in %.
78
+ # # It accouts for the nonlinearity of motor strength.
79
+ # # This is the original function that generates the LUT.
80
+ #
81
+ # # Parameter:
82
+ # # speed (number): Desired speed of the Robot in %. Range [0,100].
83
+ # # offset (number): basic power offset to add to the function.
84
+ # # Returns:
85
+ # # int: Power in range [0,255] to write to the motors via i2c.
86
+ # # """
87
+ # if speed <= 0:
88
+ # return 0
89
+ # if speed <= 33:
90
+ # return int(0.4 * speed + 11 + offset)
91
+ # elif speed <= 63:
92
+ # return int(0.89 * speed - 5 + offset)
93
+ # elif speed < 100:
94
+ # return int(min(1.0561 ** speed + 20 + offset, 255))
95
+ # else:
96
+ # return 255
97
+
98
+
99
+ def _getPowerByteLUT(speed, offset):
100
+ # """Lookup Table version of _getPowerByte"""
101
+ return min(_powerBytesLUT[speed] + offset, 255)
102
+
103
+
104
+ def _getArcBytes(r):
105
+ # """Computes the power bytes to drive an arc.
106
+
107
+ # Parameter:
108
+ # r (float): Radius in meters of the desired Arc.
109
+ # Measured from the center of the axle.
110
+ # Returns:
111
+ # (int, int): Power byte values for each motor.
112
+ # First the outer Wheels byte [0,255],
113
+ # then the inner Wheels byte [0,255].
114
+ # """
115
+ outerSpeed = _speedPercent
116
+ rCm = int(r * 100) # r in cm instead of meters
117
+ # adjust outer speed for unhealthy combinations
118
+ # That is: too low speeds and big arcs.
119
+ threshold = outerSpeed - max(rCm + 20, 40)
120
+ if threshold <= 0:
121
+ outerSpeed = min(max(rCm + 40, 40), 100)
122
+ reducedSpeed = 0
123
+ if rCm >= 4: # minimal radius is half the axle size: 3.5 cm rounded.
124
+ flattening = (100 - outerSpeed) // 2
125
+ reducedSpeed = (rCm * 10 - 35) / \
126
+ (rCm * (11 + (_arcScaling-4)/10) + 90 + flattening)
127
+ reducedSpeed = reducedSpeed * outerSpeed
128
+ innerByte = _getPowerByteLUT(int(reducedSpeed), 0)
129
+ outerByte = _getPowerByteLUT(int(outerSpeed), 0)
130
+ return (innerByte, outerByte)
131
+
132
+ # Movement Functions
133
+
134
+
135
+ def calibrate(offset, differential=0, arcScaling=0):
136
+ # """Adjust the driving behaviour of the robots
137
+
138
+ # Parameters:
139
+ # offset (int): Offsets the minimal power of the motors.
140
+ # Range [-10,50]. Highly affected by battery level.
141
+ # Adjust this value until it starts moving at speed 1%.
142
+ # differential (int, optional): Adjusts power difference
143
+ # of left and right Wheel. Range [-150, 150].
144
+ # Varies unpredictably with different speeds.
145
+ # If a Robot steers left when driving forward: negative value
146
+ # If a Robot steers right when driving forward: positive value
147
+ # Perfectly straight driving Robots can leave this at 0.
148
+ # arcScaling (int, optional): Adjusts the radius
149
+ # driven by leftArc/rightArc. Valid range [-50, 50].
150
+ # If the Robots radius is too large: positive value
151
+ # If the Robots radius is too small: negative value
152
+ # This then adjusts all radii for this Robot, by
153
+ # scaling it's internal function to the new range.
154
+ # """
155
+ global _powerDifferential
156
+ global _powerOffset
157
+ global _arcScaling
158
+ _powerOffset = max(min(int(offset), 50), -10)
159
+ _powerDifferential = max(min(int(differential), 150), -150)
160
+ _arcScaling = max(min(arcScaling, 50), -15)
161
+ setSpeed(_speedPercent)
162
+
163
+
164
+ def setSpeed(speed):
165
+ # """sets the speed for future motion
166
+
167
+ # Parameter:
168
+ # speed (int): in Range [0,100] as % of desired velocity.
169
+ # """
170
+ global _speedPercent
171
+ global _powerByteL
172
+ global _powerByteR
173
+ _speedPercent = int(min(max(speed, 0), 100))
174
+ powerByte = _getPowerByteLUT(_speedPercent, _powerOffset)
175
+ boost = round((1 - _speedPercent / 100) *
176
+ abs(_powerDifferential)) if _speedPercent > 0 else 0
177
+ reduction = round((_speedPercent / 100) * abs(_powerDifferential))
178
+ if _powerDifferential > 0:
179
+ _powerByteL = powerByte - reduction
180
+ _powerByteR = powerByte + boost
181
+ else:
182
+ _powerByteL = powerByte + boost
183
+ _powerByteR = powerByte - reduction
184
+
185
+
186
+ def resetSpeed():
187
+ setSpeed(50)
188
+
189
+
190
+ def stop():
191
+ _setMotors(0, 0, 0, 0)
192
+
193
+
194
+ def forward():
195
+ _setMotors(0, _powerByteL, 0, _powerByteR)
196
+
197
+
198
+ def backward():
199
+ _setMotors(1, _powerByteL, 1, _powerByteR)
200
+
201
+
202
+ def left():
203
+ _setMotors(1, _powerByteL, 0, _powerByteR)
204
+
205
+
206
+ def right():
207
+ _setMotors(0, _powerByteL, 1, _powerByteR)
208
+
209
+
210
+ def rightArc(radius):
211
+ # """radius must be given in meters."""
212
+ inner, outer = _getArcBytes(radius)
213
+ _setMotors(0, outer, 0, inner)
214
+
215
+
216
+ def leftArc(radius):
217
+ # """radius must be given in meters."""
218
+ inner, outer = _getArcBytes(radius)
219
+ _setMotors(0, inner, 0, outer)
220
+
221
+
222
+ class Motor:
223
+ def __init__(self, side):
224
+ # """Create a single motor.
225
+
226
+ # Parameter:
227
+ # side (8/2): 0=left, 2=right
228
+ # """
229
+ self._side = side
230
+
231
+ def rotate(self, speed):
232
+ # """Controls rotation of this motor.
233
+
234
+ # Parameters:
235
+ # speed (int): Desired speed in %.
236
+ # Valid range [-100,100].
237
+ # Negative values are for backward turning.
238
+ # """
239
+ speedClamped = int(min(max(abs(speed), 0), 100))
240
+ power = _getPowerByteLUT(speedClamped, _powerOffset)
241
+ direction = 0 if speed > 0 else 1
242
+ _setSingleMotor(self._side, direction, power)
243
+
244
+
245
+ def setServo(servo, angle):
246
+ # """Moves the Servo to position angle.
247
+ # Servos must be connected to the Maqueen Lite's Servo connectors.
248
+ # They are located in front of the left wheel.
249
+
250
+ # Parameters:
251
+ # servo (str): Desired Servo Port. Either 'S1' or 'S2'.
252
+ # angle (int): Desired angle in degrees. Range [0,180].
253
+
254
+ # raises:
255
+ # ValueError: if arguments are out of valid range
256
+ # RuntimeError: if Robot is switched off or unconnected.
257
+ # """
258
+ global _servoBytes
259
+ # Acceptance of "P0" and "P1" is for compatibility with V2.
260
+ if servo == 'S1' or servo == 'P0':
261
+ _servoBytes[0] = 0x14
262
+ elif servo == 'S2' or servo == 'P1':
263
+ _servoBytes[0] = 0x15
264
+ else:
265
+ raise ValueError("Unknown Servo. Please use 'S1' or 'S2'.")
266
+
267
+ if angle < 0 or angle > 180:
268
+ raise ValueError("Invalid angle. Must be between 0 and 180")
269
+
270
+ _servoBytes[1] = angle
271
+ try:
272
+ i2c.write(0x10, _servoBytes)
273
+ except:
274
+ raise RuntimeError(_UNCONNECTEDERRORMSG)
275
+
276
+ # Sensor functions
277
+
278
+
279
+ class IRSensor():
280
+ def __init__(self, pin):
281
+ # """Create a new IR sensor.
282
+
283
+ # Parameter:
284
+ # pin (object): pin13=left, pin14=right
285
+ # """
286
+ self._pin = pin
287
+
288
+ def read_digital(self):
289
+ # """Returns if the surface below is dark or bright.
290
+ # Result can be adjusted by putting the sensor on the dark
291
+ # surface and pressing the LineKey calibration button on the
292
+ # Robot for a few seconds, until the LED's blink.
293
+
294
+ # Returns:
295
+ # 0 if the surface is dark. No light was reflected (in Air).
296
+ # 1 if the surface is bright. A lot of light was reflected.
297
+ # """
298
+ return self._pin.read_digital()
299
+
300
+ def read_analog(self):
301
+ raise NameError(
302
+ "Maqueen Lite does not support reading analog sensor values.")
303
+
304
+
305
+ def getDistance():
306
+ # """uses the ultrasonic sensor to measure distance
307
+
308
+ # Returns:
309
+ # int: valid Distance as cm in range [0,500].
310
+ # For measurement errors or larger distances: 255.
311
+ # """
312
+ pin1.write_digital(1)
313
+ pin1.write_digital(0)
314
+ p = machine.time_pulse_us(pin2, 1, 50000)
315
+ # approximate division: cm = p / 57.5
316
+ cm = (p >> 6) + (p >> 10) + (p >> 11) + (p >> 12) + 1
317
+ return max(min(cm, 500), 0) if cm > 0 else 255
318
+
319
+ # Signaling functions
320
+
321
+
322
+ def setLED(state, stateR=None):
323
+ # """Set the front red LED's.
324
+
325
+ # Parameters:
326
+ # state (0/1): Sets the state of the left LED.
327
+ # if stateR is omitted, then both LEDS.
328
+ # 0=Off, 1=On
329
+ # stateR (0/1/None, optional): Sets the right LED state.
330
+ # 0=Off, 1=On, Default=None uses "state" for right LED.
331
+ # """
332
+ stateR = stateR if stateR != None else state
333
+ pin8.write_digital(state)
334
+ pin12.write_digital(stateR)
335
+
336
+
337
+ def setLEDLeft(state):
338
+ # """state: 0=Off, 1=On"""
339
+ pin8.write_digital(state)
340
+
341
+
342
+ def setLEDRight(state):
343
+ # """state: 0=Off, 1=On"""
344
+ pin12.write_digital(state)
345
+
346
+
347
+ def fillRGB(red, green, blue):
348
+ # """Uses Neopixel to set all 4 bottom RGB LEDs color.
349
+ # Parameters (red,green,blue) are each a byte in Range [0,255].
350
+ # """
351
+ for i in range(4):
352
+ _underglowNP[i] = (red, green, blue)
353
+ _underglowNP.show()
354
+ setRGB = fillRGB
355
+
356
+
357
+ def clearRGB():
358
+ _underglowNP.clear()
359
+
360
+
361
+ def posRGB(position, red, green, blue):
362
+ # """Uses Neopixel to set a single RGB LED of the robot.
363
+
364
+ # Parameters:
365
+ # position (int): position of the targeted LED.
366
+ # Numbers are visible at underside of Robot.
367
+ # 0=front left
368
+ # 1=back left
369
+ # 2=back right
370
+ # 3=front right
371
+ # red, green, blue (int): color byte value.
372
+ # each in range [0,255].
373
+
374
+ # raises:
375
+ # ValueError: if position argument is out of valid range
376
+ # """
377
+ if position < 0 or position > 3:
378
+ raise ValueError("invalid RGB-LED position. Must be 0,1,2 or 3.")
379
+ _underglowNP[position] = (red, green, blue)
380
+ _underglowNP.show()
381
+
382
+
383
+ def setAlarm(state):
384
+ # """state: 0=Off, 1=On"""
385
+ if state:
386
+ music.play(_alarmSequence, wait=False, loop=True)
387
+ else:
388
+ music.stop()
389
+
390
+
391
+ def beep():
392
+ music.pitch(440, 200, wait=False)
393
+
394
+
395
+ # Default instances
396
+ pin2.set_pull(pin2.NO_PULL)
397
+ delay = sleep
398
+ irLeft = IRSensor(pin13)
399
+ irRight = IRSensor(pin14)
400
+ motL = Motor(0)
401
+ motR = Motor(2)
@@ -0,0 +1,90 @@
1
+ import gc
2
+ from microbit import i2c, pin1, pin2, pin8, pin12, pin13, pin14, sleep
3
+ import machine
4
+
5
+ _axe = 0.097
6
+ def w(d1, d2, s1, s2):
7
+ try:
8
+ i2c.write(0x10, bytearray([0, d1, s1]))
9
+ i2c.write(0x10, bytearray([2, d2, s2]))
10
+ except:
11
+ print("Please switch on mbRobot!")
12
+ while True:
13
+ pass
14
+
15
+ def setSpeed(speed):
16
+ global _v
17
+ if speed < 20:
18
+ _v = speed + 5
19
+ else:
20
+ _v = speed
21
+
22
+ def forward():
23
+ w(0, 0, _v, _v)
24
+
25
+ def backward():
26
+ w(1, 1, _v, _v)
27
+
28
+ def stop():
29
+ w(0, 0, 0, 0)
30
+
31
+ def right():
32
+ w(0 if _v > 0 else 1, 1 if _v > 0 else 0, int(_v * 0.9), int(_v * 0.9))
33
+
34
+ def left():
35
+ w(1 if _v > 0 else 0, 0 if _v > 0 else 1, int(_v * 0.9) , int(_v * 0.9))
36
+
37
+ def rightArc(r):
38
+ v = abs(_v)
39
+ if r < _axe:
40
+ v1 = 0
41
+ else:
42
+ f = (r - _axe) / (r + _axe) * (1 - v * v / 200000)
43
+ v1 = int(f * v)
44
+ if _v > 0:
45
+ w(0, 0, v, v1)
46
+ else:
47
+ w(1, 1, v1, v)
48
+
49
+ def leftArc(r):
50
+ v = abs(_v)
51
+ if r < _axe:
52
+ v1 = 0
53
+ else:
54
+ f = (r - _axe) / (r + _axe) * (1 - v * v / 200000)
55
+ v1 = int(f * v)
56
+ if _v > 0:
57
+ w(0, 0, v1, v)
58
+ else:
59
+ w(1, 1, v, v1)
60
+
61
+ exit = stop
62
+ delay = sleep
63
+
64
+ def getDistance():
65
+ pin1.write_digital(1)
66
+ pin1.write_digital(0)
67
+ p = machine.time_pulse_us(pin2, 1, 50000)
68
+ cm = int(p / 58.2 + 0.5)
69
+ return cm if cm > 0 else 255
70
+
71
+ def setLED(on):
72
+ pin8.write_digital(on)
73
+ pin12.write_digital(on)
74
+
75
+ def setServo(S, Angle):
76
+ if S == "S1":
77
+ Servo = 0x14
78
+ if S == "S2":
79
+ Servo = 0x15
80
+ buf = Servo, Angle
81
+ i2c.write(0x10, bytes(buf))
82
+
83
+ pin2.set_pull(pin2.NO_PULL)
84
+ _v = 50 # entspricht default 50
85
+ irLeft = pin13
86
+ irRight = pin14
87
+ ledLeft = pin8
88
+ ledRight = pin12
89
+
90
+ forward()
@@ -0,0 +1,179 @@
1
+ # mbrobot_plus.py
2
+ # Version 1.4 (1.10.2022)
3
+
4
+ from microbit import i2c,pin0,pin1,pin2,sleep
5
+ import machine
6
+ import gc
7
+ import music
8
+
9
+ _v = 50
10
+ _axe = 0.082
11
+
12
+ def w(d1, d2, s1, s2):
13
+ try:
14
+ i2c.write(0x10, bytearray([0x00,d1, d2, s1, s2]))
15
+ except:
16
+ print("Please switch on mbRobot!")
17
+
18
+ def setSpeed(speed):
19
+ global _v
20
+ if speed < 30 and speed != 0:
21
+ setPID(1)
22
+ _v = speed + 30
23
+ elif speed >= 30 and speed < 32:
24
+ setPID(0)
25
+ _v = speed + 2
26
+ else:
27
+ setPID(0)
28
+ _v = speed
29
+
30
+ def setPID(pd):
31
+ i2c.write(0x10, bytearray([0x0A, pd]))
32
+
33
+ def stop():
34
+ setPID(0)
35
+ w(0, 0, 0, 0)
36
+
37
+ def resetSpeed():
38
+ setPID(0)
39
+ _v = 50
40
+
41
+ def forward():
42
+ w(1, _v, 1, _v)
43
+
44
+ def backward():
45
+ w(2, _v, 2, _v)
46
+
47
+ def left():
48
+ m = 1.825 -0.0175 * _v
49
+ w(2, int(_v * m), 1, int(_v * m))
50
+
51
+ def right():
52
+ m = 1.825 -0.0175 * _v
53
+ w(1, int(_v * m), 2, int(_v * m))
54
+
55
+ def rightArc(r):
56
+ v = abs(_v)
57
+ if r < _axe:
58
+ v1 = 0
59
+ else:
60
+ f = (r - _axe) / (r + _axe) * (1 - v * v / 200000)
61
+ v1 = int(f * v)
62
+ if _v > 0:
63
+ w(1, v, 1, v1)
64
+ else:
65
+ w(2, v1, 2, v)
66
+
67
+ def leftArc(r):
68
+ v = abs(_v)
69
+ if r < _axe:
70
+ v1 = 0
71
+ else:
72
+ f = (r - _axe) / (r + _axe) * (1 - v * v / 200000)
73
+ v1 = int(f * v)
74
+ if _v > 0:
75
+ w(1, v1, 1, v)
76
+ else:
77
+ w(2, v, 2, v1)
78
+
79
+ def getDistance():
80
+ pin1.write_digital(1)
81
+ pin1.write_digital(0)
82
+ p = machine.time_pulse_us(pin2, 1, 50000)
83
+ cm = int(p / 58.2 - 0.5)
84
+ return cm if cm > 0 else 255
85
+
86
+ class Motor:
87
+ def __init__(self, id):
88
+ self._id = 2 * id
89
+
90
+ def _w(self, d, s):
91
+ try:
92
+ i2c.write(0x10, bytearray([self._id, d, s]))
93
+ except:
94
+ print("Please switch on mbRobot!")
95
+ while True:
96
+ pass
97
+
98
+ def rotate(self, s):
99
+ p = abs(s)
100
+ if s > 0:
101
+ self._w(1, p)
102
+ elif s < 0:
103
+ self._w(2, p)
104
+ else:
105
+ self._w(0, 0)
106
+
107
+ class LEDState:
108
+ OFF = 0
109
+ RED = 1
110
+ GREEN = 2
111
+ YELLOW = 3
112
+ BLUE = 4
113
+ PINK = 5
114
+ CYAN = 6
115
+ WHITE = 7
116
+
117
+ def setLED(state, stateR=None):
118
+ stateR = stateR or state
119
+ i2c.write(0x10, bytearray([0x0B, state, stateR]))
120
+
121
+ def setLEDLeft(state):
122
+ i2c.write(0x10, bytearray([0x0B, state]))
123
+
124
+ def setLEDRight(state):
125
+ i2c.write(0x10, bytearray([0x0C, state]))
126
+
127
+ def setAlarm(on):
128
+ if on:
129
+ music.play(_m, wait = False, loop = True)
130
+ else:
131
+ music.stop()
132
+
133
+ def beep():
134
+ music.pitch(2000, 200, wait = False)
135
+
136
+ def ir_read_values_as_byte():
137
+ i2c.write(0x10, bytearray([0x1D]))
138
+ buf = i2c.read(0x10, 1)
139
+ return ~buf[0]
140
+
141
+ def setServo(S, Angle):
142
+ if S == "S1":
143
+ Servo = 0x14
144
+ if S == "S2":
145
+ Servo = 0x15
146
+ buf = Servo, Angle
147
+ i2c.write(0x10, bytes(buf))
148
+
149
+ class IR:
150
+ L3 = 0
151
+ L2 = 1
152
+ L1 = 2
153
+ R1 = 3
154
+ R2 = 4
155
+ R3 = 5
156
+ masks = [0x01,0x02,0x04,0x08,0x10,0x20]
157
+
158
+ class IRSensor:
159
+ def __init__(self, index):
160
+ self.index = index
161
+
162
+ def read_digital(self):
163
+ byte = ir_read_values_as_byte()
164
+ return (byte & IR.masks[self.index]) >> self.index
165
+
166
+ irLeft = IRSensor(IR.L1)
167
+ irRight = IRSensor(IR.R1)
168
+ irL1 = IRSensor(IR.L1)
169
+ irR1 = IRSensor(IR.R1)
170
+ irL2 = IRSensor(IR.L2)
171
+ irR2 = IRSensor(IR.R2)
172
+ irL3 = IRSensor(IR.L3)
173
+ irR3 = IRSensor(IR.R3)
174
+ pin2.set_pull(pin2.NO_PULL)
175
+ motL = Motor(0)
176
+ motR = Motor(1)
177
+ delay = sleep
178
+ _m = ['c6:1', 'r', 'c6,1', 'r', 'r', 'r']
179
+