-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
557 additions
and
711 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,338 +1,71 @@ | ||
## Librairie Python pour Eliobot | ||
# Eliobot Python Library | ||
|
||
### Introduction | ||
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. | ||
### Version 2.0 | ||
### 2024 - ELIO SAS | ||
|
||
### Installation | ||
Pour utiliser cette librairie, vous devez importer le fichier `code.py` dans le dossier `lib` de votre Eliobot. | ||
#### Project homepage: [https://eliobot.com](https://eliobot.com) | ||
|
||
## Introduction | ||
|
||
### Importation des librairies annexes | ||
La librairie se base sur les librairies suivantes, déjà intégrées : | ||
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. | ||
|
||
```python | ||
import time | ||
import board | ||
from digitalio import DigitalInOut, Direction, Pull | ||
from analogio import AnalogIn | ||
import pwmio | ||
import busio | ||
``` | ||
|
||
### Déclaration des broches | ||
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 : | ||
|
||
```python | ||
# Setup the BATTERY voltage sense pin | ||
vbat_voltage = AnalogIn(board.BATTERY) | ||
|
||
# Setup the VBUS sense pin | ||
vbus_sense = DigitalInOut(board.VBUS_SENSE) | ||
vbus_sense.direction = Direction.INPUT | ||
|
||
# Obstacle input Pins declaration | ||
obstacleInput = [AnalogIn(board.IO4), AnalogIn(board.IO5), AnalogIn(board.IO6), AnalogIn(board.IO7)] | ||
|
||
# Line command pin | ||
lineCmd = DigitalInOut(board.IO33) | ||
lineCmd.direction = Direction.OUTPUT | ||
|
||
lineInput = [AnalogIn(board.IO10), AnalogIn(board.IO11), AnalogIn(board.IO12), AnalogIn(board.IO13), | ||
AnalogIn(board.IO14)] | ||
|
||
# Line threshhold | ||
threshold = calibration_data['average_min_value'] + ( | ||
calibration_data['average_max_value'] - calibration_data['average_min_value']) / 2 | ||
|
||
# Motor Driver Pins declaration | ||
AIN1 = pwmio.PWMOut(board.IO36) | ||
AIN2 = pwmio.PWMOut(board.IO38) | ||
BIN1 = pwmio.PWMOut(board.IO35) | ||
BIN2 = pwmio.PWMOut(board.IO37) | ||
``` | ||
|
||
### Fonctionnalités | ||
|
||
#### Mesure de la tension de la batterie | ||
|
||
```python | ||
def get_battery_voltage(): | ||
"""Récupère la tension approximative de la batterie.""" | ||
global vbat_voltage | ||
return (vbat_voltage.value / 5371) | ||
``` | ||
|
||
Cette fonction renvoie la tension de la batterie en volts. | ||
|
||
#### Détection de la présence de l'alimentation VBUS | ||
## Installation | ||
|
||
```python | ||
def get_vbus_present(): | ||
"""Détecte si une source d'alimentation VBUS (5V) est présente.""" | ||
global vbus_sense | ||
return vbus_sense.value | ||
``` | ||
|
||
Cette fonction renvoie `True` si une source d'alimentation VBUS est détectée, sinon elle renvoie `False`. | ||
|
||
#### Roue des couleurs RVB | ||
|
||
```python | ||
def rgb_color_wheel(wheel_pos): | ||
"""Roue des couleurs pour parcourir les couleurs RVB de l'arc-en-ciel.""" | ||
wheel_pos = wheel_pos % 255 | ||
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. | ||
|
||
if wheel_pos < 85: | ||
return 255 - wheel_pos * 3, 0, wheel_pos * 3 | ||
elif wheel_pos < 170: | ||
wheel_pos -= 85 | ||
return 0, wheel_pos * 3, 255 - wheel_pos * 3 | ||
else: | ||
wheel_pos -= 170 | ||
return wheel_pos * 3, 255 - wheel_pos * 3, 0 | ||
``` | ||
Or you can download the library and drop it in the `lib` folder of your Eliobot. | ||
|
||
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. | ||
## Use the library in your Python code | ||
|
||
#### Capteurs d'obstacles | ||
To use the Eliobot Python library in your Python code, you need to import the `elio` module. Here is an example: | ||
|
||
```python | ||
def getObstacle(obstacle_pos): | ||
"""Récupère les valeurs des capteurs d'obstacles de gauche (position 0) à droite (position 3) et retour (position 4).""" | ||
obstacle_pos = obstacle_pos | ||
|
||
value = 0 | ||
|
||
value = obstacleInput[obstacle_pos].value | ||
|
||
if value < 10000: | ||
return True | ||
else: | ||
return False | ||
from elio import Eliobot | ||
``` | ||
|
||
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`. | ||
|
||
#### Contrôle des moteurs | ||
now you can create an instance of the `Eliobot` class and start controlling the robot. Here is an example: | ||
|
||
```python | ||
def setSpeed(speedValue): | ||
"""Convertit la vitesse de 0-100% en 0-65535 pour une utilisation avec pwmio.""" | ||
if speedValue > 100: | ||
speedValue = 100 | ||
elif speedValue < 15: | ||
speedValue += 15 | ||
|
||
pwmValue = int((speedValue / 100) * 65535) | ||
from elio import Eliobot # Import the Eliobot class | ||
import board # Import the board module | ||
import time # Import the time module | ||
import digitalio # Import the digitalio module | ||
import analogio # Import the analogio module | ||
import pwmio # Import the pwmio module | ||
|
||
return pwmValue | ||
vBatt_pin = analogio.AnalogIn(board.BATTERY) # Battery voltage pin | ||
|
||
obstacleInput = [analogio.AnalogIn(pin) for pin in | ||
(board.IO4, board.IO5, board.IO6, board.IO7)] # Obstacle sensors | ||
|
||
def moveForward(speed): | ||
"""Fait avancer le robot à une vitesse donnée (0-100%).""" | ||
pwm_value = setSpeed(speed) | ||
AIN1.duty_cycle = 0 | ||
AIN2.duty_cycle = pwm_value | ||
BIN1.duty_cycle = 0 | ||
BIN2.duty_cycle = pwm_value | ||
``` | ||
|
||
Les autres fonctions de contrôle des moteurs `moveBackward`, `turnLeft`, `turnRight`, `motorStop`, `motorSlow`, `spinLeftWheelForward`, `spinLeftWheelBackward`, `spinRightWheelForward`, `spinRightWheelBackward`, | ||
`moveOneStep` suivent une structure similaire. | ||
|
||
Ces fonctions permettent de contrôler les moteurs du robot pour effectuer différentes actions telles que avancer, reculer, tourner, arrêter, etc. | ||
lineCmd = digitalio.DigitalInOut(board.IO33) # Line sensors command pin | ||
lineCmd.direction = digitalio.Direction.OUTPUT # Set the direction of the line command pin | ||
|
||
#### Buzzer | ||
|
||
```python | ||
def buzzerInit(): | ||
"""Initialise le buzzer.""" | ||
buzzerPin = pwmio.PWMOut(board.IO17, variable_frequency=True) | ||
return buzzerPin | ||
|
||
lineInput = [analogio.AnalogIn(pin) for pin in | ||
(board.IO10, board.IO11, board.IO12, board.IO13, board.IO14)] # Line sensors | ||
|
||
def playFrequency(frequency, waitTime, volume): | ||
"""Joue une fréquence (en Hertz) pendant une durée donnée (en secondes) avec un volume spécifié.""" | ||
buzzer = buzzerInit() | ||
buzzer.frequency = round(frequency) | ||
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. | ||
time.sleep(waitTime) | ||
buzzer.deinit() | ||
AIN1 = pwmio.PWMOut(board.IO36) # Motor A input 1 | ||
AIN2 = pwmio.PWMOut(board.IO38) # Motor A input 2 | ||
BIN1 = pwmio.PWMOut(board.IO35) # Motor B input 1 | ||
BIN2 = pwmio.PWMOut(board.IO37) # Motor B input 2 | ||
|
||
buzzer = pwmio.PWMOut(board.IO17, variable_frequency=True) # Buzzer | ||
|
||
def playNote(note, duration, NOTES_FREQUENCIES, volume): | ||
"""Joue une note (C, D, E, F, G, A ou B) pendant une durée donnée (en secondes).""" | ||
if note in NOTES_FREQUENCIES: | ||
frequency = NOTES_FREQUENCIES[note] | ||
if frequency != 0.1: | ||
playFrequency(frequency, duration, volume) | ||
else: | ||
time.sleep(duration) | ||
# Create an instance of the Eliobot class | ||
elio = Eliobot(AIN1, AIN2, BIN1, BIN2, vBatt_pin, obstacleInput, buzzer, lineInput, lineCmd) | ||
``` | ||
|
||
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. | ||
|
||
#### Suivi de ligne | ||
|
||
```python | ||
# Get the line sensors value from Left (position 0) to Right (position 4) | ||
def getLine(line_pos): | ||
ambient = 0 | ||
lit = 0 | ||
value = 0 | ||
|
||
# Measure reflected IR | ||
lineCmd.value = True | ||
time.sleep(0.02) | ||
lit = lineInput[line_pos].value | ||
## Documentation | ||
|
||
# Measure ambient light | ||
lineCmd.value = False | ||
time.sleep(0.02) | ||
ambient = lineInput[line_pos].value | ||
|
||
# Ambient - Reflected | ||
value = ambient - lit | ||
|
||
return value | ||
|
||
|
||
# Example function to follow a black line on white paper | ||
def followLine(speed=100): | ||
if getLine(2) < threshold: | ||
moveForward(speed) | ||
|
||
elif getLine(0) < threshold: | ||
motorStop() | ||
spinRightWheelForward(speed) | ||
|
||
time.sleep(0.1) | ||
|
||
elif getLine(1) < threshold: | ||
motorStop() | ||
spinRightWheelForward(speed) | ||
|
||
elif getLine(3) < threshold: | ||
motorStop() | ||
spinLeftWheelForward(speed) | ||
|
||
elif getLine(4) < threshold: | ||
motorStop() | ||
spinLeftWheelForward(speed) | ||
time.sleep(0.1) | ||
|
||
else: | ||
motorStop() | ||
|
||
|
||
# Calibrate the line sensors | ||
def calibrateLineSensors(): | ||
time.sleep(1) | ||
wait_time = 0.5 | ||
num_samples = 5 | ||
max_values = [0] * num_samples | ||
min_values = [float('inf')] * num_samples | ||
|
||
moveForward(100) | ||
time.sleep(wait_time) | ||
motorStop() | ||
time.sleep(1) | ||
updateSensorValues(max_values, min_values) | ||
|
||
moveBackward(100) | ||
time.sleep(wait_time) | ||
motorStop() | ||
time.sleep(1) | ||
updateSensorValues(max_values, min_values) | ||
|
||
moveBackward(100) | ||
time.sleep(wait_time) | ||
motorStop() | ||
time.sleep(1) | ||
updateSensorValues(max_values, min_values) | ||
|
||
moveForward(100) | ||
time.sleep(wait_time) | ||
motorStop() | ||
time.sleep(1) | ||
updateSensorValues(max_values, min_values) | ||
|
||
avg_max_value = sum(max_values) / len(max_values) | ||
avg_min_value = sum(min_values) / len(min_values) | ||
|
||
saveCalibrationData(avg_max_value, avg_min_value) | ||
|
||
print("Calibration completed:") | ||
print("Average Max value:", avg_max_value) | ||
print("Average Min value:", avg_min_value) | ||
|
||
|
||
def updateSensorValues(max_values, min_values): | ||
for i in range(5): | ||
current_value = getLine(i) | ||
max_values[i] = max(max_values[i], current_value) | ||
min_values[i] = min(min_values[i], current_value) | ||
|
||
|
||
def saveCalibrationData(avg_max_value, avg_min_value): | ||
# Create a dictionary to hold the data | ||
calibration_data = { | ||
'average_max_value': avg_max_value, | ||
'average_min_value': avg_min_value | ||
} | ||
|
||
# Write the dictionary to a file in JSON format | ||
with open('config.json', 'w') as file: | ||
json.dump(calibration_data, file) | ||
``` | ||
|
||
#### WiFi | ||
|
||
```python | ||
# Connect to a wifi network | ||
def connectToWifi(ssid, password, webpassword): | ||
with open('settings.toml', 'w') as f: | ||
f.write('CIRCUITPY_WIFI_SSID = "' + ssid + '"\n') | ||
f.write('CIRCUITPY_WIFI_PASSWORD = "' + password + '"\n') | ||
f.write('CIRCUITPY_WEB_API_PASSWORD = "' + webpassword + '"\n') | ||
|
||
print("Settings saved") | ||
print("Restart the board to connect to the wifi network") | ||
|
||
|
||
# Disconnect from the wifi network | ||
def disconnectFromWifi(): | ||
wifi.radio.enabled = False | ||
while wifi.radio.connected: | ||
time.sleep(0.1) | ||
print("Disconnected from wifi") | ||
|
||
|
||
# Set Eliobot as an access point | ||
def setAccessPoint(ssid, password): | ||
wifi.radio.enabled = True | ||
wifi.radio.start_ap(ssid, password) | ||
|
||
|
||
# Scan for wifi networks | ||
def scanWifiNetworks(): | ||
wifi.radio.enabled = True | ||
networks = wifi.radio.start_scanning_networks() | ||
print("Réseaux WiFi disponibles:") | ||
for network in networks: | ||
# RSSI to percentage | ||
MAX_RSSI = -30 # 100% RSSI | ||
MIN_RSSI = -90 # 0% RSSI | ||
rssi = max(min(network.rssi, MAX_RSSI), MIN_RSSI) | ||
percentage = (rssi - MIN_RSSI) / (MAX_RSSI - MIN_RSSI) * 100 | ||
|
||
print("SSID:", network.ssid, ", Canal:", network.channel, ", RSSI:", network.rssi, " (", round(percentage), | ||
"%)") | ||
wifi.radio.stop_scanning_networks() | ||
return networks | ||
|
||
``` | ||
|
||
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. | ||
### Attributes | ||
|
||
- `AIN1`: Right Motor input 1 (pwmio.PWMOut) | ||
- `AIN2`: Right Motor input 2 (pwmio.PWMOut) | ||
- `BIN1`: Left Motor input 1 (pwmio.PWMOut) | ||
- `BIN2`: Left Motor input 2 (pwmio.PWMOut) | ||
- `vBatt_pin`: Battery voltage pin (analogio.AnalogIn) | ||
- `obstacleInput`: List of obstacle sensors (analogio.AnalogIn) | ||
- `buzzer`: Buzzer (pwmio.PWMOut) | ||
- `lineInput`: List of line sensors (analogio.AnalogIn) | ||
- `lineCmd`: Line sensors command pin (digitalio.DigitalInOut) | ||
|
Oops, something went wrong.