Communication RS485 et arduino

Bonjour tout le monde,

Je viens de débuter dans les Arduino.
Je suis actuellement en train de mettre en place une balance de bétail.

Pour cela j'utilise des pesons : https://www.zemiceurope.com/fr/bm8d.html

Que je connecte avec un transmitter

J'utilise un Arduino méga :

Avec un shield RS485 : https://www.gotronic.fr/art-shield-rs485-pour-arduino-25646.htm

Mon problème est que je n'arrive pas à lire les données reçu par le shield.
J'ai déjà réussi à faire la lecture sans le shield en analogique mais je veux passer sur une lecture digitale.
Pour cela je veux utiliser le protocole modbus mais je n'arrive pas à mettre en place un script qui fonctionne.
Pouvez-vous m'aider ?

Voici le script que j'ai réussi à écrire pour l'instant à partir de l'exemple du la librairie GitHub - smarmengol/Modbus-Master-Slave-for-Arduino: Modbus Master-Slave library for Arduino :

#include <ModbusRtu.h>
#include <SoftwareSerial.h>


uint16_t au16data[16];
uint8_t u8state;


Modbus master(0); 

bus_t telegram;

unsigned long u32wait;

SoftwareSerial mySerial(3, 5);

void setup() {
  Serial.begin(9600);
  master.begin( &mySerial, 9600 ); 
  master.setTimeOut( 2000 ); 
  u32wait = millis() + 1000;
  u8state = 0; 
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; 
    break;
  case 1: 
    telegram.u8id = 1;
    telegram.u8fct = 3; 
    telegram.u16RegAdd = 0;
    telegram.u16CoilsNo = 2;
    telegram.au16reg = au16data;
    master.query( telegram ); 
    u8state++;
    break;
  case 2:
    master.poll(); 
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 2000; 
        Serial.println(au16data[0]);
    }
    break;
  }
}

Le résultat obtenu pour l'instant est une succession de 0.

J'observe bien une communication entre l’Arduino et le shield grace aux leds présentes.

Merci d'avance pour vos réponses.

Pouvez-vous m'aider ?

Ça ne serait pasmodbus_t telegram;à la 6ème ligne ?

Sinon, pourquoi utiliser SoftwareSerial, alros quele Mega a 3 ports série en plus ?
Tu peux faire par exemple :

#define RS485Serial 3

// The object master of the class Modbus is initialized with three parameters.
// The first parametr specifies the address of the Modbus slave device.
// The second parameter specifies type of the interface used for communication between devices - in this sketch - RS485.
// The third parameter can be any number. During the initialization of the object this parameter has no effect.
Modbus master(0, RS485Serial, 0);

Mais je n'ai jamais utilisé ce protocole, donc je ne sais pas si ça fonctionnera... A tester.

salut Rambork
je voie que tu est audacieux pour un débutant !! c'est génial !!
mais je te conseil si tu veux aller vite sur le projet et pour éviter de te "cassé les dents" sur le MODBUS rs 485 d'utiliser le analogique ET e RS485 j'explique :

du peson a l’Arduino tu passe par un CAN ( convertisseur analogique numérique) le module s'appelle ads1115 couts<10 euros ils s'implémente très simplement avec Arduino et tu a une précision de 16 bits!!! aux lieu de 10 avec les CAN de l’Arduino seul.

Ensuite tu peux passer du premier Arduino ( a proximité immédiate du module ADS1115) a un deuxième bien plus loin si tu le souhaite en passent par le fameux RS485.

mais si tu aime le défie ( c est tout a t'on honneur ) continue a poster et fait nous savoir t'est progrès...

pour la comm modbus regarde les autre bibliothèque disponible sur GITHUB ,
verifi t'est paramètre de comm : les bauds 9600, 19200 ....
les pariter... les time-out, délais de inter trame, nombre de bits de stop.
je peu continuer a te conseiller si tu préféré ta voie car moi aussi je me sui retrouver dans le même cas que toi... ( communication avec un IHM industrielle en maitre sur un réseau RS485 MODBUS et 2 esclave Arduino )
j'ai galérer au début...

bon courage a toi !

salut Rambork

désolé de l'erreur la référence du CAN que je parlé plus haut est HX711 et la précision du CAN est de 24bits il est spécialement fait pour les pesons (ou jauge de contrainte ).
Je pense que tu veux passé obligatoirement par le MODBUS RS 485 car en fait tu utilise déjà une carte additionnelle pour lire ta valeurs genre :"Type T2 weight transmitter" de la même marque est comme elle possède un ports rs485....
je connait pas ton niveau dans l'automatisme industrielle n'y dans l’électricité tout cour .... mais groso-modo il faudrait donc trouvé une table de dialogue de ton afficheur dans la doc constructeur genre :
40001 = valeur 1 (ex valeur de lecture de la masse)
40002 =valeur 2 (ex code d'erreur)
40003.....
chaque valeur donne une adresse ( 40001) sur le réseau MODBUS donc si tu lit la bonne adresse avec ton Arduino BINGO tu trouvera la valeur courante de ton peson.
RESTE PLUS que a savoir quelle valeur lire .... le constructeur doit donne genre une fourchette de 20 /30 mots entre généralement 40000et 49999 .dans les 20/30 mots sont représenter des valeur de paramétrage/des code d'erreur.... ET ta valeur de lecture de la masse !

clemeP

Merci tout le monde pour vos réponses.

Comme Lesept me conseillait, je n'utilise plus SoftwareSerial.

J'ai trouvé ce qui n'allait pas dans mon code initial, c'était le message de j'envoyais au slave qui n'était pas bon. J'ai enfin compris plus précisément comment le protocole d'échange fonctionne et j'ai corrigé mon erreur.

Je te remercie clemeP car c'est grâce à toi que j'ai compris la manière d'échanger entre le maitre et l'esclave.

Mon code actuel est fonctionnel et ressemble à cela :

#include <ModbusRtu.h>

uint16_t au16data[16];
uint8_t u8state;


#define RS485Serial 0
Modbus master(0,RS485Serial,1);


modbus_t telegramL;
modbus_t telegramH;

int wL = 0;
int wH = 0;

unsigned long u32wait;

void setup() {
  master.begin( 9600 ); // baud-rate at 19200
  master.setTimeOut( 2000 );
  u32wait = millis() + 1000;
  u8state = 0; 
}

void loop() {

  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; 
    break;
  case 1: 
    telegramL.u8id = 1; // slave address
    telegramL.u8fct = 3; // function code (this one is registers read)
    telegramL.u16RegAdd = 6; // start address in slave
    telegramL.u16CoilsNo = 8; // number of elements (coils or registers) to read
    telegramL.au16reg = au16data; // pointer to a memory array in the Arduino

    master.query( telegramL );
    u8state++;
    break;
    
  case 2:
    master.poll(); 
    if (master.getState() == COM_IDLE) {
      u8state=0;
      u32wait = millis() + 500; 
      Serial.println();
      for(int i=0;i<telegramL.u16CoilsNo;i++){
        wL = au16data[i];
        Serial.print(i);
        Serial.print(": ");
        Serial.println(wL);
      }
    }
    break;
  }

  
}

J’obtiens comme réponse :

0: 1024  // Status register
1: 0       // Gross Weight H
2: 3393  // Gross Weight L
3: 0       // Net Weight H
4: 3323  // Net Weight L
5: 0       // Peak Weight H
6: 0       // Peak Weight L
7: 12      // Divisions of measure

Par contre j'ai un symbole qui se place dans le moniteur à chaque échange entre le maitre est le slave.
C'est un petit carré, savez-vous ce que c'est ou comment l'enlever ? (Capture d'écran en attachment).

Encore merci pour vos messages.

Rambork

Bonsoir à tous, Je m'appelle Bah Boubacar

En fait, je suis nouveau dans l'utilisation d'Arduino. Je voudrais que vous m'aidiez à faire un code pour un protocole de communication modbus RS485 pour Arduino.

Merci d'avance.

Là en commençant par casser le fil d'un autre tu es bien parti pour ne jamais avoir de réponse.
C'est d'une grande impolitesse.

Commence par lire les messages épinglés, leurs titres est assez explicite pour voir de quoi ils traitent.
Suis le tuto qu'on recommande : Eskimon
Propose un début de réalisation : ici ce n'est pas un libre service : on aide quand le demandeur bloque mais on ne fait pas son projet à sa place.