PID et robot self-balancing

Hello ! j’essaie de faire un robot d'auto équilibré (ceux avec que deux roues et bim bam boum ils tienne en équilibre) et visiblement j'ai un problème avec le PID mais je commence vraiment à être à court d'idée pour résoudre le problème.

De base je suit ce tuto
Les différences que j'ai est au niveau du contrôleur moteur, j'utilise un TB6612FNG plutôt que le DRV8833 (simple erreur de commande) lien amazon du composant

J'ai aussi remarqué quelques problème sur le tuto notament au niveau du MPU6050 qui est pas branché en I2C sur le tuto (je l'ai branché sur les bonne pin du coup)

Mon problème c'est vraiment au niveau du PID (j'utilise aussi une arduino mini). Visiblement il y à un conflit avec le contrôleur moteur, je m'explique.

Quand je veut juste faire clignoter une led avec le PID je fait comme ça :

#define Blueled 13
int count = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("[SETUP] begin ...");

  Serial.println("[SETUP] led flashing");
  pinMode(Blueled, OUTPUT); // Blue flashing
  digitalWrite(Blueled, HIGH);
  delay(500);
  digitalWrite(Blueled, LOW);
  delay(500);
  digitalWrite(Blueled, HIGH);
  delay(500);
  digitalWrite(Blueled, LOW);
  delay(500);

  Serial.println("[SETUP] init pid");  
  init_PID();
  Serial.println("[SETUP] done ...");
}

void loop() {
}

void init_PID() {
  // initialize Timer1
  cli();          // disable global interrupts
  TCCR1A = 0;     // set entire TCCR1A register to 0
  TCCR1B = 0;     // same for TCCR1B    
  // set compare match register to set sample time 5ms
  OCR1A = 9999;    
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for prescaling by 8
  TCCR1B |= (1 << CS11);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei();          // enable global interrupts
}

// The ISR will be called every 5 milliseconds
ISR(TIMER1_COMPA_vect) {
  count++;
  //Serial.println(count);
  if(count == 200)  {
    count = 0;
    Serial.println("[PID] led");
    digitalWrite(13, !digitalRead(13));
  }
}

Jusque la, aucun problème, la led clignote bien toute les seconde (timestamp du moniteur serie à l'appuis)

Le problème arrive dès que je rajoute la gestion des moteurs. Je passe par cette library qui visiblement n'utilise pas de fonctions obscure et complexe.

Quand jessaie de faire tourner le test suivant :

#define Blueled 13
int count = 0;


//===== motos =====
#include <SparkFun_TB6612.h>

// Configuration des sens de rotation des moteurs (1 ou -1)
const int offsetA = 1;
const int offsetB = -1;
// Ports numériques associés aux entrées de contrôle (les entrées PWM doivent être connectées à des ports PWM de l'Arduino)
#define AIN1 4
#define BIN1 7
#define AIN2 5
#define BIN2 6
#define PWMA 9
#define PWMB 11
#define STBY 10

volatile int motorPower = 255;

// Initialisation des moteurs
Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY); //Left motor
Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY); //Right motor


void setup() {
  Serial.begin(9600);
  Serial.println("[SETUP] begin ...");

  Serial.println("[SETUP] led flashing");
  pinMode(Blueled, OUTPUT); // Blue flashing
  digitalWrite(Blueled, HIGH);
  delay(500);
  digitalWrite(Blueled, LOW);
  delay(500);
  digitalWrite(Blueled, HIGH);
  delay(500);
  digitalWrite(Blueled, LOW);
  delay(500);

  Serial.println("[SETUP] init pid");  
  init_PID();
  Serial.println("[SETUP] done ...");
}

void loop() {
  motor1.drive(motorPower);
  motor2.drive(motorPower);
  delay(500);
  motor1.drive(-motorPower);
  motor2.drive(-motorPower);
  delay(500);

  motorPower = 100;
  motor1.drive(motorPower);
  motor2.drive(motorPower);
  delay(500);
  motor1.drive(-motorPower);
  motor2.drive(-motorPower);
  delay(500);
}

void init_PID() {
  // initialize Timer1
  cli();          // disable global interrupts
  TCCR1A = 0;     // set entire TCCR1A register to 0
  TCCR1B = 0;     // same for TCCR1B    
  // set compare match register to set sample time 5ms
  OCR1A = 9999;    
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for prescaling by 8
  TCCR1B |= (1 << CS11);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  sei();          // enable global interrupts
}

// The ISR will be called every 5 milliseconds
ISR(TIMER1_COMPA_vect) {
  count++;
  //Serial.println(count);
  if(count == 200)  {
    count = 0;
    Serial.println("[PID] led");
    digitalWrite(13, !digitalRead(13));
  }
}

Ma led se met à clignoter vitesse mach 2 (environ toute les 50ms) et j'ai plus qu'un seul des deux moteur qui tourne hyyyper lentement (bien moins que la vitesse que je lui indique)

Je suis sur de mes branchement parce que quand je test individuellement les moteurs (sans l'histoire du PID) tout roule comme sur des roulettes

Voila voila, j’espère d'avoir été le plus complet, c'est la première fois que je trafique les PID donc c'est un peu la galère.

Merci à tout ceux qui ont pris le temps de me lire et merci d'avance pour les potentielle pistes.

La bibliothèque SparkFun utilise le PWM du timer 1 Pour faire tourner le moteur. On le voit notamment quand tu écris:

Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY); //Left motor
Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY); //Right motor

Dans lequel PWMA et PWMB sont les broches PWM utilisées. La broche 9 sauf erreur de ma part correspond au timer 1 que tu utilise aussi pour faire clignotter la led. Il y a donc conflit entre les deux car c'est le même matériel (timer 1) qui est utilisé pour deux choses différentes. comme les deux changent les paramètres, on a un mix des valeurs qui ne permet pas forcément le fonctionnement correct des deux.

Effectivement, ça à l'air d'aller mieux :smiley:

Bon je suis pas encore sortie des problème, maintenant les moteurs réagisse pas au gyroscope ...

Merci pour les indication en tout cas ! Juste comment on fait pour savoir ça sans galérer ? Simplement se bouffer les data sheet de la carte ?

Peut être l'habitude? Si la led fonctionnait seule et qu'elle ne fonctionne plus avec autre chose, le conflit matériel est une piste importante. Comme elle est gérée par le timer 1, et surtout que tu as donné le lien pour la bibliothèque (sans le lien, je n'aurai pas cherché). En lisant le cpp, j'ai cherché soit analogWrite soit une fonction d'interruption (ce qui utilise le timer). J'ai aussi regardé le pinout de la carte. Il n'y a pas de datasheet de la carte, il y a la datasheet du microcontrôleur que je connais assez bien, le schém de la carte et le pinout.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.