
Build indoor air quality monitor using stm32, freertos, and modbus, integrating temperature, humidity, and voc sensors with non-volatile data storage and a modbus rtu interface for live data and logs.
Set up an STM32 F486 hardware stack with a spi fram, qty 30 sensor, and sgp 40 voc sensor for data logging, persistent configuration, and indoor air quality measurement.
Establish a structured roadmap to build the stm32f4 freertos system, from cmsis integration and clock setup to gpio drivers and sensor interfaces (i2c, uart modbus, spi).
Explore the software stack and essential documentation, including Cmsis core, cortex-m headers, and FreeRTOS, for register-level work. Set up project folders, download software and documents, and study stm32f4 datasheet, pinout, alternate function mapping, reference manuals, the Cortex-m4 programming manual, startup files, and system core clock.
Install STM32CubeIDE on Windows by downloading the latest installer and running setup. Install the drivers and consult the user manual; the next lesson covers the project template.
Set up a CubeIDE workspace, create an empty STM32F4 project, organize core CMSIS config folders, add CMSIS headers, configure include paths and device symbol, and prepare an MCU header.
Configure the STM32 debug session and runtime stats, step through startup task creation, monitor the 16MHz system clock, view the FreeRTOS task list, and confirm startup task deletion.
Explore clock initialization for the stm32 f486v board, configuring system and peripheral clocks via the rcc module, flash wait states, pll setup, prescalers, and verification tests.
Configure flash access to match the system clock by resetting the ACR, enabling data cache, instruction cache, and prefetch, and calculating wait states with latency = (hclk - 1)/30.
Master RCC clock enable and disable macros across ahb1, apb1, and apb2 buses to manage gpio, dma, adc, spi, i2c, timers, and modbus communication for power efficiency.
Review the RCC header file to learn macro definitions and static inline functions that configure the PLL, prescalers, and oscillators using the HSE frequency for the MCU's system clock.
Implement the RCC source file, compute PLL m and n, and choose PLP (2,4,6,8) to keep VCO under 432 MHz and system clock under 180 MHz in RCC init.
Configure RCC by setting the system clock frequency and flash wait states. Enable the HSC, switch to the PLL as system clock, wait for PLL stabilization, then disable the HSC.
Explore how to build a gpio driver for the emcu, centralizing initialization, pin configuration, and the public api to read, write, and toggle pins.
Define gpio ports and pins in gpio-defs.h by including gpio.h and mcu.h, centralizing definitions for code readability, with the user-led set to pa5 on the stm32f446 nucleoboard.
Explore the gpio header's enums, macros, and prototypes, including pin mappings, two-bit mode fields, alternate function selection, speed, pull up/down, and atomic set/reset operations.
Review the gpio static functions that configure pin modes (input, output, alternate function, analog), speed, type, and pull settings, with centralized gpioInit and gpioPinConfig enabling read, write, and toggle.
Implement the GPIO driver: initialize GPIOA, configure the user LED, and develop GPIOWritePin, GPIOReadPin, and GPIOTogglePin using the BitsetReset register for safe, single-port control.
Initialize the GPIOs, toggle the Nucleo board's user LED from the startup task, and validate timing with a FreeRTOS delay using the PD milliseconds to ticks macro.
Explore the error handler task that monitors and responds to errors via a FreeRTOS queue, using error types, enumeration, ISR-safe messaging, and LED indicators across sensors and Modbus components.
Create a common include structure by defining error.h that declares error_t as the return type and error_e with ok, fail, timeout, and invalid_param codes.
create the error handler task header file in application tasks inc, define stack size 256 and high priority, and declare the error event enum and start prototypes.
Define the error handler task, create its error message queue, and implement a task that receives error IDs and blinks the led while counting errors.
Implement an error handler blink routine guarded by a blinking active flag, using gpio toggle and delay to signal errors. Send messages to the error handler task via a queue.
Explore the system health monitor task in FreeRTOS that tracks the MCU internal temperature, ensures critical tasks run, and resets the independent watchdog, coordinating with the error handler.
Set up the system health monitor header, define analog watchdog thresholds, and declare the external sensors flag for FreeRTOS. Start the task with a 256-stack, low priority.
Implement a system health monitor task that tracks the MCU temperature and checks critical tasks, then resets the independent watchdog via freertos. Validate with adc temperature readings and led testing.
Learn adc initialization for the internal temperature sensor with timer-triggered sampling and an analog watchdog on channel 18.
Create an adc header file in the peripherals include folder with an adc channels enum (0–18) and prototypes for adc init and analog watchdog setup, configuring the 11.25 MHz clock.
Create the ATCC adc source file to initialize adc one for the internal temperature sensor. Configure timer two trigger, 112-cycle sampling on channel 18, and set up the analog watchdog.
Configure TIM2 as a 32-bit timer to trigger ADC1 conversions at 1 Hz for temperature readings, using a 90 MHz timer clock with prescaler 8999 and auto reload register 9999.
Create and document the timer header file and implement timer two init to trigger adc1 conversions at one hertz, configuring clock, prescaler, auto reload register, master mode, and update events.
Initialize timer two by enabling its clock and configuring a prescaler of 8999 and auto reload of 9999 to generate a 1 Hz trigger for ADC conversions.
Configure irq priorities to enable freertos safe calls from interrupts and ensure critical events like internal temperature readings and sensor communication are serviced promptly using the Nvic.
Define ADC IRQ priorities in the peripherals include folder, relative to max syscall priority, and declare the IRQ set priorities function to configure NVIC levels for FreeRTOS safe interrupts.
Configure the irq priority levels in the peripheral irq file using cmsis nvic set priority for the adc interrupt and prepare for temperature conversion testing.
Extend the system health monitor with a timer triggered ADC, adding temperature to ADC and ADC to temperature conversions and configuring the analog watchdog thresholds.
Test temperature conversions and verify freertos api use from interrupt service routines, monitor system health flags and analog watchdog thresholds, and observe error handling with a blinking led.
Understand how the independent watchdog uses a hardware timer to reset the system when not refreshed, and learn its initialization, prescaler, reload, and key sequence for the system health monitor.
Create the independent watchdog header file with key definitions and prototypes, and implement inline functions to start, enable write access, reset, and initialize a four-second timeout with prescalers.
Implement the independent watchdog driver by initializing the IWDG with the low-speed internal clock, enabling write access, and configuring the prescaler and reload value for a defined timeout.
Test the independent watchdog (iwdg) within the system health monitor, configure a four-second timeout, and verify reset behavior to ensure reliable recovery from unresponsive states.
Explore EXi and the XD driver, and learn how the XD detects button presses and watchdog events. Map GPIO lines, configure XD sources and trigger edges, and enable IRQs.
Create the S.t.h header in the peripherals include folder to configure EXi with Gpio ports, XD lines, triggers, and prototypes to set source and enable or disable irc via nvic.
Implement the exti source file to configure external interrupts, set the configuration register by port and pin, configure edge triggering, and enable or disable interrupts in the NVIC.
Explore how the user button, a gpio input on port c pin 13, acknowledges watchdog resets by blinking a led, pausing operation, and signaling via a binary semaphore in FreeRTOS.
Configure user button on pc13 with gpio c, enable gpio c and sysconfig clocks, set pull-up input for external interrupts, and define a 500 ms blink interval in peripheral header.
Create and configure a FreeRTOS semaphore-driven user button on GPIO C13, set up external interrupts, and implement watchdog acknowledgement to pause system until the user acknowledges the independent watchdog reset.
Implement a user button interrupt (xd 1510) with a FreeRTOS semaphore to wake a high-priority task, and a wait-for-acknowledge routine that blinks a status led until pressed, and interrupt priority.
Learn how the sensors task gathers temperature, humidity, and VOC data from Sensirion sensors, feeds it to the Modbus data manager, and supports real-time monitoring.
Develop the census task source file to periodically sample VOC, temperature, and humidity sensors, update the Modbus data manager, and signal status with an led indicator via a FreeRTOS queue.
Prepare and send sensor messages to sensors task queue using the ssc send function with an id and sampling interval. Create a ten-message queue and start the task.
Explore the interrupt-driven ITC I2C driver, focusing on interrupts and FreeRTOS semaphores to enable efficient real-time communication. Examine synchronization flow through start transmit and BTF events for reliable master transmission.
Explore the I2C source file for the E-2c driver, featuring an interrupt-driven transmit and receive with semaphore synchronization across Itsuki instances for reliable FreeRTOS communication.
Explore i2c1 initialization, including semaphore-based ISR synchronization, clock enablement and reset, 100 kHz timing, and error interrupts; then master transmit and receive flows with FreeRTOS-aware IRQ handling.
Analyze the I2C source file part iii, covering the event irq handler and error irq handler, including start bit, address, tx/rx flags, btf, semaphores, and port yield from irq.
Organize sensor drivers in a components folder, integrate Sensirion sgp40 with st3 over i2c, update error handling, adapt init and measure functions, and prepare for a microsecond timer.
Configure TIM5 to generate microsecond delays for the Sensirion drivers, using a FreeRTOS semaphore for interrupt-based, non-blocking timing, covering initialization, delay function, and semaphore-based integration.
Initialize timer five for microsecond delays in Sensirion communication, configuring prescaler for microsecond resolution, one-pulse mode, and NVIC interrupts to enable precise timed delays.
Master the i2c gpio overview for stm32, wiring sensors on the same bus, and configuring pb8/pb9 for i2c1 with open-drain pins and pc7 test pin for debugging.
Extend the i2c gpio implementation by defining test pins and enabling clocks, then configure sda and scl for Sensirion sensors using af4 open-drain with external pull-ups.
Set the i2c1 event interrupt priority to max syscall interrupt priority plus one and tim5 to max syscall interrupt priority plus two, prioritizing sensor communication and precise microsecond delays.
Integrate Sensirion drivers into the sensors task by initializing sensors, measuring VOC index with humidity and temperature, handling errors, and updating the sensor data structure and Modbus registers.
Verify sensor communication, initialize the census task, and test the Sensirion E-2c and SGP 40 drivers, measure VOC index, and monitor ambient temperature and humidity.
This course contains the use of artificial intelligence.
(e.g., a Python script used to test the Modbus application). Temporary AI-assisted narration in the final lessons is being replaced with natural voice recordings.
If you’ve already know the basics of STM32 driver development or FreeRTOS, you may be looking for the next step: a way to bring these skills together into a real-world, professional project.
This course is designed exactly for that purpose. You’ll build a complete indoor air quality sensor project from the ground up, using an STM32 Nucleo board, developing and integrating CMSIS-based peripheral drivers, FreeRTOS tasks, and custom Modbus RTU framework into a structured embedded software project.
By working step-by-step through the design and implementation, you’ll not only learn how these elements work individually, but also how to architect, synchronize, and integrate them into a cohesive, real-world application.
About the Course
We begin with the foundation:
Integrating CMSIS for register-level development.
Integrating FreeRTOS as our real-time operating system.
Creating the startup FreeRTOS task.
Setting up system clocks and a clean project structure.
From there, we build the project incrementally:
Writing a clean GPIO driver and non-blocking, UART, SPI, and I2C drivers that use FreeRTOS semaphores for synchronization.
Developing application-level FreeRTOS tasks to handle data acquisition, processing, and communication.
Adding external hardware: Sensirion environmental sensors (e.g., SHT3x, SGP40) and a custom FRAM driver over SPI for data storage.
Integrating a custom Modbus RTU framework, and then build the application-level tasks which support communication and data handling.
Each piece is added step by step so you’ll see not just the code, but also the reasoning behind the design choices.
Intended Outcome
By the end of the course, you’ll have:
A fully functioning Air Quality Sensor project running on an STM32 MCU.
The ability to write register-level drivers using CMSIS.
Experience applying FreeRTOS synchronization mechanisms (queues, semaphores, mutexes and task notifications).
Practical knowledge of Modbus RTU integration and implementation.
A clear understanding of how to structure and grow professional embedded projects.
This is not about isolated demos. It’s about learning how to build embedded software the way it’s done in real development environments.
Other Noteworthy Highlights
Professional, modular programming style used throughout.
I2C, SPI, and UART drivers implemented with FreeRTOS synchronization for non-blocking operation.
Error Handling, System Health Monitor, Sensor Data Acquisition, Modbus Slave & Modbus Data Manager implemented as FreeRTOS tasks.
Step-by-step incremental project development.
Real-world integration of sensors and external memory.
Hardware
STM32F446RE Nucleo Board (recommended)
A large portion of the course can be completed using just this board, so you can get started right away.
The external sensors (I2C temperature/humidity & VOC Index) and SPI FRAM can be integrated as you obtain them.
Software
STM32CubeIDE
A Modbus master tool (e.g., Simply Modbus Master) for testing communication