Modbus RTU write registers

Hi all,

i own a Controllino Maxi and i use it to interface with this sensor :

All works OK to read the input and holding registers with the code examples provided by Controllino that i changed to my needs.
https://www.controllino.com/knowledge-base/rs485-modbusrtu/

But i'm not able to write a holding register.
Does anyone know how ? I have some code to change the devices address at register 0, it's not working at all :slight_smile:

#include <Controllino.h> 
#include "ModbusRtu.h"   

#define MasterModbusAdd  0
#define SlaveModbusAdd  1
#define RS485Serial     3

int i; 
unsigned long u32wait;
uint16_t au16data[16];
uint8_t u8state;
char caracter;
String ch;
int value;

Modbus master(MasterModbusAdd, RS485Serial, 0);

modbus_t data[1];

uint16_t ModbusSlaveRegisters[4];

void setup() {
   Serial.begin(115200);
   while (!Serial){
  }
  Serial.println("Connecting to Serial3 ");
  master.begin(19200,SERIAL_8E1);
  Serial.println("Connected");
  Serial.println("Enter new address :");
  master.setTimeOut(5000); // if there is no answer in 5000 ms, roll over
  u32wait = millis() + 2000;
  u8state = 0; 
  i=0;
  ch="";
  data[0].u8id = SlaveModbusAdd; // slave address
  data[0].u8fct = 6; // function code (this one is registers read)
  data[0].u16RegAdd = 19; // start address in slave
  data[0].u16CoilsNo = 1; // number of elements (coils or registers) to read
  data[0].au16reg = 123 ; //ModbusSlaveRegisters+4; // pointer to a memory array in the Arduino 
  //ModbusSlaveRegisters[4] = 123; 
}

void loop() {

  while  (Serial.available()){
        caracter = Serial.read();
        ch.concat(caracter);
   }
   if (ch.toInt()>=1 and ch.toInt()<=247)
   {
     Serial.print("Number received: ");
     Serial.println(ch);
     value = ch.toInt();
     ch="";
     
   }
   else
   {
     //Serial.print("bad number");
     //Serial.println(ch);
     
   }
   
  delay(50);
 
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
   
    break;
  case 1: 
    if (value>=1 and value<=247)
    master.query(data[0]); // send query (only once)
    u8state++;
    break;
  case 2:
    
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      //u8state = 0;
      u32wait = millis() + 500; 
      Serial.println ("Value written : ");  
      u8state++;
    }
    break;
    
  }
} 

Did you read the comment on that code line? I doubt that 123 is pointing to a memory area with correct data.

BTW:

It's rather bad style to change the content of a code line without changing the corresponding comment. Function 6 isn't "register read"!

Well yes , i know. my bad. But that doesn't clear the problem.

I've had the memory area set in allot of different ways, and i do think 6 is holding register write..

That's correct.

Currently it's holding a fixed address which definitely doesn't work. Have you tried the example code?

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