Adventures with the ESP32

As part of a project to check if locally generated electromagnetic interference (EMI) would affect LoRa receiver performance at its weak signal limits I needed a ESP32 board that I could plug Mikrobus modules into. Faster microcontrollers, such as the ESP32 are becoming the norm, which is understandable, they are cheap, fast, have lots of memory and in the case of the ESP32, have built in Wifi and Bluetooth. Faster microcontrollers, however, generate more EMI, so I wanted to do a LoRa reception comparison with various microcontrollers. For the comparison to be valid I needed to use the same LoRa module for different controller boards, the easiest way to achieve that was to have the LoRa device on a plug in Mikrobus board, there are some details of Mikrobus modules here;

https://www.mikroe.com/blog/mikrobus-is-growing-and-its-everywhere

RFM98

The RFM98 module above is assembled using my own low cost PCBs, in this case the Mikrobus module PCB is modified from standard to allow access to all the LoRa device DIO pins. The advantage of having a controller board that accepts Mikrobus modules is that it is easy to re-purpose the controller board simply by fitting a different type of Mikrobus module, see the Mikroelectronica link above for the possibilities.

But which ESP32 board to use ?  There are several, the Wemos Lolin 32 seems popular, but I really wanted to be able to plug in a choice of batteries and not be restricted to a Lithium battery. The NodeMcu32s fits the bill, its one of the smaller ESP32 boards and provides access to the voltage(battery) in pin. The board is shown below.

NodeMcu32s

Designing a Mikrobus module PCB for the NodeMcu32s was easy enough, I use Eagle, but what had me stuck was which of the pins of the NodeMcu32s you could you use as inputs, outputs, interrupts or analogue and more importantly which pins did you need to avoid using for fear of interfering with the ESP32 itself or the attached flash.

I decided to design my board layout first and then check that I could get the functions I wanted out of the pins, the functions I needed were;

Outputs, flash an LED, drive a chip select.

Inputs, read a switch or interrupt.

Analogue, read a battery voltage for instance.

Pulse Width Modulation, not needed for my board, but useful for the Mikrobus sockets.

UART transmit and receive, two channels.

I2C, read and write to a FRAM and SSD1306 OLED display

Micro SD card read and write.

LoRa device, read and write

So as well as checking the basic pin functions, I needed test programs for each of the above to confirm it would all work in practice. After a couple of days of testing and checking I worked out which pins you can use on the NodeMcu32s and which ones to avoid, they are listed below, with comments against each pin.

esp__nodemcu-32s_pinout

0 Input, shared with the IO0 switch on the board, this switch needs to be pressed, pin held low, to download a program

1 TX output from serial console, I made no connection to this pin

2 Output, shared with the LED on the board

3 RX input to serial console, I made no connection to this pin

4 Analogue, used to read battery level

5 Output, SPI SS, used for chip select on LoRa device

6 Could not use, appears to be used by flash

7 Could not use, appears to be used by flash

8 Could not use, appears to be used by flash

9 Could not use, appears to be used by flash

10 Could not use, appears to be used by flash

11 Could not use, appears to be used by flash

12 Input, can be used as a switch input, but be sure to leave it floating during programming. There is a pull up to VCC on the board and when this pin is high the correct voltage for the Flash is selected. If the pin is low programming will fail

13 Input, Serial1 RX, you can select any of the available input pins for the RX when defining the Serial1 instance

14 Input, Serial1 TX, you can select any of the available input pins for the TX when defining the Serial1 instance

15 Input and Output, LoRa device DIO2 interrupt input or PWM output

16 Input, Serial2 RX, you can select any of the available input pins for the RX when defining the Serial2 instance

17 Output, Serial2 TX, you can select any of the available input pins for the TX when defining the Serial2 instance

18 Output, SPI SCK, used for the LoRa device and SD card

19 Input, SPI MISO, used for the LoRa device and SD card

21 SDA, used for the SSD1306 display and I2C FRAM

21 SCL, used for the SSD1306 display and I2C FRAM

23 Output, SPI MOSI, used for the LoRa device and SD card

25 Output, used for chip select on SD card

26 Analogue, used to read battery level

27 Output, used for the RST on the LoRa device

32 Output, PWM

33 Input only, used for used for reading external switch

34 Input only, needs external pull-up, used for reading DIO1 on LoRa device

35 Input only, needs external pull-up, used for reading DIO0 on LoRa device

36 Input only, needs external pull-up, used for reading DIO3 on LoRa device

39 Input only, needs external pull-up, used for reading external switch

EN Input, External reset, pull to ground for reset.

VIN External power input. Intended supply is 4 x AA Alkaline or NiMh batteries.

It is not clear why pins 6 to 11 are provided on the board, you do not appear to be able to use them. These pins are not present on some other ESP32 boards such as the Wemos Lolin32.

Although the pin mappings above are the defaults for the NodeMcu32 board you can map the pins for SPI, I2C, UART or PWM to any available pins, although not 6,7,8,9,10,11,12. I have also not tried redirecting these interfaces to 34,35,36,37.

There are some capacitors associated with pins 36 (VP) and 39 (VN) but they did not appear to interfere with the relatively slow interrupts you will get from a LoRa device for instance.

Program space

I have a program that I use for LoRa link testing, it receives LoRa packets and logs the SNR, RSSI and contents to the Serial monitor and SD card. When compiled for an Arduino Pro Mini the program consumes this much space;

Sketch uses 19562 bytes (63%) of program storage space. Maximum is 30720 bytes.
Global variables use 1292 bytes (63%) of dynamic memory, leaving 756 bytes for local variables. Maximum is 2048 bytes
.

For the NodeMcu32s it consumes this amount of space;

Sketch uses 159701 bytes (12%) of program storage space. Maximum is 1310720 bytes.
Global variables use 12348 bytes (4%) of dynamic memory, leaving 282564 bytes for local variables. Maximum is 294912 bytes.

So although the NodeMcu32s reports as having 1,310,720 bytes of available Flash, compared to 30,720 for the Pro Mini, compiled ESP32 programs consume that space at around 8 times the rate for an ATMega328 program, so you don’t have as much useable program space as you might think.


Lost in a (wet or dry) Forest

So just how far will LoRa transmissions go in a forest that is wet?

I decided to find out.

Local to me is a park that has in the middle of it an area of forest and undergrowth around 300M x 200m. I wanted a location where I could create a reference test, so at one end of the forest, the left mark in the map below, I placed a stick on the ground in the undergrowth and held it in place with pegs. I would use this to line up the tip of the antenna on the test transmitter. Thus in subsequent tests the antenna would be in the same location.

Wet or dry forest pic1

On the map the test route distance between the two marks is 200m. The forest is fairly overgrown with a lot of low level vegetation. Below are some pictures of the ‘forest’ so you can appreciate the depth of the undergrowth. The first picture below is from the transmitter location on the left of the map looking towards the receiver location on the right.

Wet or dry forest pic2

The second picture, below, is from the receiver looking towards the transmitter.

Wet or dry forest pic3

This third picture is the test transmitter, an Arduino Pro Mini and RFM98 LoRa device placed in a metal box. A ¼ wave wire antenna is used for the transmitter and receiver. The transmitter is shown bellow with a 10dB attenuator in place to reduce the signal from the antenna to both legal levels, 10dBm in the UK, and to provide a practical range for the receiver. The test transmitter is on the ground amongst the vegetation (worst case location perhaps). The receiver was held in my hand with the tip of the ¼ wave wire antenna at around 1.5M from the ground.

Wet or dry forest pic4

The test method involves sending a series of packets at descending power, 17dBm to 2dBm. The power level used to send the packet is part of the data in the packet. The receiver can then tell the power used to send the packets it is receiving. So if the receiver stops receiving packets at 10dBm, you have quantified how much power is needed to cover the distance.

The LoRa settings were, 434.4Mhz, bandwidth 62.5khz, spreading factor 8, code rate 4:5, explicit mode. This represents a data rate of 1562bps.

At the time of the test its had been raining overnight and for most of the morning. It was raining heavily during the test, the forest was very wet. The test transmitter had a 10dB attenuator in place.

Packets sent at 6dBm power were the lowest received, so taking account of the 10dB attenuator, the packets were in effect being transmitted at -4dBm or 0.4mW.

The first test was with the forest fairly wet and a couple of weeks later it had been dry for several days so I repeated the test with the same equipment with the antennas in the same position and location. This time the packets were just received at -9dB, so the dry forest was 5dB better than the wet. Or more simply when the forest was wet, signals were reduced by around 5dB.

So big question, if the transmissions had been at 10mW (normal ISM band limit) then how far might the signals propagate in worst case (wet) conditions?

If packets are sent at 10dBm but -4dBm is enough to cover the 200m then there is a link margin at 200m of 14dBm. Thus if the forest is assumed to be uniform an extra 14dB on link gain should increase the distance by 5 times, or to 1000m.

If the full 17dBm (50mW) of the transmitter was used the distance covered could increase to 2200m.

There is more, for this test the signals were being sent at a LoRa data rate of 1562bps, if the data rate was lowered to 150bps, which is fine for a lot of data gathering and control applications, range would increase by a further 3 times when using the same power.