Welcome to the Drogue IoT blog. This is where I intend to document my progress through discovering how to build enterprise-grade IoT device systems using Rust and ARM Cortex-M MCUs.


I'm coming from a background of enterprise Java development, where things can easily be rebooted, debugged, and 16gb of heap can easily be garbage-collected.

I also have virtually no experience with hardware and electronics.

As you can imagine, this journey will be full of frustrations and missteps.

Let's begin!

Status Quo

The first project I'm working on, mostly as a way to learn new things, involves replacing a project I've already built before once: Mr Weathery. Mr Weathery is built using the Particle.io cloud and Arduino-like devices, plus a Raspberry Pi 3B+ sitting in corner.

The Pi runs a node.js application that periodically polls the Netatmo weather cloud for data from my local weather sensors. It'd also poll the DarkSky APIs for weather forecasts. It would then put all of this information on the Particle.io message bus.

The first Particle.io device has both WiFi and BLE on-board, and running stock firmware it simple acts as a bridge from the IP-based Particle cloud to my main Particle.io board that only speaks BLE, which consumes all of the abovementioned data.

The BLE-only board drives an e-paper display to handily show the current and forecast weather conditions.

Mr Weathery

That's 3 boards, 2 clouds, and a 1 third-party API involved to simply tell me it's raining, or will be raining tomorrow. Given the machinations around some of these vendors, I realized I should reformulate how Mr Weathery works.

Plus, given it's a known problem domain with at least one known solution to me, I can concentrate on the implementation, not on the specification and design.

The New Plan

When originally designed, Mr Weathery was intended to be battery-powered, hence the usage of the BLE board. In reality, he's always plugged into the power mains, so the low-power requirement is less important.

If the display can also have consistent power, he can also perform all of the HTTP-over-WiFi dancing directly. That would allow me to remove both the Raspberry Pi and the WiFi-to-BLE bridge to produce a standalone device.

Instead of programming an Arduino-like device using C, I'm moving to an STM32 ARM Cortex-M chip to power it, using Rust. This is quite the change for me. So far I quite enjoy Rust, and the Cortex-M is a nice 32bit processor with more power than many Arduino-like boards.

The downside, thus far, is that the STM32s don't have WiFi on-board. While I could adapter boards or shields to a dev-kit, I'd ultimately like to fabricate a custom board around the MCU and use a simpler/smaller pre-certified WiFi module.

Given I have a bag of Espressif ESP8266 modules handy, I'm approaching it as my WiFi adapter.

STM32F401 and ESP8266

For the time-being, I'm using an STM32F401RE development board running at 84mhz for building the software. It has the benefit of having a USB port with ST-Link on-board for easily flashing and debugging the code.

Because Nothing is Easy

Of course, nothing ever is easy.

The ESP8266 is available through the USART on the STM32. It's fairly simple to wire up, and it communicates with Hayes AT commands to enumerate available WiFi access points, join a network, open sockets and communicate. The AT commands are pretty well documented, but I discovered my bag of ESP8266 were flashed with firmware in... 2016. And they don't match the current capabilities documented by Espressif.

The ESP8266 runs an Xtensa chip, which is not currently supported by embedded Rust on the mainline, and frankly, writing software directly for the ESP8266 would be an effort in Yak-shaving, so I simply need to update its stock firmware to a newer version.

While people speak of "ESP8266" as a thing, it's actually many things, with varying amount of memory on-board. Mine has 1mb. Espressif has had varying degrees of diligence in producing firmware versions that fit the various sizes of ESPs. Thankfully, a repository exists with a slightly improved build/flash situation to target whatever size ESP you might have:

ESP8266_AT_LoBo GitHub Repository

This repository is definitely Linux-centric, but a few edits to the various scripts, and it runs will enough on OSX to work.

To flash an ESP8266, you need a serial port on your machine, which is provided using an FTDI adapter. The FTDI converts a USB port into a few pins of serial port, and also provides 3.3v or 5v of power. There are many warnings on the interwebs that the current they provide is not enough to actually power an ESP during flash or usage.

To overcome this potential problem, I'm powering the ESP through a breadboard 3.3v power supply.

ESP flashing circuit

Stay Grounded

While attempting to use the ESP through a serial terminal (because it should operate like your old USRobotics 14.4k Dual Standard modem you used to connect to FidoNet...) I was finding a ton of noise, and it didn't work.

Lesson #1: All grounds must be tied together.

Even if you're not using the power from the FTDI, its ground pin needs to be connected to the same ground pin the ESP uses. Serial USART works in relation to a common reference voltage (GND), and if two devices have different concepts of ground, it's just not going to work.

Don't trust your tools

Using the flashing scripts from LoBo, everything appeared successful, yet my device kept coming up non-funcitonal. Turns out there are several flash modes for ESPs, and the esptool.py doesn't actually really verify if flashing was successful in terms of being actually successful. Rather, it just seems to think it successfully sent bytes down the wire.

Lesson #2: Try all variants until you find the one that works.

In my case, for my ESP8266, I had to use a flash-mode of dout.

Back to making progress

murray:esp8266-tcp bob$ miniterm.py /dev/tty.usbserial-AB0JSKDU 115200
--- Miniterm on /dev/tty.usbserial-AB0JSKDU  115200,8,N,1 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
LoBo ESP8266 Bootloader v1.2.0
   Flash map: 2, 1MB (512+512)
  Flash mode: DOUT, [ESP8285]
Reset reason: POWER_ON

Loading configured firmware (0)
  Address: 001000
Starting firmware 0, map 2 from 001000...


I finally got the ESP8266 updated with a modern-ish variant of the firmware and can return to writing Rust for the STM32F401RE in order to actually get that board onto the network.

More on that to come.