Due ATMEGA2560 che devono comunicare in ModBus RTU RS485

Salve a tutti.
Questo W.E. Vorrei imparare a far comunicare due ATmega2560 tramite protocollo ModBus RTU con shield RS485, ho letto alcuni post ed alla fine ho decisodi scaricare la seguente libreria:

ma ho alcune domande (ovviamente banali) da porvi:

-) aprendo l'esempio RS485_HalfDuplex il codice mi sembra abbastanza chiaro però cosa vado a caricare nella scheda slave?

Grazie anticipatamente a tutti

Ciao LUCA_ELETTRA,

se devi instaurare una comunicazione in modbus RTU master/slave tra soli arduino forse ti conviene QUESTA libreria che fa entrambe le cose...quella cha hai indicato tu, e che ho usato, fa solo master.

Grazie ORSO2001.
Ho seguito il tuo consiglio ora devo capire come utilizzarla
questa parte di codice mi inizializza la scheda come tuo post imposterei come serial la 3 per lasciare libera la seriale 0 per il pc ma non comprendo come impostare il terzo parametro (uso lo shield RS485)

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus master(0,3,0); // this is master and RS-232 or USB-FTDI

>LUCA_ELETTRA: ... in conformità al REGOLAMENTO, punto 13, il cross-posting è proibito (anche tra lingue diverse), pertanto ... il tuo post duplicato nella sezione "Generale" è stato rimosso e ti pregherei di evitare di porre la stessa domanda in più thread. Grazie.

Guglielmo

:confused:
Scusate non accadrà più :-[

Forse ci sono ........ il terzo parametro identifica il pin per l'abilitazione della trasmissione quando utilizziamo il convertitore RS485 quindi se nel mio caso utilizzo il pin 5 manderà alto questo pin quando trasmette per poi riportarlo basso per impostarsi in ricezione......giusto?

si...dovrebbe essere così.

uhm.....non mi sta funzionando mi aiutereste a trovare l'errore?
questo è il sorgente che ho caricato sulla scheda Master che vorrei che scrivesse au16data sullo slave:

#include <ModbusRtu.h>

// data array for modbus network sharing
//uint16_t au16data[16];
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, 19 };

  
uint8_t u8state;

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus master(0,0,2); // this is master and RS-232 or USB-FTDI

/**
 * This is an structe which contains a query to an slave device
 */
modbus_t telegram;

unsigned long u32wait;

void setup() {
  master.begin( 19200 ); // baud-rate at 19200
  master.setTimeOut( 2000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0; 
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1: 
    telegram.u8id = 1; // slave address
    telegram.u8fct = 6; // function code (write single register)
    telegram.u16RegAdd = 1; // start address in slave
    telegram.u16CoilsNo = 16; // number of elements (coils or registers) to read
    telegram.au16reg = au16data; // pointer to a memory array in the Arduino

    master.query( telegram ); // send query (only once)
    u8state++;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 100; 
    }
    break;
  }
}

mentre questo èil codice che ho caricato sullo slave che momentaneamente mi stampa a video il contenuto dell'array:

#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, 27
};

/**
    Modbus object declaration
    u8id : node id = 0 for master, = 1..247 for slave
    u8serno : serial port (use 0 for Serial)
    u8txenpin : 0 for RS-232 and USB-FTDI
                 or any pin number > 1 for RS-485
*/
Modbus slave(1, 3, 2); // this is slave @1 and RS-232 or USB-FTDI

void setup() {
  slave.begin( 19200 ); // baud-rate at 19200
  Serial.begin(9600);
}

void loop() {
  slave.poll( au16data, 16 );
  Serial.println(au16data[0]);
  Serial.println(au16data[1]);
  Serial.println(au16data[2]);
  Serial.println(au16data[3]);
  Serial.println(au16data[4]);
  Serial.println(au16data[5]);
  Serial.println(au16data[6]);
  Serial.println(au16data[7]);
  Serial.println(au16data[8]);
  Serial.println(au16data[9]);
  Serial.println(au16data[10]);
  Serial.println(au16data[11]);
  Serial.println(au16data[12]);
  Serial.println(au16data[13]);
  Serial.println(au16data[14]);
  Serial.println(au16data[15]);

}

au16data[15] prima di iniziare la trasmissione è impostato a 27 mentre vorrei che il master ci scriva il valore 19 ma quando stampo a videoil valore rimane a 27 .
Mi potete aiutare?
Grazie :slight_smile:

ciao...trovato ...come registro di partenza devi inserire "0" e non 1 altrimenti va fuori "conteggio" e ritorna un errore.
ti suggerisco di non selezionare sa Serial...ma almeno la Serial1
prova e fammi sapere

Ciao Orso.
ho provato a fare le modifiche che mi hai suggerito ma non mi comunica ancora, la serial del master è la zero perché provavo a far girare il codice su una scheda uno anziché sulla MEGA ma non credo sia questo il problema cmq ho provato anche con due MEGA senza risultati in più adesso se provo a caricare lo sketch sul master mi da questo messaggio di errore! :frowning:

avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xe0
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00
Errore durante il caricamento dello sketch

ciao....anch'io ho fatto le prove con una UNO ed un MEGA sia configurate come master/slave che come slave/master...per la UNO ho utilizzato la softwareSerial...in quanto come hai visto se usi la Serial hai problemi a connetterti poi, mi sono dimenticato di scrivere che avevi sbagliato a selezionare la funzione...non è la 6 ma la 16...prova ad usare questi due sketch:
UNO master con siftware serial su PIN 10 e 11 e funzione 16 partendo da registro 0:

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

SoftwareSerial mySerial (10, 11); //RX-TX

// data array for modbus network sharing
//uint16_t au16data[16];
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, 19
};


uint8_t u8state;

/**
    Modbus object declaration
    u8id : node id = 0 for master, = 1..247 for slave
    u8serno : serial port (use 0 for Serial)
    u8txenpin : 0 for RS-232 and USB-FTDI
                 or any pin number > 1 for RS-485
*/
Modbus master(0); // this is master and RS-232 or USB-FTDI

/**
   This is an structe which contains a query to an slave device
*/
modbus_t telegram;

unsigned long u32wait;

void setup() {
  master.begin( &mySerial, 19200 ); // baud-rate at 19200
  master.setTimeOut( 2000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0;
}

void loop() {
  switch ( u8state ) {
    case 0:
      if (millis() > u32wait) u8state++; // wait state
      break;
    case 1:
      telegram.u8id = 1; // slave address
      telegram.u8fct = 16; // function code (write single register)
      telegram.u16RegAdd = 0; // start address in slave
      telegram.u16CoilsNo = 16; // number of elements (coils or registers) to read
      telegram.au16reg = au16data; // pointer to a memory array in the Arduino

      master.query( telegram ); // send query (only once)
      u8state++;
      break;
    case 2:
      master.poll(); // check incoming messages
      if (master.getState() == COM_IDLE) {
        u8state = 0;
        u32wait = millis() + 100;
      }
      break;
  }
}

MEGA slave con Serial1:

#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, 27
};

/**
    Modbus object declaration
    u8id : node id = 0 for master, = 1..247 for slave
    u8serno : serial port (use 0 for Serial)
    u8txenpin : 0 for RS-232 and USB-FTDI
                 or any pin number > 1 for RS-485
*/
Modbus slave(1, 1, 0); // this is slave @1 and RS-232 or USB-FTDI

boolean trasmesso = false;

void setup() {
  slave.begin( 19200 ); // baud-rate at 19200
  Serial.begin(9600);
}

void loop() {
  slave.poll( au16data, 16 );
  if (au16data[15] != 27 && !trasmesso) {
    Serial.println(au16data[0]);
    Serial.println(au16data[1]);
    Serial.println(au16data[2]);
    Serial.println(au16data[3]);
    Serial.println(au16data[4]);
    Serial.println(au16data[5]);
    Serial.println(au16data[6]);
    Serial.println(au16data[7]);
    Serial.println(au16data[8]);
    Serial.println(au16data[9]);
    Serial.println(au16data[10]);
    Serial.println(au16data[11]);
    Serial.println(au16data[12]);
    Serial.println(au16data[13]);
    Serial.println(au16data[14]);
    Serial.println(au16data[15]);
    trasmesso = true;
  }
}

EDIT: tra i due arduino RX e TX vanno incrociati...cioè il TX della UNO va nell'RX della MEGA etc

Ciao
Forse non ho capito bene ma devo incrociare i fili A e B in uscita dagli shield RS485 oppure I tc ex in ingresso? Un’altra domanda i due sketch li posso intercambiare tra loro? Cioè master Atmega e slave la uno?
Ps: hai idea su motivo adesso mi da errore se provo a caricare un qualsiasi sketch?

scusa...mi ero dimenticato che tu usi i MAX485...io ho collegato direttamente i due arduino.

ti da problemo a caricare gli sketch perchè nei tue due sketch precedenti hai impostato la Serial per scrivere a raffica...i canali della Serial sono gli stessi usati per programmare Arduino...per questo ti avevo suggerito di non usarla.
prova ancora altre volte...altrimenti c'è un'operazione chiamate "manovra d'emergenza"...se cerchi dovresti trovare.

EDIT: i due sketch con le giuste modifiche sono intercambiabili....guarda bene le differenza

Ok provo a fare la manovra d’emergenza invece per i collegamenti niente incrocio giusto?

classico cablaggio per MAX485...no incrocio

Scusa orso ma c’è una cosa che non mi torna sulla scheda uno utilizzi una seriale software ma io utilizzando gli shield RS485 come faccio ad abilitare il pin tx enable?

Ciao...si forse sono stato poco chiaro...ero un po' di corsa...dunque se vuoi usare la softwareserial per "uscire/entrare" da/in arduino ed il MAX485 per connettere fisicamente i due arduino devi:
includere libreria SoftwareSerial
crearti l'oggetto SoftwareSerial "mySerial" indicando i pin RX,TX
crearti l'oggetto Modbus "master o slave" indicando (ID, 4, Pin controllo)
nel setup sia per master che per slave invochi begin con (&mySerial, baud)

alla fine avrai una cosa del tipo (esempio semplificato per master/slave...non includo array e comandi vari):

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

SoftwareSerial mySerial (10, 11); //RX-TX 

Modbus master(0,4,3); // pin 3 per abilitazione invio 
Modbus slave(1,4,7); // pin 7 per abilitazione invio

void setup() {
  master.begin( &mySerial, 19200 ); // indico la software serial e baud-rate a 19200
  slave.begin( &mySerial, 19200 ); // indico la software serial e baud-rate a 19200
}

void loop() {

}

EDIT : hai risolto con il "non caricamento" degli sketch?

Ciao Orso solo adesso mi son potuto rimettere sulle mi schede :frowning:
Allora per quanto riguarda la scheda che non mi si riprogrammava son riuscito dopo un bel po di tentativi a fare la procedura d'emergenza; ho provato a fare le modifiche che mi hai scritto ma sembra che ci sia ancora qualcosa che non va...però togliendo gli shield RS485 e caricando questi due sketch funziona tutto!
Adesso dovrei capire perché non mi vada in 485
intanto allego i due sketch anche per chi ne avesse necessità:

MASTER SCHEDA UNO:

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

SoftwareSerial mySerial (10, 11); //RX-TX

// data array for modbus network sharing
//uint16_t au16data[16];
uint16_t au16data[16] = {
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };


uint8_t u8state;

/**
    Modbus object declaration
    u8id : node id = 0 for master, = 1..247 for slave
    u8serno : serial port (use 0 for Serial)
    u8txenpin : 0 for RS-232 and USB-FTDI
                 or any pin number > 1 for RS-485
*/
Modbus master(0); // this is master and RS-232 or USB-FTDI

/**
   This is an structe which contains a query to an slave device
*/
modbus_t telegram;

unsigned long u32wait;

void setup() {
  master.begin( &mySerial, 19200 ); // baud-rate at 19200
  master.setTimeOut( 2000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0;
}

void loop() {
  switch ( u8state ) {
    case 0:
      if (millis() > u32wait) u8state++; // wait state
      break;
    case 1:
      telegram.u8id = 1; // slave address
      telegram.u8fct = 16; // function code (write single register)
      telegram.u16RegAdd = 0; // start address in slave
      telegram.u16CoilsNo = 16; // number of elements (coils or registers) to read
      telegram.au16reg = au16data; // pointer to a memory array in the Arduino

      master.query( telegram ); // send query (only once)
      u8state++;
      break;
    case 2:
      master.poll(); // check incoming messages
      if (master.getState() == COM_IDLE) {
        u8state = 0;
        u32wait = millis() + 100;
      }
      break;
  }
}

SLAVE SCHEDA MEGA:

#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, 27
};

Modbus slave(1, 2, 0); // this is slave @1 and RS-232 or USB-FTDI

boolean trasmesso = false;
unsigned long tempus;
void setup() {
  slave.begin( 19200 ); // baud-rate at 19200
  Serial.begin(9600);
}

void loop() {
  slave.poll( au16data, 16 );
    if (millis() > tempus)
    {
  Serial.println(au16data[0]);
  Serial.println(au16data[1]);
  Serial.println(au16data[2]);
  Serial.println(au16data[3]);
  Serial.println(au16data[4]);
  Serial.println(au16data[5]);
  Serial.println(au16data[6]);
  Serial.println(au16data[7]);
  Serial.println(au16data[8]);
  Serial.println(au16data[9]);
  Serial.println(au16data[10]);
  Serial.println(au16data[11]);
  Serial.println(au16data[12]);
  Serial.println(au16data[13]);
  Serial.println(au16data[14]);
  Serial.println(au16data[15]);
      tempus = millis() + 1000;
    }
}

con gli sketch per la comunicazione RS485 la SLAVE non mi stampa neppure a video :frowning:

guardando più a fondo nella libreria penso di aver trovato una "incompatibilità" tra l'uso della softwareSerial con modulo MAX485...infatti anche a me capitava che si bloccava e non scriveva più i valori dell'array...modificato una riga tornava a ciclare...ma purtroppo non esegue quanto richiesto.
penso che il modulo MAX485 lo puoi abbinare solo ad una delle Serial. mi sa che bisogna o cercare una nuova libreria oppure farne una :smiley:

:o fare una libreria?io???
Grazie per la fiducia ma non credo d'essere ancora all'altezza :frowning:
Allora se lo shield RS485 lo posso abbinare solamente ad una Serialx potrebbe, almeno per il master andare bene la prima libreria che ho postato giusto? quindi dovrei cercare una libreria MODBUS RTU SLAVE compatibile RS485 .... cosi potrebbe funzionare?