Activity Forums Questions & Troubleshooting Modbus communication via Controllino Reply To: Modbus communication via Controllino

  • aneh2killa

    Member
    September 28, 2021 at 1:30 pm

    Hello Sir,

    I hope you are doing well. I am also having a problem with Modbus sensors and can’t get them to work. Previously, I used ESP32 and Sparkfun RS485 Breakout and it worked fine. From my understanding, the program I use on ESP32 should work on the Controllino because the structure of the program is similar, the only difference is the pin and voltage logic (Sparkfun RS485 uses 3.3v). I also tried the provided example programs but had no luck. Perhaps my understanding is wrong somewhere. For this reason, is possible to get any information or guide to get reading from a Modbus sensor like this one;-

    https://www.amazon.com/<wbr>Temperature-Humidity-<wbr>Transmitter-Acquisition-<wbr>Transducer/dp/B07VNFDQRJ

    The program I used to read the sensor can be found in the attachment. Thank you very much for your time and support.

    #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 0x02 // BYTE 4

    #define BYTE_05 0x00 // BYTE 5

    #define BYTE_06 0x01 // BYTE 6

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

    void setup() {

    Serial.begin(115200);

    // 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

    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);

    //debugging//

    }

    *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;

    }