How to IoT: MQTT on Nucleo and ESP8266

Have you ever heard of Internet of Things? How about MQTT protocol? I think so. But maybe you didn’t start an IoT project of your own yet. If yes, the time is now. In this post you will find the details of my project on STM32F103 Nucleo board running FreeRTOS and ESP8266 WiFi module, logging temperature data to Eclipse MQTT broker using Paho Embedded library.

Short on MQTT

It is a data protocol which is the core of the most IoT devices. What makes it so special is the simplicity and efficiency of course. There is a broker (host) and multiple clients. Clients have 2 cards: they can publish a message to the broker with a topic name or they can subscribe to a topic and receive all messages that are posted to this topic. All communication passes through the broker and that is the way how it becomes efficient. A publisher has to publish a message only once, and the broker re-publishes the message to all subscribers (they don’t have to poll the broker). You can evaluate one of the public brokers or install your own Mosquitto which is free and nice.

Temperature Logger Project

Hardware

The project hardware consists of STM32f103 Nucleo-64 board featuring ARM Cortex-M3 and ESP8266 WiFi SoC (ESP-01 module in my case). The module is connected to the board via PA9(TX) and PA10(RX) pins that are internally connected to USART1. Communication baud-rate is 115200 by default.

WiFi over ESP8266

Espressif’s ESP8266 SoC is very popular among DIY people since it makes things easy with integrated TCP/IP stack and possibility to work with memory constrained microcontroller systems. It only needs full-duplex UART serial port which is nearly a default hardware in every MCU. For me the only drawback is that it operates over a terminal-friendly but not software-friendly AT command set and it makes the client interface very complex.

Software

For the ones who want to try it now, the project is on GitHub and is implemented in C language. It is ready-to-compile using GNU MCU Eclipse (compile instructions). To use the project as-is, don’t forget to edit your WiFi username and password in wifi_credentials.hfile.

ESP8266 IoT Driver

I implemented as-simple-as-possible client-mode esp8266 driver that takes care of the basic operations. The driver also uses a stream-based UART driver which is built on top of c-circus -circular buffer. Both circular buffer and UART implements can be found under this repository.

Paho Embedded MQTT Library

Eclipse supported Paho library is ported for embedded C applications and can be found here. My project uses the MQTTPacket part of the library as well as the basic transport implementation. Paho Embedded also has MQTTClient codes but it is not directly compatible with ESP8266 and supports only FreeRTOS+TCP. That is why I only made use of the Packet part because it is the core.

The Project Code

This project [download] is simple for convenience. It reads the STM32 internal temperature sensor using ADC and publishes it to tcp://iot.eclipse.org:1883in every 5s inside a FreeRTOS task. The bare-metal version of transport.c from Paho implements non-blocking transport_sendPacketBuffernb(...)and transport_getdatanb(...) methods even though that are not crucial in RTOS environment. The operational block scheme of prvTemperaturePublisher(...)task is shown below.

The main.cfile content is given below. It blinks the LED on board when it is transmitting the data.

Note that networkwrapper.c can easily be modified to use another network module since it is flexible. Currently it uses ESP8266 driver and has several state machines as an overlay to the driver.

This project is implemented on a MCU with 20kB RAM but it uses less than 8kB RAM. ESP8266 driver needs several buffers to keep things smooth. If there is a tighter RAM limitation you can modify buffer sizes in  ESP8266Client.c  as well as networkwrapper.c depending on your application.

As the final note, since this project uses TCP connection (default for MQTT) we need to set keep-alive time in CONNECTION_KEEPALIVE_S and make sure it is long enough so that you can transmit messages to keep the connection alive before it times out.

Verification

I use an Android MQTT Client app to see the messages I sent from Nucleo. From the app, I subscribe to temperature/value topic and receive the messages in dashboard screen.

Final Words

The implemented code is robust enough to return to the beginning when things go wrong. However, to improve more, it is possible to send PINGREQ and to get PINGRESP between PUBLISH messages to be sure that the broker is listening. Another way is using non-zero QoS level (i.e. QoS1 or QoS2) but handling the response requires more complex background operations. Moreover, to generalize this project more, the FreeRTOS task can wait on a queue and publish the messages that were sent to that queue by other tasks.

Keep developing ?