Sitemap

My first freelance hardware project ?

6 min read5 days ago

--

Recently a friend on X reached out to me asking if I could write firmware for an ESP32 based project.

Initially I wondered if it was for real. I was happy because people have started to take notice of the work I’ve been doing in the embedded space. I love writing code that does meaningful tasks on real hardware, but it was the first time I was about to get paid for that. I jumped at the opportunity.

I contacted the client and he sent me the project requirements, component datasheets, manuals etc.

The project -

Client wanted to make Air Quality Monitoring system using ESP32 and SHT20 and PMS5003 sensors, sending the sensor readings to client’s server (while storing the same on-device for a period of 10 hours to act as a backup), and displaying the data (from the server) on a big display board.

Press enter or click to view image in full size
A basic visualization of the project.

These two sensors are industry standard for measuring air quality. SHT20 is for recording the temperature and humidity while PMS5003 is used to measure the airborne dust particle concentration in real time. My code for ESP32 had to read the sensor readings once every minute, then it would package those readings into a proper telemetry package, and send it to the server.

I had once made something very similar to this using a DHT20 sensor from the my cheap arduino kit and an ESP32, to measure temperature & humidity and send it to my laptop via MQTT where it was displayed on a webpage. The PMS5003 sensor was new for me, but luckily Dronebot Workshop had a detailed video and an article with code examples for it. So, that was sorted too.

SHT20 would use I2C (GPIO 21 and 22) and PMS5003, a UART port (at 9600 baud) to connect to the ESP32. But there was a single problem — ESP32, SHT20 and PMS5003’s data lines worked on 3.3V, but the PMS5003's fan would need 5V.

To handle this, I would connect VCC pin of the PMS5003 to a 5V source — VIN pin of esp32 when the board was to be powered by its USB port.

Press enter or click to view image in full size
If ESP32 was powered by its USB port.

note — This VIN pin on esp32 boards is a bi-directional pin — it acts as 5V output when esp32 is powered by USB port, and it takes 5V input to power esp32 when we want to run the board from an external power supply.

Alternatively, if the client wanted to power ESP32 from an external power supply of 5V, then the output from the power supply would go into the VIN pin of esp32 and PMS5003. And their ground pins will be connected to the power supply’s ground.

Press enter or click to view image in full size
If esp32 was to be powered from an external power source.

For the firmware, I decided to use PMserial library for PMS5003 and DFRobot_SHT20 library for SHT20.

Sending data to Client’s server -

I decided to use the MQTT protocol again, as it was the easiest and the best one because : it is offline friendly, reliable, lightweight and efficient, has built-in buffering and offline support, easy to extend (in case of multiple nodes, more sensors) and could be used on the display side as well.

Press enter or click to view image in full size
ESP32 side of project,

MQTT is widely supported on ESP32 & all major server languages. There are many solid libraries that provides MQTT support for ESP32 like PubSubClient, AsyncMQTT (the one I planned to use), etc.

The setup was :

Get The Zarth Dev’s stories in your inbox

Join Medium for free to get updates from this writer.

ESP32 connects to the client’s WiFi network and sends data to a Mosquitto MQTT broker running on their server. It publishes binary messages to the topic which could be something like api/node1/readings (this makes it very easy to add more devices later).

The message is a compact struct containing a timestamp (derived from NTP), device’s health status, temperature, humidity and PM1.0, 2.5 and 10 readings. This message is also saved on the ESP32 itself.

note: All sensor readings would be calibrated before being sent, I’ll explain this later.

On-device backup for 10 hours -

An ESP32 generally comes with around 4MB of flash memory. To keep the system lean, I decided to allocate a modest 100KB partition for LittleFS, a lightweight, opensource filesystem designed for microcontrollers that use flash memory. And I decided to transmit and store binaries instead of JSON, because they take up less storage space on the microcontroller.

The client wanted to store one reading per minute, for 10 hours, which equates to 600 readings, on the hardware as a backup. These would be stored in a circular (ring-buffer style) log — delete the oldest readings to make space for the latest ones.

LittleFS handles the actual storage of data on the ESP32’s flash. It provides features like wear levelling and power-loss resilience which are really useful in a system like ours. To reduce the flash wear even further, I planned to do ‘batch writing’ — keeping a queue of recent readings inside RAM and flush them into LittleFS periodically (like once in every 10 minutes, or sooner in case of any issues in network, etc).

Calibration -

The sensor readings would be calibrated through offsets for the two sensors, that would be stored in LittleFS on ESP32 flash memory. This will keep the data safe in case of rebooting etc, and allow updation without rewriting the main code.

The offsets are small correction values that are added to the raw sensor readings to improve its accuracy.

During operation, raw sensor readings would be smoothed using a short rolling average to reduce the noise and produce more stable values. The corresponding calibration offsets are then applied to the smoothed readings before the data is packaged into a telemetry packet.

This would ensure that noise reduction and calibration correction both happen on the device itself and the server receives clean data, and has to do minimal post processing.

(I did not know how would I find these offsets. I left it for future me and moved ahead.)

Conclusion -

My plan for the sensor side of things was ready. But it was the easiest part of the project. I was not ready for the display board.

Client wanted to have a humongous bill-board size display, made out of 24 tiles of P10 display modules. These modules come together to make a single screen using special cables which is called HUB75E.

It is an entire system in itself — there is a multimedia player that receives the image/video from various sources, which is then sent to a receiving card that is responsible to make the 24 modules behave as a single large screen. The manufacturer provides software for configuration and managing what is shown on the screen. It includes APIs, libraries, and desktop, cloud and mobile applications.

This same system is used to make extra-extra large TV screens that you see on highways, concerts, stadiums, etc.

I had never worked on anything like this before. There were datasheets for the multimedia player and the receiving card, and there was manuals for configuring the display and for setting up what to play there. I am going to talk about this in the next part of my article.

If you have a project, I can help you in writing code for it.

Mail me : the.zarath.dev@gmail.com

--

--

The Zarth Dev
The Zarth Dev

Written by The Zarth Dev

If not in front of my computer, I am procrastinating.