Arduino e Modbus

Buongiorno a tutti.
Ho collegato Arduino a un PLC attraverso un convertitore RS-485 -> TTL.
Tutto perfetto perché l'output del PLC su Arduino (quindi sul suo monitor seriale) lo vedo perfettamente.

Ho avuto problemi con l'input su PLC da Arduino, ma probabilmente il problema risiede in qualche riga di ladder nel programma PLC.

Poi ho passato una intera giornata a "erudirmi" sul MODBUS, che il mio PLC supporta senza problemi: tre (3) righe di ladder per metterlo in Slave e, voilà, con un programma trovato in Internet (Modscan32.exe) vedo IN TEMPO REALE gli ingressi, le uscite, le variabili, TUTTO ! E posso pure cambiare qualsiasi variabile al volo.

Quindi vorrei passare la gestione Master su Arduino (che poi è un Wemos perché mi serve il WiFi per mandare i dati su cloud).
Ho guardato i video di Aliverti, ma mi chiedevo se qualcuno ha esperienza di Modbus in modalità Master su Arduino.

Grazie e saluti.

ciao Steve

io un po' c'ho "giocato"...cosa t'interesserebbe sapere di preciso?

Bene, ORSO2001, grazie per la risposta.
Seconda giornata di prove su quacosa che fino a tre giorni fa era SCONOSCIUTO e stavo benissimo così! :slight_smile:

Sto usando un clone FX3u di cui ho piena fiducia e mi ha dato TANTE SODDISFAZIONI.
La porta RS-485 (due semplici morsetti A e B) FUNZIONA.

Su Arduino, grazie ai video di Aliverti, ho realizzato un programma che SCRIVE i relè ausiliari (tipo M) e le variabili (tipo D) SENZA PROBLEMI.
E già sono al settimo cielo perché mi si apre un mondo che io non conoscevo e che adesso conosco.

Ho problemi a leggere.

Il semplice programma di Aliverti su Arduino:

#include <SoftwareSerial.h>
#include <ModbusMaster.h>

SoftwareSerial RS485Serial(10, 11);

#define MAX485_DE_RE   13
ModbusMaster node;

int ret = 0;

void preTransmission () {
  digitalWrite (MAX485_DE_RE, HIGH);
}

void postTransmission () {
  digitalWrite (MAX485_DE_RE, LOW);
}
void setup() {
  pinMode (MAX485_DE_RE, OUTPUT);
  digitalWrite (MAX485_DE_RE, LOW);

  Serial.begin (9600);
  RS485Serial.begin (9600);

  node.begin (1, RS485Serial);
  node.preTransmission (preTransmission);
  node.postTransmission (postTransmission);
}

void loop() {

  ret = node.readDiscreteInputs (0x0, 16);

  if (ret == node.ku8MBSuccess) {
    unsigned int nn = node.getResponseBuffer (0);
    Serial.println  (nn);
  }
  else Serial.println ("Errore");

  delay (10);
}

mi ritorna errore. E questo succede anche se leggo i COILS.

Allora ho cercato QUALE errore con questo programma:

#include <SoftwareSerial.h>
#include <ModbusMaster.h>

SoftwareSerial RS485Serial(10, 11);

#define MAX485_DE_RE   13
ModbusMaster node;

int i = 0;
int ret = 0;
bool M1 = LOW;
bool M100 = HIGH;
bool M1000 = LOW;

void preTransmission () {
  digitalWrite (MAX485_DE_RE, HIGH);
}

void postTransmission () {
  digitalWrite (MAX485_DE_RE, LOW);
}
void setup() {
  pinMode (MAX485_DE_RE, OUTPUT);
  digitalWrite (MAX485_DE_RE, LOW);

  Serial.begin (9600);
  RS485Serial.begin (9600);

  node.begin (1, RS485Serial);
  node.preTransmission (preTransmission);
  node.postTransmission (postTransmission);
}

void loop() {

  ret = node.readCoils (0x0, 8); // read M
  delay (10);
  if (ret == node.ku8MBSuccess) {
    unsigned int nn = node.getResponseBuffer (0);
    Serial.println  (nn);

  }

  if (ret == node.ku8MBIllegalFunction) Serial.println ("IllegalFunction");
  if (ret == node.ku8MBIllegalDataAddress) Serial.println ("IllegalDataAddress");
  if (ret == node.ku8MBIllegalDataValue) Serial.println ("IllegalDataValue");
  if (ret == node.ku8MBSlaveDeviceFailure) Serial.println ("SlaveDeviceFailure");
  if (ret == node.ku8MBInvalidSlaveID) Serial.println ("InvalidSlaveID");
  if (ret == node.ku8MBInvalidFunction) Serial.println ("InvalidFunction");
  if (ret == node.ku8MBResponseTimedOut) Serial.println ("ResponseTimedOut");
  if (ret == node.ku8MBInvalidCRC) Serial.println ("InvalidCRC");

  /*
    ret = node.writeSingleCoil (0x1, M1); // set M1
    M1 = !M1;
    delay (10);

    ret = node.writeSingleCoil (0x64, M100); // set M1
    M100 = !M100;
    delay (10);

    ret = node.writeSingleCoil (0x3e8, M100); // set M1
    M1000 = !M1000;
    delay (10);
  */
}

e la risposta è InvalidSlaveID

Ma la cosa non ha senso perché col pezzo di programma sotto, in SCRITTURA, l’errore non c’è e i coils vengono regolarmente scritti (ho visto che i delay sono molto importanti).

Hai qualche idea?

ciao,

tu stai usando un Wemos...quindi se non sbaglio...su base ESP8266...giusto?...quindi i livelli sono a 3,3V.
e vedo che hai impostato la "pre" e "post" tansmision...quindi utilizzi i classici MAX485.
se è così mi sembra di rivivere le esperienze che ho avuto con le ESP32...non ne andavo fuori tra gestione tempi di trasmissione e ricezione...poi ho preso questo analizzatore e tutto è stato più chiaro.

https://www.amazon.it/AZDelivery-Logic-Analyzer-compatibile-version/dp/B01MUFRHQ2/ref=asc_df_B01MUFRHQ2/?tag=googshopit-21&linkCode=df0&hvadid=279831033017&hvpos=&hvnetw=g&hvrand=17972203918424510352&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=20618&hvtargid=pla-404738525278&psc=1


da qui ho acquistato MAX3485 tipo:

https://www.amazon.it/DollaTek-convertitore-accessori-sostituzione-rimovibile/dp/B08HQMDKGR/ref=sr_1_1?adgrpid=112907733727&dchild=1&gclid=EAIaIQobChMIgfunh_zZ7AIVRviyCh2yfwIhEAAYAiAAEgIENPD_BwE&hvadid=465716269600&hvdev=c&hvlocphy=20618&hvnetw=g&hvqmt=e&hvrand=11965996543094232945&hvtargid=kwd-28510157798&hydadcr=8243_1723000&keywords=max3485&qid=1603980256&sr=8-1&tag=slhyin-21

ed ho risolto tutto!

Fermo la!
Prima di passare al WeMos collaudo tutto su un CLASSICO ARDUINO NANO.
Ne ho già avuti abbastanza di fallimenti e problemi dovuti all’uso di una scheda “diversa” e, quindi, ad eventuali librerie adattate…

Per i convertitori, ti ringrazio per la dritta.
In privato avevo chiesto a Etemenanki (per non “disturbare” il forum) cosa si capiva dal data sheet del MAX485 e cioè se secondo lui le QUESTE schedine potessero lavorare anche a 3,3 Volt… dato che io le ho usate anche su WeMos e FUNZIONANO anche a 3,3 Volt !
Diciamo che il data sheet non è chiarissimo !

Entonces, (quindi)
il cablaggio è OK e leggo/scrivo TRANQUILLAMENTE il mio PLC con MODSCAN32.exe che è un ottimo programmino su Windows e la RS-485 del PLC la mando ad un convertitore USB.

Quando stacco il convertitore USB e il filo del PLC lo mando al convertitore RS-485 → TTL e poi ad Arduino, la scrittura su Modbus funziona perchè accendo/spengo relè e flag e scrivo variabili da 16 bit.
Ma attraverso Arduino non riesco a LEGGERE da PLC.

Mentre se sul PLC non uso MODBUS ma lo metto in FREE COMMUNICATION, leggo tranquillamente su monitor seriale di Arduino tutto quello che trasmetto dal PLC in RS-485 … ma non riesco a scrivere !!!
Cioà mi succede esattamente il contrario. :o

Siccome in FREE COMMUNICATION Arduino non usa librerie se non la SoftwareSerial, do più la colpa al PLC e a qualche variabile che va settata.

Però in MODBUS con Windows funziona tutto quindi, secondo me, è la libreria ModbusMaster.h che ha dei problemi di compatibilità.
Per cui vedrò di provarne un’altra (proprio adesso che l’avevo imparata…)

Tu che libreria Modbus usi ?

ciao

quella eccezione è "sollevata" dalla libreria stessa quando verifica che il primo byte arrivato dallo slave come risposta, che dovrebbe essere appunto l'ID dello slave, non corrisponde con quello della richiesta inviata.
A suo tempo avevo avuto altri problemi usando Arduino ed i moduli MAX485 quando le alimentazioni del master (Arduino) e dello slave (PLC) non coincidevano.
Per ovviare a questo ho usato questa connessione.
costa poco...prova e facci sapere.

Per la libreria ho usato sia quella che usi tu che un'altra (che adesso non ricordo e devo verificare)...però in entrambi i casi la ricezione della risposta è "bloccante" per arduino e questo a me non piace...perchè lo slave può impiegare diverse centinaia di ms per rispondere...o addirittura arrivare al timeout (500ms di base)...se hai diversi slave da connettere questo si moltiplica.
Infatti stavo provando a mettere mano alla libreria che usi tu, per cercare di rendere non bloccante la parte di trasmissione/ricezione...poi sono passato ad usare gli ESP32 ed ho interrotto le modifiche...

V5 MAX485.jpg

V5 MAX485.jpg

Quindi tu sospetti che il problema possa risiedere nella schedina con MAX485, mentre con convertitore USB (anche lui con MAX485) questo problema non appare perchè Modscan.exe non ha problemi a leggere e a scrivere...

Mah, che strano. Comunque faccio la modifica che mi hai suggerito e provo.

ACCIDENTI !!!! FUNZIONA !!!!!

Cioè, si scopre che quelle schedine non sono ben "calibrate" ?????

Vabbè ORSO2001, non so come ringraziarti !!! Accontentati di un KARMA.

Saluti

Arrivate le schedine suggerite da ORSO2001
QUESTE

Però il modbus non funziona più!

La differenza è che in queste schedine mancano i piedini DE e RE che vanno cortocircuitati e poi collegati all'arduino che commuta la schedina in trasmissione o ricezione.

Devo cambiare libreria?

ciao,

come dicevo quelle schedine a me, con ESP32, hanno risolto i problemi.
io all'epoca non avevo usato una libreria per la comunicazione modbus, ho fatto tutto in "hard coding" in quanto ho messo l'ESP32 tra un master ed uno slave (quindi 2 schedine) e "sniffo" il flusso dati.

ieri non sono riuscito; questa sera provo ad utilizzarle con un libreria mdbus (per fare da master) e ti faccio sapere.

Mi è venuto un dubbio: io non metto le resistenze da 150 ohm.... Magari sono quelle!

intendi le terminazioni di linea?...solitamente us 150ohm?..io ho semre visto 120 Ohm per chiudere !?

Vabbè, dai, ci siamo capiti :slight_smile:
Se non le metto potrebbe succedere che non funziona nulla?
Poi quando torno ci provo!

ciao Steve,

provato con QUESTA libreria e va che è una bomba...addirittura senza resistenze di chiusura...ho provato con un ESP32...nell'ESP32 ho impostato un "hardware serial" su due pin liberi...nessuna funzione pre e post transmission (non sono obligatorie).

E’ esattamente quella che uso io. Perfetta libreria

Vabbè, se me la cavo ti informo. Grazie

La resistenza non cambia nulla.
Do per scontato che il TX della scheda vada su RX di Arduino e viceversa, vero?
mah!

ciao

si si...il classico tx->rx e rx->tx.

io ho rimosso i morsetti blu ed ho saldato dei pin al loro posto...ed uso i pin per il collegamento lato slave.

Sta a vedere che adesso devo fare la stessa modifica delle tre resistenze anche su queste schede...

Hai collegato il GND della RS485?

Quale? quello dal lato di A e B ? No, quello è un GND di schermo. Ho collegato la alimentazione (GND e 3,3volt) e TX e RX.