Activity Forums Questions & Troubleshooting Inline flow sensor not sending data to Controllino Mega

  • Inline flow sensor not sending data to Controllino Mega

     barrels updated 1 year ago 2 Members · 4 Posts
  • barrels

    Member
    February 22, 2023 at 7:53 am

    I have an Inline Flow Sensor VA521 from CS Instruments and have connected it to a Controllino Mega. The sensor turns on and reads data fine and the Controllino can send commands through modbus RTU to the sensor without issue. However, whenever I try to read data from the sensor, I get 0, even for the temperature. According to the manual and the sensor’s settings, the slave address is 1 and the modbus register for temperature is 1419. At first I took the register to mean 1 – a discrete value, and the slave address was 419. I have tried 418 or 420 or 1419 or 1418 and none on them give a different response. I adjusted my code based on the DemoModbusRTUMaster example code from Controllino.

    I also tried connecting the analog output of the sensor to the Controllino. No matter what, if the sensor is on, the value always reads about 750 (usually 748-751). I have tried different computers, connecting the analog output to an Arduino Mega 2560, changing the output from volume flow to temperature and the value still stays the same. Even if it is set to flow and the screen on the sensor reads a flow, the value does not change.
    Even though the read out from the controllino would indicate a 15 V voltage, when measured by hand, it read 5 V. Converting this to mA from the sensor, I get 3.04 mA, which would mean an error signal. I do not know what the error would be or even where to look. I’m not even sure if the error is in the code or with the sensor.

    I am completely new to modbus and have only learned the basics of Arduino. I greatly appreciate any help that you can offer!

    This is the instruction manual for the sensor:

    https://www.cs-instruments.com/fileadmin/cs-data/Bedienungsanleitungen/Instruction%20manuals_EN_new/Instruction_manual_VA521_EN.pdf

    This is my Modbus RTU Master code

    #include <Controllino.h> /* Usage of CONTROLLINO library allows you to use CONTROLLINO_xx aliases in your sketch. */

    #include "ModbusRtu.h" /* Usage of ModBusRtu library allows you to implement the Modbus RTU protocol in your sketch. */

    // This MACRO defines Modbus master address.

    // For any Modbus slave devices are reserved addresses in the range from 1 to 247.

    // Important note only address 0 is reserved for a Modbus master device!

    int D0 = CONTROLLINO_D0;

    int D1 = CONTROLLINO_D1;

    int R0 = CONTROLLINO_R0;

    int A0_ = CONTROLLINO_A0;

    //#define MasterModbusAdd 0

    #define SlaveModbusAdd 1

    // This MACRO defines number of the comport that is used for RS 485 interface.

    // For MAXI and MEGA RS485 is reserved UART Serial3.

    #define RS485Serial 3

    // The object ControllinoModbuSlave of the class Modbus is initialized with three parameters.

    // The first parametr specifies the address of the Modbus slave device.

    // The second parameter specifies type of the interface used for communication between devices - in this sketch - RS485.

    // The third parameter can be any number. During the initialization of the object this parameter has no effect.

    Modbus ControllinoModbusSlave(SlaveModbusAdd, RS485Serial, 0);

    // This uint16 array specified internal registers in the Modbus slave device.

    // Each Modbus device has particular internal registers that are available for the Modbus master.

    // In this example sketch internal registers are defined as follows:

    // (ModbusSlaveRegisters 0 - 3 read only and ModbusSlaveRegisters 4 - 7 write only from the Master perspective):

    // ModbusSlaveRegisters[0] - Read an analog value from the CONTROLLINO_A0 - returns value in the range from 0 to 1023.

    // ModbusSlaveRegisters[1] - Read an digital value from the CONTROLLINO_D0 - returns only the value 0 or 1.

    // ModbusSlaveRegisters[2] - Read the number of incoming messages - Communication diagnostic.

    // ModbusSlaveRegisters[3] - Read the number of number of outcoming messages - Communication diagnostic.

    // ModbusSlaveRegisters[4] - Sets the Relay output CONTROLLINO_R0 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[5] - Sets the Relay output CONTROLLINO_R1 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[6] - Sets the Relay output CONTROLLINO_R2 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[7] - Sets the Relay output CONTROLLINO_R3 - only the value 0 or 1 is accepted.

    uint16_t ModbusSlaveRegisters[8];

    // This is an structe which contains a query to an slave device

    modbus_t ModbusQuery[2];

    uint8_t myState; // machine state

    uint8_t currentQuery; // pointer to message query

    unsigned long WaitingTime;

    void setup() {

    // initialize serial communication at 9600 bits per second:

    Serial.begin(19200);

    Serial.println("-----------------------------------------");

    Serial.println("CONTROLLINO Modbus RTU Master Test Sketch");

    Serial.println("-----------------------------------------");

    Serial.println("");

    pinMode(D0, OUTPUT);

    pinMode(D1, INPUT);

    pinMode(R0, OUTPUT);

    pinMode(A0_, INPUT);

    // ModbusQuery 0: read registers

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

    ModbusQuery[0].u8fct = 03; // function code (this one is discrete input read)

    ModbusQuery[0].u16RegAdd = 419; // start address in slave

    ModbusQuery[0].u16CoilsNo = 25; // number of elements (coils or registers) to read

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

    /* ModbusQuery[0].u8id = SlaveModbusAdd; // slave address

    ModbusQuery[0].u8fct = 2; // function code (this one is discrete input read)

    ModbusQuery[0].u16RegAdd = 427; // start address in slave

    ModbusQuery[0].u16CoilsNo = 25; // number of elements (coils or registers) to read

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

    // ModbusQuery 1: write a single register

    ModbusQuery[1].u8id = SlaveModbusAdd; // slave address

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

    ModbusQuery[1].u16RegAdd = 4; // start address in slave

    ModbusQuery[1].u16CoilsNo = 1; // number of elements (coils or registers) to write

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

    ModbusSlaveRegisters[4] = 1; // initial value for the relays

    ControllinoModbusMaster.begin( 19200, SERIAL_8E1 ); // baud-rate at 19200

    ControllinoModbusMaster.setTimeOut( 5000 ); // if there is no answer in 5000 ms, roll over

    WaitingTime = millis() + 1000;

    myState = 0;

    currentQuery = 0;

    }

    void loop() {

    switch( myState ) {

    case 0:

    if (millis() > WaitingTime) myState++; // wait state

    break;

    case 1:

    Serial.print("---- Sending query ");

    Serial.print(currentQuery);

    Serial.println(" -------------");

    // ControllinoModbusMaster.query( ModbusQuery[currentQuery] ); // send query (only once)

    myState++;

    currentQuery++;

    if (currentQuery == 2)

    {

    currentQuery = 0;

    }

    break;

    case 2:

    ControllinoModbusMaster.poll(); // check incoming messages

    if (ControllinoModbusMaster.getState() == COM_IDLE)

    {

    // response from the slave was received

    myState = 0;

    WaitingTime = millis() + 1000;

    // debug printout

    if (currentQuery == 0)

    {

    // registers write was proceed

    Serial.println("---------- WRITE RESPONSE RECEIVED ----");

    Serial.println("");

    }

    if (currentQuery == 1)

    {

    // registers read was proceed

    Serial.println("---------- READ RESPONSE RECEIVED ----");

    Serial.print("Slave ");

    Serial.print(SlaveModbusAdd, DEC);

    Serial.print(" ADC0: 0x");

    Serial.print(ModbusSlaveRegisters[0], HEX);

    Serial.print(" , Digital0: ");

    Serial.print(ModbusSlaveRegisters[1], BIN);

    Serial.print(" , ModbusCounterIn: ");

    Serial.print(ModbusSlaveRegisters[2], DEC);

    Serial.print(" , ModbusCounterOut: ");

    Serial.println(ModbusSlaveRegisters[3], DEC);

    Serial.println(ModbusSlaveRegisters[4], DEC);

    Serial.println(ModbusSlaveRegisters[5]);

    Serial.println(ModbusSlaveRegisters[6]);

    Serial.println(ModbusSlaveRegisters[7]);

    Serial.println(ModbusSlaveRegisters[8],DEC);

    Serial.println("-------------------------------------");

    Serial.println("");

    // toggle with the relays

    ModbusQuery[1].u16RegAdd++;

    if (ModbusQuery[1].u16RegAdd == 8)

    {

    ModbusQuery[1].u16RegAdd = 4;

    if (ModbusSlaveRegisters[4])

    {

    ModbusSlaveRegisters[4] = 0;

    }

    else

    {

    ModbusSlaveRegisters[4] = 1;

    }

    }

    }

    }

    break;

    }

    }

    This is my analog code

    /*

    AnalogReadSerial

    Reads an analog input on pin 0, prints the result to the Serial Monitor.

    Graphical representation is available using Serial Plotter (Tools > Serial Plotter menu).

    Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.

    This example code is in the public domain.

    https://www.arduino.cc/en/Tutorial/BuiltInExamples/AnalogReadSerial

    */

    //#include <Controllino.h>

    // the setup routine runs once when you press reset:

    void setup() {

    // initialize serial communication at 9600 bits per second:

    Serial.begin(9600);

    Serial.println("Programm hat gestartet");

    pinMode(A1, INPUT); //establish A1 as an input

    }

    // the loop routine runs over and over again forever:

    void loop() {

    int errorCheck = 0; //will stop while loop if below error conditions are met

    while (errorCheck != 1){

    //int VolumenStrom;

    // read the input on analog pin 1: divided by 15 to correct voltage to measured values

    float sensorValue = analogRead(A1)/15;

    // print out the value you read:

    Serial.println(sensorValue);

    delay(1); // delay in between reads for stability

    // Converting to ampere value

    //Ardiuno read out from 1-1023

    //Sensor current from 2 mA to 22 mA

    float mA = (sensorValue * 0.01955) + 2; //convert 0-1023 read out to milliamps

    Serial.print(mA);

    Serial.print(" milliamps");

    Serial.println("");

    if (mA <= 3) //making sure there is no error message

    {

    Serial.println("Error: Sensor or System Error");

    errorCheck = 1;

    }

    else if (mA >= 21) {

    Serial.println("Error: Sensor or System Error");

    errorCheck = 1;

    }

    else if (mA <= 4) {

    Serial.println("Error: measurements are under the sensor's range");

    errorCheck = 1;

    }

    else if (mA >= 20) {

    Serial.println("Error: measurements are above the sensor's range");

    errorCheck = 1;

    }

    // else {

    //Current ranges from 2 mA - 22 mA

    // volume flow rate output ranges from 0 m3/h to 320 m3/h

    float volumeFlow = (mA * 20) - 80; //converting into ltr/h

    Serial.println("");

    Serial.print("The current volumetric flow is: ");

    Serial.print(volumeFlow);

    Serial.print(" ltr/h");

    Serial.println("");

    // }

    delay(2000);

    }

    delay(2000);

    }

  • Lukas

    Member
    March 15, 2023 at 3:32 pm

    Hi Barrels,

    at first to the Modbus. Before you start the integration of the sensor with the CONTROLLINO, please try to control the sensor from a PC with RS485-USB converter and some Modbus RTU Master application. You will easily fine proper registry numbers and meanings etc.

    To the analog measurement. You cannot directly connect current loop 4-20 mA to CONTROLLINO analog input. You should use external 500 Ohm resistor to convert it to voltage suitable for the CONTROLLINO analog input.

    Good luck!

    Lukas

  • barrels

    Member
    March 16, 2023 at 12:45 pm

    Hi Lukas,

    Thank you for the response! I have gotten a bit further with this since I made this post. I have connected the sensor with the computer using a converter, as you said. On ModbusPoll, I can read the temperature values out perfectly. However, when the Controllino is connected, I only read out zero’s.

    I have been playing around with the two Controllino Modbus example to understand how Modbus works better. Now I have following issue: any slave register higher than 207 returns a 0 to the master. I was trying to set up the master code so that it could also work with the sensor. The slave register I need is 1418 (notably higher than 207). This is regardless of what value the slave Controllino has in its register at the desired address.

    As for the analog, we figured that out and it works well. Ideally, we would like a digital communcation rather than an analog one.

    Here is my current slave code:

    #include <Controllino.h> /* Usage of CONTROLLINO library allows you to use CONTROLLINO_xx aliases in your sketch. */

    #include "ModbusRtu.h" /* Usage of ModBusRtu library allows you to implement the Modbus RTU protocol in your sketch. */

    /*

    CONTROLLINO - Modbus RTU protocol Slave example for MAXI and MEGA, Version 01.00

    The sketch is relevant only for CONTROLLINO variants MAXI and MEGA (because of necessity of RS485 interface)!

    This sketch is intended as an example of the communication between devices via RS485 with utilization the ModbusRTU protocol.

    In this example the CONTROLLINO is used as the Modbus slave!

    For more information about the Modbus protocol visit the website: http://modbus.org/

    Modbus master device can read Modbus 16bit registers (provided by the slave):

    0 - analog CONTROLLINO_A0 value (0 - 1024)

    1 - digital CONTROLLINO_D0 value (0/1)

    2 - Modbus messages received

    3 - Modbus messages transmitted

    Modbus master device can write Modbus 16bit registers:

    4 - relay CONTROLLINO_R0 (0/1)

    5 - relay CONTROLLINO_R1 (0/1)

    6 - relay CONTROLLINO_R2 (0/1)

    7 - relay CONTROLLINO_R3 (0/1)

    To easily evaluate this example you need a second CONTROLLINO as Modbus master running DemoModbusRTUMaster example sketch.

    Please note that both CONTROLLINOs need 12/24V external supply and you need to interconnect GND, -, + signals of RS485 screw terminal.

    Modbus Master-Slave library for Arduino (ModbusRtu.h) was taken from the website: https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino

    It was necessary to modify setting of the PORTJ for pins DE and RE control. These pins are located at the PORJ and on the pins PIN6(DE) and PIN5(RE).

    IMPORTANT INFORMATION!

    Please, select proper target board in Tools->Board->Controllino MAXI/MEGA before Upload to your CONTROLLINO.

    (Please, refer to https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library if you do not see the CONTROLLINOs in the Arduino IDE menu Tools->Board.)

    Created 30 March 2017

    by David

    https://controllino.biz/

    (Check https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library for the latest CONTROLLINO related software stuff.)

    */

    // Serial configuration settings

    #define SerialBaudRate 19200

    #define SerialConfig SERIAL_8N1 // 8 bits de datos parity:even 1 stop bit

    // This MACRO defines Modbus slave address.

    // For any Modbus slave devices are reserved addresses in the range from 1 to 247.

    // Important note only address 0 is reserved for a Modbus master device!

    #define SlaveModbusAdd 1

    // The object ControllinoModbuSlave of the class Modbus is initialized with three parameters.

    // The first parametr specifies the address of the Modbus slave device.

    Modbus ControllinoModbusSlave(SlaveModbusAdd); // Default serial interface is Serial3 where is located the RS485 on MAXI and MEGA models.

    // This uint16 array specified internal registers in the Modbus slave device.

    // Each Modbus device has particular internal registers that are available for the Modbus master.

    // In this example sketch internal registers are defined as follows:

    // (ModbusSlaveRegisters 0 - 3 read only and ModbusSlaveRegisters 4 - 7 write only from the Master perspective):

    // ModbusSlaveRegisters[0] - Read an analog value from the CONTROLLINO_A0 - returns value in the range from 0 to 1023.

    // ModbusSlaveRegisters[1] - Read an digital value from the CONTROLLINO_D0 - returns only the value 0 or 1.

    // ModbusSlaveRegisters[2] - Read the number of incoming messages - Communication diagnostic.

    // ModbusSlaveRegisters[3] - Read the number of number of outcoming messages - Communication diagnostic.

    // ModbusSlaveRegisters[4] - Sets the Relay output CONTROLLINO_R0 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[5] - Sets the Relay output CONTROLLINO_R1 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[6] - Sets the Relay output CONTROLLINO_R2 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[7] - Sets the Relay output CONTROLLINO_R3 - only the value 0 or 1 is accepted.

    const int regsize = 2000;

    uint16_t ModbusSlaveRegisters[regsize];

    // The setup function runs once when you press reset (CONTROLLINO RST button) or connect the CONTROLLINO to the PC

    // In the setup function is carried out port setting and initialization of communication of the Modbus slave protocol.

    void setup()

    {

    pinMode(CONTROLLINO_R0, OUTPUT); // Set the pin CONTROLLINO_R0 as output.

    pinMode(CONTROLLINO_R1, OUTPUT); // Set the pin CONTROLLINO_R1 as output.

    pinMode(CONTROLLINO_R2, OUTPUT); // Set the pin CONTROLLINO_R2 as output.

    pinMode(CONTROLLINO_R3, OUTPUT); // Set the pin CONTROLLINO_R3 as output.

    pinMode(CONTROLLINO_D0, INPUT); // Set the pin CONTROLLINO_D0 as input - Read digital value at the pin D0.

    pinMode(CONTROLLINO_A0, INPUT); // Set the pin CONTROLLINO_A0 as input - Read analog value at the pin A0

    ControllinoModbusSlave.begin(SerialBaudRate, SerialConfig); // Init Modbus RTU with the defined serial configs

    }

    // The loop function runs over and over again forever

    void loop()

    {

    // This instance of the class Modbus checks if there are any incoming data.

    // If any frame was received. This instance checks if a received frame is Ok.

    // If the received frame is Ok the instance poll writes or reads corresponding values to the internal registers (ModbusSlaveRegisters).

    // Main parameters of the instance poll are address of the internal registers and number of internal registers.

    ControllinoModbusSlave.poll(ModbusSlaveRegisters, regsize);

    // While are not received or sent any data, the Modbus slave device periodically reads the values of analog and digital outputs.

    // Also it updates the other values of registers.

    ModbusSlaveRegisters[9] = 5; // Read the analog input CONTROLLINO_A0.

    ModbusSlaveRegisters[1] = 4; // Read the digital input CONTROLLINO_A0.

    ModbusSlaveRegisters[207] = ControllinoModbusSlave.getInCnt(); // Read the number of incoming messages.

    ModbusSlaveRegisters[208] = ControllinoModbusSlave.getOutCnt(); // Read the number of outcoming messages

    ModbusSlaveRegisters[300] = 10;

    ModbusSlaveRegisters[70] = 10;

    ModbusSlaveRegisters[1417] = 30;

    ModbusSlaveRegisters[1418] = 30;

    ModbusSlaveRegisters[1419] = 30;

    digitalWrite(CONTROLLINO_R0, ModbusSlaveRegisters[4]); // Update the relay output CONTROLLINO_R0 - ON/OFF

    digitalWrite(CONTROLLINO_R1, ModbusSlaveRegisters[5]); // Update the relay output CONTROLLINO_R1 - ON/OFF

    digitalWrite(CONTROLLINO_R2, ModbusSlaveRegisters[6]); // Update the relay output CONTROLLINO_R2 - ON/OFF

    digitalWrite(CONTROLLINO_R3, ModbusSlaveRegisters[7]); // Update the relay output CONTROLLINO_R3 - ON/OFF

    }

    /* End of the example. Visit us at https://controllino.biz/ or contact us at info@controllino.biz if you have any questions or troubles. */

    /* 2017-03-31: The sketch was successfully tested with Arduino 1.8.1, Controllino Library 1.1.0 and CONTROLLINO MAXI and MEGA. */

    Here is my current master code:

    #include <Controllino.h> /* Usage of CONTROLLINO library allows you to use CONTROLLINO_xx aliases in your sketch. */

    #include "ModbusRtu.h" /* Usage of ModBusRtu library allows you to implement the Modbus RTU protocol in your sketch. */

    /*

    CONTROLLINO - Modbus RTU protocol Master example for MAXI and MEGA, Version 01.00

    The sketch is relevant only for CONTROLLINO variants MAXI and MEGA (because of necessity of RS485 interface)!

    This sketch is intended as an example of the communication between devices via RS485 with utilization the ModbusRTU protocol.

    In this example the CONTROLLINO is used as the Modbus master!

    For more information about the Modbus protocol visit the website: http://modbus.org/

    Modbus master device periodically reads Modbus 16bit registers (provided by the slave) and prints the current state to the debug Serial:

    0 - analog CONTROLLINO_A0 value (0 - 1024)

    1 - digital CONTROLLINO_D0 value (0/1)

    2 - Modbus messages received

    3 - Modbus messages transmitted

    Modbus master device periodically writes and toggles Modbus 16bit registers:

    4 - relay CONTROLLINO_R0 (0/1)

    5 - relay CONTROLLINO_R1 (0/1)

    6 - relay CONTROLLINO_R2 (0/1)

    7 - relay CONTROLLINO_R3 (0/1)

    To easily evaluate this example you need a second CONTROLLINO as Modbus slave running DemoModbusRTUSlave example sketch.

    Please note that both CONTROLLINOs need 12/24V external supply and you need to interconnect GND, -, + signals of RS485 screw terminal.

    Modbus Master-Slave library for Arduino (ModbusRtu.h) was taken from the website: https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino

    It was necessary to modify setting of the PORTJ for pins DE and RE control. These pins are located at the PORJ and on the pins PIN6(DE) and PIN5(RE).

    IMPORTANT INFORMATION!

    Please, select proper target board in Tools->Board->Controllino MAXI/MEGA before Upload to your CONTROLLINO.

    (Please, refer to https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library if you do not see the CONTROLLINOs in the Arduino IDE menu Tools->Board.)

    Created 30 March 2017

    by David

    https://controllino.biz/

    (Check https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library for the latest CONTROLLINO related software stuff.)

    */

    // Serial configuration settings

    #define SerialBaudRate 19200

    #define SerialConfig SERIAL_8N1 // 8 bits de datos parity:even 1 stop bit

    // This MACRO defines Modbus master address.

    // For any Modbus slave devices are reserved addresses in the range from 1 to 247.

    // Important note only address 0 is reserved for a Modbus master device!

    #define MasterModbusAdd 0

    #define SlaveModbusAdd 1

    // The object ControllinoModbuSlave of the class Modbus is initialized with three parameters.

    // The parameter specifies the address of the Modbus device.

    Modbus ControllinoModbusMaster(MasterModbusAdd); // Default serial interface is Serial3 where is located the RS485 on MAXI and MEGA models.

    // This uint16 array specified internal registers in the Modbus slave device.

    // Each Modbus device has particular internal registers that are available for the Modbus master.

    // In this example sketch internal registers are defined as follows:

    // (ModbusSlaveRegisters 0 - 3 read only and ModbusSlaveRegisters 4 - 7 write only from the Master perspective):

    // ModbusSlaveRegisters[0] - Read an analog value from the CONTROLLINO_A0 - returns value in the range from 0 to 1023.

    // ModbusSlaveRegisters[1] - Read an digital value from the CONTROLLINO_D0 - returns only the value 0 or 1.

    // ModbusSlaveRegisters[2] - Read the number of incoming messages - Communication diagnostic.

    // ModbusSlaveRegisters[3] - Read the number of number of outcoming messages - Communication diagnostic.

    // ModbusSlaveRegisters[4] - Sets the Relay output CONTROLLINO_R0 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[5] - Sets the Relay output CONTROLLINO_R1 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[6] - Sets the Relay output CONTROLLINO_R2 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[7] - Sets the Relay output CONTROLLINO_R3 - only the value 0 or 1 is accepted.

    uint16_t ModbusSlaveRegisters[8];

    // This is an structe which contains a query to an slave device

    modbus_t ModbusQuery[1];

    uint8_t myState; // machine state

    unsigned long WaitingTime;

    void setup() {

    // initialize serial communication at 9600 bits per second:

    Serial.begin(9600);

    Serial.println("-----------------------------------------");

    Serial.println("CONTROLLINO Modbus RTU Master Test Sketch");

    Serial.println("-----------------------------------------");

    Serial.println("");

    // ModbusQuery 0: read registers

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

    ModbusQuery[0].u8fct = 03; // function code (this one is registers read)

    ModbusQuery[0].u16RegAdd = 207; // start address in slave

    ModbusQuery[0].u16CoilsNo = 1; // number of elements (coils or registers) to read

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

    ControllinoModbusMaster.begin(SerialBaudRate, SerialConfig); // Init Modbus RTU with the defined serial configs

    ControllinoModbusMaster.setTimeOut(5000); // if there is no answer in 5000 ms, roll over

    WaitingTime = millis() + 1000; // Sets length of wait state time

    myState = 0; // holder for whether Master is waiting, sending a message, or recieving one

    }

    void loop() {

    switch( myState ) {

    case 0:

    if (millis() > WaitingTime) myState++; // wait state - will break once 1000 ms have passed

    break;

    case 1:

    ControllinoModbusMaster.query( ModbusQuery[0] ); // send query (only once)

    myState++;

    break;

    case 2:

    ControllinoModbusMaster.poll(); // check incoming messages (recieve message)

    if (ControllinoModbusMaster.getState() == COM_IDLE)

    {

    // response from the slave was received

    myState = 0;

    WaitingTime = millis() + 1000;

    // debug printout to check if values are correct

    Serial.println(ModbusSlaveRegisters[0], DEC);

    //Serial.println(ModbusSlaveRegisters[1], DEC);

    // Serial.println(ModbusSlaveRegisters[2], DEC);

    // Serial.println(ModbusSlaveRegisters[3], DEC);

    // Serial.println(ModbusSlaveRegisters[4], DEC);

    Serial.println(" ");

    }

    break;

    }

    }

    /* End of the example. Visit us at https://controllino.biz/ or contact us at info@controllino.biz if you have any questions or troubles. */

    /* 2017-03-31: The sketch was successfully tested with Arduino 1.8.1, Controllino Library 1.1.0 and CONTROLLINO MAXI and MEGA. */

  • barrels

    Member
    April 19, 2023 at 8:40 am

    The issue was with the parity. The sensor was sending even parity, so I changed “#define SerialConfig SERIAL_8N1” into “#define SerialConfig SERIAL_8E1”. The next challenge was converting the modbus value into a float value that I could use. Here is the current master program:

    #include <Controllino.h> /* Usage of CONTROLLINO library allows you to use CONTROLLINO_xx aliases in your sketch. */

    #include "ModbusRtu.h" /* Usage of ModBusRtu library allows you to implement the Modbus RTU protocol in your sketch. */

    /*

    CONTROLLINO - Modbus RTU protocol Master example for MAXI and MEGA, Version 01.00

    The sketch is relevant only for CONTROLLINO variants MAXI and MEGA (because of necessity of RS485 interface)!

    This sketch is intended as an example of the communication between devices via RS485 with utilization the ModbusRTU protocol.

    In this example the CONTROLLINO is used as the Modbus master!

    For more information about the Modbus protocol visit the website: http://modbus.org/

    Modbus master device periodically reads Modbus 16bit registers (provided by the slave) and prints the current state to the debug Serial:

    0 - analog CONTROLLINO_A0 value (0 - 1024)

    1 - digital CONTROLLINO_D0 value (0/1)

    2 - Modbus messages received

    3 - Modbus messages transmitted

    Modbus master device periodically writes and toggles Modbus 16bit registers:

    4 - relay CONTROLLINO_R0 (0/1)

    5 - relay CONTROLLINO_R1 (0/1)

    6 - relay CONTROLLINO_R2 (0/1)

    7 - relay CONTROLLINO_R3 (0/1)

    To easily evaluate this example you need a second CONTROLLINO as Modbus slave running DemoModbusRTUSlave example sketch.

    Please note that both CONTROLLINOs need 12/24V external supply and you need to interconnect GND, -, + signals of RS485 screw terminal.

    Modbus Master-Slave library for Arduino (ModbusRtu.h) was taken from the website: https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino

    It was necessary to modify setting of the PORTJ for pins DE and RE control. These pins are located at the PORJ and on the pins PIN6(DE) and PIN5(RE).

    IMPORTANT INFORMATION!

    Please, select proper target board in Tools->Board->Controllino MAXI/MEGA before Upload to your CONTROLLINO.

    (Please, refer to https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library if you do not see the CONTROLLINOs in the Arduino IDE menu Tools->Board.)

    Created 30 March 2017

    by David

    https://controllino.biz/

    (Check https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library for the latest CONTROLLINO related software stuff.)

    */

    // Serial configuration settings

    #define SerialBaudRate 19200

    #define SerialConfig SERIAL_8E1 // 8 bits de datos parity:even 1 stop bit

    // This MACRO defines Modbus master address.

    // For any Modbus slave devices are reserved addresses in the range from 1 to 247.

    // Important note only address 0 is reserved for a Modbus master device!

    #define MasterModbusAdd 0

    #define SlaveModbusAdd 1

    // The object ControllinoModbuSlave of the class Modbus is initialized with three parameters.

    // The parameter specifies the address of the Modbus device.

    Modbus ControllinoModbusMaster(MasterModbusAdd); // Default serial interface is Serial3 where is located the RS485 on MAXI and MEGA models.

    // This uint16 array specified internal registers in the Modbus slave device.

    // Each Modbus device has particular internal registers that are available for the Modbus master.

    // In this example sketch internal registers are defined as follows:

    // (ModbusSlaveRegisters 0 - 3 read only and ModbusSlaveRegisters 4 - 7 write only from the Master perspective):

    // ModbusSlaveRegisters[0] - Read an analog value from the CONTROLLINO_A0 - returns value in the range from 0 to 1023.

    // ModbusSlaveRegisters[1] - Read an digital value from the CONTROLLINO_D0 - returns only the value 0 or 1.

    // ModbusSlaveRegisters[2] - Read the number of incoming messages - Communication diagnostic.

    // ModbusSlaveRegisters[3] - Read the number of number of outcoming messages - Communication diagnostic.

    // ModbusSlaveRegisters[4] - Sets the Relay output CONTROLLINO_R0 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[5] - Sets the Relay output CONTROLLINO_R1 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[6] - Sets the Relay output CONTROLLINO_R2 - only the value 0 or 1 is accepted.

    // ModbusSlaveRegisters[7] - Sets the Relay output CONTROLLINO_R3 - only the value 0 or 1 is accepted.

    uint16_t ModbusSlaveRegisters[8];

    // This is an structe which contains a query to an slave device

    modbus_t ModbusQuery[1];

    uint8_t myState; // machine state

    unsigned long WaitingTime;

    void setup() {

    // initialize serial communication at 9600 bits per second:

    Serial.begin(9600);

    Serial.println("-----------------------------------------");

    Serial.println("CONTROLLINO Modbus RTU Master Test Sketch");

    Serial.println("-----------------------------------------");

    Serial.println("");

    // ModbusQuery 0: read registers

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

    ModbusQuery[0].u8fct = 3; // function code (this one is registers read)

    ModbusQuery[0].u16RegAdd = 1418; // start address in slave

    ModbusQuery[0].u16CoilsNo = 2; // number of elements (coils or registers) to read

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

    // ModbusQuery[1].u8id = SlaveModbusAdd; // slave address

    // ModbusQuery[1].u8fct = 03; // function code (this one is registers read)

    // ModbusQuery[1].u16RegAdd = 0; // start address in slave

    // ModbusQuery[1].u16CoilsNo = 1; // number of elements (coils or registers) to read

    // ModbusQuery[1].au16reg = ModbusSlaveRegisters;

    ControllinoModbusMaster.begin(SerialBaudRate, SerialConfig); // Init Modbus RTU with the defined serial configs

    ControllinoModbusMaster.setTimeOut(5000); // if there is no answer in 5000 ms, roll over

    WaitingTime = millis() + 1000; // Sets length of wait state time

    myState = 0; // holder for whether Master is waiting, sending a message, or recieving one

    }

    void loop() {

    switch( myState ) {

    case 0:

    if (millis() > WaitingTime) myState++; // wait state - will break once 1000 ms have passed

    break;

    case 1:

    ControllinoModbusMaster.query( ModbusQuery[0] ); // send query (only once)

    //ControllinoModbusMaster.query( ModbusQuery[1] ); // send query (only once)

    myState++;

    break;

    case 2:

    ControllinoModbusMaster.poll(); // check incoming messages (recieve message)

    if (ControllinoModbusMaster.getState() == COM_IDLE)

    {

    // response from the slave was received

    myState = 0;

    WaitingTime = millis() + 1000;

    // debug printout to check if values are correct

    Serial.println(ModbusSlaveRegisters[0], HEX);

    Serial.println(ModbusSlaveRegisters[1], HEX);

    Serial.println(ModbusSlaveRegisters[2], DEC);

    // float floatRes = (float)((uint32_t)ModbusSlaveRegisters[1]<<8);

    // float floatRes = (float)((((uint32_t)ModbusSlaveRegisters[1]) << 16) | ((uint32_t)ModbusSlaveRegisters[0]));

    // int16_t int16Value = (ModbusSlaveRegisters[0] << 8) | ModbusSlaveRegisters[1];

    //

    // // Convert the int16 value to a float

    // float floatValue = (float)int16Value;

    //

    // // Print the float value

    // Serial.print("Float value: ");

    // Serial.println(floatRes);

    // shift by 2 bytes

    uint32_t x = (uint32_t) ModbusSlaveRegisters[0] << 16;

    /*

    * pointer magic:

    * take theint pointer of the int x

    * cast the pointer into a float pointer

    * dereference the pointer back into a floating point value

    */

    float f = *((float*) &x);

    Serial.println(f);

    Serial.println(ModbusSlaveRegisters[0]);

    Serial.println(" ");

    }

    break;

    }

    }

    /*

    *

    * /

    */

    /* End of the example. Visit us at https://controllino.biz/ or contact us at info@controllino.biz if you have any questions or troubles. */

    /* 2017-03-31: The sketch was successfully tested with Arduino 1.8.1, Controllino Library 1.1.0 and CONTROLLINO MAXI and MEGA. */

Viewing 1 - 4 of 4 replies

Log in to reply.

Original Post
0 of 0 posts June 2018
Now