Modbus TCP/IP using Arduino uno and ENC28J60 module

I have this project where I need a modbus tcp server that will host a series of sensor data for other modbus client devices to read. I use this Library by Andresoarmento

This is the code i am using from the library example:

#include <EtherCard.h>
#include <Modbus.h>
#include <ModbusIP_ENC28J60.h>

//Modbus Registers Offsets (0-9999)
const int SENSOR_IREG = 100;
//Used Pins
//const int sensorPin = A0;

//ModbusIP object
ModbusIP mb;

long ts;

void setup() {
    // The media access control (ethernet hardware) address for the shield
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    // The IP address for the shield
    byte ip[] = { 192, 168, 1, 120 };
    //Config Modbus IP
    mb.config(mac, ip);

    // Add SENSOR_IREG register - Use addIreg() for analog Inputs
    int i = 2200;
    mb.addIreg(SENSOR_IREG,i);

    ts = millis();
}

void loop() {
   //Call once inside loop() - all magic here
   mb.task();

   //Read each two seconds
   if (millis() > ts + 2000) {
       ts = millis();
       //Setting raw value (0-1024)
       int i = 0;
       i++;
       mb.Ireg(SENSOR_IREG, i);
   }

The enj28j60 module is working as i tested it. So, I used a modbus scanner(CAS SCANNER) which was unable to detect it. Can anyone tell me how to get this all working and test it?

Thank you in advance.

Can anyone tell me how to get this all working and test it?

Check if 192.168.1.120 is a free IP of your network!

Check if you can open a connection to port 502 of that IP. Does that succeed?

Check if your scanner software is worth it's money!

Oh yes, I Connected it to a router and scanned using the CAS scanner. The CAS scanner polled a input register read command and i got a 0x02 error. as a response from the device.

deapool:
Oh yes, I Connected it to a router and scanned using the CAS scanner. The CAS scanner polled a input register read command and i got a 0x02 error. as a response from the device.

So the Modbus server works as expected. Error 2 means that the register with the given address does not exist.

I thought the same. But, I still can't figure out if the error is because of the CAS scanner or my code. I have attached the CAS error log with this post.
This time i tried with a holding register.
And below is the code I use to store data into the holding register.

#include <EtherCard.h>
#include <Modbus.h>
#include <ModbusIP_ENC28J60.h>

//Modbus Registers Offsets (0-9999)
const int SENSOR_IREG = 100;
//Used Pins
const int sensorPin = A0;

//ModbusIP object
ModbusIP mb;

long ts;

void setup() {Serial.begin(9600);
    // The media access control (ethernet hardware) address for the shield
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    // The IP address for the shield
    byte ip[] = { 192, 168, 1, 120 };
    //Config Modbus IP
    mb.config(mac, ip);

    // Add SENSOR_IREG register - Use addIreg() for analog Inputs
    //mb.addIreg(SENSOR_IREG);
    mb.addHreg(SENSOR_IREG);
    ts = millis();
}

void loop() {
   //Call once inside loop() - all magic here
   mb.task();
   
   //Read each two seconds
   if (millis() > ts + 2000) {
       ts = millis();
       //Setting raw value (0-1024)
       //mb.Ireg(SENSOR_IREG, analogRead(sensorPin));
       mb.Hreg(SENSOR_IREG, 255); //Store value in holding register
   }
}

I am unable figure out what the problem is. I checked the library files, it is able to receive the data and parse it. Just not able to send the data I want. Being very new to this protocol of communication, Any help is appreciated.

ut, I still can't figure out if the error is because of the CAS scanner or my code.

According to the screenshot it's that scanner. Requesting 100 registers starting at address 0 is quite rather stupid for a device that has only one register at address 100. So as I wrote, the Arduino is acting correctly as it doesn't have any register at the addresses 0-99.

The explanation your scanner software offers is correct but it seems you haven't read it. The only drawback of that explanation is that it assumes that every device starts at address 0 with the registers.

This makes sense, I couldn't quite understand the CAS scanner and didn't know it has been requesting data from a address that is not there in the first place. This also explains the error code. I will try to add hundred registers in the device or try to use a different scanner that can read a specified address! Thanks for the help, Pylon. I will try it and let you know!!

Hi All,
I'm using the Andre Sarmento as the original poster and I'm having a couple of issues. I'm using an Uno and a ethernet shield.

this is my code:

/*
  Modbus-Arduino Example - Servo (Modbus IP ENC28J60)
  Copyright by André Sarmento Barbosa
  http://github.com/andresarmento/modbus-arduino
*/

#include <EtherCard.h>
#include "Modbus.h"
#include "ModbusIP_ENC28J60.h"


// Modbus Registers Offsets (0-9999)
const int temp_HREG = 0;
int numberOfSensors = 40;

long ts;

// ModbusIP object
ModbusIP mb;

void setup() {

    Serial.begin(9600);
    Serial.println("ready");
    
    byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x85, 0x80 };  // Define MAc address
    byte ip[] = { 10, 0, 41, 91 };                     // Define IP address
    byte subnet[] = { 255, 255, 254, 0 };     
    //Config Modbus IP 
    mb.config(mac, ip);

    Serial.println("mb config");
    
    
    // Filling holding registers
    for(uint16_t i = temp_HREG; i < numberOfSensors; i++)
    {
      mb.addHreg(i, i);
      //Serial.println(res, DEC);  
    }

    ts = millis();
}

void loop() {
   //Call once inside loop() - all magic here
   mb.task();

   
   //Read each two seconds
   if (millis() > ts + 2000) {   
       ts = millis();
       
       for(uint16_t i = 0; i < numberOfSensors; i++)
       {
          Serial.println(mb.Hreg(i), DEC);  
       }
       
   } 
}

I'm using Serial outputs to debug the program and it seems I get into mb.config(mac, ip) and I'm not coming out of that as my following serial print is not actiuvated.

I also get these warnings on compile:

 In function 'send_dhcp_message':
warning: 'memset' writing 278 bytes into a region of size 200 overflows the destination [-Wstringop-overflow=]
     memset(gPB, 0, UDP_DATA_P + sizeof( DHCPdata ));

any help would be apreciated.

Thank you.
Best Regards
Luis

1 Like

I'm using an Uno and a ethernet shield.

The code you use is for a ENC28j60 and not for an Ethernet Shield!

You shouldn't hijack this thread as your problem is completely different to the OP's.