Re: [RESOLU] Probleme de pilotage moteurs cc via l'init infrarouge.[MERCI]

Bonjour;

Je suis en train de réaliser un « balancing-robot » un robot en équilibre sur deux roues.
Pour cela je dispose
D’une carte Arduino UNO
D’un shield Moteur PKA03’1 de chez vellman
D’un module 3axes 9-DOF de chez Adafruit
Deux moto-réducteurs MG-6-120

Voici en gros le fonctionnement
En fonction du tangage sur l’axe Y (Avant-Arrière) je commande les mouvements moteurs qui vont venir rattraper le basculement

J’ai effectué les montages à vide (châssis en cours de fabrication) et fait des test qui fonctionnent.

Je souhaite le piloter par une commande infrarouge et pour cela j’ai un récepteur infrarouge et une télécommande

Mais comme il y a toujours un mais !!
Lorsque j’ai intégré le programme de la gestion d’infrarouge.La commande des moteurs à soudainement changé.
Voici ce que j’ai observé.
Lors d’un basculement du module sur l’axe Y dans le sens avant seul le moteur A fonctionne et le moteur B démarre bien plus tard.
J’ai constaté que le moteur B démarre quant l’inclinaison est au delà ou voir très proche de la consigne maximum de tangage. Fixé à 15° (essais réalisé au moniteur série)
J’ai donc changé ma consigne maximum et passer à 45° pour voir => Le résultat a été le même

J’ai chercher dans mon programme ce qui pouvait clocher mais rien !!
J’ai donc pensé que cela venais de mon shield car il m’a poser des problème avec le SPI = incompatible car un condo est connecté sur les broches A4-A5. Idem avec SCL-SCA.

J’ai donc changer le pilotage de mes moteurs par un L293D que j’avais sous la main. Les testes moteurs fonctionnent a merveille mais revoilà mon problème a l’identique des que j’inclus l’infrarouge.
Dans un premier temps j’ai retiré la partie programme dans la fonction « loop » essais = négatif.
Ensuite j’ai retiré l’initialisation de l’infrarouge essais = positif.=> Les eux moteurs démarre en même temps

Que ce passe t-il lors de l’initialisation de l’infrarouge pour que çà perturbe la commande de mes sorties.
J’ai bien essayé de décortiquer la lib #include <Irremote.h> #include <IrremoteInt.h> mais j’ai un manque de bagage significatif pour tout comprendre et la moitié m’échappe.

C’est donc pour cela que je fait appel à la science du forum Arduino pour trouver d’où viens mon problème et le résoudre.
De puis hier soir je dort plus. Je plaisante mais ça prend la tête)!!

Merci d’avance A plus !

Je m’oriente ma recherche sur la gestion de mes “données” avec map et constrain d’où sous généré les pilotages.
Voici mon programme !! il y a peut être une erreur que j’ai pas vu !!

/*Déclaration des bibliotheques*/

//Pilotage des moteurs par un L293d, pont réversible.

//---------Communication.
#include <Wire.h>

//---------IMU
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_L3GD20_U.h>
#include <Adafruit_9DOF.h>

//ID unique pour les capteurs.
// "dof" pour la communications du module IMU => fait appel aus fonction de transmission de données.
Adafruit_9DOF                   dof   = Adafruit_9DOF();
// "accel" pour les axes X et Y => fait appel aux données de l'inclinomettre.
Adafruit_LSM303_Accel_Unified   accel = Adafruit_LSM303_Accel_Unified(30301);
// "mag" Pour l'axe d'orientation Z => fait appel aux données du magnetometre (bousole).
Adafruit_LSM303_Mag_Unified     mag   = Adafruit_LSM303_Mag_Unified(30302);

// Met à jour ce SLP avec la mesures correcte pour une altitude précises.
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;//

//---------IR
#include <IRremote.h>
#include <IRremoteInt.h>

//Affectation de la variable "ir" de reception à la broche X.
const int ir = 7; //Affectation de la variable IR.

//Déclaration de l'objet "irRecept" pour traitement de la reception signal.
IRrecv irRecept(ir);
//Déclaration de l'objet "ret_val_ir" pour le traitement du retour signal.
decode_results ret_val_ir;//---Stand by.---*/

//---------Affectation des variables de pilotages MOTEURS aux broches.
//Pilotage Moteur via un L293d. Une voie d'activation par moteurs et deux pilotes de sens de marche.
const int activMA = 2; //Activation de la voie A. => moteur A = Gauche.
const int S_1A = 3; // Activation du sens 1 = AVANT.
const int S_2A = 5; // Activation du sens 2 = ARRIERE.

const int activMB = 8; //Activation de la voie B. => moteur B = Droite.
const int S_1B = 9; // Activation du sens 1 = AVANT.
const int S_2B = 11; // Activation du sens 1 = ARRIERE.


void setup() {
  // ---- Configuration du port serie.
  Serial.begin (9600);

  // ---- Configurations des sorties Moteur A -------Gauche
  pinMode(activMA, OUTPUT); //Activation voie A.
  pinMode(S_1A, OUTPUT); //Activation Sens 1.
  pinMode(S_2A, OUTPUT); //Activation Sens 2.

  // ---- Configurations des sorties Moteur B -------Droite
  pinMode(activMB, OUTPUT);//Activation voie B.
  pinMode(S_1B, OUTPUT); //Activation Sens 1.
  pinMode(S_2B, OUTPUT); //Activation Sens 2.

  //Initialisation 9-DOF. => IMU
  initIMU();

  /* ----- Configuration de l'infra rouge.
  irRecept.enableIRIn();//--*/

  Serial.println("Equi_Bot_projet PRET"); Serial.println(' '); //Affichage du projet
} //------------FIN DE SETUP

//----------------------------Fonction d'initialisation IMU.----------------------
void initIMU()
{
  if (!accel.begin())
  {
    // Si probleme de detection.
    Serial.println("!! Erreur detection LSM303 !!");
    while (1); //Arrêt forcé du programme.
  }
  if (!mag.begin())
  {
    // Si probleme de detection.
    Serial.println("!! Erreur detection LSM303 !!!!");
    while (1); //Arrêt forcé du programme.
  }
}//-------------------------------------Fin de init IMU-----------------------------

void loop(void) {
  int Y;

  /*----------Reception signal IR.
  if (irRecept.decode(&ret_val_ir)) {
    Serial.println(ret_val_ir.value, HEX);
    irRecept.resume(); // Receive the next value
  }//--*/

  //Affectation de "mnemonique".
  sensors_event_t   accel_event;
  sensors_event_t   mag_event;
  sensors_vec_t     orientation;

  // Données brut de l'accéléromètre.
  //Interogation du capteur d'inclinaisons.
  accel.getEvent(&accel_event);
  if (dof.accelGetOrientation(&accel_event, &orientation))
  {
    //tangage valides.
    Serial.print("Axe Y: ");
    Y = orientation.pitch; //Valeur brut arrondie et chargé dans "X".
    Serial.print(Y); Serial.print(";");

    // Position du magnétomètre
    mag.getEvent(&mag_event);
    if (dof.magGetOrientation(SENSOR_AXIS_Z, &mag_event, &orientation))
    {
      //Si les données de cap sont valide.
      // Serial.print(" Z: ");
      int Z = orientation.heading;
      // Serial.print(Z);
      //Serial.print("; ");
    }
  }
  Serial.println("");
  //delay(200);

  //////////// Gestion de la consigne. ////////
  // Consigne = 0 = le point d'équilibre.
  // Traitement de la donnée de tangage en valeur absolu.
  int order = abs(Y); //Variable de consigne "order" en anglais.

  //Mise à l'echelle consigne.
  order = map(order, 1, 15, 0, 255); //De 1° à 15° pour un signale de 0 à 255.

  //Mise en butée de l'echelle brut.
  order = constrain(order, 0, 255);
  Serial.print("Consigne :"); Serial.println(order); Serial.print(";");//--

  //----------Regulation proportionelle (integral). ==> A l'étude.
  float Ke = 0.3; //Coef d'integration.
  float Porder = order + (order * Ke); //Calcul en integral.
  // Mise en butée de la consigne à 80 pour accrochage du couple moteur.
  // Mise en butée de la consigne à 255 pour limitation à 5V PMW.
  Porder = constrain(Porder, 80, 255); //--*/

  /*Simulation de mouvement = TEST.
    for (int i = 80 ; i < 255; i++) { //init à 80 pour accrochage du couple moteur.
    Porder = i;
    Y=-2;//-Debug IR-*/

  ////////////Gestion des moteurs.//////////
  //Activation des voie A et B.
  digitalWrite(activMA, HIGH); digitalWrite(activMB, HIGH);

  //----------Definition du sens de "marche" et mise en service.
  if (Y > 1) {//Contrôle du sens de basclulement (+) = avant.(filtre à +1 dégrés).
    analogWrite(S_1A, Porder); analogWrite(S_1B, Porder); //Top sens AVANT.
    analogWrite(S_2A, 0); analogWrite(S_2B, 0); //Stop sens ARRIERE.
    Serial.print("Avant : "); Serial.print(Porder); Serial.print("; "); Serial.println();
  }//if.
  else {
    analogWrite(S_1A, 0); analogWrite(S_1B, 0); //sens AVANT.
  }

  if (Y < -1) {//Contrôle du sens de basclulement (-) = arriere.(filtre à -1 dégrés).
    analogWrite(S_2A, Porder); analogWrite(S_2B, Porder);//Top sens ARRIERE.
    analogWrite(S_1A, 0); analogWrite(S_1B, 0);//Stop sens AVANT.
    Serial.print("Arriere : "); Serial.print(Porder); Serial.print("; "); Serial.println(activMB);
  }//if.
  else {
    analogWrite(S_2A, 0); analogWrite(S_2B, 0);  //sens ARRIERE.
  }

  /*Serial.print("TEST : ");Serial.println(i);
    //delay(200);//  TEST => ou for.
    }//fin de for TEST Debug IR------------------------------*/

  Serial.println("");
  delay(300);

}//Fin de loop.

A plus !!

Hello,

Tout d'abord : quel plaisir de lire un code formaté et commenté... !
Que les petits gars qui débarquent ici avec le code de leur projet en prennent de la graine.

Pour ce qui est de ton problème... Comme la même consigne est appliquée aux deux moteurs, (si j'ai bien tout compris), ce ne peut être dans le PID que le problème se trouve.

Par contre, je lis que la broche IR est la 8... Et la broche ActivMB est la 8 également...
Est-ce bien normal ?

Coyotte

Salut Coyotte !

Et bien non :fearful: c'est pas normale et je suis passé 3
fois à coté !! je vais corriger et essayer.

Merci !!
A plus !

Bonjour;

J'ai corrigé mon erreur et fait des essais => NEGATIF.

J'ajoute la remarque que dans un sens ou dans l'autre le problème s"inverse.

  • Sens avant moteur A démarre et B plus tard.
  • Sens arrière moteur B démarre et A plus tard.

J'ai tenté un pilotage progressif et simulé par une boucle "for" pour isoler ce dernier des mise a l’échelle et tout le tralala de PID. => NEGATIF.

Je vais faire un programme à part pour essayer mais cette fois sans le L293d et le 9-DOF!!

Je commence vraiment a croire que cela viens de la biblio "IR".

A plus!

Re,

En regardant le code d'exemple de Velleman, il y a par moteur :
1 pin pour la commande de marche
1 pin pour le sens

Or, lorsque je lis ton code, je vois que tu changes 2 pins de sens par moteur.
(Par exemple S_1A et S_2A)
Pour quelle raison ?

D'autre part, est-ce que la commande de changement de sens ne pourrait pas être

  1. Stop du moteur
  2. Changement de sens
  3. Réactivation du moteur

Il me semble que tu donne l'ordre de vitesse avant de d'en spécifier le sens... (La carte le gère peut-être correctement... Mais est-ce logique ? )

Coyotte

Salut Coyotte !!

Il est vrais que je n'ai pas spécifié que le pilotage des moteurs sur ce programme est géré par un L293d.

A plus !

J'ai ajouté les modifs. au programme avec la spécification de pilotage.

A plus !!

Salut;

J'ai isolé ma consigne "Porder" de tout traitements de mise à valeur absolu, mise à l’échelle et de mise en butée.
J'ai appliqué une consigne directe d'une valeur de 255, activé l'infrarouge et fait le test = les deux moteurs démarre en même temps.
Mais lorsque je diminue la consigne à 254 plus rien ne se passe. Et mes pilotes passent a l'état bas 0v.

Je désactive l'infrarouge dans le setup() et là tout vas bien !!

IRremot.h perturbe le pilotage de mes sorties ??
Quelqu’un peut il me donner plus de détaille sur le traitement des entrées sorties via les biblo.?

En attendant je vais traduire le datasheet de l'ATMEGA 328p pour en savoir plus sur les entrées sorties.

A plus !!

Salut ;

J'ai continué a chercher !!

Suivant les dernier essais Je focalise sur la bibliothèque.

la fonction de "IRremot.h" utilisé qui me pose problème est la suivante

//+=============================================================================
// initialization
//
void  IRrecv::enableIRIn ( )
{
	cli();
	// Setup pulse clock timer interrupt
	// Prescale /8 (16M/8 = 0.5 microseconds per tick)
	// Therefore, the timer interval can range from 0.5 to 128 microseconds
	// Depending on the reset value (255 to 0)
	TIMER_CONFIG_NORMAL();

	// Timer2 Overflow Interrupt Enable
	TIMER_ENABLE_INTR;

	TIMER_RESET;

	sei();  // enable interrupts

	// Initialize state machine variables
	irparams.rcvstate = STATE_IDLE;
	irparams.rawlen = 0;

	// Set pin modes
	pinMode(irparams.recvpin, INPUT);
}

De mon interprétation ça fait appel aux temps d'interruptions et aux paramètres des broches.
Pas mal de choses m'échappe pour le moment; fonctions cli() sei(); je suis en cours de décryptage. Mais de laide serrais la bienvenu. SVP.

A plus!!

Salut;

J'ai continue seul à chercher ! :sweat_smile:
Mais j'ai avancè !!!!
j'ai donc éplucher le datasheet de l'ATMEGA et j'y ai découvert ce que font ces fonction cli() et sei().
je les ai donc désactivé a tour de rôle pour cibler mon problème mais il n’étaient pas en cause.
Mais plutôt cette ligne dont je n'ai pas trouvé l'origine de sa construction.
// Timer2 Overflow Interrupt Enable ==> Configuration du second temps d'interruption.
TIMER_ENABLE_INTR;

==> DOC Lorsque TOIE le bit 2 est écrit à un et le bit I dans le registre d'état est défini (=1), le timer / Counter2 interruption de débordement est activée. L'interruption correspondante est exécutée si un débordement dans Timer / Counter2 se produit, à-savoire que
lorsque le bit de TOV2 est situé dans le Timer / Compteur Interrupt Flag Registe-TIFR2..
Une fois désactivé (par une mise en commentaire) et rechargé tout fonctionne normalement mais l'infrarouge ne fonctionne pas!
J'ai donc réactiver cette ligne pour confirmer mes soupçons et la patatra !!!!!! ça remarche correctement !!! ==> Utiliser pour la gestion des sorties.

Si je me réfère a la doc j'ai réinitialiser les temps d'interruptions définis.

Quelque chose a bougé je ne sais pas quoi mais ca marche !
je confirmerais si ça intéresse !! (j'a l'impression du faire du mono logue sur le sujet)
je pense avoir résolu mon problème.
Merci a ceux qui ont aidé.

A plus!!

manumanu:
je confirmerais si ça intéresse !! (j'a l'impression du faire du mono logue sur le sujet)

personnellement j'essaye de suivre tous les posts de la section Française, je n'ai encore pas eu l'occasion de mettre en oeuvre d'IR et moteurs mais j'utilise couramment le timer 2 pour des interruptions temporelles (par ex pour faire une action toutes les secondes), donc ton information pourra m'éviter de passer des heures a rechercher le même pb ... c'est ça la puissance d'un forum

Salut ;

Merci rjnc38 !

La je sais plus quoi faire !! Ce qui marchais hier ne fonctionne plus. :cry:

je comprend plus !! j'ai essayé les dernier manip. rien a faire !!

Et là c'est confirmé => IRremot.h fout le bordel
Je vais essayé de piloter des LED pour isoler le L293d du problème.
c'est la dernière chose que je n'ai pas mis en doute a défaut de rester borné sur ma lib.

A plus !

vas voir ici timer-and-interrupt-tutorial tu auras certainement la réponse a ton pb (Timer 2 et PWM pin 3 et 11 pour l’UNO)

Merci !!

J'ai un peu de mal avec les interruptions surtout leurs modes de fonctionnement et les paramétrage AVR possible. Ça vas m'aider a mieux comprendre.

Je fait le montage test avec des leds et je vous tiens au courants !!

A plus !!

manumanu:
J'ai un peu de mal avec les interruptions surtout leurs modes de fonctionnement et les paramétrage AVR possible. Ça vas m'aider a mieux comprendre.

en fait le PWM des pins 3 et 11 de l'UNO utilisent le timer2 et la lib IR aussi d’où le conflit ...

The Arduino has 3 timers and 6 PWM output pins. The relation between timers and PWM outputs is:
Pins 5 and 6: controlled by Timer0
Pins 9 and 10: controlled by Timer1
Pins 11 and 3: controlled by Timer2

tu peux donc utiliser ces pins en digital mais pas en PWM

Ok je fait le test !!

Je change mes broches

Merci !

J'ai changé de broches.
J'ai également "shunté" l'activation des voie A et B => branché au 5V = activation permanente.
Ne reste actif que le pilotage.

4 et 5 pour le pilotage voie A.
9 et 10 Pour le pilotage voie B.

Mais le résultat reste le même.

Je récapitule (car il y a du nouveau depuis) : Dans un sens les deux moteurs marche en PMW et démarre en même temps mais dans l'autre sens le moteur A démarre en PMW et le B démarrent seulement quant il atteint une inclinaison de 7° mais a pleine puissance.

A plus!

J'ai changé les broches de la voie A.

J'y ai mis 8 et 11 = Je me retrouve avec un autre fonctionnement.

Dans les deux sens le moteur A démarre en PMW et le B avec du retard toujours sur le même angle 7°.

A plus !!

Salut ;

Je viens de faire des essais en pilotant deux LEDS avec un signale analogique par un simple programme.

Et la surprise => Le même phénomène.
La LED 2 s'allume en PMW et la 1 reste éteinte jusqu'à 126 point environ.

J'y est branché un appareil de mesure à la 2 => Elle passe immédiatement en full tension. 5V au dessus des 126 de PMW. Alors que la 1 continu sa progression normale.

Ce n'est don pas la lib Rremote.h mais autre chose. d'externe au programme => de plus j'ai fait ce test avec une autre carte => mes pilotes (IDE) ??
Je vais mettre a jours pour voir. (recharger l'ide avec les pilotes)

A plus !