A complete workflow for building, training, and deploying a lightweight LSTM Autoencoder anomaly detector for temperature data on the ESP32 microcontroller—without TensorFlow or TFLite. This project uses PyTorch, ONNX, and C++ for efficient, real-time anomaly detection on edge devices.
- Project Overview
- Setup & Quickstart
- File & Data Explanations
- Interpreting Training Output
- Automated Deployment Steps
- How Model Weights & LSTM Logic Are Used
- Contributing
- Goal: Detect abnormal temperature spikes on an ESP32 using a trained LSTM Autoencoder.
- Workflow:
- Generate or collect temperature data
- Train an LSTM Autoencoder in PyTorch
- Export the model to ONNX and convert weights to C header
- Extract normalization and threshold parameters to C header
- Deploy and run anomaly detection on ESP32 (Arduino/PlatformIO)
pip install -r requirements.txt
python generate_synthetic_data.py --minutes 1440 --anomalies 10 --outfile temperature_log.csv
- This creates a realistic temperature time-series with injected anomalies.
python train_lstm_autoencoder.py
- Trains the LSTM autoencoder and exports ONNX, scaler, and threshold.
python convert_to_header.py --onnx lstm_autoencoder.onnx --header lstm_autoencoder_weights.h
- Converts ONNX weights to a C header for ESP32 deployment.
python extract_params_to_header.py
- Generates
model_params.h
with min/max normalization values and anomaly threshold for direct use in your ESP32 code.
- Use
esp32_anomaly_detector.ino
and include bothlstm_autoencoder_weights.h
andmodel_params.h
in your Arduino/PlatformIO project. - The sketch now automatically uses the correct normalization and threshold values.
- Upload to ESP32 and connect your DHT22 sensor.
One-Step Automated Deployment
For a fully automated setup, simply run:
python prepare_esp32_deployment.pyThis script will execute all the above steps in sequence, generating all required files for ESP32 deployment in one go.
File | Type/Format | Purpose/Role |
---|---|---|
generate_synthetic_data.py | Python script | Generate synthetic training data |
temperature_log.csv | CSV | Training data for model |
train_lstm_autoencoder.py | Python script | Train and export LSTM autoencoder |
lstm_autoencoder.pth | PyTorch model | Trained model weights |
scaler.save | Joblib binary | Fitted scaler for normalization |
anomaly_threshold.npy | NumPy binary | Anomaly detection threshold |
lstm_autoencoder.onnx | ONNX model | Model for conversion to C/C++ |
convert_to_header.py | Python script | Convert ONNX weights to C header |
lstm_autoencoder_weights.h | C header | Model weights for ESP32 (autogenerated, safe to delete) |
extract_params_to_header.py | Python script | Extracts scaler min/max and threshold to C header |
model_params.h | C header | Normalization and threshold constants for ESP32 (autogenerated, safe to delete) |
generate_lstm_cpp.py | Python script | Auto-generates C++ LSTM forward pass from ONNX |
lstm_forward_pass.cpp | C++ source | (Optional) Standalone LSTM forward pass (autogenerated, safe to delete) |
prepare_esp32_deployment.py | Python script | One-step deployment: runs all steps and generates all required files |
data_collector.ino | Arduino sketch | Collect and log real sensor data |
esp32_anomaly_detector.ino | Arduino sketch | Run anomaly detection on ESP32 |
requirements.txt | Text | Python dependencies |
- Note: All autogenerated files (
lstm_autoencoder_weights.h
,model_params.h
,lstm_forward_pass.cpp
) can be safely deleted and will be recreated by the deployment script. Always back up headers if you want to preserve a specific version. - The LSTM logic and weights are always up-to-date and automated—no manual editing required.
- The one-step deployment script (
prepare_esp32_deployment.py
) is available in both the Setup & Quickstart and the file table above.
- During training, you'll see output like:
Epoch 1/30, Loss: 0.495228 Epoch 2/30, Loss: 0.326717 ...
- Loss: Measures how well the model reconstructs normal temperature patterns. Lower loss = better reconstruction.
- Decreasing loss: Indicates the model is learning.
- Threshold: The script prints and saves a suggested anomaly threshold. Use this value on the ESP32 to flag anomalies.
- Run all Python scripts in order:
generate_synthetic_data.py
train_lstm_autoencoder.py
convert_to_header.py
extract_params_to_header.py
- Copy the generated headers (
lstm_autoencoder_weights.h
,model_params.h
) to your ESP32 project. - Upload
esp32_anomaly_detector.ino
to your ESP32. - No manual copying of normalization or threshold values is needed!
- The LSTM forward pass logic is now implemented directly in the sketch and uses the latest weights automatically.
Bonus: One-Step Deployment
For a fully automated setup, you can simply run:
python prepare_esp32_deployment.pyThis script will execute all the above steps in sequence, generating all required files for ESP32 deployment in one go.
- The deployment pipeline automatically extracts the latest model weights from ONNX and writes them to
lstm_autoencoder_weights.h
. - The ESP32 sketch (
esp32_anomaly_detector.ino
) includes this header and uses the weights directly in the LSTM cell math. - The LSTM forward pass logic is implemented in C++ in the sketch, so every time you retrain and regenerate weights, your ESP32 will use the new model without manual changes.
- Tip: If you want to keep a specific set of weights, back up the header before rerunning the deployment script.
- Contributions, bug reports, and improvements are welcome!
- Please open an issue or submit a pull request.
- When contributing, ensure your code is robust (error handling, clear comments) and follows the modular structure of this project.
Project maintained by fellow developers and contributors.