@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.
- package/CHANGELOG +68 -0
- package/LICENSE +373 -0
- package/README.md +81 -0
- package/calliope/README.md +15 -0
- package/calliope/callibot.py +176 -0
- package/calliope/callibotmot.py +46 -0
- package/calliope/callimk.py +143 -0
- package/calliope/cbalarm.py +14 -0
- package/calliope/cpglow.py +76 -0
- package/calliope/cpmike.py +16 -0
- package/calliope/cprover.py +33 -0
- package/calliope/cputils.py +23 -0
- package/calliope/libraries.json +10 -0
- package/calliope/libraries.raw.json +10 -0
- package/calliope/min/callibot.py +97 -0
- package/calliope/min/callibotmot.py +23 -0
- package/calliope/min/callimk.py +47 -0
- package/calliope/min/cbalarm.py +6 -0
- package/calliope/min/cpglow.py +29 -0
- package/calliope/min/cpmike.py +8 -0
- package/calliope/min/cprover.py +9 -0
- package/calliope/min/cputils.py +7 -0
- package/dist/index.d.mts +124 -0
- package/dist/index.d.ts +124 -0
- package/dist/index.js +2896 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2862 -0
- package/dist/index.mjs.map +1 -0
- package/microbit/README.md +48 -0
- package/microbit/controller.py +212 -0
- package/microbit/huskylens.py +479 -0
- package/microbit/libraries.json +19 -0
- package/microbit/libraries.raw.json +19 -0
- package/microbit/mbalarm.py +15 -0
- package/microbit/mbbitbot.py +127 -0
- package/microbit/mbglow.py +77 -0
- package/microbit/mbled.py +56 -0
- package/microbit/mbmarsrover.py +216 -0
- package/microbit/mbminibit.py +139 -0
- package/microbit/mbrobot.py +401 -0
- package/microbit/mbrobot_legacy.py +90 -0
- package/microbit/mbrobot_plus.py +179 -0
- package/microbit/mbrobot_plusV2.py +490 -0
- package/microbit/mbrobot_plusV3.py +427 -0
- package/microbit/mbrobotmot.py +49 -0
- package/microbit/mbthetabot.py +167 -0
- package/microbit/mbwait.py +50 -0
- package/microbit/mbxgo.py +173 -0
- package/microbit/min/controller.py +42 -0
- package/microbit/min/huskylens.py +145 -0
- package/microbit/min/mbalarm.py +6 -0
- package/microbit/min/mbbitbot.py +40 -0
- package/microbit/min/mbglow.py +29 -0
- package/microbit/min/mbled.py +18 -0
- package/microbit/min/mbmarsrover.py +62 -0
- package/microbit/min/mbminibit.py +50 -0
- package/microbit/min/mbrobot.py +82 -0
- package/microbit/min/mbrobot_legacy.py +45 -0
- package/microbit/min/mbrobot_plus.py +75 -0
- package/microbit/min/mbrobot_plusV2.py +102 -0
- package/microbit/min/mbrobot_plusV3.py +194 -0
- package/microbit/min/mbrobotmot.py +25 -0
- package/microbit/min/mbthetabot.py +47 -0
- package/microbit/min/mbwait.py +23 -0
- package/microbit/min/mbxgo.py +37 -0
- package/package.json +54 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from neopixel import *
|
|
2
|
+
import gc
|
|
3
|
+
from microbit import pin2
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
_nbLeds = 24
|
|
7
|
+
_np = NeoPixel(pin2, _nbLeds)
|
|
8
|
+
|
|
9
|
+
# Fill all pixels with the same color.
|
|
10
|
+
# The color is specified by giving values between 0 and 255 for red, green and blue
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def fill(red, green, blue):
|
|
14
|
+
for i in range(_nbLeds):
|
|
15
|
+
_np[i] = (red, green, blue)
|
|
16
|
+
_np.show()
|
|
17
|
+
|
|
18
|
+
# Set the specified pixel to the specified color.
|
|
19
|
+
# The pixel is specified by a number between 0 and 23.
|
|
20
|
+
# The color is specified by giving values between 0 and 255 for red, green and blue
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def set_led(pos, red, green, blue):
|
|
24
|
+
_np[pos] = (red, green, blue)
|
|
25
|
+
_np.show()
|
|
26
|
+
|
|
27
|
+
# clears all LEDS by turning them off
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def clear():
|
|
31
|
+
_np.clear()
|
|
32
|
+
|
|
33
|
+
# shift the displayed image by as many led-positions as specified in parameter "amount".
|
|
34
|
+
# LED strip behaves like a cycle and wraps around when shifting across borders.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def shift_by(amount):
|
|
38
|
+
shifted_copy = [None]*_nbLeds
|
|
39
|
+
for n in range(0, _nbLeds):
|
|
40
|
+
next_i = (n + amount) % _nbLeds
|
|
41
|
+
shifted_copy[n] = _np[next_i]
|
|
42
|
+
for n in range(0, _nbLeds):
|
|
43
|
+
_np[n] = shifted_copy[n]
|
|
44
|
+
_np.show()
|
|
45
|
+
|
|
46
|
+
# get linearly interpolated colors in RGB space.
|
|
47
|
+
# "percent" is the blending distance between the two colors. 0 is first color only, and 100 is second color only.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def lerp_RGB(r1, g1, b1, r2, g2, b2, percent):
|
|
51
|
+
if percent < 0.0 or percent > 100.0:
|
|
52
|
+
raise RuntimeError("Argument 'percent' must be between 0 and 100.")
|
|
53
|
+
red = max(0, min(255, round(r1 + (r2 - r1) * (percent/100.0))))
|
|
54
|
+
green = max(0, min(255, round(g1 + (g2 - g1) * (percent/100.0))))
|
|
55
|
+
blue = max(0, min(255, round(b1 + (b2 - b1) * (percent/100.0))))
|
|
56
|
+
return red, green, blue
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
from microbit import *
|
|
2
|
+
from neopixel import *
|
|
3
|
+
import utime
|
|
4
|
+
|
|
5
|
+
_servoArray = [0, 9, 11, 13, 15]
|
|
6
|
+
_servoOffset = [0, 0, 0, 0, 0]
|
|
7
|
+
_initI2C = False
|
|
8
|
+
|
|
9
|
+
_nbLeds = 4
|
|
10
|
+
_np = NeoPixel(pin2, _nbLeds)
|
|
11
|
+
|
|
12
|
+
_speedPercent = 50
|
|
13
|
+
_powerByteL = 40
|
|
14
|
+
_powerByteR = 40
|
|
15
|
+
|
|
16
|
+
_powerOffset = 0
|
|
17
|
+
_powerDifferential = 0
|
|
18
|
+
_arcScaling = 0
|
|
19
|
+
|
|
20
|
+
_MAX_CM_DISTANCE = 500
|
|
21
|
+
_CM_PER_MICROSECOND = 29.1
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _setMotors(dirL, powerL, dirR, powerR):
|
|
25
|
+
pinsL = (pin1, pin12)
|
|
26
|
+
pinsR = (pin8, pin0)
|
|
27
|
+
|
|
28
|
+
pinsL[dirL].write_analog(powerL)
|
|
29
|
+
pinsL[1 - dirL].write_analog(0)
|
|
30
|
+
|
|
31
|
+
pinsR[dirR].write_analog(powerR)
|
|
32
|
+
pinsR[1 - dirR].write_analog(0)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _setSingleMotor(side, direction, power):
|
|
36
|
+
if side == 0:
|
|
37
|
+
pins = (pin1, pin12)
|
|
38
|
+
elif side == 1:
|
|
39
|
+
pins = (pin8, pin0)
|
|
40
|
+
|
|
41
|
+
pins[direction].write_analog(power)
|
|
42
|
+
pins[1 - direction].write_analog(0)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _getArcBytes(r):
|
|
46
|
+
outerSpeed = _speedPercent
|
|
47
|
+
rCm = int(r * 100)
|
|
48
|
+
threshold = outerSpeed - max(rCm + 20, 40)
|
|
49
|
+
if (threshold <= 0):
|
|
50
|
+
outerSpeed = min(max(rCm + 40, 40), 100)
|
|
51
|
+
reducedSpeed = 0
|
|
52
|
+
if rCm >= 4:
|
|
53
|
+
flattening = (100 - outerSpeed) // 2
|
|
54
|
+
reducedSpeed = (rCm * 10 - 35) / \
|
|
55
|
+
(rCm * (11 + (_arcScaling - 4) / 10) + 90 + flattening)
|
|
56
|
+
reducedSpeed = reducedSpeed * outerSpeed
|
|
57
|
+
innerByte = _convertSpeedToAnalogValue(int(reducedSpeed), 0)
|
|
58
|
+
outerByte = _convertSpeedToAnalogValue(int(outerSpeed), 0)
|
|
59
|
+
return (innerByte, outerByte)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _initPCA():
|
|
63
|
+
global _initI2C
|
|
64
|
+
_initI2C = True
|
|
65
|
+
i2cData = bytearray(2)
|
|
66
|
+
i2cData[0] = 0
|
|
67
|
+
i2cData[1] = 0x10
|
|
68
|
+
i2c.write(0x40, i2cData)
|
|
69
|
+
|
|
70
|
+
i2cData[0] = 0xFE
|
|
71
|
+
i2cData[1] = 101
|
|
72
|
+
i2c.write(0x40, i2cData)
|
|
73
|
+
|
|
74
|
+
i2cData[0] = 0
|
|
75
|
+
i2cData[1] = 0x81
|
|
76
|
+
i2c.write(0x40, i2cData)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _pulse_in(pin, value, timeout):
|
|
80
|
+
start_time = utime.ticks_us()
|
|
81
|
+
|
|
82
|
+
while pin.read_digital() != value:
|
|
83
|
+
if utime.ticks_diff(utime.ticks_us(), start_time) > timeout:
|
|
84
|
+
return 0
|
|
85
|
+
|
|
86
|
+
start_time = utime.ticks_us()
|
|
87
|
+
while pin.read_digital() == value:
|
|
88
|
+
if utime.ticks_diff(utime.ticks_us(), start_time) > timeout:
|
|
89
|
+
return 0
|
|
90
|
+
|
|
91
|
+
return utime.ticks_diff(utime.ticks_us(), start_time)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def calibrate(offset, differential=0, arcScaling=0):
|
|
95
|
+
global _powerDifferential
|
|
96
|
+
global _powerOffset
|
|
97
|
+
global _arcScaling
|
|
98
|
+
|
|
99
|
+
_powerOffset = max(min(int(offset), 500), -50)
|
|
100
|
+
_powerDifferential = max(min(int(differential), 150), -150)
|
|
101
|
+
_arcScaling = max(min(arcScaling, 50), -15)
|
|
102
|
+
setSpeed(_speedPercent)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def setSpeed(speed):
|
|
106
|
+
global _speedPercent
|
|
107
|
+
global _powerByteL
|
|
108
|
+
global _powerByteR
|
|
109
|
+
|
|
110
|
+
_speedPercent = int(min(max(speed, 0), 100))
|
|
111
|
+
powerValue = _convertSpeedToAnalogValue(_speedPercent, _powerOffset)
|
|
112
|
+
boost = round((1 - _speedPercent / 100) *
|
|
113
|
+
abs(_powerDifferential)) if _speedPercent > 0 else 0
|
|
114
|
+
reduction = round((_speedPercent / 100) * abs(_powerDifferential))
|
|
115
|
+
if _powerDifferential > 0:
|
|
116
|
+
_powerByteL = powerValue - reduction
|
|
117
|
+
_powerByteR = powerValue + boost
|
|
118
|
+
else:
|
|
119
|
+
_powerByteL = powerValue + boost
|
|
120
|
+
_powerByteR = powerValue - reduction
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _convertSpeedToAnalogValue(speed, offset):
|
|
124
|
+
analogValue = int(speed * 1023 / 100) + offset
|
|
125
|
+
return min(max(analogValue, 0), 1023)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def stop():
|
|
129
|
+
_setMotors(0, 0, 0, 0)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def forward():
|
|
133
|
+
_setMotors(0, _powerByteL, 0, _powerByteR)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def backward():
|
|
137
|
+
_setMotors(1, _powerByteL, 1, _powerByteR)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def setServo(servoNum, angle):
|
|
141
|
+
global _servoArray, _initI2C
|
|
142
|
+
if _initI2C == False:
|
|
143
|
+
_initPCA()
|
|
144
|
+
offsetNum = servoNum
|
|
145
|
+
servoNum = _servoArray[servoNum]
|
|
146
|
+
i2cData = bytearray(2)
|
|
147
|
+
start = 0
|
|
148
|
+
angle = max(min(angle, 90), -90)
|
|
149
|
+
stop = 396 + (angle + _servoOffset[offsetNum]) * 223 / 90
|
|
150
|
+
i2cData[0] = 0x06 + servoNum * 4 + 2
|
|
151
|
+
i2cData[1] = int(stop) + 0xff
|
|
152
|
+
i2c.write(0x40, i2cData)
|
|
153
|
+
|
|
154
|
+
i2cData[0] = 0x06 + servoNum*4 + 3
|
|
155
|
+
i2cData[1] = int(stop) >> 8
|
|
156
|
+
i2c.write(0x40, i2cData)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def clearServos():
|
|
160
|
+
setServo(0, 0)
|
|
161
|
+
setServo(1, 0)
|
|
162
|
+
setServo(2, 0)
|
|
163
|
+
setServo(3, 0)
|
|
164
|
+
setServo(4, 0)
|
|
165
|
+
sleep(500)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def steer(angle):
|
|
169
|
+
angle = max(min(angle, 45), -45)
|
|
170
|
+
setServo(1, angle)
|
|
171
|
+
setServo(2, -angle)
|
|
172
|
+
setServo(3, -angle)
|
|
173
|
+
setServo(4, angle)
|
|
174
|
+
sleep(500)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def setLED(pos, red, green, blue):
|
|
178
|
+
_np[pos] = (red, green, blue)
|
|
179
|
+
_np.show()
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def fill(red, green, blue):
|
|
183
|
+
for i in range(_nbLeds):
|
|
184
|
+
_np[i] = (red, green, blue)
|
|
185
|
+
_np.show()
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def getDistance():
|
|
189
|
+
trig = pin13
|
|
190
|
+
echo = pin13
|
|
191
|
+
|
|
192
|
+
d = 10
|
|
193
|
+
|
|
194
|
+
trig.set_pull(trig.NO_PULL)
|
|
195
|
+
|
|
196
|
+
for _ in range(10):
|
|
197
|
+
trig.write_digital(0)
|
|
198
|
+
utime.sleep_us(2)
|
|
199
|
+
trig.write_digital(1)
|
|
200
|
+
utime.sleep_us(10)
|
|
201
|
+
trig.write_digital(0)
|
|
202
|
+
|
|
203
|
+
duration = _pulse_in(echo, 1, _MAX_CM_DISTANCE * _CM_PER_MICROSECOND)
|
|
204
|
+
if duration > 0:
|
|
205
|
+
d = duration
|
|
206
|
+
break
|
|
207
|
+
|
|
208
|
+
return round(d / _CM_PER_MICROSECOND)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def calibrateServo(pos, angleDifferential):
|
|
212
|
+
global _servoOffset
|
|
213
|
+
|
|
214
|
+
angleDifferential = max(min(angleDifferential, 90), -90)
|
|
215
|
+
_servoOffset[pos] = angleDifferential
|
|
216
|
+
clearServos()
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
from microbit import *
|
|
2
|
+
from neopixel import *
|
|
3
|
+
import utime
|
|
4
|
+
|
|
5
|
+
_nbLeds = 4
|
|
6
|
+
_np = NeoPixel(pin13, _nbLeds)
|
|
7
|
+
|
|
8
|
+
_speedPercent = 50
|
|
9
|
+
_powerLeft = 90
|
|
10
|
+
_powerRight = 90
|
|
11
|
+
|
|
12
|
+
_powerOffset = 0
|
|
13
|
+
_powerDifferential = 0
|
|
14
|
+
_arcScaling = 0
|
|
15
|
+
|
|
16
|
+
_MAX_CM_DISTANCE = 500
|
|
17
|
+
_CM_PER_MICROSECOND = 29.1
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _setMotors(dirL, powerL, dirR, powerR):
|
|
21
|
+
pin8.write_analog(powerL if dirL == 1 else 0)
|
|
22
|
+
pin12.write_analog(0 if dirL == 1 else powerL)
|
|
23
|
+
pin16.write_analog(0 if dirR == 1 else powerR)
|
|
24
|
+
pin14.write_analog(powerR if dirR == 1 else 0)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _pulse_in(pin, value, timeout):
|
|
28
|
+
start_time = utime.ticks_us()
|
|
29
|
+
while pin.read_digital() != value:
|
|
30
|
+
if utime.ticks_diff(utime.ticks_us(), start_time) > timeout:
|
|
31
|
+
return 0
|
|
32
|
+
start_time = utime.ticks_us()
|
|
33
|
+
while pin.read_digital() == value:
|
|
34
|
+
if utime.ticks_diff(utime.ticks_us(), start_time) > timeout:
|
|
35
|
+
return 0
|
|
36
|
+
return utime.ticks_diff(utime.ticks_us(), start_time)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _getArcBytes(r):
|
|
40
|
+
outerSpeed = _speedPercent
|
|
41
|
+
if r > 0:
|
|
42
|
+
innerSpeed = outerSpeed * max(0.2, min(1, 1 - r / 100))
|
|
43
|
+
else:
|
|
44
|
+
innerSpeed = 0
|
|
45
|
+
|
|
46
|
+
innerByte = _convertSpeedToAnalogValue(int(innerSpeed), 0)
|
|
47
|
+
outerByte = _convertSpeedToAnalogValue(int(outerSpeed), 0)
|
|
48
|
+
return (innerByte, outerByte)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _convertSpeedToAnalogValue(speed, offset):
|
|
52
|
+
analogValue = int(speed * 255 / 100) + offset
|
|
53
|
+
return min(max(analogValue, 0), 255)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def calibrate(offset, differential=0, arcScaling=0):
|
|
57
|
+
global _powerDifferential
|
|
58
|
+
global _powerOffset
|
|
59
|
+
global _arcScaling
|
|
60
|
+
_powerOffset = max(min(int(offset), 100), -10)
|
|
61
|
+
_powerDifferential = max(min(int(differential), 150), -150)
|
|
62
|
+
_arcScaling = max(min(arcScaling, 50), -15)
|
|
63
|
+
setSpeed(_speedPercent)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def setSpeed(speed):
|
|
67
|
+
global _speedPercent
|
|
68
|
+
global _powerLeft
|
|
69
|
+
global _powerRight
|
|
70
|
+
_speedPercent = int(min(max(speed, 0), 100))
|
|
71
|
+
powerByte = _convertSpeedToAnalogValue(_speedPercent, _powerOffset)
|
|
72
|
+
boost = round((1 - _speedPercent / 100) *
|
|
73
|
+
abs(_powerDifferential)) if _speedPercent > 0 else 0
|
|
74
|
+
reduction = round((_speedPercent / 100) * abs(_powerDifferential))
|
|
75
|
+
if _powerDifferential > 0:
|
|
76
|
+
_powerLeft = powerByte - reduction
|
|
77
|
+
_powerRight = powerByte + boost
|
|
78
|
+
else:
|
|
79
|
+
_powerLeft = powerByte + boost
|
|
80
|
+
_powerRight = powerByte - reduction
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def stop():
|
|
84
|
+
_setMotors(0, 0, 0, 0)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def forward():
|
|
88
|
+
_setMotors(0, _powerLeft, 0, _powerRight)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def backward():
|
|
92
|
+
_setMotors(1, _powerLeft, 1, _powerRight)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def left():
|
|
96
|
+
_setMotors(1, _powerLeft, 0, _powerRight)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def right():
|
|
100
|
+
_setMotors(0, _powerLeft, 1, _powerRight)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def rightArc(radius):
|
|
104
|
+
inner, outer = _getArcBytes(radius)
|
|
105
|
+
_setMotors(0, outer, 0, inner)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def leftArc(radius):
|
|
109
|
+
inner, outer = _getArcBytes(radius)
|
|
110
|
+
_setMotors(0, inner, 0, outer)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def setLED(pos, red, green, blue):
|
|
114
|
+
_np[pos] = (red, green, blue)
|
|
115
|
+
_np.show()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def fill(red, green, blue):
|
|
119
|
+
for i in range(_nbLeds):
|
|
120
|
+
_np[i] = (red, green, blue)
|
|
121
|
+
_np.show()
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def getDistance():
|
|
125
|
+
trig = pin15
|
|
126
|
+
echo = pin15
|
|
127
|
+
d = 10
|
|
128
|
+
trig.set_pull(trig.NO_PULL)
|
|
129
|
+
for _ in range(10):
|
|
130
|
+
trig.write_digital(0)
|
|
131
|
+
utime.sleep_us(2)
|
|
132
|
+
trig.write_digital(1)
|
|
133
|
+
utime.sleep_us(10)
|
|
134
|
+
trig.write_digital(0)
|
|
135
|
+
duration = _pulse_in(echo, 1, _MAX_CM_DISTANCE * _CM_PER_MICROSECOND)
|
|
136
|
+
if duration > 0:
|
|
137
|
+
d = duration
|
|
138
|
+
break
|
|
139
|
+
return round(d / _CM_PER_MICROSECOND)
|