If the device is to be standalone, then Serial.print etc messages will not be received (over USB Serial). Discussion of workarounds, with a formal solution.

In the main, because RTS-CTS handshaking is not used here with USB Serial, Serial.print/Serial.println serial data can be ignored without consequence.

 if(Serial)

and

 while(!Serial)

are more problematic though and will be blocking without any serial transmission.

It would be “tidier” but onerous to remove all Serial.print/ln commands and make the condition of the other 2 always true and always false respectively. This may introduce timing issues though. It is better use some hash defines and conditional macros to switch the Serial commands on and off as required.

The Solution

A header file serial_macros.h was created and included in softata.h.

The solution was to allow for a multi-pronged solution in that it allowed for a variety options with respect to serial debug messages:

#ifdef SOFTATA_DEBUG_MODE
 #define USE_USB_SERIAL
#else
// #define INSTEAD_OF_USB_SERIAL_DELAY 10
// #define INSTEAD_OF_USB_USE_SERIAL1
// #define INSTEAD_OF_USB_USE_SERIAL2  
// #define INSTEAD_OF_USB_USE_BTSERIAL
#endif

To send the debug messages over USB-Serial just define SOFTATA_DEBUG_MODE in softata.h. If not defined then one of the other can be uncommented. Alternatively, if none are uncommented then the serial print macros evaluate to a null bracket. The delay option is similar to the null option except that in the bracket a 10mS delay is implemented. SERiAL1 and SERIAL2 options require RS232TTL level to USB adapter, that can be displayed in a PC using, for example, Putty. The Bluetooth option can be monitored on a Bluetooth terminal. I use “Serial Bluetooth Terminal” on my phone.

The Serial.print marcos in the source code are turned into macros by replacing in bulk the dot with an underscore.

Serial.begin

becomes

Serial_begin

Each option has a specific implementation of the set of macros such as for USB Serial:

#ifdef USE_USB_SERIAL
#define Serial_begin(...) Serial.begin(__VA_ARGS__)
#define ifSerial()   if(Serial)
#define whileNotSerial() while(!Serial)
#define Serial_print(...) Serial.print(__VA_ARGS__)
#define Serial_printf(...) Serial.printf(__VA_ARGS__)
#define Serial_println(...) Serial.println(__VA_ARGS__)
#elif INSTEAD_OF_USB_SERIAL_DELAY
...

The macros for when USB Serial is used.

Note that with most of the macros, variable arguments are facilitated. if(Serial) and while(!Serial) had to be treated differently as the macros ifSerial() and whileNotSerial() respectively.

Each of the alternatives implements the same set of macros. The complete set is:

#ifdef USE_USB_SERIAL
#define Serial_begin(...) Serial.begin(__VA_ARGS__)
#define ifSerial()   if(Serial)
#define whileNotSerial() while(!Serial)
#define Serial_print(...) Serial.print(__VA_ARGS__)
#define Serial_printf(...) Serial.printf(__VA_ARGS__)
#define Serial_println(...) Serial.println(__VA_ARGS__)
#elif INSTEAD_OF_USB_SERIAL_DELAY
#define Serial_begin(...) {delay(INSTEAD_OF_USB_SERIAL_DELAY);}
#define ifSerial()  {delay(INSTEAD_OF_USB_SERIAL_DELAY);}if(true)
#define whileNotSerial()  {delay(INSTEAD_OF_USB_SERIAL_DELAY);}while(false)
#define Serial_print(...) {delay(INSTEAD_OF_USB_SERIAL_DELAY);}
#define Serial_printf(...) {delay(INSTEAD_OF_USB_SERIAL_DELAY);}
#define Serial_println(...) {delay(INSTEAD_OF_USB_SERIAL_DELAY);}
#elif defined(INSTEAD_OF_USB_USE_SERIAL1)
// UART0RX etc defined in softata.h
#define Serial_begin(...) {Serial1.setRX(UART0RX);Serial1.setTX(UART0TX);}Serial1.begin(__VA_ARGS__)
#define ifSerial(...)   if(Serial1)
#define whileNotSerial() while(!Serial1)
#define Serial_print(...) Serial1.print(__VA_ARGS__)
#define Serial_printf(...) Serial1.printf(__VA_ARGS__)
#define Serial_println(...) Serial1.println(__VA_ARGS__)
#elif defined(INSTEAD_OF_USB_USE_SERIAL2)
// UART1RX etc defined in softata.h
#define Serial_begin(...) {Serial1.setRX(UART1RX);Serial1.setTX(UART1TX);}Serial1.begin(__VA_ARGS__)
#define ifSerial(...)   if(Serial1)
#define whileNotSerial(...) while(!Serial1)
#define Serial_print(...) Serial1.print(__VA_ARGS__)
#define Serial_printf(...) Serial1.printf(__VA_ARGS__)
#define Serial_println(...) Serial1.println(__VA_ARGS__)
#elif defined(INSTEAD_OF_USB_USE_BTSERIAL)
#include <SerialBT.h>
// Nb: Start this Sketch. Connect from BT Terminal and press [Enter] there.
#define Serial_begin(...) {if(!SerialBT){SerialBT.begin();while (!SerialBT);while(!SerialBT.available());}}
#define ifSerial(...)   if(SerialBT)
#define whileNotSerial() while (!SerialBT)
#define Serial_print(...) SerialBT.print(__VA_ARGS__)
#define Serial_printf(...) SerialBT.printf(__VA_ARGS__)
#define Serial_println(...) SerialBT.println(__VA_ARGS__)
#else
#define Serial_begin(...) {}
#define ifSerial(...)  if(false)
#define whileNotSerial(...)  while(false)
#define Serial_print(...) {}
#define Serial_printf(...) {}
#define Serial_println(...) {}
#endif

These all work except the Serial2 option. (2Do).

One issue

One coding clean up was required when using these macros. Where there was code such as …

if (<some condition>)
    Serial.println("OK");
else
    Serial.print("NOK");

This required brackets such as:

if (<some condition>)
{
    Serial_println("OK");
}
else
{
    Serial_print("NOK");
}

Usage

  • Use the SoftataOptSerial version of the sketch in the repository. This will at a later stage replace the original sketch in the repository.
  • If using Serial1 connect a TTL to RS232 converter (first socket at bottom on left of Grove RPi Pico shield). Nb: Serial2 version isn’t working. For example use Freetronics USB Serial Adapter. Three wires only needed:
    • USBDev-Grove Socket
    • Gnd-Gnd (black Grove cable)
    • Tx-Rx (yellow Grove cable)
    • Rx-Tx (white grove cable)
  • define/or not SOFTATA_DEBUG_MODE in softata.h
  • If not defined and messages are not required build and deploy this version of Softata, over USB serial.
  • Otherwise uncomment one of the options build and deploy.
  • The device can now be booted without the USB connection if that mode is not used.
  • If using Bluetooth or Serial1 mode open a terminal to it. The sketch will block until it opens. Also, for Bluetooth send a [Return] and it will activate once the top level app connects.
    • Connect a top level app ie the Console, Blazor or Blockly apps and drive the device.

Conclusion

These serial debug macros work quite seamlessly in Softata and provide a blueprint for anyone wishing to switch debug messages in and out of Arduino C/C++ code.

The next step is to modify the Softata code, with these macros, for the OTA capability


 TopicSubtopic
   
 This Category Links 
Category:Softata Index:Softata
  Next: > Softata
<  Prev:   Softata