ESP32, Arduino and EEPROM memory

ESP32 MCUs can be a great replacement for popular ATmega328 Arduino boards, but they are somewhat different. Even if ESP32 Espressif Arduino core is used, some of the libraries will not work out of the box.

Just like EEPROM will not work without changes. Mainly because ESP32 does not have EEPROM memory. An external flash is used instead.

Good thing, ESP32 EEPROM library distributed together with Espressif ESP32 Arduino core solves this problem in a quite nice way. All you have to do is to call EEPROM.begin with a size of emulated storage size in bytes as an argument. From there, everything goes as before.

ESP32 and GPS with a help of TinyGPS++ library

One of the first projects I did with ESP32 development boards is a simple GPS tracker. OK, it's not really a tracker since it does not store the position anywhere, more like distance meter with a UBLOX Neo-8M Beitian BN-880 GPS unit and small SSD1306 OLED display.

This ESP32 GPS Thingy as I call it uses one button to store current position and then report straight line distance, speed and altitude compared to "Home Point". GPS communication is handled by TinyGPS++ library.

Oh, one the best things about ESP32 is that you can map ports to almost any pin you want. It's not like on ATmega328 where UART and I2C are always the same pins. Here you can choose them. How nice is that?

Code is available on GitHub.

Getting started with ESP32 development boards and Arduino

However fond of good old Arduinos based on ATmega328 and ATmega32u4 we might be, no one can now say they are state of the art. Sure, they might be the first choice to do something cheap and simple, but compared to most more modern designs, they are just too old and too weak. Slow, little flash memory, little RAM, no built-in connectivity: no Bluetooth or WiFi.

When a few years ago ESP8266 started to appear, everything changed. The tinkers finally got something small and cheap with WiFi. And then, the world has changed, since ESP32 it the market.

Geekcreit ESP32 development board

Continue reading Getting started with ESP32 development boards and Arduino

Crossbow LRS: ready for next tests

Looks like I was able to solve all major known problems with my DIY long range radio system Crossbow. I'm writing known, since no idea what lies beneath… Anyhow… What changed? Quite a lot:

  • I've extended Arduino-LoRa library with ability to transfer full packet in single SPI transaction. Right now, each read of write to SX1276 uses single transaction. Previously, there were 2 transactions per byte…
  • The same library now has ability to send packets in async mode. Previously it was blocking code execution until LoRa packet was transmitted. Huge waste on processing time
  • With OpenTX 2.2.1 on the loose, I was finally able to drop PPM input from Taranis to TX module and replace it with S.BUS. But not without problems. According to specification, S.Bus should be SERIAL_8E2. But my Taranis clearly outputs it as SERIAL_8N2
  • For now, OLED display is disabled. It was taking too much time to update it using I2C and TX module was loosing S.Bus packets
  • I've improved RC channels processing time, time required for encoding/decoding went down by 1ms
  • It is still LoRa32u4 II 868MHz based but I'm considering different hardware. For example ESP32 with LoRa. Time will show

Crossbow LRS development with LoRa32u4 and SX1276

Next test hopefully this weekend. If weather allows, of course. We have very wet autumn this winter in central Europe this year…

Crossbow LRS, I’m still doing this wrong…

Only two weeks ago I thought I solved all my major problems with DIY LoRa RC link. I was wrong. I was able to solve one problem (link unstable due to rouge packets messing up with protocol decoding), but an old problem came up again: PPM input from Taranis is no longer stable. At least I know why since this is a second time this is happening.

Current code read bytes from SX1276 buffer inside interrupt callback procedure (ISR). PPM decoding is also done in ISR. How many threads ATmega has? What happens when one ISR is triggered while second is still executed? Problems. The solution is to keep ISRs as simple and fast as possible. My code was not simple and fast enough.

On top of that, it turned out that Arduino LoRa library I’m using is not efficient. It performs 2 SPI transactions to read one byte from SX1276 FIFO buffer. So, 12 bytes of typical data packet equals 24 SPI transaction… Looks like I will have to do some low-level coding I wanted to avoid in the beginning… Oh well…

Arduino hygrometer with DHT11 and SSD1306 OLED display

One of the things I like about Arduino ecosystem is that you can prototype pretty decent device in very short time. It might not be pretty, but will work. Just like my DIY hygrometer built with DHT11 and SS1306 OLED display I've built few weeks ago:

Simple, efficient and runs on 4 AA batteries. The best part is that it can be powered all the time. Arduino does humidity measurement, display the result and then powers itself down to conserve power. Cool, right?

Arduino DHT11 hygrometer with OLED SSD1306 display

Code is available in GitHub repository.

Visual Studio Code as Arduino IDE replacement

I can say a lot of good things about Arduino ecosystem. List will quite long, trust me on that. But Arduino ecosystem has one thing that sucks a lot: Arduino IDE. Programming environment for Arduino is crap. Period. I would not call it the worse development environment ever, but it's pretty close to that title. C'mon, Turbo Pascal from the early nineties of previous century was a better IDE!

There were few project to fix that problem. Somehow none of those really worked until Microsoft did not decided to do something about it and created

Visual Studio Code extension for Arduino

Arduino for Visual Studio Code
Continue reading Visual Studio Code as Arduino IDE replacement

Arduino, ESP32 and 3 hardware serial ports

When working with ESP32 WiFi/Bluetooth MCU under Arduino SDK for ESP32, you will notice that Serial work just fine. But Serial1 and Serial2 do not. ESP32 has 3 hardware UARTs that can be mapped to almost any pin. But, Serial1 and Serial2 will not work. In case of ESP32 this just has to be done in a slightly different way:

The trick is to use HardwareSerial library to access UART 1 and 2 instead of Serial1 and Serial2

ESP32 WiFi bluetooth development board

  • Class HardwareSerial accepts one parameter in constructor, it is a number of UART. Values from 0 (UART 1) to 2 (UART 3)
  • HardwareSerial(0) is the same as Serial so be aware
  • begin method accepts 4 parameters
    • baud speed
    • UART mode
    • RX pin
    • TX pin
      The real beauty of this solution is that almost any pin can be used as TX or RX pin for any UART. Most ESP32 dev boards have labels like TX2 or RX2, but you really do not have to exactly those pins. Every other GPIO pin can act as Serial RX, but only the ones between GPIO0 and GPIO31 can be used as TX. Still, that gives plenty of pins to choose from…

More about ESP32 can be read in Getting Started With ESP32 and Arduino post.

Crossbow LRS, hardware

Weather outside is bitchy. Period. It rains, then it's windy and then maybe there is some direct sunlight for 15 minutes. No way to fly or test my DIY RC radio link.

Weather is bitchy

But, there is some progress after all. My latest changes seems to be working just fine. On a bench link was stable for almost 3 hours. Later I too it for a standard range test: 2.8km LOS. It also worked, I still had around 5dB of link budget left on a ground level.

Back to the topic. Crossbow LRS is open source and open hardware. Maybe open hardware is too much, since there is almost no hardware to build. After all, first iteration is based on LoRa32u4 II development boards and running good old Arduino.

RX module requires no additional hardware:

Crossbow LRS receiver module

TX module is slightly more complex. It required voltage stabilizer and inverter/level shifter made with single 2N7000 FET transistor. I2C OLED display is an option:

Crossbow LRS transmitter module

A proper way of doing read callback receive with Arduino LoRa

Arduino LoRa is a great library that brings LoRa support (SX1276/SX1277/SX1278/SX1279) to Arduino world. I'm using it in my Crossbow LRS project (still not stable enough for flight, work in progress). Until now, the biggest problem with this library I've found is that examples suggests that heavy protocol processing inside interrupt callback is fine.

Unfortunately, it is not. It can lead to unexpected processing delays, create conflicts with other interrupts, bus clashes and other hard to debug things. This is why, the better way is to do packet reading (and processing) inside main loop and use read callback only to set a flag. Like this:

Only please remember to set all variables modified in ISR routine as volatile.