Ciao a tutti
sono un neofita di Arduino con un pò di esperienza informatica/elettronica e dopo vari sketch ben riusciti mi sto cimentando nella supervisione di un dispositivo via MODBUS e dopo un paio di settimane di test (quasi vani) sono qui a chiedere aiuto!
Ho utilizzato la libreria SimpleModbusMaster per leggere da un dispositivo (id 2) ed ho collegato l'integrato MAX485 come da schema.
Utilizzando l'esempio SimpleModbusMaster ho testato il collegamento e funziona, perchè monitorando la variabile regs[4] (richieste con successo) continua ad incrementare, inoltre il led collegato sull'uscita allarme non si accende (cosa che avviene non appena scollego un filo bus o cambio l'indirizzo del dispositivo slave 485).
La cosa che non riesco a capire è come leggere i valori che lo slave mi dovrebbe mandare indietro! è perchè non è implementata nella libreria o non sono riuscito a capire io cosa fare? Purtroppo le mie nozioni informatiche sono molto arrugginite dopo un decennio di inutilizzo...
Grazie per l'aiuto, solo che non ho ben compreso come utilizzare getData()... essendo una funzione dovrebbe restituirmi un unsigned char, giusto?
Per leggere i pacchetti trasmessi, la devo utilizzare nel loop giusto? perchè se provo ad fare un semplice variabile=getData() mi dice:
"error: 'getData' was not declared in this scope"
Immagino debba tornare a studiare ancora un bel pò, dopo 10 anni i miei ricordi sono scarsi
tapirinho:
.. di un dispositivo via MODBUS e dopo un paio di settimane di test (quasi vani) sono qui a chiedere aiuto!
Mi fa piacere leggere che non sono l'unico..
Anche io sto facendo a pugni con il modbus e per ora vince Lui XD e non ai punti...
perchè hai scelto SimpleModbus e non il ModbusMaster?
Io ho tovato che per compilare ModbusMaster bisogna usare la versione :arduino-1.0 il perchè lo ignoro....
Invece dell'IDE 1.0 usate l'1.0.1 corregge alcuni bug presenti nella 1.0
E' probabile che serva la versione 1 invece delle precedenti perché include i file Arduino.h e non il Wprogram.h delle versioni precedenti.
Ma visto che io devo monitorare un dispositivo Modbus, non dovrei usare la libreria Master invece della Slave?
Leggendo più a fondo la libreria, ho visto che funziona così (se sbaglio correggetemi) :
nel loop viene lanciata la funzione modbus_update, la quale inizializza la comunicazione e controlla se va a buon fine
tramite la funzione construct_packet, in base alla funzione richiesta, crea il pacchetto contenente indirizzo, funzione, indirizzo di partenza ecc...
con check_response richiama la funzione check_F3_data (nel caso che mi interessa)
nella funzione check_response memorizza i dati ricevuti in "packet->register_array = (frame[index] << 8 ) | frame[index + 1]; " quindi io nello sketch esempio dovrei trovare in packet1->register_array[ i ] i valori Holding Register dello Slave. Sempre che il mio ragionamento sia corretto... Per Illuca: in realtà li ho provati entrambi, solo che con SimpleModbusMaster ho anche un feedback sul funzionamento della comunicazione, e come spiegavo all'inizio mi ha dato subito esito positivo, per cui ho deciso di partire da questa base... :*
ciao,
Nella mia ricerca per ora vana di capire questo protocollo mi sono inbattuto in: http://www.modbus.pl/node/10
sinceramente per ora io non ho risultati ma forse può essere di aiuto...
Ciao Paolo,
grazie per le letture
modificando opportunamenteil codice Slave che hai suggerito con:
modbus_configure(9500, 1, 2, TOTAL_REGS_SIZE);
per monitorare i dati ho pensato di usare un lcd in questo modo:
#include <SimpleModbusMaster.h>
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 8);
// led to indicate that a communication error is present
#define connection_error_led 13
//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
// If the packets internal retry register matches
// the set retry count then communication is stopped
// on that packet. To re-enable the packet you must
// set the "connection" variable to true.
#define retry_count 10
// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2
// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
PACKET1,
PACKET2,
// leave this last entry
TOTAL_NO_OF_PACKETS
};
// Create an array of Packets for modbus_update()
Packet packets[TOTAL_NO_OF_PACKETS];
// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];
// The data from the PLC will be stored
// in the regs array
unsigned int regs[9];
void setup()
{
lcd.begin(16, 2);
// read 3 registers starting at address 1
packet1->id = 2;
packet1->function = READ_HOLDING_REGISTERS;
packet1->address = 1;
packet1->no_of_registers = 3;
packet1->register_array = regs;
// P.S. the register_array entries above can be different arrays
// Initialize communication settings etc...
modbus_configure(baud, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
pinMode(connection_error_led, OUTPUT);
}
void loop()
{
unsigned int connection_status = modbus_update(packets);
if (connection_status != TOTAL_NO_OF_PACKETS)
{
digitalWrite(connection_error_led, HIGH);
// You could re-enable the connection by:
//packets[connection_status].connection = true;
lcd.print("errore ricezione");
}
else
digitalWrite(connection_error_led, LOW);
lcd.print("Dati ricevuti");
// update the array with the counter data
regs[3] = packet1->requests;
regs[4] = packet1->successful_requests;
regs[5] = packet1->total_errors;
// lcd.setCursor(0, 1);
// vorrei vedere qualche dato:
// lcd.print("qualche dato???");
}
Finalmente ho avuto risultati!
In effetti utilizzando la libreria SimpleModbusMaster sono finalmente riuscito a leggere quelle 3 variabili che mi servono!
X Luca: i risultati li trovi già nell'array regs. Funzionava già da subito, solo che io andavo a leggere gli indirizzi sbagliati!!!
anch'io sto cercando di comunicare in Modbus con un PowerMeter ma non riesco a capire come funziona la classe messa a disposizione.
In pratica io dovrei mandare allo strumento :
Device Addr : 0x01
Function : 0x03
MSB 1 Word Addr : 0x03
LSB 1 Word Addr : 0x25
Words number MSB: 0x00
Words number LSB: 0x04
CRC 16 MSB: 0x55
CRC 16 LSB: 0x86