Modbus Timeout Issue with DAQFactory and Arduino Uno for Sensor Data Logging


Recommended Posts

Hi everyone,

I'm experiencing an issue with my DAQFactory setup and would appreciate any help you can offer. Here’s a summary of my setup and the problem I’m facing:

Setup:

  • Sensors: Sensirion SCD30 (CO2, temperature, and humidity)
  • Microcontroller: Arduino Uno
  • Communication Protocol: I2C between sensors and Arduino; Serial Modbus between Arduino and DAQFactory on the computer
  • DAQFactory: Used as the master for controlling the Arduino and logging the data

Problem:

Initially, the setup works perfectly, and the graphs display the measurements accurately. However, after some time, the measurements turn into flat lines, indicating that no data updates are being received. The error messages in DAQFactory indicate a timeout issue.

Observed Errors:

  • Multiple ModbusRTU 0010: Timeout errors.

Configuration Details:

  1. DAQFactory Interface:

    • The interface shows average CO2 concentration, temperature, and relative humidity.
    • Graphs display data correctly initially but then become flat lines after a period.
  2. Serial Port Configuration:

    • Baud Rate: 9600
    • Byte Size: 8
    • Parity: None
    • Stop Bits: 1
    • Timeout: 1000 ms
  3. Channel Configuration:

    • Channels for CO2 concentration, temperature, and humidity are set to read using the Modbus conversion.
    • The channels are linked to the Arduino Uno device, set to read holding registers.
  4. Sensor Code on Arduino:

    • The Arduino code is set to measure every 2 seconds using an if statement, allowing the slave.poll to run continuously.

Synchronization Attempt:

The measurement interval on the Arduino is set to 2 seconds, which is the same as the timing interval assigned to the channels in DAQFactory. Initially, I suspected that this synchronization might be causing the problem. If the computer attempts to poll data while the Arduino is busy measuring, it could result in continuous errors. To avoid this, a colleague suggested using the command Device.Arduino_Uno.SetDelay(40) in DAQFactory to introduce a slight delay. However, this hasn't resolved the issue.

Troubleshooting Steps Taken:

 

  • Ensured all connections between sensors and Arduino and between Arduino and the computer were secure.
  • Double-checked the serial port and channel configurations in DAQFactory to match the hardware setup.
  • Reviewed the Arduino code for any potential issues with data reading or communication but found none.
  • Noted that the data logging stops after a period, and error messages suggest a timeout in the Modbus communication.
  • Tried using Device.Arduino_Uno.SetDelay(40) to introduce a slight delay and avoid timing conflicts, but this did not resolve the issue.

Request for Assistance:

I am seeking help to understand why the Modbus communication is timing out after an initial period of successful data logging. Any insights into potential causes or further troubleshooting steps would be greatly appreciated. If you need more information or specific details about my setup, please let me know!

Thank you so much for your assistance!

Connection.JPG

Air_Monitor_error.JPG

Link to comment
Share on other sites

  • Luca changed the title to Modbus Timeout Issue with DAQFactory and Arduino Uno for Sensor Data Logging

Using SetDelay() isn't going to help.  That won't change the interval between queries.  Instead, just change the timing.  So if the arduino is every 2 seconds, set the timing to 2.1.  But, this is really just chasing the symptoms, not determining the cause and thus the cure.  The problem is certainly to do with the Arduino and its capabilities (or lack of), and as you suggested, probably it is busy when DAQFactory makes its query.  Do you have access to the Arduino code?  If so, and all you are using it for is reading 3 variables, I would just not use Modbus and instead just have the Arduino dump the three readings as an ASCII string every time it gets a new reading.  Something like:

402.324, 23.4, 32.4\r\n

A few lines of script would allow DAQFactory to parse that easily and then you won't have any synchronization problems trying to get DAQFactory to only query the Arduino when the Arduino is not busy.

Link to comment
Share on other sites

Thank you for your the suggestion. I will try using the Arduino to dump the three readings as an ASCII string and parse that in DAQFactory, as you suggested. This seems like a good way to avoid the synchronization issues.

Additionally, I'm experiencing another error intermittently: P-ModbusRTU 0014: ID Mismatch. This error occurs for about 30 seconds at a time and then stops. I suspect that using another protocol of communication as you suggested might resolve this issue as well, but I would like to understand why this error occurs in the first place.

Here is the Arduino code that might help diagnose the issue: 

#include <Arduino.h>
#include <SensirionI2cScd30.h>
#include <Wire.h>
#include <ModbusRtu.h>

// Data array for Modbus network sharing
uint16_t au16data[3] = {0, 0, 0}; // Initialize only the required registers

// Modbus object declaration
Modbus slave(1, Serial, 0); // This is slave @1 and RS-232 or USB-FTDI

SensirionI2cScd30 sensor;

float co2Concentration = 0.0;
float temperature = 0.0;
float humidity = 0.0;

unsigned long previousMillis = 0UL;
int waiting_time = 2000;

void setup() {
    slave.begin(9600); // Start Modbus communication

    Wire.begin();
    sensor.begin(Wire, SCD30_I2C_ADDR_61);

    // Initialize sensor for periodic measurements
    int16_t error = sensor.stopPeriodicMeasurement();
    if (error != NO_ERROR) {
        Serial.print("Error stopping periodic measurement: ");
        Serial.println(error);
    }
    
    error = sensor.softReset();
    if (error != NO_ERROR) {
        Serial.print("Error performing soft reset: ");
        Serial.println(error);
    }

    delay(2000); // Allow time for reset

    error = sensor.startPeriodicMeasurement(0); // Start measurement without ambient pressure compensation
    if (error != NO_ERROR) {
        Serial.print("Error starting periodic measurement: ");
        Serial.println(error);
    } else {
        Serial.println("Periodic measurement started.");
    }

    Serial.println("Setup completed.");
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis > waiting_time) {
    // Check if sensor data is ready
    uint16_t dataReady = 0;
    int16_t error = sensor.getDataReady(dataReady);
    if (error != NO_ERROR) {
        Serial.print("Error getting data ready status: ");
        Serial.println(error);
        return;
    }

    if (dataReady == 1) {
        error = sensor.readMeasurementData(co2Concentration, temperature, humidity);
        if (error != NO_ERROR) {
            Serial.print("Error reading sensor data: ");
            Serial.println(error);
        } else {
            // Map sensor data to Modbus registers
            au16data[0] = (co2Concentration); // CO2 concentration in ppm
            au16data[1] = (temperature * 100); // Temperature in degrees Celsius (scaled by 100)
            au16data[2] = (humidity * 100); // Humidity in % (scaled by 100)

            Serial.print("CO2 : ");
            Serial.print(au16data[0]);
            Serial.print(", Temperature : ");
            Serial.print(au16data[1]);
            Serial.print(", Humidity : ");
            Serial.println(au16data[2]);
        }
    } else {
        Serial.println("Data not ready.");
    }

    previousMillis = currentMillis;
  }

  // Poll Modbus
  slave.poll(au16data, 3);
}

I hope this helps to understand the root cause of the ID Mismatch error. I look forward to your insights on this issue.

Thanks again for your assistance!

Link to comment
Share on other sites

I'd really have to see the comm monitor in DAQFactory to tell what is happening.  It sounds like a simple synchronization issue, but I'd have to see what the Arduino unit was sending back from DAQFactory queries.

Link to comment
Share on other sites

Thank you for your follow-up. I tried the method you previously proposed, where the Arduino dumps the three readings as an ASCII string, and now it is working correctly. This approach has resolved the synchronization issues.

Thanks again for your help and guidance.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.