Skip to content

Modbus communication fails when using the library, even when debugging mode is disabled #35

@haveyouseenf

Description

@haveyouseenf

I wrote a sketch for my Opta that reads periodically from the register of a device connected via Modbus, then writes the value in a text file stored on a USB device. Unfortunately, I noticed that when using this library I am no longer able to read from the device using the Modbus channel, as ModbusRTUClient.read() returns -1 which corresponds to an error.

I suspect this happens because on the Opta the Arduino_UnifiedStorage library uses serial RS485 for debug purposes. I set debuggingModeEnabled to false in my code, but nothing changed.
The only workaround I was able to find is to move the RS485 and Modbus initialization at the end of my setup() code, however it is error prone and I find it odd that the Arduino_UnifiedStorage would change my serial configuration when debugging is disabled. Furthermore, I could not find any documentation on this.

I managed to reproduce the issue multiple times, so I will attach the setup() code below so you can see how moving the serial and Modbus init code changes the behavior of the ModbusRTUClient.read():

void setup()
{
    // Here read fails.
    // Output is: "Read value is: 4294967295", which is 0xFFFFFFFF error from ModbusRTUClient.read()
    // modbusInit(38400, SERIAL_8N1);

    // Disable debugging of storage operations.
    Arduino_UnifiedStorage::debuggingModeEnabled = false;

    // Init USBStorage object.
    usbStorage = USBStorage();

    // Here read fails.
    // Output is: "Read value is: 4294967295", which is 0xFFFFFFFF error from ModbusRTUClient.read()
    // modbusInit(38400, SERIAL_8N1);

    // Register connect and disconnect callback.
    usbStorage.onConnect(connectionCallback);
    usbStorage.onDisconnect(disconnectionCallback);

    // Here read works.
    // Output is: "Read value is: 17968", which is expected
    modbusInit(38400, SERIAL_8N1);

    delay(5000);
}

For completeness, I will also attach the full code of the sketch so you can take a look and try to reproduce the issue if you want:

Click to expand
#include <ArduinoModbus.h>
#include <ArduinoRS485.h>
#include <Arduino_UnifiedStorage.h>

USBStorage usbStorage;
volatile bool usbAvailable = false;

int address = 20;
int reg = 9;
int numBytes = 1;

int readDelay = 5000;

void setup()
{
    // Here read fails.
    // Output is: "Read value is: 4294967295", which is 0xFFFFFFFF error from ModbusRTUClient.read()
    // modbusInit(38400, SERIAL_8N1);

    // Disable debugging of storage operations.
    Arduino_UnifiedStorage::debuggingModeEnabled = false;

    // Init USBStorage object.
    usbStorage = USBStorage();

    // Here read fails.
    // Output is: "Read value is: 4294967295", which is 0xFFFFFFFF error from ModbusRTUClient.read()
    // modbusInit(38400, SERIAL_8N1);

    // Register connect and disconnect callback.
    usbStorage.onConnect(connectionCallback);
    usbStorage.onDisconnect(disconnectionCallback);

    // Here read works.
    // Output is: "Read value is: 17968", which is expected
    modbusInit(38400, SERIAL_8N1);

    delay(5000);
}

void loop()
{
    if (usbAvailable)
    {
        digitalWrite(LED_USER, HIGH);
        ModbusRTUClient.requestFrom(address, INPUT_REGISTERS, reg, numBytes);
        uint32_t data = ModbusRTUClient.read();
        String out = "Read value is: " + String(data) + "\n";
        writeToFile(out);

        digitalWrite(LED_D0, LOW);
        digitalWrite(LED_D1, LOW);
        digitalWrite(LED_D2, LOW);
        digitalWrite(LED_D3, LOW);
        digitalWrite(LED_USER, LOW);
    }

    unsigned long start = millis();
    while (millis() < start + readDelay)
    {
        digitalWrite(LED_D0, LOW);
        digitalWrite(LED_D1, LOW);
        digitalWrite(LED_D2, LOW);
        digitalWrite(LED_D3, LOW);
        delay(500);
        digitalWrite(LED_D0, HIGH);
        digitalWrite(LED_D1, HIGH);
        digitalWrite(LED_D2, HIGH);
        digitalWrite(LED_D3, HIGH);
        delay(500);
    }
}

// Modbus operations.

void modbusInit(int baudrate, int serialConfig)
{
    uint32_t preDelay, postDelay, timeout;
    float bitDuration = 1.f / baudrate;

    if (baudrate <= 19200)
    {
        preDelay = postDelay = bitDuration * 9.6f * 3.5f * 1e6;
        timeout = 200;
    }
    else
    {
        preDelay = postDelay = 1750;
        timeout = 1000;
    }

    RS485.setDelays(preDelay, postDelay);
    ModbusRTUClient.setTimeout(timeout);
    if (ModbusRTUClient.begin(baudrate, serialConfig) != 1)
    {
        while (1)
        {
        }
    }
}

// Write operations.

void writeToFile(String data)
{
    if (!usbStorage.isMounted())
    {
        digitalWrite(LED_D0, HIGH);
        usbStorage.begin();
    }

    Folder rootDir = usbStorage.getRootFolder();
    UFile outFile = rootDir.createFile("output.txt", FileMode::APPEND);

    outFile.write(data);
    digitalWrite(LED_D1, HIGH);

    outFile.close();
    digitalWrite(LED_D2, HIGH);

    usbStorage.unmount();
    digitalWrite(LED_D3, HIGH);
}

// // Callbacks.

void connectionCallback()
{
    usbAvailable = true;
    usbStorage.removeOnConnectCallback();
}

void disconnectionCallback()
{
    usbAvailable = false;
    usbStorage.onConnect(connectionCallback);
}

For the record, I tried patching the library by changing Boards.h at line 24 like this:

#if defined(ARDUINO_OPTA)
    #define HAS_USB
    #define HAS_QSPI
    #define USES_MBED_CORE
    #define QSPI_STORAGE_SIZE 16384
    // #define HAS_RS485
#endif 

but the library would still change my serial configuration. If I can provide further details or assistance just let me know!

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions