RobotTondeuse
Sommaire
Présentation du projet
Objectif
Le projet consiste à fabriquer un robot tondeuse autonome capable d'éviter les obstacles grâce à des capteurs de distance et faire tourner un moteur brushless désignant la lame de la tondeuse.
Tâches individuelles
- Arel RAKO :
* capteur VL53L1X - programmé et connecté le capteur
* moteur brushless - programmé, connecté, fait les soudures nécessaires pour le connecteur de la batterie
* interrupteur - programmé en PULL UP pour faire tourner le moteur à l'état haut et l'arrêter à l'état bas
* plaque pastillée - toutes les soudures de la plaque, qui seront détaillés un peu plus tard
- Anthony JEAN-BAPTISTE-ADOLPHE :
* gyroscope MPU9250 - programmé et connecté le gyroscope
* capteur VL53L1X - programmation pour faire fonctionner 3 capteurs en même temps avec le gyroscope aussi
* code général - programmation
* différentes soudures
Découpage fonctionnel
Travail à réaliser
Objectif
L'objectif sera bien évidemment de terminer le projet de sorte qu'il réponde au cahier des charges décrit précédemment.
Pour ce faire, il conviendra de :
- rechercher des solutions à partir du schéma fonctionnel fourni ( schéma électronique et composants )
- dimensionner les composants utilisés
- tester les différents blocs fonctionnels
- programmer les composants
- valider le fonctionnement
Choix des composants
- 3 capteurs de distance VL53L1X
- 1 arduino uno
- 1 shield avec drivers
- 1 gyroscope MPU9250
- 1 batterie EMMERICH 12.8V
- 1 abaisseur de tension LM2596
- 1 moteur brushless
- 1 interrupteur
- 2 moteurs MDP (moteurs des roues)
Explications
- les capteurs de distance
* connectés en I2C via les ports SCL et SDA de l'arduino * alimentés en 5V via le pin VIN, ils possèdent un régulateur qui transforme le 5V en 2.8V (sortie VDD) * placés au côté gauche, droit et au milieu du robot pour avoir un plus grand champ de vision * détails de fonctionnement:
- si le capteur à gauche détecte un obstacle à moins de 20cm, le robot tourne à droite - si le capteur à droite détecte un obstacle à moins de 20cm, le robot tourne à gauche - si le capteur du milieu détecte un obstacle à moins de 20cm, le robot s'arrête et fait demi-tour vers la droite
- le gyroscope
* connecté en I2C comme les capteurs de distance * alimenté en 5V comme les capteurs de distance * prend la valeur de 100 angles et fait leur moyenne pour plus de précision
- moteur brushless
* connecté à un pin PWM de l'arduino pour pouvoir le piloter * alimenté directement via la batterie car nécessite 12V * sur le rotor on a mis du scotch pour modéliser la lame
- interrupteur
* connecté en PULL-UP à un pin quelconque de l'arduino * alimenté en 5V * s'il envoie 1, le moteur brushless commence à tourner, s'il envoie 0, le moteur s'arrête Attention! Prévoir 5 secondes pour l'arrêt du moteur
- abaisseur de tension
* transforme le 12V de la batterie en 5V pour alimenter les capteurs
- plaque pastillée
* constituée de 6 parties: - le 12V pour alimenter l'arduino, on y branche aussi le connecteur AMASS du moteur brushless et l'abaisseur de tension - le 5V où sont connectés tous les capteurs, le gyroscope et l'interrupteur - SCL où est connecté le pin SCL des capteurs et du gyroscope au pin SCL de l'arduino - SDA où est connecté le pin SDA des capteurs et du gyroscope au pin SDA de l'arduino - masse du 12V - masse du 5V
- moteurs MDP
Programmation
Code des différents composants
- programmation des capteurs de distance
-Bibliothèque pour le capteur de distance : Bibliothèque
Code distance
#include <Wire.h>
#include <VL53L1X.h>
VL53L1X sensor; // Déclaration des sensors
VL53L1X sensor2;
VL53L1X sensor3;
//USE_I2C_2V8K;
void setup()
{
pinMode(2, OUTPUT); // On déclare les pins en sortie
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
digitalWrite(2, LOW); // On met les sorties à l'état bas pour définir leurs adresses
digitalWrite(3, LOW);
digitalWrite(4, LOW);
// Initialisation I2C
delay(500);
Wire.begin();
Wire.beginTransmission(0x29);
Serial.begin (9600);
digitalWrite(3,HIGH); // On met la sortie à l'état haut pour définir l'adresse de la sortie
delay(150);
sensor2.init(); // On initialise le capteur
Serial.println("01");
delay(100);
sensor2.setAddress(0x33); // On définit l'adresse du capteur
Serial.println("02");
digitalWrite(4,HIGH); // On met la sortie à l'état haut pour définir l'adresse de la sortie
delay(150);
sensor3.init(); // On initialise le capteur
Serial.println("03");
delay(100);
sensor3.setAddress(0x35); // On définit l'adresse du capteur
Serial.println("04");
digitalWrite(2, HIGH); // On n'a pas besoin de définir l'adresse du premier capteur, il garde son adresse de base
delay(150);
Serial.println("09");
sensor.init();
Serial.println("10");
delay(100);
sensor.setDistanceMode(VL53L1X::Long); // On définit le mode du capteur
sensor.setMeasurementTimingBudget(50000);
sensor.startContinuous(50);
sensor.setTimeout(100);
sensor2.setDistanceMode(VL53L1X::Long); // On définit le mode du capteur
sensor2.setMeasurementTimingBudget(50000);
sensor2.startContinuous(50);
sensor2.setTimeout(100);
sensor3.setDistanceMode(VL53L1X::Long); // On définit le mode du capteur
sensor3.setMeasurementTimingBudget(50000);
sensor3.startContinuous(50);
sensor3.setTimeout(100);
delay(150);
Serial.println("addresses set");
Serial.println ("I2C scanner. Scanning ..."); // C'est un programme pour voir combien et quelles sont adresses des différents composants utilisant l'I2C
byte count = 0;
for (byte i = 1; i < 120; i++)
{
Wire.beginTransmission (i);
if (Wire.endTransmission () == 0)
{
Serial.print ("Found address: ");
Serial.print (i, DEC);
Serial.print (" (0x");
Serial.print (i, HEX);
Serial.println (")");
count++;
delay (1);
} // end of good response
} // end of for loop
Serial.println ("Done.");
Serial.print ("Found ");
Serial.print (count, DEC);
Serial.println (" device(s).");
}
void loop()
{
Serial.print("Sensor1: ");
Serial.print(sensor.read()); // écrit la distance du capteur 1
if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
Serial.println();
delay(500);
Serial.print("Sensor2: "); // écrit la distance du capteur 2
Serial.print(sensor2.read());
if (sensor2.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
Serial.println();
delay(500);
Serial.print("Sensor3: "); // écrit la distance du capteur 3
Serial.print(sensor3.read());
if (sensor3.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
Serial.println();
delay(500);
}
- programmation moteur brushless avec l'interrupteur
Code brushless
const int escPin = 5; // pin de commande
int a= digitalRead(13); // pin interrupteur
void setup() {
//Init Serial
Serial.begin(9600);
Serial.println(F("Initialize System"));
//Init ESC
pinMode(escPin, OUTPUT); // on met le pin en sortie pour pouvoir le piloter
}
void loop() {
a= digitalRead(13);
Serial.println(a);
if(a<1)
{
Serial.println(a);
}else {
Serial.println(a);
digitalWrite(escPin, HIGH); // fait un signal carré qui permet la commutation rapide entre état haut et bas, ce qui permet de faire tourner le moteur
delayMicroseconds(1350);
digitalWrite(escPin, LOW);
delay(20);
}
}
- programmation gyroscope
- Bibliothèque du MPU9250 : Bibliothèque
Code gyro
#include "MPU9250.h"
MPU9250 IMU(Wire,0x68);
int status;
double moyenne;
double moyenneFinal;
int i;
double angle(){
double Module_magnetic;
double angle;
double Xmagnetic;
double Ymagnetic;
double Zmagnetic;
IMU.readSensor();
Xmagnetic = IMU.getMagX_uT();
Ymagnetic = IMU.getMagY_uT();
Zmagnetic = IMU.getMagZ_uT();
Module_magnetic = Xmagnetic * Xmagnetic + Ymagnetic * Ymagnetic + Zmagnetic * Zmagnetic; // formule pour définir l'angle en degré
Module_magnetic = sqrt(Module_magnetic);
angle= atan2(Ymagnetic,Xmagnetic) * (180 / 3.14159265); // angle en degré
if (angle<0) {angle=angle+360;}
return angle;
}
void setup() {
Serial.begin(115200);
while(!Serial) {}
// début de la communication IMU
status = IMU.begin();
if (status < 0) {
Serial.println("IMU initialization unsuccessful");
Serial.println("Check IMU wiring or try cycling power");
Serial.print("Status: ");
Serial.println(status);
while(1) {}
}
// setting the accelerometer full scale range to +/-8G
IMU.setAccelRange(MPU9250::ACCEL_RANGE_8G);
// setting the gyroscope full scale range to +/-500 deg/s
IMU.setGyroRange(MPU9250::GYRO_RANGE_500DPS);
// setting DLPF bandwidth to 20 Hz
IMU.setDlpfBandwidth(MPU9250::DLPF_BANDWIDTH_20HZ);
// setting SRD to 19 for a 50 Hz update rate
IMU.setSrd(19);
}
void loop() {
//Module du champ
Serial.print(" ");
Serial.print("Angle "); //en degré
Serial.println(angle());
moyenne = 0;
for (i=0; i<100; i++)
{
moyenne = moyenne + angle();
delay(10);
}
moyenneFinal = moyenne/100;
Serial.print("Moyenne : ");
Serial.println(moyenneFinal);
// Affiche les différentes valeurs du capteur
Serial.print("AccelX : ");
Serial.print(IMU.getAccelX_mss(),6);
Serial.print("\t");
Serial.print("AccelY : ");
Serial.print(IMU.getAccelY_mss(),6);
Serial.print("\t");
Serial.print("AccelZ : ");
Serial.print(IMU.getAccelZ_mss(),6);
Serial.print("\t");
Serial.print("GyroX : ");
Serial.print(IMU.getGyroX_rads(),6);
Serial.print("\t");
Serial.print("GyroY : ");
Serial.print(IMU.getGyroY_rads(),6);
Serial.print("\t");
Serial.print("GyroZ : ");
Serial.print(IMU.getGyroZ_rads(),6);
Serial.print("\t");
Serial.print("MagX : ");
Serial.print(IMU.getMagX_uT(),6);
Serial.print("\t");
Serial.print("MagY: ");
Serial.print(IMU.getMagY_uT(),6);
Serial.print("\t");
Serial.print("MagZ : ");
Serial.print(IMU.getMagZ_uT(),6);
Serial.print("\n");
Serial.print("Temp : ");
Serial.println(IMU.getTemperature_C(),6);
delay(1000);
}
- programmation moteurs MDP
Code moteurs MDP
int E1 = 5; // Moteur droite
int M1 = 4;
int E2 = 6; // Moteur gauche
int M2 = 7;
void setup() {
Serial.println("Initialisation des moteurs...");
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(E1, OUTPUT);
pinMode(E2, OUTPUT);
Serial.println("Moteurs opérationnels");
}
void loop {
//mode marche avant (m1 high m2 low)
//mode marche arrière (m1 low m2 high)
//tourner à gauche (m1 high m2 high)
//tourner à droite (m1 low m2 low)
digitalWrite(M1,LOW);
digitalWrite(M2,HIGH);
analogWrite(E1, 255);
analogWrite(E2, 255);
delay(30);
}
Code général
Code_tondeuse
#include <Arduino.h>
#include <Moteurs.h>
#include <Wire.h>
#include <VL53L1X.h>
#include "MPU9250.h"
int E1 = 5; // Moteur droite
int M1 = 4;
int E2 = 6; // Moteur gauche
int M2 = 7;
int escPin = 5; // Pin de contrôle moteur simulation lame
int a = digitalRead(12);
VL53L1X sensor;
VL53L1X sensor2;
VL53L1X sensor3;
MPU9250 IMU(Wire,0x68);
int status;
void setupLaser();
void setupLame();
void runLame();
void setupMoteurs();
double readGyro();
void setupGyro();
double angle();
void Moteurs();
void setup() {
Serial.begin(115200);
Wire.begin();
Wire.setClock(400000);
setupGyro();
setupLaser();
setupMoteurs();
//setupLame();
}
void loop(){
runLame();
Serial.print(" Distance 1 : ");
Serial.print(sensor.read());
Serial.print(" - Distance 2 : ");
Serial.print(sensor2.read());
Serial.print(" - Distance 3 : ");
Serial.print(sensor3.read());
Serial.print("\tEtat: ");
Serial.print(VL53L1X::rangeStatusToString(sensor.ranging_data.range_status));
Serial.print(" Angle : ");
Serial.println(angle());
runLame();
if((sensor3.read())<=150) //capteur 3 est à droite
{
digitalWrite(M1,HIGH); //tourner à gauche
digitalWrite(M2,HIGH);
analogWrite(E1, 180);
analogWrite(E2, 150);
delay(300);
}else
{
digitalWrite(M1,HIGH); // marche avant
digitalWrite(M2,LOW);
analogWrite(E1, 150);
analogWrite(E2, 170);
delay(30);
}
runLame();
if((sensor2.read())<=200) //capteur 2 est devant milieu
{
digitalWrite(M1,LOW); // reculer à gauche
digitalWrite(M2,HIGH);
analogWrite(E1, 100);
analogWrite(E2, 200);
delay(1000);
digitalWrite(M1,LOW); // arrêt
digitalWrite(M2,HIGH);
analogWrite(E1, 0);
analogWrite(E2, 0);
delay(1000);
digitalWrite(M1,HIGH); //marche avant
digitalWrite(M2,LOW);
analogWrite(E1, 150);
analogWrite(E2, 170);
delay(30);
}else
{
digitalWrite(M1,HIGH); //marche avant
digitalWrite(M2,LOW);
analogWrite(E1, 150);
analogWrite(E2, 170);
delay(30);
}
runLame();
if((sensor.read())<=150) //capteur 1 est à gauche
{
digitalWrite(M1,LOW); // tourner à droite
digitalWrite(M2,LOW);
analogWrite(E1, 150);
analogWrite(E2, 150);
delay(300);
}else
{
digitalWrite(M1,HIGH); // marche avant
digitalWrite(M2,LOW);
analogWrite(E1, 150);
analogWrite(E2, 170);
delay(30);
}
runLame();
}
double angle(){
double angle;
double Xmagnetic;
double Ymagnetic;
IMU.readSensor();
Xmagnetic = IMU.getMagX_uT();
Ymagnetic = IMU.getMagY_uT();
angle= atan2(Ymagnetic,Xmagnetic) * (180 / 3.14159265); // angle en degres
if (angle<0) {angle=angle+360;}
return angle;
}
void setupGyro(){
Serial.println("Initialisation du Gyroscop...");
status = IMU.begin();
if (status < 0) {
Serial.println("IMU initialization unsuccessful");
Serial.println("Check IMU wiring or try cycling power");
Serial.print("Etat: ");
Serial.println(status);
Serial.println("Problème avec le Gyroscop");
}
// setting the accelerometer full scale range to +/-8G
IMU.setAccelRange(MPU9250::ACCEL_RANGE_8G);
// setting the gyroscope full scale range to +/-500 deg/s
IMU.setGyroRange(MPU9250::GYRO_RANGE_500DPS);
// setting DLPF bandwidth to 20 Hz
IMU.setDlpfBandwidth(MPU9250::DLPF_BANDWIDTH_20HZ);
// setting SRD to 19 for a 50 Hz update rate
IMU.setSrd(19);
Serial.println("Gyroscope opérationnel");
}
double readGyro(){
double moyenne;
double moyenneFinal;
moyenne = 0;
for (int j =0; j<100; j++)
{
moyenne = moyenne + angle();
delay(10);
}
moyenneFinal = moyenne/100;
return moyenneFinal;
}
void setupLaser(){
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
// initialise I2C
delay(500);
Wire.begin();
Wire.beginTransmission(0x29);
digitalWrite(3,HIGH);
delay(150);
sensor2.init();
Serial.println("01");
delay(100);
sensor2.setAddress(0x33);
Serial.println("02");
digitalWrite(4,HIGH);
delay(150);
sensor3.init();
Serial.println("03");
delay(100);
sensor3.setAddress(0x35);
Serial.println("04");
digitalWrite(2, HIGH);
delay(150);
Serial.println("09");
sensor.init();
Serial.println("10");
delay(100);
sensor.setDistanceMode(VL53L1X::Long); // On définit le mode du capteur
sensor.setMeasurementTimingBudget(50000);
sensor.startContinuous(50);
sensor.setTimeout(100);
sensor2.setDistanceMode(VL53L1X::Long); // On définit le mode du capteur
sensor2.setMeasurementTimingBudget(50000);
sensor2.startContinuous(50);
sensor2.setTimeout(100);
sensor3.setDistanceMode(VL53L1X::Long); // On définit le mode du capteur
sensor3.setMeasurementTimingBudget(50000);
sensor3.startContinuous(50);
sensor3.setTimeout(100);
delay(150);
Serial.println("addresses set");
Serial.println ("I2C scanner. Scanning ..."); // C'est un programme pour voir combien et quelles sont adresses des différents composants utilisant l'I2C
byte count = 0;
for (byte i = 1; i < 120; i++)
{
Wire.beginTransmission (i);
if (Wire.endTransmission () == 0)
{
Serial.print ("Found address: ");
Serial.print (i, DEC);
Serial.print (" (0x");
Serial.print (i, HEX);
Serial.println (")");
count++;
delay (1);
}
}
Serial.println ("Done.");
Serial.print ("Found ");
Serial.print (count, DEC);
Serial.println (" device(s).");
}
void setupMoteurs(){
Serial.println("Initialisation des moteurs...");
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(E1, OUTPUT);
pinMode(E2, OUTPUT);
Serial.println("Moteurs opérationnels");
}
void runLame(){
pinMode (5, OUTPUT);
pinMode (12, INPUT);
a= digitalRead(12);
if(a<1){
Serial.println(a);
}
else {
Serial.println(a);
digitalWrite(escPin, HIGH); // fait un signal carré qui permet la commutation rapide entre état haut et bas, ce qui permet de faire tourner le moteur
delayMicroseconds(1350);
digitalWrite(escPin, LOW);
delay(20);
}
}
void Moteurs()
{
//mode marche avant (m1 high m2 low)
//mode marche arrière (m1 low m2 high)
//tourner à gauche (m1 high m2 high)
//tourner à droite (m1 low m2 low)
digitalWrite(M1,LOW);
digitalWrite(M2,HIGH);
analogWrite(E1, 255);
analogWrite(E2, 255);
delay(30);
}
// End of file
Vidéos
Vidéo de démonstration du robot qui roule
Vidéo du moteur de coupe