Pages: [1]   Go Down
Author Topic: Problemi comunicazione MODBUS [RISOLTO]  (Read 3020 times)
0 Members and 1 Guest are viewing this topic.
Conegliano
Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

http://simple-modbus.googlecode.com/files/SimpleModbusV4.1.zip

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 già da ora a tutti!!!
« Last Edit: January 06, 2013, 09:11:20 am by tapirinho » Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 110
Posts: 6974
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dentro la libreria trovi le varie funzioni che si occupano della trasmissione ad esempio getData(); e sendPacket(unsigned char bufferSize);
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Conegliano
Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Scusa il ritardo, ero via per alcuni giorni...

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  smiley-red
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 110
Posts: 6974
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Da link da te indicato ho trovato un esempio
Code:
#include <SimpleModbusSlave.h>
#define  CE_Pin   8          // Chip Enable
#define  baudrate 57600
byte ID = 1;

//////////////// registers of your slave ///////////////////
enum
{     
  // ---- Addres Reg. 0 Lecturas de Valores 
  I,     
  V,       
  E,
  RAD,
  TEMP,
  PvGiro,
  PvEleva,
  VelGiro,
  VelEleva,
  AL1,
  AL2,
 
  // ---- Addres Reg. 11 Escrituras. Parametrso
  MaxGiroPot,
  LGi,
  LGiC,
  CalibraGiEl,
  LElMaMe,
  LElCMaMe,
  VelGiElminAl,
  ZmGiEl,
  T1,
  T2,
  TEWeb_AngPosSeg,
 
  // ---- Addres Reg. 22 Escrituras. Posicion y Ordenes
  SV_Giro,
  SV_Eleva,
  FLOrdenes,
 
  // ---- Addres Reg. 25 Escrituras. Fecha y Hora
  Ano,
  MesDia,
  HoraMin,
 
  TOTAL_ERRORS,
 
  // leave this one
  TOTAL_REGS_SIZE
 
};

unsigned int holdingRegs[TOTAL_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////

void setup()
{
  // parameters(long baudrate, unsigned char ID, unsigned char transmit enable pin, unsigned int holding registers size)
  modbus_configure(115200, ID, CE_Pin, TOTAL_REGS_SIZE);  //No es necesario definir CE_Pin como OutPut, lo hace la libreria   
}


void loop()
{
  // modbus_update() is the only method used in loop(). It returns the total error
  // count since the slave started. You don't have to use it but it's useful
  // for fault finding by the modbus master.
 
  holdingRegs[I] = millis() / 1000;     
  holdingRegs[V] = 2;       
  holdingRegs[E] = 3;
  holdingRegs[RAD] = 4;
  holdingRegs[TEMP] = 5;
  holdingRegs[PvGiro] = 6;
  holdingRegs[PvEleva] = 7;
  holdingRegs[VelGiro] = 8;
  holdingRegs[VelEleva] = 9;
  holdingRegs[AL1] = 10;
  holdingRegs[AL2] = 11;
 
  //------------//
  holdingRegs[MaxGiroPot] = 12;
  holdingRegs[LGi] = 13;
  holdingRegs[LGiC] = 14;
  holdingRegs[CalibraGiEl] = 15;
  holdingRegs[LElMaMe] = 16;
  holdingRegs[LElCMaMe] = 17;
  holdingRegs[VelGiElminAl] = 18;
  holdingRegs[ZmGiEl] = 19;
  holdingRegs[T1] = 20;
  holdingRegs[T2] = 21;
  holdingRegs[TEWeb_AngPosSeg] = 22;
 
  //------------//
  holdingRegs[SV_Giro] = 23;
  holdingRegs[SV_Eleva] = 24;
  holdingRegs[FLOrdenes] = 25;
 
  //------------//
  holdingRegs[Ano] = 26;
  holdingRegs[MesDia] = 27;
  holdingRegs[HoraMin] = 28;
 
  holdingRegs[TOTAL_ERRORS] = modbus_update(holdingRegs);
 
  for (byte i = 0; i < 29; i++)
   {
      Serial.print (holdingRegs[i]);
      Serial.print ("/");
    }
  Serial.println (TOTAL_REGS_SIZE);
  delay(1000);
}

forse ti potrebbe chiarire meglio come funziona la libreria.
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Offline Offline
Full Member
***
Karma: 1
Posts: 169
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

.. 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    smiley-lol 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....


  smiley-confuse mal comune mezzo Sketch

Luca
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 110
Posts: 6974
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Conegliano
Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...   smiley-kiss
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 169
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ciao,
Nella mia ricerca per ora vana di capire questo protocollo mi sono inbattuto in:
http://www.modbus.pl/node/10
sinceramente   smiley-red per ora io non ho risultati ma forse può essere di aiuto...

Luca
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 110
Posts: 6974
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Se proprio te lo vuoi studiare --> http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf

e questo --> http://www.modbus.org/docs/Modbus_over_serial_line_V1_02.pdf
« Last Edit: November 16, 2012, 05:50:19 pm by PaoloP » Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Offline Offline
Full Member
***
Karma: 1
Posts: 169
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao Paolo,
grazie per le letture
modificando opportunamenteil codice Slave che hai suggerito  con:
Code:
modbus_configure(9500, 1, 2, TOTAL_REGS_SIZE);

per monitorare i dati ho pensato di usare un lcd in questo modo:

Code:
#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???");
}

indovina cosa mi apapre sull' lcd ???

Quote
  errore ricezione

hai idea quale sia l' errore?

Luca
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 110
Posts: 6974
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hai messo 9500 al posto di 9600.  smiley-sweat
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Offline Offline
Full Member
***
Karma: 1
Posts: 169
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 smiley-cry GRAZIE !  smiley-red

Purtroppo era solo un errore nel postare il codice.

ma come faccio a vedere
Code:
packet1->function = READ_HOLDING_REGISTERS;
sul master per poi visualizzarlo
sulla seconda riga del lcd

Quote
lcd.setCursor(0, 1);
  // vorrei vedere qualche dato:
  lcd.print(??? );

Grazie

Luca
Logged

Conegliano
Offline Offline
Full Member
***
Karma: 5
Posts: 219
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!!!  smiley-red
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Buongiorno a tutti,

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

Grazie ragazzi.
Logged

Pages: [1]   Go Up
Jump to: