i2c, perte de connection

Bonjour,
Je suis en train de créer un système d'alarme intrusion avec un Mega (maître) comme centrale d'alarme, une horloge DS3231, un digicode sur la base d'un nano.
Je me rend compte que quand je coupe l'alimentation du nano (et donc le bus) le Mega se fige et bien sure la sécurité n'est plus assurée.
Je suppose qu'il attend après le bus et que le bus du maître fonctionne sur le principe d'interruption au même titre que l'esclave.

Comment faire pour que le méga sorte de ce freez et que je puissent générer une alarme?

Merci.

Vous pouvez utiliser le principe de scanner de bus I2C (cf le code de Nick posté dans cet article) pour détecter la présence d’un esclave avant de faire quoi que ce soit:

// I2C Scanner
// Written by Nick Gammon
// Date: 20th April 2011

#include <Wire.h>

void setup() {
 Serial.begin (115200);
 Serial.println ();
 Serial.println ("I2C scanner. Scanning ...");
 byte count = 0;
 
 Wire.begin();
 for (byte i = 1; i < 120; i++)
 {
   Wire.beginTransmission (i);
   if (Wire.endTransmission () == 0)
     {
     Serial.print ("Found address: ");
     Serial.print (i, DEC);
     Serial.print (" (0x");
     Serial.print (i, HEX);
     Serial.println (")");
     count++;
     } // end of good response
    delay (5);  // give devices time to recover
 } // end of for loop
 Serial.println ("Done.");
 Serial.print ("Found ");
 Serial.print (count, DEC);
 Serial.println (" device(s).");
}  // end of setup

void loop() {}

L’idée puisque vous savez quel est votre esclave c’est qu’au lieu de scanner de 1 à 119, vous faites juste le test pour votre esclave à l’adresse 0x[color=red][b]XX[/b][/color]

   Wire.beginTransmission (0x[color=red][b]XX[/b][/color]);
   if (Wire.endTransmission () == 0) {
        // ici vous savez que l'esclave est présent vous pouvez envoyer des ordres

   }

sinon je n’ai pas bien compris à quoi sert le Nano si vous avez les fils du bus I2C qui partent du Nano pour aller au MEGA, pourquoi vous ne câblez pas directement les fils du digicode jusqu’au MEGA?

Merci J-M-L pour votre réponse.
Je viens de tester sans succès. Quand je débranche l'alim, toujours pareil.
Je suis alors reparti avec le code du scanner et, même résultat, ça freeze. Par contre, quand j'ouvre le bus (scl) il n'y à pas de problème, le scanner continue sans détecter le participant.
D'autres idées?

Bonjour,

Ton code tombe peut-être dans une boucle infinie quand il n'y a plus personne sur le bus. Tu devrais regarder par là.

Zarb94:
Je suis alors reparti avec le code du scanner et, même résultat, ça freeze. Par contre, quand j'ouvre le bus (scl) il n'y à pas de problème, le scanner continue sans détecter le participant.
D'autres idées?

prendre la tension sur SCL dans ce cas
et voir ou sont les résistances de tirage pull-up

c’est le code qu’on trouve partout:

#include <Wire.h>
 
 
void setup()
{
  Wire.begin();
 
  Serial.begin(9600);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknow error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

Pour les résistances, elles sont en sortie du mega celui sur lequel j’ téléversé le scanner. quand je débranche l’alim du nano, ça freeze toujours.

Pas de probleme quand je débranche le bus.

vous pouvez mettre un petit schéma explicatif the comment tout est connecté et alimenté?

Bonjour

Voici ce que j'ai vu de mon côté il y a quelques temps, en analysant plus en détail l'I2C et la bibliothèque Wire.h

Il est effectivement tout à fait possible de "freezer" un arduino maître I2C.

Cela provient de la combinaison de plusieurs facteurs :

  1. la norme I2C prévoit la possibilité de présence de plusieurs maîtres sur un même bus I2C, avec une règle de protocole simple : quand un maître veut causer sur le bus et que celui-ci est occupé par un autre maître, il doit patienter jusqu'à la libération du bus avant de causer.

  2. Un problème électrique sur le bus (par ex absence de résistances de pull up) qui maintient les lignes à GND.
    D'un point de vue protocole, cela donne l'impression que le bus est occupé par un autre maître.

  3. Une faiblesse des fonctions de wire.h : par exemple à l'intérieur de Wire.endTransmission(), il y a un bon vieux while() qui attend éternellement que l'autre maître imaginaire libère le bus.

Trois solutions possibles :

a) modifier la bibliothèque wire.h de l'IDE arduino pour y ajouter des timeout dans les fonctions potentiellement bloquantes, avec des codes retours qui permettront (enfin !) d'écrire des programmes propres et sécurisés.

b) revoir le câblage électrique pour sécuriser le bus I2C

c) ajouter un reset automatique par watchdog pour sortir du while infernal. C'est la solution la plus crade et dans ton cas cela risque de ne rien résoudre car tu risques de rerentrer dans un while sans fin.

bricoleau:
a) modifier la bibliothèque wire.h de l'IDE arduino pour y ajouter des timeout dans les fonctions potentiellement bloquantes, avec des codes retours qui permettront (enfin !) d'écrire des programmes propres et sécurisés.

il me semble que la lib WSWire résoud ces pb de blocage avec des timeout