Communication I2C 1 maitre 3 esclaves

Bonjour

Dans mon projet solaire, J’ai un contrôleur maitre avec un Atmega1284P. J’ai 3 passerelles RS485 I2C avec un Atmega328P Arduino.

La passerelle « Transmetteur » Reçoit une chaine de 8 octet sur le port série. Les 8 octets sont stockés dans un tableau. Le maitre récupère les 8 octets via l’I2C. Cette passerelle est unidirectionnelle.

Le 2 autre passerelles « Onduleur » reçoivent les 8 octets sur le bus I2C pour les renvoyer à l’onduleur via le port série. En retour elle reçoit 15 octets émis par l’onduleur, pour les stokers dans un tableau, qui sera lu par le maitre via l’I2C. cette passerelle est bidirectionnelle.

Dans mon contrôleur maitre, il y a plusieurs modes de fonctionnement. On va rester sur le MODE 1.

Dans ce mode, je récupère les 8 octets depuis la passerelle « Transmetteur » pour les renvoyer à l’identique vers les 2 autres passerelle « Onduleur ».

Mon souci, c’est que je ne parviens pas à lire les 8 octets le la passerelle transmetteur via l’I2C.

Code du maitre

if (BoucleR == 100) 
    {
      i2c_Trs();                                                      // Recuperation des données du Tansmetteur de mesure de puissance
      //Transforme deux byte de 8 bits en un mot 16 bits
      Pconsommer = (Transmetteur[4] << 8) | Transmetteur[5];          // Recuperation de la puissance consomé instantané
      SommeDeControle = Transmetteur[7];                              // Recuperation de la somme de controle
    }                
if (Mode == 1)                                                        // ~~~~~~~~~~ MDE DIRECT, RENVOIE LA MESURE DE PUISSANCE DANS CHAQUES ONDULEURS
  {  
    aff1();                                                           // AFFICHE 1 sur 7 SEGMENTS pour le mode 1                                       
    for (int p = 0; p < 8; p++)
      {
        Onduleur1send[p] = Transmetteur[p];                           // Transfére les données du transmetteur directement dan l'onduleurs N°1
        Onduleur2send[p] = Transmetteur[p];                           // Transfére les données du transmetteur directement dan l'onduleurs N°2 
      }
        PU_inst = Pconsommer * N_Onduleurs;                           // ON LA RE-MILTIPLIE PAR LE NOMBRE D'ONDULEUR POUR L'AFFICHAGE
        A_PuissanceInjecte = PU_inst / N_Onduleurs;                   // Affichage de la puissance envoyer dan l'onduleur N°1
        if (A_PuissanceInjecte > 700)                                 // Si la puissance est superieure a 700 Watts
          {
            A_PuissanceInjecte = 700;                                 // On affiche la puissance maxi de l'onduleur qui est de 700 Watts
          }
        B_PuissanceInjecte = PU_inst / N_Onduleurs;                   // Affichage de la puissance envoyer dan l'onduleur N°2
        if (B_PuissanceInjecte > 700)                                 // Si la puissance est superieure a 700 Watts
          {
            B_PuissanceInjecte = 700;                                 // On affiche la puissance maxi de l'onduleur qui est de 700 Watts
          }       
  } 
if (BoucleR == 500 && Commtrs_ok == true)                                                 // Au cycle 150, on interoge les onduleurs solaire
    {
      i2c_OndA();                                                     // Appel sous programme de communication I2C Onduleur N°1
      Onduleur1Ubatt = (Onduleur1rcv[5]  << 8) | Onduleur1rcv[6];     // On met deux octets da un mot
      Onduleur1Ibatt = (Onduleur1rcv[7]  << 8) | Onduleur1rcv[8];     // On met deux octets da un mot
      Onduleur1Ures  = Onduleur1rcv[10];                              // Tension reseau
      Onduleur1Freq  = Onduleur1rcv[11] / 2;                          // Frequence reseaux
      int Calcul11 = (Onduleur1rcv[13] >> 4) | 0x000F;
      int Calcul12 = Onduleur1rcv[13] | 0X000f;
      int Calcul13 = (Calcul11 * Calcul12) / 10;
      int Calcul14 = Onduleur1rcv[12] | 0X000f;
      int Calcul15 = Calcul14 / 10;
      Onduleur1Temp  = Calcul13 + Calcul15;                           //
    }

// _______________________________________________________________ ONDULEUR N°2
if (BoucleR == 1000 && Commtrs_ok == true)
    {
      i2c_OndB();                                                     // Appel sous programme de communication I2C Onduleur N°2
      Onduleur2Ubatt = (Onduleur2rcv[5]  << 8) | Onduleur2rcv[6];     // On met deux octets da un mot
      Onduleur2Ibatt = (Onduleur2rcv[7]  << 8) | Onduleur2rcv[8];     // On met deux octets da un mot
      Onduleur2Ures  = Onduleur2rcv[10];                              // Tension reseau
      Onduleur2Freq  = Onduleur2rcv[11] / 2;                          // Frequence reseaux
      int Calcul21 = (Onduleur2rcv[13] >> 4) | 0x000F;
      int Calcul22 = Onduleur2rcv[13] | 0X000f;
      int Calcul23 = (Calcul21 * Calcul22) / 10;
      int Calcul24 = Onduleur2rcv[12] | 0X000f;
      int Calcul25 = Calcul24 / 10;
      Onduleur2Temp  = Calcul23 + Calcul25;
    }

Code de la passerelle transmetteur

void loop()
{
Cycle = Cycle + 1;                                    // Incrementation du cycle programme

//------------------------------------------------------
if (Cycle == 1)                                       // Au cycle 1 appel sous programme affichage RUN
  {
    LCDrun();                                         // Appel sous programme
  }
  
//------------------------------------------------------
if (Serial.available() > 0)                           // tant qu'il y a quelque chose à lire 
  {
    int rLen = Serial.readBytes(Transmetteur, 8);     // Reception des 8 octets depuis le transmetteur
    CommRS485_OK = true;                              // On a bien recu la chaine d'octets depuis le transmetteur, on met le bit a 1
  } 
if (CommI2C_OK == false)                              // Si le bit de comm est a 0, il y a une erreur
  {
    TimeoutI2C = TimeoutI2C + 1;
    if (TimeoutI2C > 1000000)
      {
        Cerreur = 10;
        void LCDtimeoutE1();                          // Appel sous programme d'affichage de l'erreur
        TimeoutI2C = 0; 
      }                            
  } else if (CommRS485_OK == false)
              {
                TimeoutRS485 = TimeoutRS485 + 1;
                if (TimeoutRS485 > 1000000)
                  {
                    Cerreur = 20;
                    void LCDtimeoutE2();              // Appel sous programme d'affichage de l'erreur
                    TimeoutRS485 = 0;
                  }
              } else {
                      Cerreur = 0;
                      TimeoutI2C = 0;
                      TimeoutRS485 = 0;
                     }

//------------------------------------------------------
if (Cycle == 10)                                      // Au 10eme cycle on affice la puissance conssomé
  {
    Pinst = (Transmetteur[4] << 8) | Transmetteur[5]; // Puissance consomé instantané, 2 bytes dans un Mot
    LCDaffiche();                                     // Appel sous programme d'affichage de la puissance
  }
  
//------------------------------------------------------
if (Cycle >= 90000)
  {
    Cycle = 0;                                        // Remise a ZERO du Cycle
    CommI2C_OK = false;                               // Remise a ZERO du bit de communication I2C
    CommRS485_OK = false;                             // Remise a ZERO du bit de communication RS485
  }
}

//------------------------------------------------------
// réponse à une requête I2C
// mode Esclave
// cette fonction "handler" a été enregistrée dans le setup()
//------------------------------------------------------
void requestEvent()
{
//for (int t = 0; t < 8; t++)
    //{
    Wire.write(Transmetteur[0]);      // répond par un message
    Wire.write(Transmetteur[1]);      // répond par un message
    Wire.write(Transmetteur[2]);      // répond par un message
    Wire.write(Transmetteur[3]);      // répond par un message
    Wire.write(Transmetteur[4]);      // répond par un message
    Wire.write(Transmetteur[5]);      // répond par un message
    Wire.write(Transmetteur[6]);      // répond par un message
    Wire.write(Transmetteur[7]);      // répond par un message
    CommI2C_OK = true;                // Le maitre a bien recupéré les octets, on met le bit a 1
    //}
}

Sur mes circuits, j’ai mi une LED sur le signal SDA pour visualisé l’activité du bus. Dans mon code, j’ai mis des bits de surveillance de la communication. Si la passerelle transmetteur ne répond pas, on ne dialogue plus avec les passerelles des onduleurs. Ça fonctionne.

Cdt

un oubli.

//------------------------------------------
void i2c_Trs()                              // CHAINE D'OCTETS Transmetteur Via passerele I2C RS485
{ 
int t = 0;
Wire.requestFrom(10, 8);                    // demande à recevoir 8 octets du périphérique d'adresse 10
while (Wire.available())                    // attente des octets
   {
    Transmetteur[t] = Wire.read();          // Recuperation des données de la passerelle I2C RS485
    t++;                                    // Incrementation de la boucle de reception
    Commtrs_ok = true;                      // On a bien recu les octets.
   }
}

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