Problème avec rotoshield et LCD sur I2C

Bonjour, dans le cadre de construction d'un 1er robot basé sur Arduino je rencontre des problèmes de blocage entre un rotoshield (de snootlab) et un LCD utilisant I2C (de DFRobot).

La plateforme :

  • Carte Arduino Uno
  • 2 moteurs Micro DC Geared Motor sur une plateforme 4AWD New de dfrobot (sur laquelle je ne met que 2 moteurs avec une roulette)
  • Pilotage des moteurs par Rotoshield de Snootlab. Ce shield a pour particularité d'utiliser I2C pour recevoir les ordres.
  • Ecran I2C/TWI LCD1602 de DFRobot
  • Alimentation de la carte Arduino par USB (ou pile 9V en mode autonome)
  • Alimentation des moteurs via rotoshield par un bloc de 5 accus

Le problème : au bout de quelques secondes de fonctionnement des moteurs, des caractères "étranges" apparaissent sur le LCD, et celui-ci n'affiche généralement plus rien ensuite.
En retirant différents éléments (capteur de distance IR, télécommande IR, encodeurs, ...), le problème survient avec seulement le Rotoshield et le LCD.
J'ai simplifié le programme pour cerner le problème (cf. en fin de post) :

  • Suppression des messages sur la console
  • Dans loop, démarrage des moteurs puis simple boucle d'affichage d'un message sur le LCD

Les tests ont été les suivants :

  • Changement de la librairie de pilotage du LCD (au début celle indiquée sur le site DFRobot) : le problème continue à se produire

  • Ajout de délais dans le setup : amélioration de la stabilité mais le problème continue à se produire

  • Moteurs débranchés : tout est ok, les LED du Rotoshield s'allument et pas de blocage sur le LCD

  • LCD débranché (sortie des messages sur la console) : tout est ok

  • Moteurs et LCD branchés, pas d'appel à la fonction mycar.accel, moteurs initialisés : tout est ok

  • Moteurs et LCD branchés, pas d'appel à lcd.print, lcd initialisé, sortie des messages sur la console : tout est ok

  • Moteurs et LCD branchés, appels à mycar.accel et lcd.print : le problème survient au bout d'un temps variable (apparition de caractères "étranges", puis généralement le lcd s'efface, et parfois les moteurs continuent à tourner comme si le programme ne s'exécutait plus)

  • En faisant varier la fréquence d'initialisation des moteurs (dans car.init), avec une vitesse constante (160) : le problème survient moins fréquemment lorsque la fréquence augmente (1, 2, 8, 64KHz)

  • En faisant varier la vitesse, à fréquence constante (1KHz) : le problème survient moins fréquemment lorsque la vitesse diminue

Le dernier test a consisté à ajouter des condensateurs d'anti-parasitage sur chaque moteur, comme indiqué à l'adresse http://p.loussouarn.free.fr/technic/moteur/moteur.pdf. Cela n'a rien changé et le problème survient toujours.

Quelqu'un a-t-il déjà utilisé cette combinaison "Rotoshield + LCD I2C/TWI de DFRobot" ?
Quelles librairies et code avez-vous alors utilisés ?
Auriez-vous des idées sur la cause de ce problème (code, moteur, shield, LCD, ...) ?
Je n'ai malheureusement pas d'autres composants utilisant I2C pour faire des tests complémentaires.
Merci d'avance pour votre aide.

Voici le code utilisé (j'ai simplifié des fonctions propres au rotoshield qui sont issues de l'exemple fourni avec le shield) :

//Bus I2C : pour snootor (rotoshield) et LCD
#include <Wire.h>

//Rotoshield
#include <snootor.h>
// moves
#define LEFT_TURN 7
#define RIGHT_TURN 8
#define BLOCK_RIGHT 9
#define BLOCK_LEFT 10
#define BLOCK_FRONT 11
#define BLOCK_REAR 12

#define FRONT_LEFT 3
#define FRONT_RIGHT 4
#define REAR_LEFT 1
#define REAR_RIGHT 2

//Ecran LCD
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

class car {
  SnootorDC MRL; // arrière gauche
  SnootorDC MRR; // arrière droit
 public:
  uint8_t carDirect;
  car(){}
  void init(){
    MRL.init(REAR_LEFT, MOTOR12_1KHZ);
    MRR.init(REAR_RIGHT, MOTOR12_1KHZ);    //MOTOR12_1KHZ
    carDirect = RELEASE;
  }
  car* run(uint8_t direction){
    ...
  }

  car* accel(uint8_t direction, uint8_t maxspeed) {
    return run(direction)->setSpeed(60)->delay(200)->setSpeed(160)->delay(200)->setSpeed(maxspeed);
  }

  car* stop(){
    return setSpeed(120)->delay(100)->setSpeed(60)->delay(100)->run(RELEASE);
  }

  car* turn(uint8_t direction){
    return run(direction)->setSpeed(100)->delay(100)->delay(500)->run(RELEASE);
  }

  car* setSpeed(uint8_t speed){
    MRL.setSpeed(speed);
    MRR.setSpeed(speed);
    return this;
  }

  car* delay(uint16_t ms){
    SC.delay(ms);
    return this;
  }

  void invert(uint8_t motor){
	...
  }
};


car mycar;

void setup(){
  //Initialisation bus I2C
  Wire.begin();
  mycar.delay(1000);

  //LCD
  lcd.init();
  lcd.backlight();
  lcd.print("Init");

  mycar.delay(1000);
  mycar.init();

  mycar.delay(1000);
}

void loop(){
  int d = 100;
  mycar.delay(d);
  mycar.accel(FORWARD, 160);
  mycar.delay(d);
  for (int i = 1; i < 10; i++) {
    lcd.setCursor(0,0);
    lcd.print("Step ");
    lcd.print(i,DEC);
    mycar.delay(d);
  }
  mycar.stop();
}

La réponse m'aurait grandement intéressé, pourrait tu poster une copie sur le forum Snootlab s'il te plait ?

http://forum.snootlab.com/

Tu auras bien plus de chances d'obtenir une réponse.

Bonjour,

Sur ces deux shields tu as deux résistances de pull-up sur SDA et SCL (lignes du bus I2C).
Ces résistances sont donc en paralléle ce qui divise leurs valeurs (résistances en série = addition, en paralléle = division).

A mon avis le probléme vient de là, essaye (si tu peut) de dessouder une des pattes des résistances R10 et R11 de la "rotoshield".
Si cela résout le probléme dessoude les deux autres pattes pour enlever complétement les deux résistances, sinon tu ressoude les deux pattes pour revenir comme avant.

Vérifie aussi qu'au niveau du code tu n'utilise pas les même adresses I2C pour le lcd et la rotoshield (peu probable mais bon).

A mon avis le probléme vient de là, essaye (si tu peut) de dessouder une des pattes des résistances R10 et R11 de la "rotoshield".

C'est pas évident, je ne dis pas que dans certains cas cela a pu fonctionner mais....
Il clairement indiqué dans la norme I2c [NXP(ex philips semi-conducteur)rev4 du 4 fev 2012] que plus il y a de modules connectées plus la capa augmente sur le bus et dans ce cas il faut diminuer la valeur des résistances (un produit RC trop grand sur le bus écroule les fronts de montée des signaux-> constitution d'un filtre passe bas).
Donc le principe que quand on double le nombre de module connectés on divise par 2 la valeur de la résistance pour compenser le doublement de la capacité ne me choque absolument pas.

68tjs:
Donc le principe que quand on double le nombre de module connectés on divise par 2 la valeur de la résistance pour compenser le doublement de la capacité ne me choque absolument pas.

Je suis d'accord avec toi.
Mais la résistance n'est divisé par deux que si les deux résistances en paralléle sont de même valeur, or (je ne suis pas allez vérifier dans la librairie) si jamais les résistances de pull-up interne sont activité il y aura une grosse différence entre les deux valeurs.

Les résistances de pull up sont comprises entre 30 et 70 kohms.
J'ai une abaque sous les yeux ou Npx ne conseille pas de choisir des valeurs au-delà de 20kohms, la moyenne se situe plutôt autour de 5/8 kohms.
Les pull- up sont effectivement activées dans la librairie Wire mais avec de telles valeurs cela ne doit pas se voir, je me demande même à quoi elle peuvent servir sachant que selon le lot de fabrication des micro-controleurs on peut avoir 70kohms.

68tjs:
Je me demande même à quoi elle peuvent servir sachant que selon le lot de fabrication des micro-controleurs on peut avoir 70kohms.

Bonne question ... c'est peut être aussi une histoire de norme TWI (atmel) vs I2C (philips) ?

C'est un fichier d'origine Wiring et non pas Arduino, le développeur était sans doute plus artiste qu'électronicien.....