communication automate et arduino en rs485(parti code)

bonjour les amis je suis entrain de programmer mon arduino nano pour la communication avec mon automate , je travaille avec la bibliotheque <SimpleModbusSlave.h> j’arrive a envoyer les informations des sonde a l’automate tel que la température … la question qui me perturbe c’est que je veux que l’automate puisse écrire dans un registre que je l’ai déja déclarer dans mon programme pour que je puisse faire des condition .

Merci pour votre aide les amis

Bonjour,

Je ne vois pas trop ton problème.
Dans l'exemple SimpleModbusSlaveArduino tu as un exemple pour envoyer et recevoir des infos.

Bonjour Kamill j’espère que vous allez bien

Boitier=holdingRegs[10] ; c'est just de mettre comme çà pour recevoir l'info ?

Merci

Oui pour exploiter l'info que le maitre a envoyé dans le registre 10.

Merci kamil ,j’ai une question hort sujet de la cummunication modbus

vous savais que j’utilise un multiplexeur tca9548a pour communiquer avec mes sonde en i2c et je ne veux pas passer par la boucle
vu que je vais travailler avec des condition dans chaque sonde il faut que je les sépare à mon avis

je veux passer par chaque adresse indépendamment comme ca

void loop() {
  
  tcaselect(0);
  if( sht[0].readSample())
  {
     Humidity0 = sht[0].getHumidity();
       holdingRegs[0] = (int16_t)(100 * Humidity0);
        Temperature0 = sht[0].getTemperature();
          holdingRegs[1] = (int16_t)( 100 * Temperature0);
  holdingRegs[2] = 1; // indique etat OK
       
  }
  else
  {
      holdingRegs[0] = 0;
      holdingRegs[1] = 0;
      holdingRegs[2] = 0; 
    
    }
      tcaselect(1);
  if( sht[1].readSample())
  {
     Humidity1 = sht[1].getHumidity();
       holdingRegs[3] = (int16_t)(100 * Humidity1);
        Temperature1 = sht[0].getTemperature();
          holdingRegs[4] = (int16_t)( 100 * Temperature1);
  holdingRegs[5] = 1; // indique etat OK
       
  }
  else
  {
      holdingRegs[3] = 0;
      holdingRegs[4] = 0;
      holdingRegs[5] = 0;
 
    
    }
void tcaselect(uint8_t i) {
  if (i > 7) return;

  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();
}

mais il m’envoi l’erreur que tcaselect n’est pas déclarer , je serai reconnaissant si vous pouvez m’aider

Vérifies tes {}
Il semble manquer un } avant void tcaselect

oui pas c’est pas ca le probleme je pense bon voila le code que j’ai fait si vous pouvez jeté un oeil j’essaye d’envoyer les valeur en modbus et il y as une erreur de communication

#include <Wire.h>

#include <SHTSensor.h>
#include <SimpleModbusSlave.h>
#define TCAADDR 0x70
const byte NBSENSORS =2;
byte i=0;
SHTSensor sht;
// To use a specific sensor instead of probing the bus use this command:
// SHTSensor sht(SHTSensor::SHT3X);
float Humidity ;
float Temperature;

enum
{
  SHT_ETAT,         // etat du premier sht
  SHT_TEMP,         // température lue sur le premier sht
  SHT_HUM,          // humidité lue sur le premier sht
  SHT_NBREGS,       // nombre de registres par sht
  BOITIER,
  
  TOTAL_ERRORS = SHT_NBREGS * NBSENSORS, // reserve la place et numéro du registre d'erreur

  HOLDING_REGS_SIZE // nombre total de registres
};


unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup() {
 modbus_configure(&Serial1, 38400, SERIAL_8E1, 199, 2, HOLDING_REGS_SIZE, holdingRegs);
 modbus_update_comms(38400, SERIAL_8E1, 199);
  
  // put your setup code here, to run once:
  //Serial.begin(9600);
  Wire.begin();

 // Serial.begin(38400);
  //delay(1000); // let serial console settle

  
  
    tcaselect(0);     // sélectionne le sht qui va bien

    if (sht.init()) {
      //Serial.print("init(): success\n");
     // holdingRegs[3i+2]=(int16_t) (1);
    } else {
     // Serial.print("init(): failed\n");
      //holdingRegs[3i+3]=(int16_t) (0);
    }
    sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM); // only supported by SHT3x
  
}

void loop() {


 
    tcaselect(0);
 
    //Serial.print("SHT: ");
   
    if (sht.readSample()) {
   Humidity = sht.getHumidity();
       holdingRegs[0] = (int16_t)(100 * Humidity);
        Temperature = sht.getTemperature();
          holdingRegs[1] = (int16_t)( 100 * Temperature);
  holdingRegs[2] = 1; // indique etat OK
        
    }

 
}

void tcaselect(uint8_t i) {
  //if (i > 7) return;

  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << 7);
  Wire.endTransmission();
}

Merci beaucoup pour votre aide

Dans la loop() il faut que tu appelles modbus_update() si tu veux que ça communique

boujour Kamill Merci ca marche mais je récupére que des 0 , pour éliminer la boucle

il faut faire des changement ici ou non

void tcaselect(uint8_t i) {
  if (i > 7) return;

  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();
}

Qu'est ce que tu veux changer?
Mets ton programme complet.

vu que je vais utiliser de capteur i2c et des capteur analogique et numérique et envoyer ces information en modbus , j’ai pensé , a attribuer chaque capteur avec ces registre manuellement sans l’utilisation des boucle
voila le code

#include <Wire.h>

#include <SHTSensor.h>
#include <SimpleModbusSlave.h>
#define TCAADDR 0x70
const byte NBSENSORS =2;
byte i;
SHTSensor sht;
// To use a specific sensor instead of probing the bus use this command:
// SHTSensor sht(SHTSensor::SHT3X);
float Humidity ;
float Temperature;

enum
{
  //SHT_ETAT,         // etat du premier sht
  //SHT_TEMP,         // température lue sur le premier sht
 // SHT_HUM,          // humidité lue sur le premier sht
  //SHT_NBREGS,       // nombre de registres par sht
 // BOITIER,
  
 // TOTAL_ERRORS = SHT_NBREGS * NBSENSORS, // reserve la place et numéro du registre d'erreur

  HOLDING_REGS_SIZE, // nombre total de registres
};


unsigned int holdingRegs[HOLDING_REGS_SIZE];

void setup() {
 modbus_configure(&Serial1, 38400, SERIAL_8E1, 199, 2, HOLDING_REGS_SIZE, holdingRegs);
 modbus_update_comms(38400, SERIAL_8E1, 199);
  
  // put your setup code here, to run once:
  //Serial.begin(9600);
  Wire.begin();

 // Serial.begin(38400);
  //delay(1000); // let serial console settle
for (byte i = 0; i < NBSENSORS; i++)
  {
    tcaselect(i);     // sélectionne le sht qui va bien
    if (sht.init()) {
      //      Serial.print("init(): success\n");
      holdingRegs[3] = 1;
      sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM); // only supported by SHT3x
    }
    else
    {
      //      Serial.print("init(): failed\n");
      holdingRegs[3] = 0;
    }
  }
  
}

void loop() {


 
    tcaselect(0);
 
    
   
    if (sht.readSample()) {
   Humidity = sht.getHumidity();
  // Serial.print(Humidity);
       holdingRegs[0] = (int16_t)(100 * Humidity);
        Temperature = sht.getTemperature();
          holdingRegs[1] = (int16_t)( 100 * Temperature);
  holdingRegs[2] = 1; // indique etat OK
        
    }
    tcaselect(1);
 
    
   
    if (sht.readSample()) {
   Humidity = sht.getHumidity();
   Serial.print(Humidity);
       holdingRegs[3] = (int16_t)(100 * Humidity);
        Temperature = sht.getTemperature();
          holdingRegs[4] = (int16_t)( 100 * Temperature);
  holdingRegs[5] = 1; // indique etat OK
        
    }
  modbus_update();
 
}

void tcaselect(uint8_t i) {
  if (i > 7) return;

  Wire.beginTransmission(TCAADDR);
  Wire.write(1<<i);
  Wire.endTransmission();
}

Si tu n'utilises pas l'enum pour l'accès aux registres il faut aussi que tu initialises manuellement le nombre de registres

const int HOLDING_REGS_SIZE=6;

Bien sur tu le supprimes de l'enum.

Bonjour Kamill effectivement j’ai corriger la faute et ça marche ,

le soucis maintenant c’est que j’ai déclarer 34 registre et quand je dépasse les 28 registre,le Programme QmodbusSlave commence par m’afficher une erreur et inférieur ou egale à 28 ca fonctionne normal

vous en pensez quoi

Merci Pour votre aide .

inf28.PNG

Qmodbus.PNG

Quand tu parles du programme QmodbusSlave, je suppose que tu veux parler de QmodMaster.

Je ne sais pas si le problème vient de la librairie ou de QmodMaster.
En tout cas tu n'es pas obligé de lire tous les registres à la fois. Tu peux lire uniquement les registres qui t'intéressent ou lire les registres en plusieurs fois.

 Note:  
   The Arduino serial ring buffer is 64 bytes or 32 registers.
   Most of the time you will connect the arduino to a master via serial
   using a MAX485 or similar.
 
   In a function 3 request the master will attempt to read from your
   slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
   and two BYTES CRC the master can only request 58 bytes or 29 registers.
 
   In a function 16 request the master will attempt to write to your 
   slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS, 
   NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
   54 bytes or 27 registers.
 
   Using a USB to Serial converter the maximum bytes you can send is 
   limited to its internal buffer which differs between manufactures. 
*/

Bonjour j'ai trouvé ca dans les commentaires du programme , j'ai pas bien compris mais je pense que c'est un probleme de librairie

j'ai pas bien compris quand vous dites que je suis pas obligé de lire tous les registres à la fois

Pr exemple, si tu veux lire le premier sht, tu lis les registres 0 à 2, puis si tu veux lire le deuxième sht tu lis les registres 3 à 5 ...

Bonjour ,j'ai changé le buffer sur la bibliothèque et ca marche .

mais j'ai rencontrer un problème.

void loop() {
  holdingRegs[0]=1;//Numéro de Boitier
//*******************Lecture des registre********************
   BORNIER_1= holdingRegs[1];//lecture de numero de bornier
   BORNIER_2= holdingRegs[5];//lecture de numero de bornier
    BORNIER_3= holdingRegs[9];//lecture de numero de bornier
    BORNIER_5= holdingRegs[17];//lecture de numero de bornier
   BORNIER_6=  holdingRegs[21];//lecture de numero de bornier
    BORNIER_7=  holdingRegs[25];//lecture de numero de bornier
 BORNIER_8=  holdingRegs[29];
 tcaselect(0); 
    if (sht.readSample()) {
       Humidity_1 = sht.getHumidity();
   Temperature_1 = sht.getTemperature();
  
    }
       else
   holdingRegs[4] = 0;
    tcaselect(1);
   
    if (sht.readSample()) {
   Humidity_2 = sht.getHumidity();
        Temperature_2 = sht.getTemperature();        
  }
     else
   holdingRegs[8] = 0;
  tcaselect(2);
 
    if (sht.readSample()) {
   Humidity_3 = sht.getHumidity();
        Temperature_3 = sht.getTemperature();         
    }
       else
   holdingRegs[12] = 0;
      tcaselect(3);
      
    if (sht.readSample()) {
   Humidity_4 = sht.getHumidity();
   Temperature_4 = sht.getTemperature();
             
    }
       else
   holdingRegs[16] = 0;
     tcaselect(4);

    if (sht.readSample()) {
   Humidity_5 = sht.getHumidity();
   Temperature_5 = sht.getTemperature();
      
    }
       else
   holdingRegs[20] = 0;
      tcaselect(5);
  
    if (sht.readSample()) {
   Humidity_6 = sht.getHumidity();
   Temperature_6 = sht.getTemperature();
     
    }
   else
   holdingRegs[24] = 0;
    tcaselect(6);
 
    if (sht.readSample()) {
   Humidity_7 = sht.getHumidity();
   Temperature_7 = sht.getTemperature();
        
    }
    tcaselect(7);
 
    if (sht.readSample()) {
   Humidity_8 = sht.getHumidity();
        Temperature_8 = sht.getTemperature();
        
    }
       else
   holdingRegs[28] = 0;

    //Affectation 
   //*******************************************************************BORNIER_1******************************************  
  if( BORNIER_1=1)
 { holdingRegs[3] =(int16_t)(100 * Humidity_1);       
      holdingRegs[2] = (int16_t)( 100 * Temperature_1);
      holdingRegs[4] = 1; // indique etat OK 
    }
     
   else   if (BORNIER_1=2)
    { holdingRegs[3] =(int16_t)(100 * Humidity_2);       
      holdingRegs[2] = (int16_t)( 100 * Temperature_2);
      holdingRegs[4] = 1; // indique etat OK 
    }
     

      else if (BORNIER_1=3)
    { holdingRegs[3] =(int16_t)(100 * Humidity_3);       
      holdingRegs[2] = (int16_t)( 100 * Temperature_3);
      holdingRegs[4] = 1; // indique etat OK
       }
  
       else if (BORNIER_1=4)
    { holdingRegs[3] =(int16_t)(100 * Humidity_4);       
      holdingRegs[2] = (int16_t)( 100 * Temperature_4);
      holdingRegs[4] = 1; // indique etat OK   
     }
  
     else if (BORNIER_1=5)
    { holdingRegs[3] =(int16_t)(100 * Humidity_5);       
      holdingRegs[2] = (int16_t)( 100 * Temperature_5);
      holdingRegs[4] = 1; // indique etat OK  
    }
  
 else if (BORNIER_1=6)
    { holdingRegs[3] =(int16_t)(100 * Humidity_6);       
      holdingRegs[2] = (int16_t)( 100 * Temperature_6);
      holdingRegs[4] = 1; // indique etat OK 
    }

    else  if (BORNIER_1=7)
    { holdingRegs[3] =(int16_t)(100 * Humidity_7);       
      holdingRegs[2] = (int16_t)( 100 * Temperature_7);
      holdingRegs[4] = 1; // indique etat OK 
    }
   
      else  if (BORNIER_1=8)
    { holdingRegs[3] =(int16_t)(100 * Humidity_8);       
      holdingRegs[2] = (int16_t)( 100 * Temperature_8);
      holdingRegs[4] = 1; // indique etat OK 
    }
      else if (BORNIER_1=0)
{      holdingRegs[3] =0;       
      holdingRegs[2] = 0;
      holdingRegs[4] = 0;
}

quand j'écrie dans le logiciel QMODBUSMASTER ca passe rien je sais pas si y as un problem avec le code

si vous pouvez jetez un œil Merci Kamill

Le test d'égalité c'est == et non =
Changes if(BORNIER_1=1) en if( BORNIER_1==1)
idem pour les autres if

bonjour Kamill j'espere que vous allez bien

si il vous plais si vous pouvez m'aider a simplifier le code car il prend beaucoup de mémoire

if(  BORNIER_1==1)
 { holdingRegs[39] = (int16_t)( 10 * Temperature_1); 
  holdingRegs[40] =(int16_t)(10 * Humidity_1);       
     
      holdingRegs[41] = 1; // indique etat OK 
    }
     
   else if ( BORNIER_1==2)
    {       
      holdingRegs[39] = (int16_t)( 10 * Temperature_2);
      holdingRegs[40] =(int16_t)(10 * Humidity_2); 
      holdingRegs[41] = 1; // indique etat OK 
    }
     

   else    if ( BORNIER_1==3)
    {      
      holdingRegs[39] = (int16_t)( 10 * Temperature_3);
      holdingRegs[40] =(int16_t)(10 * Humidity_3);  
      //holdingRegs[41] = 1; // indique etat OK
       }
  
     else   if ( BORNIER_1==4)
    {    
      holdingRegs[39] = (int16_t)( 10 * Temperature_4);
      holdingRegs[40] =(int16_t)(10 * Humidity_4);    
      //holdingRegs[41] = 1; // indique etat OK   
     }
  
     else if ( BORNIER_1==5)       
    {   holdingRegs[39] = (int16_t)( 10 * Temperature_5);
      
    holdingRegs[40] =(int16_t)(10 * Humidity_5);
      //holdingRegs[4] = 1; // indique etat OK  
    }
  
 else if ( BORNIER_1==6)
    {       
      holdingRegs[39] = (int16_t)( 10 * Temperature_6);
      holdingRegs[40] =(int16_t)(10 * Humidity_6); 
      //holdingRegs[41] = 1; // indique etat OK 
    }

 else     if ( BORNIER_1==7)
    {       
      holdingRegs[39] = (int16_t)( 10 * Temperature_7);
      holdingRegs[40] =(int16_t)(10 * Humidity_7); 
      //holdingRegs[41] = 1; // indique etat OK 
    }
   
   else     if ( BORNIER_1==8)
    {       
      holdingRegs[39] = (int16_t)( 10 * Temperature_8);
      holdingRegs[40] =(int16_t)(10 * Humidity_8); 
      //holdingRegs[41] = 1; // indique etat OK 
    }
    else  if ( BORNIER_1==0)
{      holdingRegs[39] =0;       
      holdingRegs[40] = 0;
      holdingRegs[41] = 0;
}

A quoi sert BORNIER_1?
Je ne comprend pas ce que tu veux faire.