Micro contrôleurs AVR/Travail pratique/Equilibre sur deux roues d'un Robot
Apparence
Les sites commerciaux ont adoptés l'appellation Robot auto équilibré pour traduire les termes anglo-saxons instabots ou self balancing bot.
Présentation du Robot
[modifier | modifier le wikicode]Nous allons étudier la mise en œuvre d'un MPU6050 (TP précédent) avec comme application la programmation d'un robot sur deux roues.
Le robot que nous allons étudier est vendu en kit (sainsmart balancing robot kit).
Ce robot sera contrôlé par deux cartes Arduino UNO :
- la première sera intégrée dans la manette de commande, manette dotée de deux joysticks analogiques, ainsi que d'un module de communication radio ;
- la seconde carte sera dans le robot proprement dit (le robot possède son unité centrale, toute la commande de puissance des moteurs et bien sûr un module radio).
Spécifications du robot
[modifier | modifier le wikicode]- taille : 200 × 65 × 180
- poids : 526 g
- Vitesse à vide : 400 tr/min sous 12 V
- diamètre de la roue : 65 mm
- plage de tension : 10 V ~ 13 V
Communication entre la manette et le robot
[modifier | modifier le wikicode]Code de la manette
[modifier | modifier le wikicode]/*
émission d’une valeur integer via module nRF24L01
*/
#include <SPI.h> // gestion du bus SPI
#include <Mirf.h> // gestion de la communication
#include <nRF24L01.h> // définition des registres du nRF24L01
#include <MirfHardwareSpiDriver.h> // communication SPI nRF24L01
//Variables joystick
int xPinG = A2;
int yPinG = A3;
int buttonPinG = 3;
int xPinD = A0;
int yPinD = A1;
int buttonPinD = 2;
int xPositionG = 0;
int yPositionG = 0;
int buttonStateG = 0;
int xPositionD = 0;
int yPositionD = 0;
int buttonStateD = 0;
//
//int valeur1 = 1; // contient la valeur à envoyer
//int valeur2 = 0;
byte yPositionG_octet[2]; // contient la valeur découpée en octet pour l’envoi
byte yPositionD_octet[2]; // contient la valeur découpée en octet pour l’envoi
void setup()
{
//Initialisation pin Joystick
pinMode(xPinG, INPUT);
pinMode(yPinG, INPUT);
pinMode(xPinD, INPUT);
pinMode(yPinD, INPUT);
//activate pull-up resistor on the push-button pin
pinMode(buttonPinG, INPUT_PULLUP);
pinMode(buttonPinD, INPUT_PULLUP);
Mirf.cePin = 8; // CE sur broche 8
Mirf.csnPin = 7; // CSN sur broche 7
Mirf.spi = &MirfHardwareSpi; // utilisation du port SPI hardware
Mirf.init(); // initialise le module SPI
Mirf.channel = 0; // utilisation canal 0 pour communiquer (128 canaux disponible, de 0 à 127)
Mirf.payload = sizeof(unsigned int); // = 2, déclaration taille du message à transmettre, max 32 octets
// RF_SETUP=0000abcd : a=1–>2Mb/s, a=0–>1Mb/s; puissance émission bc=00–>-18 dBm, bc=01–>-12dBm, bc=10–>-6dBm, bc=11–>0dBm;
// d=0 pas de gain sur le bruit en réception
Mirf.configRegister(RF_SETUP, 0x06); // 1 Mb/s et 0 dBm (puissance maximum)
Mirf.config(); // configure le canal et la taille du message
Mirf.setTADDR((byte *)"ardu2"); // définition adresse sur 5 octets de la 2ème carte Arduino
Mirf.setRADDR((byte *)"ardu1"); // définition adresse sur 5 octets de la 1ere carte Arduino
}
void loop()
{
int yPositionG = analogRead(yPinG);
int yPositionD = analogRead(yPinD);
while(Mirf.isSending())
{
// en cours d’émission
delay(5);
}
yPositionG_octet[0] = yPositionG & 0xFF; // 1er octet
yPositionG_octet[1] = (yPositionG & 0xFF00) >> 8; // 2ème octet
Mirf.send(yPositionG_octet);
yPositionD_octet[0] = yPositionD & 0xFF; // 1er octet
yPositionD_octet[1] = (yPositionD & 0xFF00) >> 8; // 2ème octet
Mirf.send(yPositionD_octet);
// Serial.print(yPositionD);
delay(10);
}
Partie robot
[modifier | modifier le wikicode]/*
réception d’une valeur integer via module nRF24L01
*/
#include <SPI.h> // gestion du bus SPI
#include <Mirf.h> // gestion de la communication
#include <nRF24L01.h> // définition des registres du nRF24L01
#include <MirfHardwareSpiDriver.h> // communication SPI nRF24L01
int yPositionG; // contient la valeur à recevoir
byte yPositionG_octet[2]; // contient la valeur découpée en octet pour la réception
int yPositionD; // contient la valeur à recevoir
byte yPositionD_octet[2]; // contient la valeur découpée en octet pour la réception
int IN1 = 3;
int IN2 = 4;
int ENA = 9;
int IN3 = 5;
int IN4 = 6;
int ENB = 10;
void setup()
{
pinMode(13, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);
Mirf.cePin = 8; // CE sur broche 8
Mirf.csnPin = 7; // CSN sur broche 7
Mirf.spi = &MirfHardwareSpi; // utilisation du port SPI hardware
Mirf.init(); // initialise le module SPI
Mirf.channel = 0; // utilisation canal 0 pour communiquer (128 canaux disponible, de 0 à 127)
Mirf.payload = sizeof(unsigned int); // = 2, déclaration taille du message à transmettre, max 32 octets
// RF_SETUP=0000abcd : a=1–>2Mb/s, a=0–>1Mb/s; puissance émission bc=00–>-18 dBm, bc=01–>-12dBm, bc=10–>-6dBm, bc=11–>0dBm;
// d=0 pas de gain sur le bruit en réception
Mirf.configRegister(RF_SETUP, 0x06); // 1 Mb/s et 0 dBm (puissance maximum)
Mirf.config(); // configure le canal et la taille du message
Mirf.setTADDR((byte *)"ardu1"); // définition adresse sur 5 octets de la 2ème carte Arduino
Mirf.setRADDR((byte *)"ardu2"); // définition adresse sur 5 octets de la 1ere carte Arduino
Serial.begin(9600);
pinMode(6, OUTPUT);
}
void loop()
{
while (!Mirf.dataReady())
{
// pas prêt à recevoir
delay(5);
}
Mirf.getData(yPositionG_octet); // récupére 2 octets
yPositionG = yPositionG_octet[0] + (yPositionG_octet[1] << 8); // transforme en int
/* Serial.println(yPositionG, DEC);
Serial.print(" ");
// Serial.print(valeur_octet[0]);
Serial.print(" ");
// Serial.print(valeur_octet[1]);
// digitalWrite(6, 1);
*/
int A = (yPositionG - 513) / 2;
int B = (510 - yPositionG) / 2;
if (yPositionG > 530) {
analogWrite(ENA, A);
digitalWrite(IN1, 0);
digitalWrite(IN2, 1);
}
else analogWrite(ENA, 0);
if (yPositionG < 500) {
analogWrite(ENA, B);
digitalWrite(IN1, 1);
digitalWrite(IN2, 0);
}
while (!Mirf.dataReady())
{
// pas prêt à recevoir
delay(5);
}
Mirf.getData(yPositionD_octet); // récupére 2 octets
yPositionD = yPositionD_octet[0] + (yPositionD_octet[1] << 8); // transforme en int
int C = (yPositionD - 515) / 2;
int D = (510 - yPositionD) / 2;
if (yPositionD > 530) {
analogWrite(ENB, C);
digitalWrite(IN3, 0);
digitalWrite(IN4, 1);
}
else analogWrite(ENB, 0);
if (yPositionD < 510) {
analogWrite(ENB, D);
digitalWrite(IN3, 1);
digitalWrite(IN4, 0);
}
delay(10);
}
La carte de puissance
[modifier | modifier le wikicode]La carte de puissance de SainSmart nous a laché. Nous l'avons remplacé par un autre double pont en H décrit dans ce WIKI.
Voir aussi
[modifier | modifier le wikicode]- sainsmart balancing robot kit
- How to build SainSmart Instabots (3 steps)
- How to build SainSmart Instabots (9 steps)