arduino-libraries / Arduino_UnifiedStorage

Read and write files to flash, USB mass storage and SD cards in a unified way.
GNU Lesser General Public License v2.1
11 stars 3 forks source link

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

Closed haveyouseenf closed 5 months ago

haveyouseenf commented 8 months ago

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 ```cpp #include #include #include 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!

sebromero commented 8 months ago

Thank you @haveyouseenf for reporting! We will investigate.

sebromero commented 6 months ago

Potential fix is being tested. See https://github.com/arduino-libraries/Arduino_POSIXStorage/pull/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 commented 5 months ago

@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?