Modbus Help! What are function code in the Mudbus example???

So I am using the below example I found online:

#include <SPI.h>
#include <Ethernet.h>

#include "Mudbus.h"

Mudbus Mb;
//Function codes 1(read coils), 3(read registers), 5(write coil), 6(write register)
//signed int Mb.R[0 to 125] and bool Mb.C[0 to 128] MB_N_R MB_N_C
//Port 502 (defined in Mudbus.h) MB_PORT

void setup()
{
  uint8_t mac[]     = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
  uint8_t ip[]      = { 192, 168, 10, 245};
  uint8_t gateway[] = { 192, 168, 10, 1 };
  uint8_t subnet[]  = { 255, 255, 255, 0 };
  Ethernet.begin(mac, ip, gateway, subnet);
  //Avoid pins 4,10,11,12,13 when using ethernet shield

  delay(5000);
  Serial.begin(9600);
  
  //pinMode(13, OUTPUT);
  pinMode(14, OUTPUT); 
}

void loop()
{
  Mb.Run();
  
  //Analog inputs 0-1023
  Mb.R[1] = analogRead(A0); //pin A0 to Mb.R[0]
  Mb.R[2] = analogRead(A1);
  Mb.R[3] = analogRead(A2);
  Mb.R[4] = analogRead(A3);
  Mb.R[5] = analogRead(A4);
  Mb.R[6] = analogRead(A5);//analogRead(A5);

  //Analog outputs 0-255
  analogWrite(6, Mb.R[6]); //pin ~6 from Mb.R[6]

  //Digital inputs
  Mb.C[7] = digitalRead(7); //pin 7 to Mb.C[7]

  //Digital outputs
  digitalWrite(13, Mb.R[13]); //pin 13 from Mb.C[8]
}

I am trying to get Advanced HMI to talk to the Arduino and so far I guessed at which registers to use and could only get the Analog Inputs to work.

I don't know what registers I need to drive in order to read or write to the pins.

For example:

  Mb.R[1] = analogRead(A0); //Register 40002
  Mb.R[2] = analogRead(A1); //Register 40003
  Mb.R[3] = analogRead(A2); //Register 40004
  Mb.R[4] = analogRead(A3); //Register 40005
  Mb.R[5] = analogRead(A4); //Register 40006
  Mb.R[6] = analogRead(A5); //Register 40007

I guessed to find out that the 4000x registers are to read the assigned registers. And so far, they are the only ones I got to work.

I was expecting that the 1000x, and 3000x registers to be for reading and writing to digital inputs/outputs.

Can anyone explain the function codes of modbus for this idiot??? I've spent the last hour looking for answers and explanations but all of the hex stuff gets to me.

Ive used this code before when connecting my arduino via serial (rs232/485) but the above code I found for Modbus TCP and want to get it to work similar to the below:

#include <modbus.h>
#include <modbusDevice.h>
#include <modbusRegBank.h>
#include <modbusSlave.h>

/*
This example code shows a quick and dirty way to get an
arduino to talk to a modbus master device with a
device ID of 1 at 9600 baud.
*/

//Setup the brewtrollers register bank
//All of the data accumulated will be stored here
modbusDevice regBank;
//Create the modbus slave protocol handler
modbusSlave slave;

void setup()
{   

//Assign the modbus device ID.  
  regBank.setId(1);

/*
modbus registers follow the following format
00001-09999  Digital Outputs, A master device can read and write to these registers
10001-19999  Digital Inputs, A master device can only read the values from these registers
30001-39999  Analog Inputs, A master device can only read the values from these registers
40001-49999  Analog Outputs, A master device can read and write to these registers 

Analog values are 16 bit unsigned words stored with a range of 0-32767
Digital values are stored as bytes, a zero value is OFF and any nonzer value is ON

It is best to configure registers of like type into contiguous blocks.  this
allows for more efficient register lookup and and reduces the number of messages
required by the master to retrieve the data
*/

//Add Digital Output registers 00001-00016 to the register bank
  regBank.add(1);
  regBank.add(2);
  regBank.add(3);
  regBank.add(4);
  regBank.add(5);
  regBank.add(6);
  regBank.add(7);
  regBank.add(8);
  regBank.add(9);
  regBank.add(10);
  regBank.add(11);
  regBank.add(12);
  regBank.add(13);
  regBank.add(14);
  regBank.add(15);
  regBank.add(16);

//Add Digital Input registers 10001-10008 to the register bank
  regBank.add(10001);  
  regBank.add(10002);  
  regBank.add(10003);  
  regBank.add(10004);  
  regBank.add(10005);  
  regBank.add(10006);  
  regBank.add(10007);  
  regBank.add(10008);  

//Add Analog Input registers 30001-10010 to the register bank
  regBank.add(30001);  
  regBank.add(30002);  
  regBank.add(30003);  
  regBank.add(30004);  
  regBank.add(30005);  
  regBank.add(30006);  
  regBank.add(30007);  
  regBank.add(30008);  
  regBank.add(30009);  
  regBank.add(30010);  

//Add Analog Output registers 40001-40020 to the register bank
  regBank.add(40001);  
  regBank.add(40002);  
  regBank.add(40003);  
  regBank.add(40004);  
  regBank.add(40005);  
  regBank.add(40006);  
  regBank.add(40007);  
  regBank.add(40008);  
  regBank.add(40009);  
  regBank.add(40010);  
  regBank.add(40011);  
  regBank.add(40012);  
  regBank.add(40013);  
  regBank.add(40014);  
  regBank.add(40015);  
  regBank.add(40016);  
  regBank.add(40017);  
  regBank.add(40018);  
  regBank.add(40019);  
  regBank.add(40020);  

/*
Assign the modbus device object to the protocol handler
This is where the protocol handler will look to read and write
register data.  Currently, a modbus slave protocol handler may
only have one device assigned to it.
*/
  slave._device = &regBank;  

// Initialize the serial port for coms at 9600 baud  
  slave.setBaud(9600);   
}

void loop()
{
//put some data into the registers
  regBank.set(1, 1);  
  regBank.set(2, 1);  
  regBank.set(3, 0);  
  regBank.set(4, 1);  
  regBank.set(5, 1);  
  regBank.set(6, 0);  
  regBank.set(7, 1);  
  regBank.set(8, 0);  

  regBank.set(10001, 1);
  regBank.set(10002, 1);  
  regBank.set(10003, 1);  
  regBank.set(10004, 1);  
  regBank.set(10005, 0);  
  regBank.set(10006, 0);  
  regBank.set(10007, 0);  
  regBank.set(10008, 0);  


  regBank.set(30001,1);
  regBank.set(30002,2);
  regBank.set(30003,3);
  regBank.set(30004,4);
  regBank.set(30005,5);
  regBank.set(30006,6);
  regBank.set(30007,7);
  regBank.set(30008,8);
  regBank.set(30009,9);
  regBank.set(30010,10);

  regBank.set(40001,1);
  regBank.set(40002,2);
  regBank.set(40003,2);
  regBank.set(40004,4);
  regBank.set(40005,5);
  regBank.set(40006,6);
  regBank.set(40007,7);
  regBank.set(40008,8);
  regBank.set(40009,9);
  regBank.set(40010,10);
  
while(1)
  {
    //put a random number into registers 1, 10001, 30001 and 40001
    regBank.set(1, (byte) random(0, 2));
    regBank.set(10001, (byte) random(0, 2));
    regBank.set(30001, (word) random(0, 32767));
    regBank.set(40001, (word) random(0, 32767));
    
     slave.run();  
  }
}

Can you post some links? I have no idea what you are talking about, sorry.

Im not sure what links I would post.

All I want to know if what Modbus registers to use, in order to read and right to the didgtial and analog pins on the Arudino.

My 2nd post above, you can see how the IO is mapped and assigned to registers. But in my first post, the creator of the code I am using didn't use the same type of mapping. Or atleast I can't decode it all except for the Analog Input registers I guessed at.

Hi dpslusser,

I have been using the Mudbus library for some time now and I like it. It has never given me any issues.

AFAIK currently the only two types of registers that are working on this library is:
Mb.R(1-125) - 0x4000X - Read/Write (Holding Register) = Used for Analog read/write
Mb.C(1-125) - 0x0000X - Read/Write (Coil Status) = Used for digital read/write

Hope this helps. I know it is kinda late, hope someone may find it useful.

Hey guys, Im using a controllino, but the concept is the same. For forcing a coil, true and false are represented as 1 and 0 respectively. Ran into the same issue when trying to force coil from my modbus master. Hope the code below helps

#include <SPI.h>
#include <Ethernet.h>

#include "Mudbus.h"

Mudbus Mb;
//Function codes 1(read coils), 3(read registers), 5(write coil), 6(write register)
//signed int Mb.R[0 to 125] and bool Mb.C[0 to 128] MB_N_R MB_N_C
//Port 502 (defined in Mudbus.h) MB_PORT

void setup()
{
 uint8_t mac[]     = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
 uint8_t ip[]      = { 192, 168, 1, 8 };
 uint8_t gateway[] = { 192, 168, 1, 1 };
 uint8_t subnet[]  = { 255, 255, 255, 0 };
 Ethernet.begin(mac, ip, gateway, subnet);
 //Avoid pins 4,10,11,12,13 when using ethernet shield

 delay(5000);
 Serial.begin(9600);
 
 pinMode(7, INPUT);
 pinMode(22, OUTPUT); 
}

void loop()
{
 Mb.Run();
 Mb.C[22] == 0;
 //Analog inputs 0-1023
 Mb.R[0] = analogRead(A0); //pin A0 to Mb.R[0]
 Mb.R[1] = analogRead(A1);
 Mb.R[2] = analogRead(A2);
 Mb.R[3] = analogRead(A3);
 Mb.R[4] = analogRead(A4);
 Mb.R[5] = analogRead(A5);

 //Analog outputs 0-255
 analogWrite(6, Mb.R[6]); //pin ~6 from Mb.R[6]

 //Digital inputs
 Mb.C[7] = digitalRead(7); //pin 7 to Mb.C[7]

 //Digital outputs
 if (Mb.C[22] == 1){
   digitalWrite(22, HIGH);
 }
if (Mb.C[22] == 0) {
   digitalWrite(22, LOW);
   Serial.println ("im totally flase");
}
delay(1000);
}

Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the "Code" icon above the posting area. It is the first icon, with the symbol: </>

How to use this forum


  Mb.C[22] == 0;

Hi, dpslusser
Do you know how to use your code to read and write Modbus coil in Arduino?

You can write Analog value to a Register, look like..

void ReadAinValuesAndSaveDoDiAiAoRegisters()
        { 
      // READ the ANALOG IN value: 
          //reset sychain
        if(sychnAin == 15){
          sychnAin = 0;
            }
          else{
            sychnAin++;
          }   
 
 switch (sychnAin) 
    {  
    case 0: AiLocation=60;sensorValue0 = analogRead(AinPin0);AinVal = map(sensorValue0, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 1: AiLocation=61;sensorValue1 = analogRead(AinPin1);AinVal = map(sensorValue1, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 2: AiLocation=62;sensorValue2 = analogRead(AinPin2);AinVal = map(sensorValue2, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 3: AiLocation=63;sensorValue3 = analogRead(AinPin3);AinVal = map(sensorValue3, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 4: AiLocation=64;sensorValue4 = analogRead(AinPin4);AinVal = map(sensorValue4, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 5: AiLocation=65;sensorValue5 = analogRead(AinPin5);AinVal = map(sensorValue5, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 6: AiLocation=66;sensorValue6 = analogRead(AinPin6);AinVal = map(sensorValue6, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 7: AiLocation=67;sensorValue7 = analogRead(AinPin7);AinVal = map(sensorValue7, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 8: AiLocation=68;sensorValue8 = analogRead(AinPin8);AinVal = map(sensorValue8, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 9: AiLocation=69;sensorValue9 = analogRead(AinPin9);AinVal = map(sensorValue9, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 10: AiLocation=70;sensorValue10 = analogRead(AinPin10);AinVal = map(sensorValue10, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 11: AiLocation=71;sensorValue11 = analogRead(AinPin11);AinVal = map(sensorValue11, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 12: AiLocation=72;sensorValue12 = analogRead(AinPin12);AinVal = map(sensorValue12, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 13: AiLocation=73;sensorValue13 = analogRead(AinPin13);AinVal = map(sensorValue13, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 14: AiLocation=74;sensorValue14 = analogRead(AinPin14);AinVal = map(sensorValue14, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
    case 15: AiLocation=75;sensorValue15 = analogRead(AinPin15);AinVal = map(sensorValue15, 0, 1023, 0, 1023);ChannAdress=sychnAin;break;
      }

     Serial.println(sychnAin);Serial.print("...");Serial.println(AinVal);
      //save Ain and Cin 
    RegisterDoDiAiAo[AiLocation] = AinVal; 
            decToHex(AinVal, 4);
           
     delay(10);
        }

you don't need to do modbus addressing according to the national standards on your own mpu device. Mega2560 has 16 analog and 16 digital readings. Define a variable called int AiDiRegister (40). Save AiDiRegister (0 -19) digitals inputs to the first 20 s. In the AiDiRegister (20 -39) section, record the analog values. When the Modbus read request comes from Scada, for example 04 function(Read analogue values) read and send these values you have saved to AiDiRegister.