CMB27 / ModbusRTUSlave

This is an Arduino library that implements the slave/server logic of the Modbus RTU protocol.
MIT License
58 stars 14 forks source link

Compile problem with ARM based boards like RP2040 and STM32 #22

Closed aquiot-inc closed 1 year ago

aquiot-inc commented 1 year ago

There seems to be a compile problem with data types for some ARM based boards like RP2040 and STM32.

The example below is Arduino 2 using ModbusRTUSlave Arduino library V1.0.5 for example file Coils_HardwareSerial.ino for board Raspberry Pi Pico using the Arduino Mbed OS RP2040 Boards core:

C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino: In function 'void setup()':
C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino:80:54: error: invalid conversion from 'char (*)(unsigned int)' to 'ModbusRTUSlave::BoolRead {aka signed char (*)(short unsigned int)}' [-fpermissive]
   modbus.configureCoils(numCoils, coilRead, coilWrite);
                                                      ^
In file included from C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino:28:0:
c:\proj\Arduino\libraries\ModbusRTUSlave\src/ModbusRTUSlave.h:15:10: note:   initializing argument 2 of 'void ModbusRTUSlave::configureCoils(uint16_t, ModbusRTUSlave::BoolRead, ModbusRTUSlave::BoolWrite)'
     void configureCoils(uint16_t numCoils, BoolRead coilRead, BoolWrite coilWrite);
          ^~~~~~~~~~~~~~
C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino:80:54: error: invalid conversion from 'boolean (*)(unsigned int, boolean) {aka bool (*)(unsigned int, bool)}' to 'ModbusRTUSlave::BoolWrite {aka bool (*)(short unsigned int, bool)}' [-fpermissive]
   modbus.configureCoils(numCoils, coilRead, coilWrite);
                                                      ^
In file included from C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino:28:0:
c:\proj\Arduino\libraries\ModbusRTUSlave\src/ModbusRTUSlave.h:15:10: note:   initializing argument 3 of 'void ModbusRTUSlave::configureCoils(uint16_t, ModbusRTUSlave::BoolRead, ModbusRTUSlave::BoolWrite)'
     void configureCoils(uint16_t numCoils, BoolRead coilRead, BoolWrite coilWrite);
          ^~~~~~~~~~~~~~

exit status 1

Compilation error: invalid conversion from 'char (*)(unsigned int)' to 'ModbusRTUSlave::BoolRead {aka signed char (*)(short unsigned int)}' [-fpermissive]

Similar compile problems also for STM32. Would be good to support the newer ARM based processors as AVR has supply chain issues and is old/expensive technology.

CMB27 commented 1 year ago

I think this has to do with the way different microcontrollers interpret the unsigned int datatype. With an AVR, unsinged int is always a 16 bit variable. On other processors, unsigned int may be a 32 bit datatype.

In the library files, ModbusRTUSlave.h and ModbusRTUSlave.cpp, I use the datatypes uint16_t, which specifies an unsigned 16 bit integer, regardless of processor, but in the example programs I used unsigned int, because this is in line with the Arduino style.

I have no plans of specifically supporting STM32 or ARM microcontrollers at this time, but I will be giving some thought on how to better deal with processors that consider an unsigned int to be a 32 bit variable.

A quick fix to your issue (I think) would be to change all the Unsigned ints in the sketch to uint16_ts.

aquiot-inc commented 1 year ago

Yes, ambiguous data types are the problem. These changes fix Coils_HardwareSerial.ino so that it compiles. I have not tested it in hardware yet.

@@ -44,7 +44,7 @@ boolean toneActive = 0;
 unsigned int toneFrequency = 2000;

 // This is a function that will be passed to ModbusRTUSlave for reading coils.
-char coilRead(unsigned int address) {
+int8_t coilRead(uint16_t address) {
   switch (address) {
     case 0:
       return digitalRead(ledPin);
@@ -57,7 +57,7 @@ char coilRead(unsigned int address) {
 }

 // This is a function that will be passed to ModbusRTUSlave for writing to coils.
-boolean coilWrite(unsigned int address, boolean value) {
+boolean coilWrite(uint16_t address, boolean value) {
   switch (address) {
     case 0:
       digitalWrite(ledPin, value);

I'm always in favour of using unambiguous data types from stdint.h.