Transmission Trame RS485

Bonjour à tous,

je souhaite faire exécuter une trame MODBUS RTU, je rencontre des difficulté de mise en oeuvre,
j'ai tenté d'utiliser la bibliothèque ModbusMAster mais je n'arrive pas à exécuter l'envoie d'une trame.

j'ai utiliser une Arduino MEGA2560 en Master

un module RS485 il est cablé :

RO-> 1 TX0
DI-> 0 RX0
DE RE > 2

J'ai donc tenté d'utiliser les exemples de la bibliothèque mais je n'arrive pas à construire la trame.

voici la trame à transmettre :

0B 0F 02 11 00 01 01 01 92 C9

0B est l’adresse de l’esclave.
0F est la fonction utilisée. Écrivez plusieurs bobines.
02 11 est l’adresse de la première coil à écrire.
00 01 est le nombre de coil à écrire. 1 dans ce cas.
01 est le nombre d’octets de données envoyées.
01 est l’ensemble de valeur.
92 C9 est le CRC.

J'ai donc calé ma vitesse à 9600 Baud puisque c'est ce qui est déterminé.

si il y a de l'aide pour des explications voir un exemple sur cette première trame.

En vous remerciant tous par avance

bonjour

quel est le code que vous avez essayé ? le poster en utilisant les balises. merci

J'ai fait un test avec la version d'exemple Basic de la bibliothèque.

Mais rien de concret.

Oui, super mais nous on a peut-être pas installé cette librairie et donc on a pas l'exemple dont tu parles.
Donc poste le code que tu testes.

#include <ModbusMaster.h>


// instantiate ModbusMaster object
ModbusMaster node;


void setup()
{
  // use Serial (port 0); initialize Modbus communication baud rate
  Serial.begin(19200);

  // communicate with Modbus slave ID 2 over Serial (port 0)
  node.begin(2, Serial);
}


void loop()
{
  static uint32_t i;
  uint8_t j, result;
  uint16_t data[6];
  
  i++;
  
  // set word 0 of TX buffer to least-significant word of counter (bits 15..0)
  node.setTransmitBuffer(0, lowWord(i));
  
  // set word 1 of TX buffer to most-significant word of counter (bits 31..16)
  node.setTransmitBuffer(1, highWord(i));
  
  // slave: write TX buffer to (2) 16-bit registers starting at register 0
  result = node.writeMultipleRegisters(0, 2);
  
  // slave: read (6) 16-bit registers starting at register 2 to RX buffer
  result = node.readHoldingRegisters(2, 6);
  
  // do something with data if read is successful
  if (result == node.ku8MBSuccess)
  {
    for (j = 0; j < 6; j++)
    {
      data[j] = node.getResponseBuffer(j);
    }
  }
}

Voici le code d'exemple

Et que se passe-t-il?
Le programme plante?
Est-ce que quelque chose passe sur la ligne?

et bien justement il ne se passe absolument rien, le programme tourne aucune réception, et le moniteur série retourne des symboles rien de plus.

Ce que tu vois dans le moniteur série correspond aux caractères envoyés vers la carte Modbus donc quelque chose doit "partir".
Est-ce que DE/RE est bien piloté?

et bien en tout cas rien n'est reçu,

justement je ne sais pas car le moniteur série n'a aucune info cohérente et le slave n'a pas le voyant de trame en communication en cours !

c'est pas bien clair tout ça .

Bonjour,

Comme ta transmission se fait en binaire et non en ascii, tu ne vas rien voir de cohérent sur le moiteur série.
C'est qui ton slave?

Bonjour,

Ok c'est ce qui me semble le cas, mon slave est une vanne.

La trame que j'ai mise doit lancer un cycle prédéfini, mais dans se code d'exemple il n'y a pas d'explication.

Comment donner les bonnes valeurs de bits dans la trame.

Je n'arrive pas a comprendre la méthodologie.

pas d'idées ?

Bonjour,

j'ai refais des essais, et sur ses test j'ai bien le signal au carré sur ma sortie TX0 qui entre en DI

la trame s'affiche sur le moniteur série mais aucune information du slave !

pas d'info du signal pourtant a l'osciloscope j'ai bien la trame sur la borne A du slave.

je vous joint la doc de la vanne ainsi que le shield RS485 si cela peut aider.

merci

#include <SoftwareSerial.h>
// assemble message
byte msgpertama [] = {
    0x0B,    // slave address
    0x0F,    // function code
    0x02,    // data address coil
    0x11,    // data address coil
    0x00,    // status to write
    0x01,    // status to write
    0x01,    // status to write
    0x92,    // CRC
    0xC9,    // CRC
};

byte msgkedua [] = {
    0x0B,    // slave address
    0x0F,    // function code
    0x02,    // data address coil
    0x11,    // data address coil
    0x01,    // status to write
    0x01,    // status to write
    0x92,    // CRC
    0xC9,    // CRC
};


#define pushpertama 4              // define first pushbutton to commandOFF
#define pushkedua 5                // define second pushbutton to commandON
#define TX_ENABLE_PIN 9            // define the EIA-485 transmit driver pin ( RE + DE pin's modules)
SoftwareSerial rs485(0, 1); // SoftwareSerial rs485(RX-RO, TX-DI); pins name on the module

void setup()
{                                  // klasifikasi variabel
  pinMode(TX_ENABLE_PIN, OUTPUT);
  pinMode(pushpertama,INPUT_PULLUP);  
  pinMode(pushkedua, INPUT_PULLUP);     
  rs485.begin (9600);              // vitesse com  
  Serial.begin(9600);
}

void loop()
{
if(digitalRead(pushpertama)== HIGH)
 {
  digitalWrite (TX_ENABLE_PIN, HIGH);       // enable transmit driver
 
    for (int i = 0; i < 9; i++)
    {
        Serial.print(msgpertama[i], HEX);   // console print the data
        rs485.write(msgpertama[i]);         // flip display print
        if (i < 8)
        {
            Serial.print(", ");             // print a comma between data
        }
    }
    Serial.println();
    delay(6);
    digitalWrite(TX_ENABLE_PIN, LOW);       // disable transmit driver
    delay(500);
 }

if(digitalRead(pushkedua)== HIGH)
 {
  digitalWrite (TX_ENABLE_PIN, HIGH);       // enable transmit driver
 
    for (int j = 0; j < 8; j++)
    {
        Serial.print(msgkedua[j], HEX);     // console print the data
        rs485.write(msgkedua[j]);           // flip display print
        if (j < 7)
        {
            Serial.print(", ");             // print a comma between data
        }
    }
    Serial.println();
     delay(6);
    digitalWrite(TX_ENABLE_PIN, LOW);       // disable transmit driver
    delay(500);
 }
rs485.read(); 
}

AMPV_Modbus_Manual_en_2.1.pdf (580 KB)

Tu es certain de tes trames?
Dans la doc en pièce jointe, les trames ont 10 octets pas 9.

Transmit Message : 0B 0F 02 11 00 01 01 01 92 C9

Je viens de corriger effectivement !!! Mais ça ne change pas le problème pour autant !

Merci.

Voici le code corrigé et le moniteur série

#include <SoftwareSerial.h>
// assemble message
byte msgpertama [] = {
    0x0B,    // slave address
    0x0F,    // function code
    0x02,    // data address coil
    0x11,    // data address coil
    0x00,    // is the number of coils to be written. 
    0x01,    // is the number of coils to be written. 1 in this case
    0x01,    // is the number of bytes of data sent
    0x01,    // is the value set
    0x92,    // CRC
    0xC9,    // CRC
};

byte msgkedua [] = {
    0x0B,    // slave address
    0x0F,    // function code
    0x02,    // data address coil
    0x11,    // data address coil
    0x01,    // status to write
    0x01,    // status to write
    0x92,    // CRC
    0xC9,    // CRC
};


#define pushpertama 4              // define first pushbutton to commandOFF
#define pushkedua 5                // define second pushbutton to commandON
#define TX_ENABLE_PIN 2            // define the EIA-485 transmit driver pin ( RE + DE pin's modules)
SoftwareSerial rs485(0, 1); // SoftwareSerial rs485(RX-RO, TX-DI); pins name on the module

void setup()
{                                  // klasifikasi variabel
  pinMode(TX_ENABLE_PIN, OUTPUT);
  pinMode(pushpertama,INPUT_PULLUP);  
  pinMode(pushkedua, INPUT_PULLUP);     
  rs485.begin (9600);              // vitesse com  
  Serial.begin(9600);
}

void loop()
{
if(digitalRead(pushpertama)== HIGH)
 {
  digitalWrite (TX_ENABLE_PIN, HIGH);       // enable transmit driver
 
    for (int i = 0; i < 10; i++)
    {
        Serial.print(msgpertama[i], HEX);   // console print the data
        rs485.write(msgpertama[i]);         // flip display print
        if (i < 9)
        {
            Serial.print(", ");             // print a comma between data
        }
    }
    Serial.println();
    delay(6);
    digitalWrite(TX_ENABLE_PIN, LOW);       // disable transmit driver
    delay(5000);
 }

if(digitalRead(pushkedua)== HIGH)
 {
  digitalWrite (TX_ENABLE_PIN, HIGH);       // enable transmit driver
 
    for (int j = 0; j < 8; j++)
    {
        Serial.print(msgkedua[j], HEX);     // console print the data
        rs485.write(msgkedua[j]);           // flip display print
        if (j < 7)
        {
            Serial.print(", ");             // print a comma between data
        }
    }
    Serial.println();
     delay(6);
    digitalWrite(TX_ENABLE_PIN, LOW);       // disable transmit driver
    delay(5000);
 }
rs485.read(); 
}

Moniteur serie.JPG

Pas certain que cette portion de code soit bonne.

    Serial.println();
    delay(6);
    digitalWrite(TX_ENABLE_PIN, LOW);       // disable transmit driver

Il y a 9 caractères ( ou 8 ) dans le buffer d'émission.
A 9600 bauds, il faut 1ms pour émettre un caractère. Si delay() est trop court, la trame sera coupée avant d'avoir été transmise.
Pour confirmer cela, il faudrait passer delay() à 10ms pour être certain que toute la trame a bien été envoyée.

Autre chose, tes 2 trames sont différentes et le CRC est identique cela me semble assez surprenant.

Alors en fait je ne me sert que de le première trame j'ai mis un seul BP pour envoyer la trame la deuxième n'est pas utilisé.

je viens de passer le délai a 10 ms mais ça na rien changé.