Note-arduino library: could you add Rx, Tx pin options to Notecard.begin()

I am using the note-arduino library, with an ESP32-S3 microprocessor, in my cellular IoT prototype. I use UART1 to talk to the Notecard. The ESP32-S3 supports reassigning serial ports to most any of the GPIO pins, and my PCB design takes advantage of this feature. The Arduino code would be Serial.begin (9600, 8N1, RX_PIN, TX_PIN);

The Note-arduino does not support the pin number arguments in Notecard.begin() but I’ve been able to succeed by defining them with this workaround code:

Serial1.begin(9600, SERIAL_8N1, PIN_RX_FROM_NOTECARD,PIN_TX_TO_NOTECARD);
delay(1000);
notecard.begin(Serial1, 9600);

BUT beginning with V1.6.0 of the library, the workaround stopped working! I can see in the library that a Serial.end is now being issued before Serial.begin. This must be wiping out my pin definitions, I’m stuck on V1.5.4 of the library and worried my product will stop working in the future.

So I’m entering this as a fix/enhancement request: support optional definition of alternative Serial port pins in the Notecard.begin() function.

2 Likes

Apparently, ESP32 has extended the standard Arduino begin() method (shown below), and this is the source of the problem. I believe the bug you are experiencing is a side effect of Espressif’s implementation.

The standard Arduino HardwareSerial::begin method does not allow you to declare the pins, only a baud and configuration.

AVR Core: HardwareSerial::begin

    void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
    void begin(unsigned long, uint8_t);

Typically, you would need to create a new SoftwareSerial object, and provide the pins to the constructor.

AVR Core: SoftwareSerial:SoftwareSerial

SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false);

Here is a link to the reference material for the SoftwareSerial library.


1 Like

Hi Zak,
I did try SoftwareSerial, but although it compiles, my board locks up. I don’t have deep debugging, but I’d guess it’s an interrupt or timing conflict. That’s why I used one of the ESP32’s three hardware UART peripherals rather than implementing a UART in software. And it worked fine until library version 1.60.

Unless you have a way to extend the library to support ESP32 devices, I’m stuck on 1.54. I could redesign the PCB to use i2c instead of serial comms, but that’s a major setback when a few lines of code could (I think) fix it.

I agree that a hardware redesign is most likely not the correct path forward.

Maybe you can help me level up my ESP32 knowledge.

If you are using one of the ESP32’s three hardware UART peripherals, then why it is necessary to specify the pin numbers?

For example, STM32 creates different Serial objects for each interface (e.g. Serial, Serial1, Serial2, etc…), and each of those objects have the pins predefined by the ST BSP.

I’m surprised the ESP32 doesn’t work in a similar fashion.

Putting my curiosity aside, let me attempt to devise a compromise that will allow you to provide an “as is” Serial object that I will use and not modify.

Best,
Zak

I greatly appreciate your looking into a compromise solution that lets me pass an “as is” Serial object to the library.

Regarding your curiosity about the ESP32, I think the issue is that there are so many variations available, and so many built-in peripherals besides its 3 UARTs, that Expressif decided to only route UART0 to pins 36/37 by default, and default the rest of the pins to GPIOs (the ESP32 has a matrix that allows routing most of its peripherals to most any pins).

Here’s the datasheet for the ESP32-S3 module which I use. I tried tweaking the board variant file to route UART1 (which I use for the Notecard) to the pins I wanted. It worked – in firmware 1.54 – but also broke in 1.6.x.

If you can solve this you will have my eternal gratitude!

Hi @mark_pdx,

I have not forgotten about you. I’m currently reviewing the code to find a path forward.

Here is the exact line that was introduced in v1.6.0, which is causing you grief.

Unfortunately, I cannot change this behavior. To do so would be introducing a bug.

I do have an ESP32-S3 on my bench. Tomorrow, I will do some more digging, and see if I can figure out some alternatives for you.

Best,
Zak

@mark_pdx,

I have an ESP32-S3-WROOM-1, and I’m trying to work up a repro.

Can you tell me the exact pins you are using for TX/RX?

Thanks,
Zak

Sure thing:
#define PIN_RX_FROM_NOTECARD 18
#define PIN_TX_TO_NOTECARD 17

Oops, let me clarify that:
I’m using GPIO pin 18 (physical pin 11 on the WROOM-1 module) to RECEIVE from the Notecard serial port (pin 64 on the socket).
I’m using GPIO pin 17 (physical pin 10 on the WROOM-1 module) to TRANSMIT to the Notecard serial port (pin 62 on the socket).

1 Like

Hi @mark_pdx

What board definition are you using with the Arduino SDK?

I’ve got the ESP32-S3-DevKitC-1, and I’m struggling to find an Arduino board definition.

Thanks,
Zak

After you go into preferences for the Arduino IDE, you put https://espressif.github.io/arduino-esp32/package_esp32_index.json
into the “Additional Boards Manager URLs”. Restart the IDE and you should find the ESP32 option under Tools>Boards. Under the ESP32 option, there are dozens of choices. I am using the “Adafruit Feather ESP32-S3 No PSRAM” choice but you should be able to use any of the ESP32-S3 boards.

Actually, this article probably explains it better than I can.

@mark_pdx,

I’m not sure it’s quite as simple as selecting any choice from the list.

Are you actually using the “Adafruit Feather ESP32-S3” in your hardware configuration? If so, then perhaps I can purchase one so we can compare apples and apples.

Thanks,
Zak

My hardware isn’t an Adafruit Feather PCB. It’s my own custom PCB, using the module from Expressif (ESP32-S3-WROOM-1-N8). I simply chose the Adafruit board file because it’s one that matched the flash and PSRAM specs of the module.

Is the issue that the DevKit you obtained not listed?

Hi @mark_pdx,

Thanks for sharing that.

Yes, that is part of my problem. I have the ESP32-S3-WROOM-1-N8R2, configured as a ESP32-S3-DevKitC-1.

The chip itself is equivalent to the Adafruit Feather ESP32-S3 2MB PSRAM, but the pins are routed differently on the ESP32-S3-DevKitC-1 than they are on the Feather and the board is not behaving correctly as a result.

I’m curious something similar is causing your attempt at using SoftwareSerial to manifest as a runtime error.

I will purchase a the Adafruit Feather ESP32-S3 No PSRAM, and see if I can get things working.

Setting that aside for a moment, it seems like the best path forward for you today would be for you to patch note-arduino, and provide an empty NoteSerial_Arduino::reset function.

Change the following lines:

to:

bool
NoteSerial_Arduino::reset (
    void
)
{
    return true;
}

Can you give that a try and tell me if that fixes your immediate problem?

Thanks,
Zak

1 Like

OK, I updated to Blues library V1.6.3 (was running on 1.5.4 before), then edited by commenting out the two lines.

Voila! Compiles, runs, ESP talks to Notecard, and cellular connection established. Sweet!

What issue was that Serial.end / Serial/begin reset function addressing? Is there something else I should test?

Hi @mark_pdx,

That’s great, I’m glad to hear I was able to correctly identify the issue, and now you have a workaround.

In general, NoteSerial_Arduino::reset allows the host to teardown and rebuild the communication channel with the Notecard when communication errors are detected. It also performs a reset as the very first interaction with the Notecard as a simple handshake to ensure the Notecard is ready and listening. It is not strictly necessary, as you have discovered.

The reason the change was implemented is due to the fact that some (not all) platforms leak memory if HardwareSerial.begin() is called multiple times without calling HardwareSerial.end() in between.

This was discovered when we created our ArduinoIoTCloud integration. When unable to connect, the ArduinoIoTCloud library will tear down and rebuild the connection as many times as it requires to successfully establish a connection.

If you want to create a test, I would suggest calling HardwareSerial.begin(), measure the memory usage using the standard malloc.h library, then call HardwareSerial.begin() 100 times in a loop and measure the memory again.

Checking the memory usage would look something like this:

 #include <malloc.h>
 ...
 size_t allocated_memory;
 size_t heap_size;
 size_t free_memory;
 ...
 void updateMemoryAllocationInfo (void) {
   struct mallinfo mem;
   memset(&mem, 0, sizeof(struct mallinfo));
   mem = mallinfo();
 
   allocated_memory = mem.uordblks;
   heap_size = mem.arena;
   free_memory = mem.fordblks;
   return;
}

I’m aware that some popular Arduino libraries have memory leak issues, in particular the WiFi library. Also strings can cause fragmentation. My design automatically reboots every night after midnight to mitigate this. I have test units that have been running for 9 months without a problem thanks to this.

Hi @mark_pdx,

Perhaps a bit unorthodox, but it sounds like your implementation is impervious to any memory leak issues. :joy:

In your case, it sounds like you don’t need to create any additional tests. Also, the Notecard should be able to recover (the original purpose of NoteSerial_Arduino::reset), nightly at a bare minimum.

Best,
Zak