Visualizzazione post con etichetta RS485. Mostra tutti i post
Visualizzazione post con etichetta RS485. Mostra tutti i post

mercoledì 28 luglio 2021

ESP32 esperienze con ModBus

 Nell'era di Industria 4.0 tutte le aziende stanno effettuando la conversione dei propri sistemi verso i nuovi metodi di  gestione dei dati. Oggi i nuovi macchinari sono tutti "intelligenti", cioè sono in grado di trasmettere il proprio stato e lo stato delle lavorazioni, verso dashboard di controllo sempre più avanzate, che rendono la gestione del tempo e delle lavorazioni sempre più efficacie e consentono anche la manutenzione preventiva, per evitare i malfunzionamenti ed eventuali onerosi blocchi macchina.


Anche i macchinari più anziani, però, possono essere resi Smart, con l'ausilio di sensori e metodi di trasmissione dei dati sempre più piccoli e facilmente integrabili.

In questi giorni sto aiutando un amico proprio in un progetto di questo tipo, cioè la conversione di un macchinario al quale è stato già integrato un sistema di trasmissione dei dati su modulo ModBus seriale RS485. Il sistema attualmente trasmette i dati via cavo seriale RS485, l'intenzione è quella di convertire il sistema per poter trasmettere via WiFi gli stessi dati.


La scelta naturalmente è stata quella di utilizzare i moduli ESP32, che sono economici e molto facili da utilizzare, veloci e sicuri.

Riporto qui a fianco lo schema della GPIO del modulo che ho utilizzato per fare i test. Ho scelto il modello Mini ESP32 in quanto per questo progetto non ci sono particolari necessità di piedinatura, ed il fattore forma, per semplificare la possibilità di integrazione è una delle variabili più importanti.

Per prima cosa, ho caricato sul mio ESP32 il Micropython, come descritto in questa veloce guida ed anche in questo post qui

Successivamente, come spiegato qui, ho collegato il modulo attraverso RSHELL che per lavorare con Micropython è lo strumento più utile in assoluto.

. Sempre attraverso RSHELL ho caricato la libreria che gestirà la comunicazione con il device già inserito nella apparecchiatura, la libreria uModBus che è molto essenziale e gestisce in modo corretto la conversione dei pacchetti con i device in modalità RTU.


Per fare i primi test ho caricato la libreria direttamente dentro la flash del ESP32, anche se la maniera migliore per lavorare con librerie specifiche sarebbe quella di compilare il Micropython direttamente con le librerie che servono, attraverso l'SDK che Espressif mette a disposizione. Lo farò sicuramente finiti i primi test.

A questo punto, per poter controllare il funzionamento o meno del sistema appena montato ho bisogno di un device slave che risponda a chiamate ModBus. Problema!. In casa non ho nulla di questo genere! Ho scoperto però, che esiste un programma linux che consente di simulare il comportamento di un device slave ModBus, proprio per poter testare sistemi come il mio..... Ottimo!

Diagslave funziona in diverse modalità, a me interessa che risponda a chiamate RTU seriali, quindi , caricato su una Raspberry Pi sulla quale sta girando un Debian appena aggiornato all'utlima versione, faccio partire il programma con :

arm-linux-gnueabihf/diagslave -a 1 -m rtu -b 4800 -d 8 -s 1 -p none /dev/ttyAMA0

chiamando l'help si ha la spiegazione di ogni parametro utilizzabile, per la mia configurazione io chiamo il nuovo device 1 con -a 1 (a = address), scelgo il modo RTU con -m rtu, scelgo la velocità di comunicazione con -b 4800 -d 8 -s 1 -p none   e scelgo la seriale sul quale inviare la comunicazione  /dev/ttyAMA0

che corrisponde ai pin UART0 della Raspberry Pi

Pin 8 e 10 come da schema GPIO qui a fianco riportato.

Infatti, proprio sui Pin 8 e 10 , rispettivamente TX e RX della seriale interna UART0 di Raspberry Pi mi sono collegato con i cavetti provenienti dall'ESP32. Sul ESP32 ho indirizzato la seriale sui Pin 12 e 4 (sono Pin non utilizzati da nessun servizio interno e sui quali avevo gia' saldato di Pin rigidi, quindi ho scelto questi per comodità, ma possono essere scelti due Pin qualsiasi, ovviamente liberi da altri servizi).

A questo punto, facendo una richiesta ModBus da ESP32 il programma che gira su Raspberry Pi e che è in ascolto sulla seriale ttyAMA0, dovrebbe rispondere regolarmente.

Per effettuare le richieste dal lato ESP32 ho creato queste  poche righe di codice Micropython:

from uModBusSerial import uModBusSerial as Seriale

seriale = Seriale(uart_id = 2, baudrate = 4800, data_bits=8, stop_bits=1, parity= None, pins=(12,4), ctrl_pin=None) # inizializzo la seriale e creo l'oggetto

seriale.write_single_register(1, 100, 111, True)    #Scrive un singolo registro  sullo Slave 1 nel registro 100 scrive il valore 111

seriale.read_input_registers(1, 100, 3, signed=True) #Legge 3 registri a partire dal 100 

seriale.read_discrete_inputs(1, 99, 3)[0:3] #Legge 3 registri a partire dal 99


Il codice sopra ovviamente è solo per testare la comunicazione e fa queste cose:

from uModBusSerial import uModBusSerial as Seriale

Carica la libreria, 

seriale = Seriale(uart_id = 2, baudrate = 4800, data_bits=8, stop_bits=1, parity= None, pins=(12,4), ctrl_pin=None)

crea l'oggetto "seriale " ,passando i parametri per la configurazione della seriale sui PIN scelti in fase di cablaggio.

seriale.write_single_register(1, 100, 111, True)

Crea una chiamata di scrittura  con seriale.write_single_register(device_ID, REGISTRO, VALORE, segno)

device_ID = il numero identificativo del device ( in una rete ModBus su seriale RS485 possono coesistere fino a 255 device, che avranno ID diversi in funzione della loro collocazione fisica (1, 2 3,......, 255) 

REGISTRO E VALORE sono parametri intuitivi

segno se settato = a True, mantiene il segno scritto nel registro, se settato a False, rende il valore del registro senza tenere conto del segno eventuale (elimina il segno meno davanti al valore del registro se esiste)

seriale.read_input_registers(1, 100, 3, signed=True)

Crea una chiamata di lettura di uno specifico registro (in questo caso il 100, quello su cui, alla riga precedente, avevo scritto il valore 111) il valore 3 indica al sistema di leggere 3 registri consecutivi, che nel nostro caso varranno 111 (l'unico valore che ho programmato alla riga precedente), 0, 0 (naturalmente i valori dei registri 101 e 102 saranno 0 in quanto non sono ancora stati scritti.

seriale.read_discrete_inputs(1, 99, 3)[0:3] 

Questo è un metodo di lettura alternativo, che consente di leggere il contenuto di uno o più  registri di un determinato device. Questo metodo ha bisogno della specifica dell'intervallo di lettura tra parentesi quadre, come riportato nel comando sopra.

Qui sotto il video dove e' possibile vedere le due finestre di terminale affiancate, una corrisponde al sistema Diagslave (quella in alto a DX) l'altra finestra, corrisponde alle chiamate effettuate dal modulo ESP32 utilizzato come Master in questa configurazione.



Buon Lavoro a tutti
TecnoGeppetto

venerdì 8 luglio 2016

RS485 + FTDI232 + Arduino test di linea

Per un nuovo progetto  in questi giorni ho dovuto testare il funzionamento di una connessione RS485 attraverso un cavo lungo più di 100 metri.

Se cercate un po' in giro ci sono tanti tutorial sul funzionamento di questo metodo di trasmissione. Anche io non ho fatto altro che leggere qualche tutorial in giro e poi costruire il semplice circuito composto da 2 moduli RS485 che si parleranno a distanza attraverso il cavo.

La teoria dice che circuiti come quello riportato nello schema qui sotto possono raggiungere i 1200 metri senza problemi di decadimento della comunicazione, ma considerato che il progetto e' particolarmente importante in termini di sicurezza, e' stato fondamentale per me poter mettere sotto stress la comunicazione per poter controllare il regolare funzionamento anche sulla tratta di circa 100 metri di cui ho necessità.


Come si può vedere nello schema sia in testa che in fondo al cavo sono previsti dei carichi, che nel nostro caso sono già inseriti nel modulo che ho scelto per questo progetto.
Infatti nel modulino della LC Electronics di cui riporrto lo schema qui a fianco, ci sono già tutte le resistenze che servono per il corretto funzionamento del circuito.
Durante i test ho anche potuto sperimentare che il modulo e' anche molto sensibile alle sovratensioni, infatti prolungati periodi di sovra alimentazione anche di solo 1 volt in piu' hanno provocato la rottura del Max232 che e' l'integrato contenuto nel circuito del modulo.










Dopo aver fatto i primi test collegando un adattatore seriale USB-TTL come interfaccia tra il pc ed il modulo RS485, utilizzando un FTDI232, poi ho scelto di costruire un sistema basato su Arduino che si preoccupi di mantenere sempre viva la comunicazione e che segnali eventuali anomalie, nel caso la comunicazione non andasse a buon fine.

Il circuito e' molto semplice, dal FTDI232 prendiamo la alimentazione per il modulo collegando VCC e GND , nel caso del MASTER i due PIN  DE  ed RE devono essere collegati anch'essi a GND, mentre DI ed RO  rispettivamente a TX  ed RX della seriale.
DI -- TX   ed    RO -- RX

Per il modulo scelto per essere SLAVE (quello che trasmette l'informazione) si dovra' solamente collegare i PIN  DE ed RE a Vcc anziche' a GND

DE+RE --- GND (master), in questo modo abbiamo ottenuto un circuito che consente di trasmettere solamente in un verso l'informazione ( da Master a Slave ) che vengono definiti appunto scegliendo di mettere allo stato BASSO  DE ed RE  per il Master ed allo stato ALTO per lo Slave.
Per le prime prove va bene, ovviamente, ma per poter testare meglio in tutti e due i "sensi di marcia", per non fare lo switch degli stati a mano, ho preferito montare un circuito basato su Arduino.

Ho quindi montato il circuito che dal lato master invia un messaggio contenente un carattere (1), poi si mette in ascolto,  se riceve un carattere stabilito come ACK (7) fa lampeggiare il suo LED collegato al PIN13, altrimente ripete l'invio del messaggio.

Dal lato Slave, il modulo sta sempre in ascolto, quando riceve un messaggio stabilito (1) si mette in trasmissione, mandando un segnale convenzionale (7) per confermare l'avvenuta ricezione, e poi torna subito in ricezione per attendere il nuovo messaggio.

Prendendo l'alimentazione dei moduli RS485 direttamente da Arduino, ho lasciato fare lo switch degli stati al PIN 3  ed ho utilizzato questi due programmini per gestire la comunicazione:

**************************************

// software per lo SLAVE



void setup() {
  Serial.begin(57600);
  pinMode(3, OUTPUT);
  pinMode(13, OUTPUT);
  digitalWrite(3,LOW);
  digitalWrite(13,LOW);
}

void loop() {
 while (Serial.available()) {
    digitalWrite(3,LOW);
    delay(1);
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '1') {
           
     // fai quello che devi fare
    digitalWrite(3,HIGH);
    delay(10);
    Serial.print(7);
    delay(1);
    digitalWrite(3,LOW);
 
   
    }else{
   
        // fai quello che devi fare se non e' arrivato il carattere giusto
    for(int i=1 ; i=10 ; i++){
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,LOW);
    delay(100);
    }
    }
  }

}

 ***********************************************************


// software per lo MASTER



void setup() {
  Serial.begin(57600);
  pinMode(3, OUTPUT);
  pinMode(13, OUTPUT);
  digitalWrite(3,HIGH);
  digitalWrite(13,LOW);
}

void loop() {
 // while (Serial.available()) {
 
    digitalWrite(3,HIGH);
    delay(10);
    Serial.println(1);
    delay(1);
 
      digitalWrite(3,LOW);
      delay(1);
      char c = Serial.read();  //gets one byte from serial buffer
      if (c == '7') {

        // fai quello che devi fare
   // Serial.print("sentito il ACK");
      lampeggia();
   

 
      }
   
    }

  }
void lampeggia(){
  for(int i=1 ; i<3 i="" p="">    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,LOW);
    delay(100);
  }
}