|
1 |
| -## Librairie Python pour Eliobot |
| 1 | +# Eliobot Python Library |
2 | 2 |
|
3 |
| -### Introduction |
4 |
| -La librairie Python fournit des fonctionnalités pour contrôler un robot. Elle utilise les bibliothèques `time`, `board`, `digitalio`, `analogio`, `pwmio` et `busio` pour interagir avec les différents composants matériels du robot, tels que les capteurs, les moteurs, les LED, etc. |
| 3 | +### Version 2.0 |
| 4 | +### 2024 - ELIO SAS |
5 | 5 |
|
6 |
| -### Installation |
7 |
| -Pour utiliser cette librairie, vous devez importer le fichier `code.py` dans le dossier `lib` de votre Eliobot. |
| 6 | +#### Project homepage: [https://eliobot.com](https://eliobot.com) |
8 | 7 |
|
| 8 | +## Introduction |
9 | 9 |
|
10 |
| -### Importation des librairies annexes |
11 |
| -La librairie se base sur les librairies suivantes, déjà intégrées : |
| 10 | +The Eliobot Python library provides functionality to control the Eliobot robot. It leverages libraries like `time`, `board`, `digitalio`, `analogio` and `pwmio` to interact with various hardware components of the robot, including sensors, motors, LEDs, and more. |
12 | 11 |
|
13 |
| -```python |
14 |
| -import time |
15 |
| -import board |
16 |
| -from digitalio import DigitalInOut, Direction, Pull |
17 |
| -from analogio import AnalogIn |
18 |
| -import pwmio |
19 |
| -import busio |
20 |
| -``` |
21 |
| - |
22 |
| -### Déclaration des broches |
23 |
| -Avant d'utiliser les différents composants du robot, vous devez déclarer les broches utilisées pour chaque composant. Voici les déclarations des broches pour les différents composants : |
24 |
| - |
25 |
| -```python |
26 |
| -# Setup the BATTERY voltage sense pin |
27 |
| -vbat_voltage = AnalogIn(board.BATTERY) |
28 |
| - |
29 |
| -# Setup the VBUS sense pin |
30 |
| -vbus_sense = DigitalInOut(board.VBUS_SENSE) |
31 |
| -vbus_sense.direction = Direction.INPUT |
32 |
| - |
33 |
| -# Obstacle input Pins declaration |
34 |
| -obstacleInput = [AnalogIn(board.IO4), AnalogIn(board.IO5), AnalogIn(board.IO6), AnalogIn(board.IO7)] |
35 |
| - |
36 |
| -# Line command pin |
37 |
| -lineCmd = DigitalInOut(board.IO33) |
38 |
| -lineCmd.direction = Direction.OUTPUT |
39 |
| - |
40 |
| -lineInput = [AnalogIn(board.IO10), AnalogIn(board.IO11), AnalogIn(board.IO12), AnalogIn(board.IO13), |
41 |
| - AnalogIn(board.IO14)] |
42 |
| - |
43 |
| -# Line threshhold |
44 |
| -threshold = calibration_data['average_min_value'] + ( |
45 |
| - calibration_data['average_max_value'] - calibration_data['average_min_value']) / 2 |
46 |
| - |
47 |
| -# Motor Driver Pins declaration |
48 |
| -AIN1 = pwmio.PWMOut(board.IO36) |
49 |
| -AIN2 = pwmio.PWMOut(board.IO38) |
50 |
| -BIN1 = pwmio.PWMOut(board.IO35) |
51 |
| -BIN2 = pwmio.PWMOut(board.IO37) |
52 |
| -``` |
53 |
| - |
54 |
| -### Fonctionnalités |
55 |
| - |
56 |
| -#### Mesure de la tension de la batterie |
57 |
| - |
58 |
| -```python |
59 |
| -def get_battery_voltage(): |
60 |
| - """Récupère la tension approximative de la batterie.""" |
61 |
| - global vbat_voltage |
62 |
| - return (vbat_voltage.value / 5371) |
63 |
| -``` |
64 |
| - |
65 |
| -Cette fonction renvoie la tension de la batterie en volts. |
66 |
| - |
67 |
| -#### Détection de la présence de l'alimentation VBUS |
| 12 | +## Installation |
68 | 13 |
|
69 |
| -```python |
70 |
| -def get_vbus_present(): |
71 |
| - """Détecte si une source d'alimentation VBUS (5V) est présente.""" |
72 |
| - global vbus_sense |
73 |
| - return vbus_sense.value |
74 |
| -``` |
75 |
| - |
76 |
| -Cette fonction renvoie `True` si une source d'alimentation VBUS est détectée, sinon elle renvoie `False`. |
77 |
| - |
78 |
| -#### Roue des couleurs RVB |
79 |
| - |
80 |
| -```python |
81 |
| -def rgb_color_wheel(wheel_pos): |
82 |
| - """Roue des couleurs pour parcourir les couleurs RVB de l'arc-en-ciel.""" |
83 |
| - wheel_pos = wheel_pos % 255 |
| 14 | +To install the Eliobot Python library, on your Eliobot go to: [https://app.eliobot.com/update/](https://app.eliobot.com/update/) and update Eliobot it will install the latest version of the library. |
84 | 15 |
|
85 |
| - if wheel_pos < 85: |
86 |
| - return 255 - wheel_pos * 3, 0, wheel_pos * 3 |
87 |
| - elif wheel_pos < 170: |
88 |
| - wheel_pos -= 85 |
89 |
| - return 0, wheel_pos * 3, 255 - wheel_pos * 3 |
90 |
| - else: |
91 |
| - wheel_pos -= 170 |
92 |
| - return wheel_pos * 3, 255 - wheel_pos * 3, 0 |
93 |
| -``` |
| 16 | +Or you can download the library and drop it in the `lib` folder of your Eliobot. |
94 | 17 |
|
95 |
| -Cette fonction prend une position de roue en entrée (0-254) et renvoie la couleur correspondante en RVB. Elle permet de parcourir les couleurs de l'arc-en-ciel. |
| 18 | +## Use the library in your Python code |
96 | 19 |
|
97 |
| -#### Capteurs d'obstacles |
| 20 | +To use the Eliobot Python library in your Python code, you need to import the `elio` module. Here is an example: |
98 | 21 |
|
99 | 22 | ```python
|
100 |
| -def getObstacle(obstacle_pos): |
101 |
| - """Récupère les valeurs des capteurs d'obstacles de gauche (position 0) à droite (position 3) et retour (position 4).""" |
102 |
| - obstacle_pos = obstacle_pos |
103 |
| - |
104 |
| - value = 0 |
105 |
| - |
106 |
| - value = obstacleInput[obstacle_pos].value |
107 |
| - |
108 |
| - if value < 10000: |
109 |
| - return True |
110 |
| - else: |
111 |
| - return False |
| 23 | +from elio import Eliobot |
112 | 24 | ```
|
113 | 25 |
|
114 |
| -Cette fonction prend la position d'un capteur d'obstacle en entrée (0-4) et renvoie `True` s'il détecte un obstacle, sinon elle renvoie `False`. |
115 |
| - |
116 |
| -#### Contrôle des moteurs |
| 26 | +now you can create an instance of the `Eliobot` class and start controlling the robot. Here is an example: |
117 | 27 |
|
118 | 28 | ```python
|
119 |
| -def setSpeed(speedValue): |
120 |
| - """Convertit la vitesse de 0-100% en 0-65535 pour une utilisation avec pwmio.""" |
121 |
| - if speedValue > 100: |
122 |
| - speedValue = 100 |
123 |
| - elif speedValue < 15: |
124 |
| - speedValue += 15 |
125 |
| - |
126 |
| - pwmValue = int((speedValue / 100) * 65535) |
| 29 | +from elio import Eliobot # Import the Eliobot class |
| 30 | +import board # Import the board module |
| 31 | +import time # Import the time module |
| 32 | +import digitalio # Import the digitalio module |
| 33 | +import analogio # Import the analogio module |
| 34 | +import pwmio # Import the pwmio module |
127 | 35 |
|
128 |
| - return pwmValue |
| 36 | +vBatt_pin = analogio.AnalogIn(board.BATTERY) # Battery voltage pin |
129 | 37 |
|
| 38 | +obstacleInput = [analogio.AnalogIn(pin) for pin in |
| 39 | + (board.IO4, board.IO5, board.IO6, board.IO7)] # Obstacle sensors |
130 | 40 |
|
131 |
| -def moveForward(speed): |
132 |
| - """Fait avancer le robot à une vitesse donnée (0-100%).""" |
133 |
| - pwm_value = setSpeed(speed) |
134 |
| - AIN1.duty_cycle = 0 |
135 |
| - AIN2.duty_cycle = pwm_value |
136 |
| - BIN1.duty_cycle = 0 |
137 |
| - BIN2.duty_cycle = pwm_value |
138 |
| -``` |
139 |
| - |
140 |
| -Les autres fonctions de contrôle des moteurs `moveBackward`, `turnLeft`, `turnRight`, `motorStop`, `motorSlow`, `spinLeftWheelForward`, `spinLeftWheelBackward`, `spinRightWheelForward`, `spinRightWheelBackward`, |
141 |
| -`moveOneStep` suivent une structure similaire. |
142 |
| - |
143 |
| -Ces fonctions permettent de contrôler les moteurs du robot pour effectuer différentes actions telles que avancer, reculer, tourner, arrêter, etc. |
| 41 | +lineCmd = digitalio.DigitalInOut(board.IO33) # Line sensors command pin |
| 42 | +lineCmd.direction = digitalio.Direction.OUTPUT # Set the direction of the line command pin |
144 | 43 |
|
145 |
| -#### Buzzer |
146 |
| - |
147 |
| -```python |
148 |
| -def buzzerInit(): |
149 |
| - """Initialise le buzzer.""" |
150 |
| - buzzerPin = pwmio.PWMOut(board.IO17, variable_frequency=True) |
151 |
| - return buzzerPin |
152 |
| - |
| 44 | +lineInput = [analogio.AnalogIn(pin) for pin in |
| 45 | + (board.IO10, board.IO11, board.IO12, board.IO13, board.IO14)] # Line sensors |
153 | 46 |
|
154 |
| -def playFrequency(frequency, waitTime, volume): |
155 |
| - """Joue une fréquence (en Hertz) pendant une durée donnée (en secondes) avec un volume spécifié.""" |
156 |
| - buzzer = buzzerInit() |
157 |
| - buzzer.frequency = round(frequency) |
158 |
| - buzzer.duty_cycle = int(2 ** (0.06 * volume + 9)) # La valeur 32768 correspond à un cycle de service de 50 % pour obtenir une onde carrée. |
159 |
| - time.sleep(waitTime) |
160 |
| - buzzer.deinit() |
| 47 | +AIN1 = pwmio.PWMOut(board.IO36) # Motor A input 1 |
| 48 | +AIN2 = pwmio.PWMOut(board.IO38) # Motor A input 2 |
| 49 | +BIN1 = pwmio.PWMOut(board.IO35) # Motor B input 1 |
| 50 | +BIN2 = pwmio.PWMOut(board.IO37) # Motor B input 2 |
161 | 51 |
|
| 52 | +buzzer = pwmio.PWMOut(board.IO17, variable_frequency=True) # Buzzer |
162 | 53 |
|
163 |
| -def playNote(note, duration, NOTES_FREQUENCIES, volume): |
164 |
| - """Joue une note (C, D, E, F, G, A ou B) pendant une durée donnée (en secondes).""" |
165 |
| - if note in NOTES_FREQUENCIES: |
166 |
| - frequency = NOTES_FREQUENCIES[note] |
167 |
| - if frequency != 0.1: |
168 |
| - playFrequency(frequency, duration, volume) |
169 |
| - else: |
170 |
| - time.sleep(duration) |
| 54 | +# Create an instance of the Eliobot class |
| 55 | +elio = Eliobot(AIN1, AIN2, BIN1, BIN2, vBatt_pin, obstacleInput, buzzer, lineInput, lineCmd) |
171 | 56 | ```
|
172 | 57 |
|
173 |
| -Ces fonctions permettent de contrôler le buzzer pour jouer des fréquences spécifiques et des notes de musique avec une durée et un volume donnés. |
174 |
| - |
175 |
| -#### Suivi de ligne |
176 |
| - |
177 |
| -```python |
178 |
| -# Get the line sensors value from Left (position 0) to Right (position 4) |
179 |
| -def getLine(line_pos): |
180 |
| - ambient = 0 |
181 |
| - lit = 0 |
182 |
| - value = 0 |
183 |
| - |
184 |
| - # Measure reflected IR |
185 |
| - lineCmd.value = True |
186 |
| - time.sleep(0.02) |
187 |
| - lit = lineInput[line_pos].value |
| 58 | +## Documentation |
188 | 59 |
|
189 |
| - # Measure ambient light |
190 |
| - lineCmd.value = False |
191 |
| - time.sleep(0.02) |
192 |
| - ambient = lineInput[line_pos].value |
193 |
| - |
194 |
| - # Ambient - Reflected |
195 |
| - value = ambient - lit |
196 |
| - |
197 |
| - return value |
198 |
| - |
199 |
| - |
200 |
| -# Example function to follow a black line on white paper |
201 |
| -def followLine(speed=100): |
202 |
| - if getLine(2) < threshold: |
203 |
| - moveForward(speed) |
204 |
| - |
205 |
| - elif getLine(0) < threshold: |
206 |
| - motorStop() |
207 |
| - spinRightWheelForward(speed) |
208 |
| - |
209 |
| - time.sleep(0.1) |
210 |
| - |
211 |
| - elif getLine(1) < threshold: |
212 |
| - motorStop() |
213 |
| - spinRightWheelForward(speed) |
214 |
| - |
215 |
| - elif getLine(3) < threshold: |
216 |
| - motorStop() |
217 |
| - spinLeftWheelForward(speed) |
218 |
| - |
219 |
| - elif getLine(4) < threshold: |
220 |
| - motorStop() |
221 |
| - spinLeftWheelForward(speed) |
222 |
| - time.sleep(0.1) |
223 |
| - |
224 |
| - else: |
225 |
| - motorStop() |
226 |
| - |
227 |
| - |
228 |
| -# Calibrate the line sensors |
229 |
| -def calibrateLineSensors(): |
230 |
| - time.sleep(1) |
231 |
| - wait_time = 0.5 |
232 |
| - num_samples = 5 |
233 |
| - max_values = [0] * num_samples |
234 |
| - min_values = [float('inf')] * num_samples |
235 |
| - |
236 |
| - moveForward(100) |
237 |
| - time.sleep(wait_time) |
238 |
| - motorStop() |
239 |
| - time.sleep(1) |
240 |
| - updateSensorValues(max_values, min_values) |
241 |
| - |
242 |
| - moveBackward(100) |
243 |
| - time.sleep(wait_time) |
244 |
| - motorStop() |
245 |
| - time.sleep(1) |
246 |
| - updateSensorValues(max_values, min_values) |
247 |
| - |
248 |
| - moveBackward(100) |
249 |
| - time.sleep(wait_time) |
250 |
| - motorStop() |
251 |
| - time.sleep(1) |
252 |
| - updateSensorValues(max_values, min_values) |
253 |
| - |
254 |
| - moveForward(100) |
255 |
| - time.sleep(wait_time) |
256 |
| - motorStop() |
257 |
| - time.sleep(1) |
258 |
| - updateSensorValues(max_values, min_values) |
259 |
| - |
260 |
| - avg_max_value = sum(max_values) / len(max_values) |
261 |
| - avg_min_value = sum(min_values) / len(min_values) |
262 |
| - |
263 |
| - saveCalibrationData(avg_max_value, avg_min_value) |
264 |
| - |
265 |
| - print("Calibration completed:") |
266 |
| - print("Average Max value:", avg_max_value) |
267 |
| - print("Average Min value:", avg_min_value) |
268 |
| - |
269 |
| - |
270 |
| -def updateSensorValues(max_values, min_values): |
271 |
| - for i in range(5): |
272 |
| - current_value = getLine(i) |
273 |
| - max_values[i] = max(max_values[i], current_value) |
274 |
| - min_values[i] = min(min_values[i], current_value) |
275 |
| - |
276 |
| - |
277 |
| -def saveCalibrationData(avg_max_value, avg_min_value): |
278 |
| - # Create a dictionary to hold the data |
279 |
| - calibration_data = { |
280 |
| - 'average_max_value': avg_max_value, |
281 |
| - 'average_min_value': avg_min_value |
282 |
| - } |
283 |
| - |
284 |
| - # Write the dictionary to a file in JSON format |
285 |
| - with open('config.json', 'w') as file: |
286 |
| - json.dump(calibration_data, file) |
287 |
| -``` |
288 |
| - |
289 |
| -#### WiFi |
290 |
| - |
291 |
| -```python |
292 |
| -# Connect to a wifi network |
293 |
| -def connectToWifi(ssid, password, webpassword): |
294 |
| - with open('settings.toml', 'w') as f: |
295 |
| - f.write('CIRCUITPY_WIFI_SSID = "' + ssid + '"\n') |
296 |
| - f.write('CIRCUITPY_WIFI_PASSWORD = "' + password + '"\n') |
297 |
| - f.write('CIRCUITPY_WEB_API_PASSWORD = "' + webpassword + '"\n') |
298 |
| - |
299 |
| - print("Settings saved") |
300 |
| - print("Restart the board to connect to the wifi network") |
301 |
| - |
302 |
| - |
303 |
| -# Disconnect from the wifi network |
304 |
| -def disconnectFromWifi(): |
305 |
| - wifi.radio.enabled = False |
306 |
| - while wifi.radio.connected: |
307 |
| - time.sleep(0.1) |
308 |
| - print("Disconnected from wifi") |
309 |
| - |
310 |
| - |
311 |
| -# Set Eliobot as an access point |
312 |
| -def setAccessPoint(ssid, password): |
313 |
| - wifi.radio.enabled = True |
314 |
| - wifi.radio.start_ap(ssid, password) |
315 |
| - |
316 |
| - |
317 |
| -# Scan for wifi networks |
318 |
| -def scanWifiNetworks(): |
319 |
| - wifi.radio.enabled = True |
320 |
| - networks = wifi.radio.start_scanning_networks() |
321 |
| - print("Réseaux WiFi disponibles:") |
322 |
| - for network in networks: |
323 |
| - # RSSI to percentage |
324 |
| - MAX_RSSI = -30 # 100% RSSI |
325 |
| - MIN_RSSI = -90 # 0% RSSI |
326 |
| - rssi = max(min(network.rssi, MAX_RSSI), MIN_RSSI) |
327 |
| - percentage = (rssi - MIN_RSSI) / (MAX_RSSI - MIN_RSSI) * 100 |
328 |
| - |
329 |
| - print("SSID:", network.ssid, ", Canal:", network.channel, ", RSSI:", network.rssi, " (", round(percentage), |
330 |
| - "%)") |
331 |
| - wifi.radio.stop_scanning_networks() |
332 |
| - return networks |
333 |
| - |
334 |
| -``` |
335 |
| - |
336 |
| -Ces fonctions permettent de détecter et de suivre une ligne noire sur une surface blanche à l'aide de capteurs de ligne. La fonction `getLine` récupère les valeurs des capteurs de ligne de gauche à droite et calcule la différence entre la lumière ambiante et la lumière réfléchie pour déterminer la position de la ligne. La fonction `followLine` utilise ces valeurs pour prendre des décisions sur la direction à suivre. Si la ligne est détectée par le capteur central, le robot avance, s'il est détecté par le capteur gauche, le robot tourne à gauche, s'il est détecté par le capteur droit, le robot tourne à droite, sinon le robot recule à une vitesse plus lente. |
| 60 | +### Attributes |
337 | 61 |
|
| 62 | +- `AIN1`: Right Motor input 1 (pwmio.PWMOut) |
| 63 | +- `AIN2`: Right Motor input 2 (pwmio.PWMOut) |
| 64 | +- `BIN1`: Left Motor input 1 (pwmio.PWMOut) |
| 65 | +- `BIN2`: Left Motor input 2 (pwmio.PWMOut) |
| 66 | +- `vBatt_pin`: Battery voltage pin (analogio.AnalogIn) |
| 67 | +- `obstacleInput`: List of obstacle sensors (analogio.AnalogIn) |
| 68 | +- `buzzer`: Buzzer (pwmio.PWMOut) |
| 69 | +- `lineInput`: List of line sensors (analogio.AnalogIn) |
| 70 | +- `lineCmd`: Line sensors command pin (digitalio.DigitalInOut) |
338 | 71 |
|
0 commit comments