Modbus TCP/IP on Arduino Nano + ENC28J60

mb00.jpg



What is Modbus? :



Jumper setting of 0517 matrix board and 5V/3V3 power supply:

Matrix settings


Connection between ENC28J60 board and 0522 adapter using 5x2 ribbon cable :

ENC28J60 to 0522

Connection between ENC28J60 board and 0522 adapter using 5x2 ribbon cable , and 0522 adapter to 0517 matrix board and 5V/3V3 power supply:

mb01.jpg


TcpServer03.ino code :

#include <UIPEthernet.h>

#define AREF_VOLTS 5.0

EthernetServer server = EthernetServer(502);

void vHex2n(char X) {
   if (X < 16) {Serial.print("0");}
   Serial.print(X, HEX);
}

unsigned int uiHexToInt(String hex) {
  int intValue = (int)strtol(&(hex[0]), NULL, 16);
  return intValue;
}

uint8_t* uiHex(uint8_t* m,String str){
  int nStr = str.length();
  String strAux;
  char sz[3];
  
  for(int i = 0; i < nStr; i += 2 ){
    sz[0] = str.charAt(i);
    sz[1] = str.charAt(i+1);
    sz[2] = 0;
    m[i/2] = uiHexToInt(sz);
  }
  return m;
}

void setup(){
  Serial.begin(9600);

  uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
  IPAddress myIP(192,168,1,108);

  Ethernet.begin(mac,myIP);

  analogReference(DEFAULT);
  
  server.begin();
}

void loop(){
  size_t size;
  int nTransactionID,nProtocolID,nLengthOfNext,nL;
  uint8_t uiTr0,uiTr1,ui_nID,uiAD1,uiAD0;
  uint16_t uiValorAn = analogRead(A0);
  uiAD0 = (uint8_t)(uiValorAn & 0x00FF);
  uiAD1 = (uint8_t)(uiValorAn >> 8);

  if (EthernetClient client = server.available()){
      while((size = client.available()) > 0){
          uint8_t* msg = (uint8_t*)malloc(size);
          size = client.read(msg,size);
          for(uint8_t i=0 ; i < size ; i++){
//Serial.print(msg[i],HEX);
                vHex2n(msg[i]);
          }
          Serial.println();
          if(size >= 6){
            nTransactionID = word(msg[0],msg[1]);
            uiTr0 = msg[0];
            uiTr1 = msg[1];
            ui_nID = msg[6];
            nProtocolID = word(msg[2],msg[3]);
            nLengthOfNext = word(msg[4],msg[5]);
          }
          free(msg);
        }
        String szStr = "0000000000050103020000";
        nL = szStr.length() / 2;
        uint8_t* msg = (uint8_t*)malloc(nL*sizeof(uint8_t));
        msg = uiHex(msg,szStr);
        msg[0] = uiTr0;
        msg[1] = uiTr1;
        msg[6] = ui_nID;
        msg[9] = uiAD1;
        msg[10] = uiAD0;
        client.write(msg,nL);
        free(msg);
    }
}
First include use UIPEthernet: A plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS. Build around Adam Dunkels uIP Stack.
#include <UIPEthernet.h>


Be aware of MAC address should be registered for commercial purposes and should be unique in your network (for our test has been used {0x00,0x01,0x02,0x03,0x04,0x05} and a static IP 192.168.1.108 ).
  uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
  IPAddress myIP(192,168,1,108);

Analog read value (10 bits) is split in two bytes (2 x 8 bits) :
  uint16_t uiValorAn = analogRead(A0);
  uiAD0 = (uint8_t)(uiValorAn & 0x00FF);
  uiAD1 = (uint8_t)(uiValorAn >> 8);

This code answers from any requested Modbus TCP/IP address because it is not filtered from original message.


For testing has been used an Android App, Modbus-Droid :

Modbus-Droid :  A Modbus scanner / client for Android. Polls Modbus TCP server at regular intervals.
Uses a modified version of Modbus4J library. The modified source for this library is available in the project source repository at https://launchpad.net/modbusdroid, and the original library is available at http://sourceforge.net/projects/modbus4j



Involved boards :

nano-eCat
I/O matrix
Breadboard adapter
Analog Inputs





Ethernet / SPI
5V / 3V3