Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
haveyouseenf opened this issue Jan 25, 2024 · 3 comments
Assignees
Labels
conclusion: resolved Issue was resolved topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project

Comments

@haveyouseenf
Copy link

haveyouseenf commented Jan 25, 2024

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!

@per1234 per1234 added type: imperfection Perceived defect in any part of project topic: code Related to content of the project itself labels Jan 25, 2024
@sebromero
Copy link
Contributor

Thank you @haveyouseenf for reporting! We will investigate.

@sebromero
Copy link
Contributor

Potential fix is being tested. See arduino-libraries/Arduino_POSIXStorage#21
@haveyouseenf If you like to help testing you would need to install the latest version of Arduino_POSIXStorage library from its main branch in the repository.

@haveyouseenf
Copy link
Author

@sebromero sorry for the delay! I tested with the patched Arduino_POSIXStorage library and that indeed fixed the issue. I plan to close this issue once the updated library is officially available via arduino-cli, agreed?

@per1234 per1234 closed this as completed Apr 12, 2024
@per1234 per1234 added the conclusion: resolved Issue was resolved label Apr 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
conclusion: resolved Issue was resolved topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
Development

No branches or pull requests

4 participants