Skip to content

B1jam1-74/MetAI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌦️ MetAI — Embedded Weather Prediction with AI on STM32U545

Université Savoie Mont-Blanc — Licence 3 ESET
 Maram Mezlini & Benjamin Avocat-Maulaz

Summary

Introduction

MetAI is an embedded AI project that runs a weather prediction model directly on an ultra-low-power STM32U545 microcontroller. Using onboard sensors (temperature, humidity, pressure), the system infers the current weather condition locally — no cloud compute required — and transmits the result over LoRaWAN for remote monitoring. The project demonstrates that meaningful AI inference can coexist with strict energy budgets, making it relevant for battery-operated or energy-harvesting IoT nodes.

Part 1 — Hardware

STM32U545 — The Microcontroller

The brain of the project is the STM32U545, a member of STMicroelectronics' ultra-low-power STM32U5 family. Key characteristics relevant to this project:

Feature Value
CoreArm Cortex-M33, up to 160 MHz
Flash1 MB
RAM786 KB (SRAM1 + SRAM2 + ICACHE)
Supply voltage1.71 V - 3.6 V
Low-power modesStop 0/1/2/3, Standby, Shutdown
Neural-ART AcceleratorHardware MAC units for AI inference
Development boardNUCLEO-U545RE-Q

The U545's Neural-ART Accelerator is what makes on-device AI inference viable at milliwatt-level power: it offloads the multiply-accumulate operations of the neural network from the CPU, dramatically reducing inference time and energy per prediction.

STM32U545 board

Extension Board

The U545 board is connected to an IKS01A3 extension board. It carries all kind of sensors such as :

  • temperature (°C)
  • relative humidity (%)
  • barometric pressure (hPa) The three inputs fed to the AI model.

IKS01A3 extension board

LoRa-E5 module

Handles the LoRaWAN radio link (see Part 3).

LoRa-E5 module

Part 2 — AI Models

Both models were trained in Python (TensorFlow/Keras) on historical meteorological data sourced via Meteostat, using a weather station near Le Bourget du Lac, France. They take three scalar inputs:

Input Unit
Temperature°C
Relative humidity%
Barometric pressurehPa

Model overview

Model A — Binary Rain Classifier

The first and simpler model answers a single question: will it rain? It outputs a sigmoid probability and is thresholded at 0.5 to produce a binary label. This model is extremely lightweight and was used as a baseline to validate the implementation of an AI model on the board.

Model B — Multi-class Weather Classifier

The second model extends the output to 12 weather classes, enabling a richer description of conditions. After training and quantization, it is converted to a TFLite FlatBuffer and deployed on the U545 using STM32Cube.AI with the Neural-ART runtime.
The 12 predicted classes are:

# French label Description International
0Clair / ensoleilléClear sky☀️
1Peu nuageuxMostly sunny🌤️
2Partiellement nuageuxPartly cloudy
3Nuageux / couvertOvercast☁️
4PluieRain🌧️
5AversesShowers🌦️
6NeigeSnow❄️
7Neige légère / averses de neigeLight snow / snow showers🌨️
8Pluie et neige mêléesSleet🌨️🌧️
9OrageThunderstorm⛈️
10Brouillard / brumeFog / mist🌫️
11Vent fortStrong wind💨
12Orage violentSevere thunderstorm🌩️

The firmware reads the argmax of the softmax output and encodes both the class index (predicted_class) and its French label (prediction_fr) into the LoRaWAN uplink payload.

This model does not deliver the highest possible accuracy: predicting upcoming weather conditions from only three instantaneous meteorological measurements, without temporal context, is inherently challenging. A key improvement would be to include additional temporal features (for example, measurements from the previous hour) to increase predictive reliability. Due to project time constraints, we could not fully validate this approach and therefore kept the current model:

Model overview

Part 3 — LoRaWAN

What is LoRaWAN?

LoRa is a spread-spectrum radio modulation developed by Semtech, designed for low-power, long-range communication (up to tens of kilometres in open terrain). LoRaWAN is the MAC layer protocol built on top of LoRa that defines how devices connect to a network of gateways and route packets to an application server. Its key properties for embedded IoT are:

  • Very low transmit power (typically 14–20 dBm)
  • Extremely low device power budget — devices can run for years on a battery
  • Star-of-stars topology: end-nodes → gateways → Network Server (e.g. TTN) → Application Server

Payload Encoding and TTN Decoding

On the STM32U545, the uplink payload is encoded as a compact binary frame carrying:

  1. Temperature (signed 16-bit, ×100 for two-decimal precision)
  2. Humidity (unsigned 8-bit, integer %)
  3. Pressure (unsigned 16-bit, integer hPa)
  4. Predicted class index (unsigned 8-bit)

On The Things Network (TTN), a JavaScript Payload Formatter (uplink codec) decodes this binary frame back into a structured JSON object:

function decodeUplink(input) {
  var classesFr = [
    "Clair / ensoleille",
    "Peu nuageux",
    "Partiellement nuageux",
    "Nuageux / couvert",
    "Pluie",
    "Averses",
    "Neige",
    "Neige legere / averses de neige",
    "Pluie et neige melees",
    "Orage",
    "Brouillard / brume",
    "Vent fort",
    "Orage violent"
  ];

  var text = "";
  for (var i = 0; i < input.bytes.length; i++) {
    text += String.fromCharCode(input.bytes[i]);
  }

  var data = {};
  var parts = text.split(",");

  for (var j = 0; j < parts.length; j++) {
    var kv = parts[j].split("=");
    if (kv.length !== 2) continue;

    var key = kv[0].trim();
    var raw = kv[1].trim();

    if (key === "C") {
      var cls = parseInt(raw, 10);
      if (!isNaN(cls)) {
        data.predicted_class = cls;
        data.prediction_fr =
          (cls >= 0 && cls < classesFr.length) ? classesFr[cls] : "Classe inconnue";
      }
      continue;
    }

    var val = parseFloat(raw);
    if (isNaN(val)) continue;

    if (key === "P") data.pressure_hpa = val;
    else if (key === "H") data.humidity_percent = val;
    else if (key === "T") data.temperature_deg_c = val;
    else data[key] = val;
  }

  return {
    data: data
  };
}

 

Node-RED Integration

Once decoded by TTN, the data is forwarded to a Node-RED flow that performs an HTTP POST to a Request Baskets endpoint. This makes the payload immediately inspectable from a browser, as shown in the screenshot below, and provides a convenient webhook URL that any downstream service can subscribe to.

Flow NodeRED

Note on the network side: Routing, cloud dashboards, and persistent storage fall outside our electronics/embedded speciality, so we kept the network stack intentionally minimal and modular. In practice, Node-RED already emits a complete JSON payload (device_id, timestamp, sensors, prediction), so the ingestion layer can be swapped without touching the STM32 firmware. We currently run a lightweight Docker setup with a FastAPI service for /uplink ingestion and /stats exposure, plus a Streamlit dashboard for visualization; adding another backend (InfluxDB/TimescaleDB) or another frontend (Grafana/Datacake) is therefore mostly a wiring/configuration task.

Web page of the server

The server receives uplinks from Node-RED, stores each sample in a local SQLite database, fetches real weather from Open-Meteo for comparison, then serves both raw history and aggregate metrics to the dashboard. This gives a full end-to-end pipeline (sensor -> TTN -> Node-RED -> API -> dashboard) while keeping deployment simple and reproducible with Docker Compose.

Part 4 — Power Consumption

Why It Matters for AI

Neural network inference is inherently compute-intensive. On a general-purpose server, a single forward pass through even a small model draws hundreds of milliwatts. As an example, a simple google search consumes 0.3 W while a ChatGPT request is 3 W !
The U545's Neural-ART accelerator helps significantly: by executing MAC operations in dedicated hardware rather than running them on the Cortex-M33, inference completes faster and at lower energy per operation than a pure software implementation.

Measuring Power Consumption with the LPM01A

STMicroelectronics' X-NUCLEO-LPM01A (Power Shield) is the reference tool for accurate current measurement on NUCLEO boards. The procedure is as follows:

  1. Hardware setup: Remove the IDD jumper on the NUCLEO-U545RE-Q and connect the LPM01A in series on the 3.3 V / VDD supply rail using the dedicated headers.
  2. Software: Install STM32CubeMonitor-Power on the host PC and connect to the LPM01A over USB.
  3. Run the acquisition: Flash the firmware, trigger a measurement session, and observe the current waveform. STM32CubeMonitor-Power integrates the waveform to give average current, peak current, and total charge (µAh) per acquisition cycle.

U545 without jumper

Power Measurement

Measured Power Budget

Our system operates at 1.8 V supply and draws approximately 3 mA in the active sensing + inference phase, corresponding to:
$$P = V \times I = 1.8,\text{V} \times 3,\text{mA} = \mathbf{5.4,mW}$$
Between acquisitions, the MCU enters a low-power Stop mode, bringing average consumption well below the active peak.

Power Consumption

Part 5 — Conclusion

This project was an introduction to on-device artificial intelligence in a constrained embedded context. Building and training the models highlighted how much representational power even a small dense network can have — the multi-class classifier reaches solid accuracy using only three sensor inputs. Deploying that model on a Cortex-M33 with a hardware neural accelerator, and watching it produce correct predictions at 5 mW, made the energy argument for edge AI very concrete.
At the same time, the project reinforced that energy consumption is a first-class constraint in embedded AI, not an afterthought. Every design choice — quantization, model depth, duty cycle, supply voltage — has a direct impact on battery life. Future work could explore INT8 quantization (vs the current float32 baseline) and adaptive duty cycling to extend autonomy further.
More broadly, the number of connected objects in our daily lives keeps growing — smartphones, cars, dishwashers, toothbrushes — and it seems inevitable that AI will progressively find its way into all of them. MetAI is a small but concrete glimpse of what that future could look like: intelligence running locally, efficiently, at the very edge of the network.

Repository Structure

MetAI/
├── LICENSE
├── README.md
├── AI Models/ # Exported TFLite models
│ ├── meteo_multiclasse.tflite
│ └── rain_model.tflite
├── Binaries/ # Compiled binaries grouped by test/project
│ ├── Final project/
│ ├── First AI model/
│ └── Simple board test/
├── Firmwares/ # STM32CubeIDE firmware projects
│ ├── implementation_gros_model/
│ ├── model_IA/
│ └── test/
├── Images/ # Figures used in the README
│ └── ...
├── Jupyter Notebooks/ # Model training/testing notebooks
│ ├── Model_final.ipynb
│ └── Model_test.ipynb
├── NodeRED/ # Node-RED assets/flows
│ └── flows.json
├── scripts/ # Utility scripts
├── Serveur/ # Backend API + Streamlit dashboard + compose
│ ├── docker-compose.yml
│ ├── api/
│ │ ├── Dockerfile
│ │ ├── main.py
│ │ └── requirements.txt
│ ├── dashboard/
│ │ ├── app.py
│ │ ├── Dockerfile
│ │ └── requirements.txt
│ └── data/
└── TTN/ # TTN payload formatter
└── function decodeUplink.txt
 

Complete Project Implementation

This section gives a practical end-to-end sequence to run the full MetAI chain: STM32 board -> LoRaWAN (TTN) -> Node-RED -> server API/dashboard.

1) Clone the repository

git clone https://github.com/MetAI/MetAI.git
cd MetAI

2) Flash the binaries on the STM32U545 board

This project supports two flash paths:

  • Prebuilt binaries from Binaries/ for fast deployment.
  • Build + flash from Firmwares/ when you modify the source code.

The firmware projects in Firmwares/ are generated with Makefiles, so you can work from VS Code and a terminal (not only STM32CubeIDE).

If you want to compile from source before flashing:

  1. Go to the target firmware folder (example):
    • cd Firmwares/implementation_gros_model
  2. Build:
    • make -j
  3. Flash with Make (when target is configured):
    • make flash

To flash a prebuilt image with STM32CubeProgrammer:

  1. Connect the NUCLEO-U545RE-Q over USB (ST-LINK).
  2. Open STM32CubeProgrammer and select ST-LINK as the connection type.
  3. Pick the firmware image you want from Binaries/:
    • Binaries/Final project/implementation_gros_model.hex for the complete AI + LoRaWAN project.
    • Binaries/First AI model/model_IA.hex for the first AI model test.
    • Binaries/Simple board test/test.hex for basic board validation.
  4. Program the image, verify flashing, then reset/run the board.
  5. Open a serial terminal at 115200 baud to check runtime logs and LoRa responses.

3) Configure the LoRaWAN device

  1. In TTN, create an Application and register an End Device (OTAA).
  2. Keep your device identifiers and keys ready:
    • JoinEUI/AppEUI
    • DevEUI
    • AppKey
  3. Provision the LoRa-E5 module once over UART (example AT sequence):
    • AT
    • AT+MODE=LWOTAA
    • AT+ID=DevEui,"<YOUR_DEV_EUI>"
    • AT+ID=AppEui,"<YOUR_JOIN_EUI>"
    • AT+KEY=APPKEY,"<YOUR_APP_KEY>"
    • AT+DR=EU868 (or your TTN regional band)
    • AT+JOIN
  4. Confirm the join is accepted in TTN (Live data).

In this project firmware, uplinks are sent as text payloads through AT+MSG in the format: P=<pressure>,H=<humidity>,T=<temperature>,C=<predicted_class>

4) Set up the TTN payload formatter function

  1. Open TTN Console -> your Application -> Payload formatters -> Uplink.
  2. Copy/paste the decoder function from:
    • TTN/function decodeUplink.txt
  3. Save the formatter.
  4. Trigger an uplink and verify decoded fields in TTN Live data:
    • pressure_hpa
    • humidity_percent
    • temperature_deg_c
    • predicted_class
    • prediction_fr

Once this is done, TTN can forward decoded JSON to Node-RED, and Node-RED can POST it to the API /uplink endpoint used by the dashboard.

5) Mount the server using the Serveur folder

  1. Go to Serveur/.
  2. Start the stack with Docker Compose:
    • docker compose up --build -d
  3. Validate services:
  4. Optional checks:
    • docker compose ps
    • docker compose logs -f api
    • docker compose logs -f dashboard

The compose file starts two services:

  • api (FastAPI ingestion and stats)
  • dashboard (Streamlit visualization)

Dependencies

Tool Purpose
STM32CubeIDEFirmware development
STM32Cube.AI / STEdgeAIModel conversion and deployment
TensorFlow / KerasModel training
MeteostatHistorical weather data
The Things NetworkLoRaWAN network server
Node-REDPayload forwarding
STM32CubeMonitor-PowerPower consumption measurement
DockerDeployment of the web server
*Université Savoie Mont-Blanc — Licence Électronique et Systèmes Embarqués et Télécommunications (ESET) — 2025/2026*  

About

Embedded Weather Prediction with AI on STM32U545

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors