3. Modbus Mapping

Prima di implementare lo Slave su Arduino  è necessario decidere il mapping dei PIN e delle caratteristiche del dispositivo con l’indirizzamento ed il tipo di dato tipici del mondo Modbus. Lo strato software che si appoggia all’Arduino Helper si chiama ArduMap (MBArduMap.h e MBArduMap.cpp) e mappa Arduino con gli address modbus (e quindi le relative funzioni) secondo il seguente schema:

MBAddrMap

Come vediamo in tabella, i valori dei PIN analogici sono implementati come INPUT REGISTER (quindi a sola lettura) che hanno un valore a 16bit che rappresenta il valore di tensione (in mV) letta sul PIN dalla scheda Arduino. Questi registri hanno un address Modbus che va da 00H a 05H.

Gli I/O digitali sono implementati come COILS (registri da 1 bit in lettura e scrittura). Per gestire il tipo di COIL (se in lettura o in scrittura) c’è a disposizione un Holding Register che permette di settare il tipo di COIL, il registro si chiama COILS_SET00 ed ha indirizzo Modbus F0H. Nel registro ogni 2 bit rappresentano la configurazione di un PIN di I/O digitale. Il valore di questi 2 bit possono essere:

  • 00: il PIN è settato come INPUT
  • 01: il PIN è settato come OUTPUT
  • 10: il PIN è settato come INPUT con resistenza di PULLUP
  • 11: combinazione non ammessa.

Il mapping per il nostro caso specifico è il seguente:

Possible Value:
  - INPUT (default): Pins configured this way are said to be in a high-impedance state.
  - OUTPUT: Pins configured as OUTPUT are said to be in a low-impedance state.
  - INPUT_PULLUP: There are 20K pullup resistors built into the Atmega chip that can be accessed from software. The value of this pullup depends on the microcontroller used. On most AVR-based boards, the value is guaranteed to be between 20kO and 50k. On the Arduino Due, it is between 50k and 150k.
2 bit mapping:
  00: INPUT
  01: OUTPUT
  10: INPUT_PULLUP
*/
// bit 8, 9: DIGITAL4
// bit 6, 7: DIGITAL3
// bit 4, 5: DIGITAL2
// bit 2, 3: DIGITAL1
// bit 0, 1: DIGITAL0
#define MB_DIGITALS_SET00  0xF0

I COILS hanno indirizzamento Modbus da 20H a 24H.

I COUNTERS di Arduino hanno valori a 32bit. Abbiamo deciso di trattare questi registri in due modi distinti che possono essere utilizzati contemporaneamente:

  • Come Holding Register standard (indirizzi 10H-11H e 12H-13H): quindi ogni registro in realtà rappresenta o la word meno significativa o la word più significativa del dato a 32bit; questo tipo di gestione però ha il side effect che dalla lettura di una word alla lettura dell’altra word può passare un certo tempo ed il contatore potrebbe cambiare valore.
  • Come Holding Register Custom a 32bit (indirizzi 10H e 12H) con funzioni custom definite dall’utente.

Anche in questo caso abbiamo un Holding Register per il set dei contatori. Ogni 4 bit di questo registro serve a configurare un contatore con il seguente schema:

  • XY00: il contatore cambia quando il PIN relativo va a 0;
  • XY01: il contatore cambia quando il PIN cambia valore (da 0 a 1 o viceversa);
  • XY10: il contatore cambia quando il PIN relativo va ad 1;
  • XY11: il contatore cambia quando il PIN relativo va da 1 a 0.

I valori X ed Y hanno il seguente significato:

  • X=0: il contatore è disabilitato;
  • X=1: il contatore è abilitato;
  • Y=0: il contatore è incrementato;
  • Y=1: il contatore è decrementato.

Quindi nello specifico abbiamo:

Possible IRQ trigger:
  - LOW to trigger the interrupt whenever the pin is low,
  - CHANGE to trigger the interrupt whenever the pin changes value
  - RISING to trigger when the pin goes from low to high,
  - FALLING for when the pin goes from high to low. 
4 bit mapping:
  XY00: LOW
  XY01: CHANGE
  XY10: RISING
  XY11: FALLING
  X=0 counter is disabled, X=1 counter is enabled
  Y=0 increase counter, Y=1 decrease counter

In questi file (MBArduMap.h e MBArduMap.cpp) ci sono anche le funzioni per leggere i registri con gli indirizzi Modbus che verranno utilizzate nell’implementazione dello slave TCP e RTU. Il prototipo di queste funzioni è coerente per tutte e prevede come parametri di input il valore del registro Modbus, una variabile che contiene il dato da inserire nel registro oppure il valore letto dal registro. Le funzioni ritornano poi un eventuale errore tra quelli standard del protocollo:

// Exceptions code
enum MBException {
 // Success
 OK                     = 0,
 // FUNC non implemented or unknow
 EXC_ILLEGAL_FUNC_CODE  = 0x01,
 // Illegal address or address range
 EXC_ILLEGAL_DATA_ADDR  = 0x02,
 // Illegal data
 EXC_ILLEGAL_DATA_VALUE = 0x03,
 // Server internal error
 EXC_SERVER_FAILURE     = 0x04,
 // ACK, postpone the response
 EXC_ACKNOWLEDGE        = 0x05,
 // Server busy
 EXC_SERVER_BUSY        = 0x06,
 // Generate by gateway
 EXC_GW_PATH_NOT_AVAIL  = 0x0A,
 // Generate by gateway
 EXC_GW_DEVICE_FAIL     = 0x0B
};

Il prototipo delle fiìunzioni definite nei file è il seguente:

namespace MBArduMap {
	
 void ardumap_init();
    
 // Function return value are in MBException

 // Analogs
 int getInputReg(unsigned addr, unsigned* val);

 // Holding Register
 // No Atomic for Counters (so stop counter before get)
 int getHoldingReg(unsigned addr, unsigned* val);
 int setHoldingReg(unsigned addr, unsigned val);

 // 32bits Holding Register
 int getHoldingReg32(unsigned addr, unsigned long* val);
 int setHoldingReg32(unsigned addr, unsigned long val);

 // Digitals (only RO)
 int getDiscreteReg(unsigned addr, bool* val);
 // Coils
 int getCoilReg(unsigned addr, bool* val);
 int setCoilReg(unsigned addr, bool val);
};

La libreria fino a questo articolo si può scaricare al link qui riportato, i file vanno inseriti nella directory arduino/libraries lasciandoli nel loro folder MBArduino.
"Download (12,5 kB)"

Sketch per il test della libreria di mapping descritta in questo articolo.
"Download (1,6 kB)"

 

Print Friendly

Lascia una risposta

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *

È possibile utilizzare questi tag ed attributi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Elettronica, programmazione embedded (Arduino, Raspberry PI) ed altro