Help with ModBus RTU Master-Slave: ModbusRTU Library

Hi all..
I'm currently working on a project where I will send DHT11 and SW420 sensor data use RS485 Module from slaves 1 and 2 (using Arduino Nano) to the master (Arduino Uno). Here I use the modbus RTU library from GitHub - smarmengol/Modbus-Master-Slave-for-Arduino: Modbus Master-Slave library for Arduino.

When I try to use 1 slave, the data is successfully sent to the master. However, when I try to use 2 slaves, the data from the 2nd slave cannot be received by the master.

Can anyone provide a solution or suggestion regarding my problem?

MASTER


#include <Wire.h>
#include <ModbusRtu.h>
#define slaveNumber 5
#define delayCom 15
#define maxQuery 2*2//slaveNumer*2
#include <SoftwareSerial.h>
//#include <LiquidCrystal_I2C.h>
SoftwareSerial mySerial(2, 3);
//LiquidCrystal_I2C lcd(0x27,16,2);

uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query

uint16_t dataBus[slaveNumber*5];
uint16_t lastPrint=100;
int slaveID[slaveNumber] = {11,12,13,14,15};
/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  port : Serial1 port
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus master(0,mySerial,4); // ID, seriapNumber, enablePin

/**
 * This is an structe which contains a query to an slave device
 */
modbus_t telegram[slaveNumber*2];

unsigned long u32wait;

void init_modBus(){
  int num=0;
  int addr=0;
////SLAVE 1
  // Read 1 data from Slave 11
  telegram[num].u8id = slaveID[0]; // slave address
  telegram[num].u8fct = 3; // function code (this one is registers read)
  telegram[num].u16RegAdd = 0; // start address in slave
  telegram[num].u16CoilsNo = 5; // number of elements (coils or registers) to read
  telegram[num].au16reg = dataBus; // pointer to a memory array in the Arduino
  num+=1;
  addr+=2;
  
  // Write 1 data to Slave 11
  telegram[num].u8id = slaveID[0]; // slave address
  telegram[num].u8fct = 16; // function code (this one is write a multiple register)
  telegram[num].u16RegAdd = 2; // start address in slave
  telegram[num].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[num].au16reg = dataBus+2; // pointer to a memory array in the Arduino
  num+=1;
  addr+=1;

//SLAVE 2
  // Read 1 data from Slave 2
  telegram[num].u8id = slaveID[1]; // slave address
  telegram[num].u8fct = 3; // function code (this one is registers read)
  telegram[num].u16RegAdd = 0; // start address in slave
  telegram[num].u16CoilsNo = 5; // number of elements (coils or registers) to read
  telegram[num].au16reg = dataBus+3; // pointer to a memory array in the Arduino
  num+=1;
  addr+=2;
  
  // Write 1 data to Slave 2
  telegram[num].u8id = slaveID[1]; // slave address
  telegram[num].u8fct = 16; // function code (this one is write a multiple register)
  telegram[num].u16RegAdd = 2; // start address in slave
  telegram[num].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[num].au16reg = dataBus+5; // pointer to a memory array in the Arduino
  num+=1;
  addr+=1;

  master.start();
  master.setTimeOut( 100 ); // if there is no answer in 100 ms, roll over
  u32wait = millis() + 40;
  u8state = u8query = 0; 
  
}

void rtuState(){
  switch( u8state ) {
  case 0: 
    if (millis() >= u32wait) u8state++; // wait state
    break;
  case 1: 
    master.query( telegram[u8query] ); // send query (only once)
    u8state++;
    u8query++;
    if (u8query >= maxQuery) 
      u8query = 0;
    break;
  case 2:
    master.poll(); // check incoming messages if communication in idle state
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + delayCom;  //delay for next state
    }
    break;
  }
}
void printData(){
  if (millis() - lastPrint>200){
    //print data to validate
    Serial.print(dataBus[0]); Serial.print(":");
    Serial.print(dataBus[1]); Serial.print(":");
    Serial.print(dataBus[2]); Serial.print(":");
    Serial.print(dataBus[3]); Serial.print(":");
    Serial.print(dataBus[4]); Serial.print("\t:\t");
    Serial.print(dataBus[5]); Serial.print(":");
    Serial.print(dataBus[6]); Serial.print(":");
    Serial.print(dataBus[7]); Serial.print(":");
    Serial.print(dataBus[8]); Serial.print(":");
    Serial.print(dataBus[9]); 
    Serial.println();
  }
}

void processData(){
  //data to be sent so slave 1 based on slave 2 data
  dataBus[4] = dataBus[4]*0.25; //convert 1023 to 255
  //data to be sent so slave 2 based on slave 1 data
  dataBus[8] = dataBus[1]*0.25; 
}

void setup() {
  Serial.begin (9600); //baud rate of Serial PC
  mySerial.begin( 19200 ); // baud-rate of RS485
  init_modBus();
}

void loop() {
  rtuState();
  printData();
  processData();
}

SLAVE 1 & 2 ( only different slave ID

#include <ModbusRtu.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);
#include <DHT.h>

#define slaveID 11
#define DHTPIN 7
#define DHTTYPE DHT11
int SWPIN=8;
DHT dht(DHTPIN,DHTTYPE);
int t;
int h;
int g;


uint16_t Suhu = 0;
uint16_t Lembab = 0;
uint16_t Getar = 0;
unsigned long lastPrint = 0;

// data array for modbus network sharing
uint16_t au16data[6] = {
  slaveID, 225, 255,255, 8888, 9999
};

Modbus slave(slaveID, mySerial, 4); // this is slave @1 and RS-232 or USB-FTDI

void setup() {
  Serial.begin(9600);
  mySerial.begin( 19200 ); // baud-rate at 19200
  dht.begin();
  pinMode (SWPIN, INPUT);
  slave.start();
  delay(10);
}

void loop() {
  slave.poll( au16data, 6 );
  if (millis() - lastPrint > 200) {
    Serial.print(au16data[0]); Serial.print(":");
    Serial.print(au16data[1]); Serial.print(":");
    Serial.print(au16data[2]); Serial.print(":");
    Serial.print(au16data[3]); Serial.print(":");
    Serial.print(au16data[4]); Serial.println();
    lastPrint = millis();
  }
  readSensor(); //for ultrasonic sensor
}

long vibration(){
  long g=pulseIn (SWPIN, HIGH);
  return g;
}
void readSensor() {
  t = dht.readTemperature();
  h = dht.readHumidity();
  g = vibration();
  cekGetar();

  if (isnan(h) || isnan (t)){
    au16data[1] = 0;
    au16data[2] = 0;
  }
  
  Suhu = t;
  Lembab = h;
  au16data[1] = Suhu; //data to be sent to slave device
  au16data[2] = Lembab;
  au16data[3] = Getar;
  
}

void cekGetar(){
  if (g==0){
    Getar = 0;
  }
  if (g>0 && g<=1000){
    Getar = 1;
  }
  if (g>1000 && g<=10000){
    Getar = 2;
  }
  if (g>10000){
    Getar = 3;
  }
  return Getar;
}

Result (Left : Slave1, Right : Master) :

You shouldn't do low level pointer arithmetic if you don't know exactly what you're doing.

This reads 5 16bit integer into the first 5 items of the array dataBus.

This reads 5 16bit integers into items at index 4 to 8 of the array dataBus. Do you see the problem? This operation will overwrite the content of the item at index 4.

Sorry that I can answer your message today

Yes as I thought, the problem is where when reading the databus array. I'm still a beginner in this field, any suggestions or do you know the solution I should do?

I really need help, it's been 3 weeks since I started this project. Whatever advice or solution you give is very helpful

Yes, don't do pointer arithmetic. Don't use that dataBus array but make a separate array for every message (you might organize these arrays into another array if you know how that has to be done).

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.