Micro contrôleurs AVR/Travail pratique/Equilibre sur deux roues d'un Robot

Début de la boite de navigation du travail pratique

Les sites commerciaux ont adoptés l'appellation Robot auto équilibré pour traduire les termes anglo-saxons instabots ou self balancing bot.

Equilibre sur deux roues d'un Robot
Image logo représentative de la faculté
T.P. no 3
Leçon : Micro contrôleurs AVR

TP de niveau 15.

Précédent :Utilisation d'un Accéléromètre MPU6050
Suivant :Réalisation d'un quadricoptère et de son contrôle
En raison de limitations techniques, la typographie souhaitable du titre, « Travail pratique : Equilibre sur deux roues d'un Robot
Micro contrôleurs AVR/Travail pratique/Equilibre sur deux roues d'un Robot
 », n'a pu être restituée correctement ci-dessus.

Présentation du Robot

modifier
 
Autre projet évoquant le MPU6050
 
Carte Arduino UNO

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
  • 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

Code de la manette

modifier
/* 
    é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
/*
    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

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