I am trying to implement Modbus slave device, which will take data from I2C sensor and store the values on it's modbus slave registry. If I am polling data from the sensor modbus is not working, and when I commented the polling function modbus works fine. So my setup is basically modbus slave + I2C master.
Previously I was successfully able to implement modbus slave + I2C slave, where my Arduino was acting as I2C slave for other IC. THat was another project.
Anyways for this current modbus slave + I2c master setup, any ideas. The following is my code.
#include <ModbusSlave.h> // https://github.com/yaacov/ArduinoModbusSlave
#include <Wire.h>
#include "SHT2x.h"
#include <AltSoftSerial.h>
AltSoftSerial debug;
/* slave id = 1, rs485 control-pin = 2, baud = 9600
*/
#define SLAVE_ID 1
#define CTRL_PIN 2
#define BAUDRATE 9600
#define FIRMWARE_VER 0.5
double ver = FIRMWARE_VER;
/**
* Modbus object declaration
*/
Modbus slave(SLAVE_ID, CTRL_PIN);
// Using the enum instruction allows for an easy method for adding and
// removing registers. Doing it this way saves you #defining the size
// of your slaves register array each time you want to add more registers
// and at a glimpse informs you of your slaves register layout.
//////////////// registers of your slave ///////////////////
enum
{
// The first register starts at address 0
// can add more or remove exixting registers if wanted anytime
// zeroth register
// Register 0
zeroth,
// device name
// Register 1
device_name,
// device parameters register
// Register 2
params,
// filler registers
// Register 3-6
filler1,
filler2,
filler3,
filler4,
// error flag register
// Register 7
errorFlag,
// register to store packet number
// Register 8
packetNo,
// 1 temperature register
// Register 9
temp,
// 1 humidity register
// Register 10
hum,
// firmware version register
// Register 15
fv,
// dont remove this
// total number of registers -
TOTAL_REGS_SIZE
};
int sensors[TOTAL_REGS_SIZE];
#define LED 4
#define Upper_Limit_Temperature 50
#define Upper_Limit_Humidity 95
// Varaibles for sensor data -
struct value
{
double temperature = 0;
double humidity = 0;
} previous,current;
char sensor_array[6] = {};
int i;
int packet_count = 1;
void setup()
{
Wire.begin();
pinMode(CTRL_PIN, OUTPUT);
/* register handler functions
* into the modbus slave callback vector.
*/
slave.cbVector[CB_READ_HOLDING_REGISTERS] = readRegistry;
debug.begin( BAUDRATE );
// set Serial and slave at baud 9600.
Serial.begin(BAUDRATE);
slave.begin( BAUDRATE );
pinMode(LED,OUTPUT);
digitalWrite(LED,HIGH);
delay(500);
digitalWrite(LED,LOW);
delay(500);
digitalWrite(LED,HIGH);
delay(500);
digitalWrite(LED,LOW);
delay(500);
digitalWrite(LED,HIGH);
delay(500);
digitalWrite(LED,LOW);
delay(500);
digitalWrite(LED,HIGH);
delay(500);
digitalWrite(LED,LOW);
delay(500);
digitalWrite(LED,HIGH);
delay(500);
digitalWrite(LED,LOW);
delay(500);
}
void loop()
{
modbusValues();
/* listen for modbus commands con serial port
*
* on a request, handle the request.
* if the request has a user handler function registered in cbVector
* call the user handler function.
*/
slave.poll();
}
/*
* Handel Read Holding Registers (FC=03)
* write back the values from eeprom (holding registers).
*/
uint8_t readRegistry(uint8_t fc, uint16_t address, uint16_t length)
{
// read sensors registry values
for (int i = 0; i < length; i++)
{
slave.writeRegisterToBuffer(i, sensors[address + i]);
}
return STATUS_OK;
}
void temphum()
{
current.temperature = SHT2x.GetTemperature();
current.humidity = SHT2x.GetHumidity();
if(current.humidity > Upper_Limit_Humidity)
{
current.humidity = Upper_Limit_Humidity;
}
if(current.temperature > Upper_Limit_Temperature)
{
current.temperature = Upper_Limit_Temperature;
}
debug.print(F("temp: "));debug.println(current.temperature);
debug.print(F("hum: "));debug.println(current.humidity);
}
void sensor_poll()
{
temphum();
//current.temperature = 28.5;
//current.humidity = 56.4;
}
void modbusValues()
{
sensor_poll();
sensors[device_name] = SLAVE_ID;
sensors[params] = 0x03;
sensors[errorFlag] = error_code();
sensors[packetNo] = packet_count;
sensors[temp] = current.temperature;
sensors[hum] = current.humidity;
sensors[fv] = ver;
}
int error_code()
{
return 0;
}