Activity Forums Questions & Troubleshooting Controllino MAXI RS485 Modbus

  • Controllino MAXI RS485 Modbus

     Lukas updated 6 months ago 3 Members · 6 Posts
  • Kwaaigone

    Member
    November 3, 2021 at 2:32 pm

    Hi

    I have recently acquired a Controllino MAXI with which I am trying to use it as a Modbus master to communicate with a slave.

    I can read holding registers (Function 3) etc, but I cannot seem to be able to write to single registers (Function 6).

    When I use a Modbus testing tool, and a Usb to RS485 device, I can write to said slave with no issues. The Frame looks like this: (In Hex format) 04 06 00 83 00 01 B9 B7

    04 – Slave Address

    06 – Function

    00 83 – (Register Address : Decimal = 131)

    00 01 – (Value to write)

    B9 B7 – CRC

    This works, just fine in that context.

    When translating to Controllino Master for the MAXI to perform the same task, I cannot get it to work:

    I translated the above as follows (based on the tutorials examples for Controllino MAXI including ModbusRtu.h):

    ModbusQuery[0].u8id = 4; // slave address

    ModbusQuery[0].u8fct = 6; // function code (this one is register write)

    ModbusQuery[0].u16RegAdd = 131; // start address in slave – DEC to HEX

    ModbusQuery[0].u16CoilsNo = 1; // Value To Write

    ModbusQuery[0].au16reg = ModbusSlaveRegisters; // pointer to a memory array in the CONTROLLINO

    This does not work.

    Please assist. Any help will be appreciated.

  • Lukas

    Member
    November 5, 2021 at 4:32 pm

    Hi,

    the code seems to be correct and it should work.

    Please, share the part of the sketch where you set the ModbusSlaveRegisters value.

    Thanks,

    Lukas

  • Nestor973

    Member
    November 7, 2021 at 9:23 am

    Hi,

    i’m facing some simular problem. Can you share your code?

  • Kwaaigone

    Member
    November 8, 2021 at 6:07 am

    Hi Everyone

    I managed to solve my own issue by just using normal serial communication, like the tutorial example of the DemoRS485, and not using the ModbusRtu.h related modbus code available in the tutorials.


    Although I did manage to have the controllino MAXI act as a master and perform the required operations, I do still experience some sort of issue where it seems the device does not handle multiple slave addresses and quick concurrent communication to said devices very well.


    I hooked up 3 slave devices to my MAXI master, with slave addresses 1, 3, 4.

    A SH20 temperature and Humidity sensor, a Modbus RTU 4CH relay module and a N4DBA06 analogue and digital input /output device. In my loop code I would perform various register read and write operations like reading the humidity, then reading a 4-20mA input, and setting a voltage output, etc.., and like I stated, the device seems to struggle and sometimes not work as expected or not at all. I had to put in multiple delays between code lines and that would seem to sometimes either help or hinder.


    <font face=”inherit”>Maybe someone has similar experiences and could share some </font>insight<font face=”inherit”>? Is this perhaps a possible hardware issue, or a software issue?</font>


    Any info would be appreciated.

  • Kwaaigone

    Member
    November 8, 2021 at 6:14 am

    my and originally someone else’s code: (Thanks to whomever I don’t recall)

    #include <SPI.h>

    #include <Controllino.h>

    float RH;

    //———————————————————————————–

    #define MAX_MILLIS_TO_WAIT 300

    #define FRAMESIZE 9

    //———————————————————————————–

    #define ADDRESS 0x01 // BYTE 1

    #define FUNCTION_CODE 0x04 // BYTE 2

    #define BYTE_03 0x00 // BYTE 3

    #define BYTE_04 0x01 // BYTE 4

    #define BYTE_05 0x00 // BYTE 5

    #define BYTE_06 0x01 // BYTE 6

    //———————————————————————————–

    void setup() {

    Serial.begin(9600);

    // initialize the modbus communication

    Serial3.begin(9600);

    Controllino_RS485Init();

    Controllino_RS485RxEnable();

    /* This will initialize Controllino RS485 pins */

    }

    void loop() {

    if (runEvery(3000)) {

    Serial.println(“===================================”);

    uint16_t ws;

    soil(&ws);

    //for debugging purpose

    RH = ws / 10; Serial.println(” Temp: \t” + String(RH));

    }

    }

    /////////////////////////////function: access modbus data/////////////////////

    float soil(uint16_t* ws) {

    uint16_t temp;

    unsigned long resptime;

    uint8_t frame[FRAMESIZE] = {ADDRESS, FUNCTION_CODE, BYTE_03, BYTE_04, BYTE_05, BYTE_06, 0, 0, 0};

    temp = calculateCRC(frame, FRAMESIZE – 3); // calculate out crc only from first 6 bytes

    frame[6] = lowByte(temp);

    frame[7] = highByte(temp);

    Serial.println(“=========================================================”);

    //=====================For debugging purposes======================//

    String request = “Request: “;

    for (int n = 0; n < FRAMESIZE – 1; n++) {

    request += frame[n] < 0x10 ? ” 0″ : ” “;

    request += String(frame[n], HEX);

    request.toUpperCase();

    }

    Serial.println(request);

    //=========================================================//

    Controllino_RS485TxEnable();

    Serial3.write(frame, FRAMESIZE – 1); // send 8 bytes

    Serial3.flush(); // wait until the trasmission is complete

    //delay(1000);

    uint8_t DoPON[8] = {0x02, 0x06, 0x00, 0x83, 0x00, 0x01, 0xB9, 0x0D1};

    Serial3.write(DoPON, 8);

    Serial3.flush();

    Controllino_RS485RxEnable();

    resptime = millis();

    while ((Serial3.available() < FRAMESIZE) && ((millis() – resptime) < MAX_MILLIS_TO_WAIT) ) {

    delay(50);

    }

    String Response = “Response: “;

    if (Serial3.available()) {

    for (int n = 0; n < FRAMESIZE – 2; n++) {

    frame[n] = Serial3.read();

    //debugging//

    Response += frame[n] < 0x10 ? ” 0″ : ” “;

    Response += String(frame[n], HEX);

    Response.toUpperCase();

    }

    Serial.println(Response);

    *ws = ((uint16_t)frame[3] << 8) | frame[4];

    }

    }

    /////////////////////////////function: access modbus data/////////////////////

    uint16_t calculateCRC(uint8_t *array, uint8_t num) {

    uint16_t temp, flag;

    temp = 0xFFFF;

    for (uint8_t i = 0; i < num; i++) {

    temp = temp ^ array[i];

    for (uint8_t j = 8; j; j–) {

    flag = temp & 0x0001;

    temp >>= 1;

    if (flag)

    temp ^= 0xA001;

    }

    }

    return temp;

    }

    //————————————————-//

    boolean runEvery(unsigned long interval)

    {

    static unsigned long previousMillis = 0;

    unsigned long currentMillis = millis();

    if ((currentMillis – previousMillis) >= interval)

    {

    previousMillis = currentMillis;

    return true;

    }

    return false;

    }

    • Lukas

      Member
      January 4, 2022 at 3:09 pm

      Hi Kwaaigone,

      I think that your sketch may stuck when the reply from the Modbus slave is shorter than 7 bytes. It will stay in the blocking function Serial3.read.

      And what can be the reason? Maybe you switch the RS485 direction too fast. The flush function may end when the last byte is loaded into the trasmit buffer, but not transmitted yet. As described here.

      And your runEvery function may have a problem with millis overflow.

      Good luck!

      Lukas

Viewing 1 - 5 of 5 replies

Log in to reply.

Original Post
0 of 0 posts June 2018
Now