Are you looking for Modbus over Serial or over Ethernet, I didn't see this mentioned anywhere. If you want a Modbus/TCP slave then I have included the Mudbus library. I have an Arduino Mega 2560 with all of it's pins mapped out with the exception of those required by the Ethernet shield. I have this sketch working with an industrial HMI for a home automation type system, it works quite well. Some of the pins have thermistors connected, I multiply by 10 so I can divide by 10 on the master and carry a decimal place. For diagnostics I made a holding register for the Slave's free ram as well as two holding registers that hold the 32bit millis() value split into two 16 bit words. All of the other holding registers are just raw ADC values from analogRead(). If you're using an UNO or any other Arduino with less pins then just remove the lines that map to pins you don't have.
Hope this helps.
#include <SPI.h>
#include <Ethernet.h>
#include "Mudbus.h"
Mudbus Mb;
void setup()
{
//Setup networking
uint8_t mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
IPAddress ip(10, 0, 0, 11);
IPAddress gateway = ( 10, 0, 0, 53 );
IPAddress subnet = ( 255, 255, 255, 0 );
Ethernet.begin(mac, ip, gateway, subnet);
Mb.ConnectionTimeout = 100;
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}
void loop()
{
// Read the current state of the pins before calling Run()
// This allows you to read forced pin state changes
// Any writes after connecting to the master are written after
Mb.C[0] = digitalRead(0);
Mb.C[1] = digitalRead(1);
//Mb.C[2] = digitalRead(2);
//Mb.C[3] = digitalRead(3);
Mb.C[4] = false;
//Mb.C[5] = digitalRead(5);
//Mb.C[6] = digitalRead(6);
Mb.C[7] = digitalRead(7);
Mb.C[8] = digitalRead(8);
Mb.C[9] = digitalRead(9);
Mb.C[10] = false;
Mb.C[11] = digitalRead(11);
Mb.C[12] = digitalRead(12);
Mb.C[13] = digitalRead(13);
Mb.C[14] = digitalRead(14);
Mb.C[15] = digitalRead(15);
Mb.C[16] = digitalRead(16);
Mb.C[17] = digitalRead(17);
Mb.C[18] = digitalRead(18);
Mb.C[19] = digitalRead(19);
Mb.C[20] = digitalRead(20);
Mb.C[21] = digitalRead(21);
Mb.C[22] = digitalRead(22);
Mb.C[23] = digitalRead(23);
Mb.C[24] = digitalRead(24);
Mb.C[25] = digitalRead(25);
Mb.C[26] = digitalRead(26);
Mb.C[27] = digitalRead(27);
Mb.C[28] = digitalRead(28);
Mb.C[29] = digitalRead(29);
Mb.C[30] = digitalRead(30);
Mb.C[31] = digitalRead(31);
Mb.C[32] = digitalRead(32);
Mb.C[33] = digitalRead(33);
Mb.C[34] = digitalRead(34);
Mb.C[35] = digitalRead(35);
Mb.C[36] = digitalRead(36);
Mb.C[37] = digitalRead(37);
Mb.C[38] = digitalRead(38);
Mb.C[39] = digitalRead(39);
Mb.C[40] = digitalRead(40);
Mb.C[41] = digitalRead(41);
Mb.C[42] = digitalRead(42);
Mb.C[43] = digitalRead(43);
Mb.C[44] = digitalRead(44);
Mb.C[45] = digitalRead(45);
Mb.C[46] = digitalRead(46);
Mb.C[47] = digitalRead(47);
Mb.C[48] = digitalRead(48);
Mb.C[49] = digitalRead(49);
Mb.C[50] = false;
Mb.C[51] = false;
Mb.C[52] = false;
Mb.C[53] = false;
//Analog inputs 0-1023
// Temperature readings using a 3k NTC thermistor
Mb.R[0] = int(tempFromADC(analogRead(1)) * 10); //pin A0 to Mb.R[0]
Mb.R[1] = int(tempFromADC(analogRead(2)) * 10);
Mb.R[2] = int(tempFromADC(analogRead(2)) * 10);
Mb.R[3] = analogRead(A3);
Mb.R[4] = analogRead(A4);
// Basic light measurement using a photoresistor
Mb.R[5] = lightScale();
Mb.R[6] = analogRead(A6);
Mb.R[7] = analogRead(A7);
Mb.R[8] = analogRead(A8);
Mb.R[9] = analogRead(A9);
Mb.R[10] = analogRead(A10);
Mb.R[11] = analogRead(A11);
Mb.R[12] = analogRead(A12);
Mb.R[13] = analogRead(A13);
Mb.R[14] = analogRead(A14);
Mb.R[15] = analogRead(A15);
// Slave Memory
Mb.R[16] = freeRam();
// Slave uptime, 32 bits carried by two (2) 16 bit registers
long uptime = millis();
// High word
Mb.R[17] = uptime >> 16 & 0xFFFF;
// Low word
Mb.R[18] = uptime & 0xFFFF;
// Listen for the master
Mb.Run();
// This delay improves stability by orders of magnitude
delay(10);
// Set digital outs
digitalWrite(2, Mb.C[2]);
digitalWrite(3, Mb.C[3]);
digitalWrite(5, Mb.C[5]);
digitalWrite(6, Mb.C[6]);
}
double tempFromADC(int adcVal)
{
double temp;
// See http://en.wikipedia.org/wiki/Thermistor for explanation of formula
temp = log(((10240000/adcVal) - 10000));
temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
temp = temp - 273.15; // Convert Kelvin to Celcius
temp = (temp * 1.8) + 32.0; // Comment this line for C instead of F
return temp;
}
int lightScale()
{
double val = analogRead(5) / 1023.0;
int returnVal = int(val * 1000);
return returnVal;
}
int freeRam()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
Mudbus.zip (16.2 KB)