Compare commits

..

2 Commits

Author SHA1 Message Date
9096866812 documentation 2026-05-29 11:49:55 +03:00
21141c29b2 readme 2026-05-29 09:07:29 +03:00
7 changed files with 513 additions and 57 deletions

View File

@@ -1,49 +1,277 @@
IR allsky-camera project using 5 sensors MLX90640
=================================================
# IR All-Sky Camera Documentation
When attached, udev will create symlink /dev/ir-allsky0. This is the udev rule:
## Project Overview
```
This firmware implements an **infrared all-sky camera system** based on up to five **MLX90640**
thermal imaging sensors (32×24 pixels each), designed for **cloud monitoring** at the Special
Astrophysical Observatory of the Russian Academy of Sciences. The system automates sky quality
assessment for 0.5-meter telescopes of the "Astro-M" complex.
ACTION=="add", ENV{USB_IDS}=="0483:5740", ATTRS{interface}=="?*", PROGRAM="/bin/bash -c \"ls /dev | grep $attr{interface} | wc -l \"", SYMLINK+="$attr{interface}%c", MODE="0666", GROUP="tty"
The device continuously captures thermal images from multiple sensors (Zenith, East, South, West, North), processes environmental data from a **BMP280** pressure/humidity/temperature sensor, and controls **PWM heaters** to prevent dew formation on optics.
```
**Repository:** [https://github.com/eddyem/stm32samples/tree/master/F3%3AF303/MLX90640-allsky](https://github.com/eddyem/stm32samples/tree/master/F3%3AF303/MLX90640-allsky)
Protocol:
---
```
dn - draw nth image in ASCII
gn - get nth image 'as is' - float array of 768x4 bytes
l - list active sensors IDs
mn - show temperature map of nth image
tn - show nth image aquisition time
B - reinit BME280
E - get environment parameters (temperature etc)
G - get MLX state
R - reset device
T - print current Tms
Debugging options:
aa - change I2C address to a (a should be non-shifted value!!!)
c - continue MLX
i0..4 - setup I2C with speed 10k, 100k, 400k, 1M or 2M (experimental!)
p - pause MLX
s - stop MLX (and start from zero @ 'c')
C - "cartoon" mode on/off (show each new image) - USB only!!!
Dn - dump MLX parameters for sensor number n
Ia addr [n] - set device address for interactive work or (with n) change address of n'th sensor
Ir reg n - read n words from 16-bit register
Iw words - send words (hex/dec/oct/bin) to I2C
Is - scan I2C bus
Us - send string 's' to other interface
```
To call this help just print '?', 'h' or 'H' in terminal.
## Hardware Requirements
### Microcontroller
- **STM32F303** series (tested on F303)
- 72 MHz system clock (HSE) or 48 MHz (HSI)
### Sensors
| Sensor | Interface | Purpose |
|--------|-----------|---------|
| MLX90640 (up to 5) | I²C (400 kHz) | Thermal imaging (32×24 pixels, -40..+300°C) |
| BMP280 / BME280 | SPI | Ambient temperature, pressure, humidity |
| NTC thermistors (4) | ADC (12-bit) | Heater feedback / backup temperature |
### Outputs
- **DAC output** (PA5) Onboard heater control (03.3V)
- **PWM channels** (TIM3) External heaters (PA6, PA7, PB0, PB1)
- **UART1** Main debug/auxiliary interface
- **USB** (CDC class) Secondary interface
### Pin Assignment (STM32F303)
| Pin | Function | Notes |
|-----|----------|-------|
| PA0PA3 | NTC1NTC4 | ADC inputs |
| PA4 | DAC_OUT1 | Onboard heater |
| PA5 | ADC_IN2 | DAC feedback |
| PA6, PA7 | PWM CH1, CH2 | TIM3_CH1, TIM3_CH2 (external heaters) |
| PA9, PA10 | UART1 TX/RX | Controlling interface |
| PA11, PA12 | USB DP/DM | CDC virtual COM |
| PA13, PA14 | SWD | Programming/debug |
| PA15 | USB DP pullup | USB pullup management for development board |
| PB0, PB1 | PWM CH3, CH4 | TIM3_CH3, CH4 (sky-quality + T-proportional) |
| PB3, PB4, PB5 | SPI SCK, MISO, MOSI | BMP280 interface |
| PB6, PB7 | I²C1 SCL/SDA | MLX90640 bus |
| PB9 | SPI CS | BMP280 chip select |
---
## Firmware Architecture
The firmware is **event-driven** with a **state machine** for MLX90640 data acquisition and a
**command parser** for bidirectional communication over USB and UART.
### Core Modules
| File | Responsibility |
|------|----------------|
| `main.c` | Main loop, SysTick, initialization, state machine orchestration |
| `adc.c/h` | ADC setup (DMA, median filtering), NTC reading, Vdd measurement |
| `i2c.c/h` | I²C low-level + DMA, multi-word transfers, bus scanning |
| `mlxproc.c/h` | MLX90640 state machine (5 sensors), parameter caching, image processing |
| `mlx90640.c/h` | MLX90640 calibration math (from Melexis datasheet) |
| `BMP280.c/h` | SPI-based BMP280/BME280 driver |
| `heater.c/h` | PWM heater control, dew-point avoidance logic |
| `commproto.cpp/h` | Command parser (USB/UART), ASCII maps, binary image export |
| `usb_dev.c/h` | USB CDC stack (bulk endpoints, ring buffers) |
| `usart.c/h` | UART driver with DMA and ring buffers |
| `spi.c/h` | SPI driver for BMP280 |
| `ringbuffer.c/h` | Circular buffers |
| `strfunc.c/h` | Number/string conversions, hexdumps |
### Data Flow
```
MLX90640 sensors (I²C DMA)
mlxproc.c (state machine, 5× parameter loading)
mlx90640.c (pixel-by-pixel temperature calculation)
user requests via USB/UART (ASCII map, binary, temperature map)
BMP280 (SPI)
Temperature, Pressure, Humidity, Dew point
Heater logic (auto or setpoint) → PWM outputs
ADC (DMA + median filter)
NTC temperatures, MCU temperature, Vdd
```
---
## MLX90640 Processing
### State Machine (`mlxproc.c`)
The firmware manages up to **5 sensors** (addresses 0x10..0x14 left-shifted for I²C). The state
machine cycles through:
1. **NOTINIT** Read calibration parameters (832 words) from each sensor over I²C DMA.
2. **WAITPARAMS** Wait for DMA completion, calculate parameters via `get_parameters()`.
3. **WAITSUBPAGE** Poll `REG_STATUS` for `NEWDATA` flag, skip subpage 0.
4. **READSUBPAGE** Read image data (832 words) via DMA, process with `process_image()`.
**Key features:**
- Automatic sensor exclusion after `MLX_MAX_ERRORS` (default 11) consecutive errors.
- `Tlastimage[]` timestamps for each sensor (used by "cartoon mode" and timeout recovery).
- Supports changing sensor I²C addresses at runtime (`mlx_sethwaddr()`).
### Temperature Calculation (`mlx90640.c`)
Implementation follows **Melexis MLX90640 Datasheet (Section 11)**:
- Supply voltage compensation (`kVdd`, `vdd25`)
- Ambient temperature (`KvPTAT`, `KtPTAT`, `vPTAT25`)
- Gain normalization
- Offset correction (per-pixel `offset[]`, `kta[]`, `kv[]`)
- TGC (temperature gradient compensation)
- Pixel sensitivity (`alpha[]`) + KsTa, KsTo, range detection (CT3, CT4)
- **Extended temperature range** (up to 400°C) via `alphacorr[]`
Output: **float array of 768 temperatures** (°C) per sensor.
---
## Environmental & Heater Control
### BMP280/BME280 Readings
- **Temperature** (°C)
- **Pressure** (Pa, also converted to hPa and mmHg)
- **Humidity** (%)
- **Dew point** (°C) calculated via Magnus formula.
Measurements are triggered every `ENV_MEAS_PERIOD` (10 seconds) in forced mode.
### Heater Modes
| Mode | Activation | Behavior |
|------|------------|----------|
| **Auto** (`autoheater=1`) | Humidity > 90% | Sets holding temperature = ambient + dew_over_delta (7°C) + 0.5°C (min 5°C) |
| **Hold** (`setheater N`) | Manual command | Maintains N°C ±5°C hysteresis using PWM |
| **Off** | Default | All heaters disabled |
**PWM channels:**
- `ch0`, `ch1` External heaters (controlled identically for symmetry)
- `ch2` Proportional to ambient temperature: `(T_ambient + 20) × 2` %, clamped 0100
- `ch3` Proportional to `(35°C T_ambient + T_sky) × 2.5` %, clamped 0100
**Anti-overheating:** If any NTC exceeds setpoint by >5°C, PWM is reduced to `PWM_HOLD_VAL` (10%).
---
## Command Protocol
The device presents a **virtual COM port** (CDC) over USB and a second UART interface. Both share the same command set.
### Command Syntax
```
<command> [parameter] [= value]
```
- Commands are **case-sensitive** (lowercase).
- Parameters are **decimal** (or hex with `0x`, binary with `b`).
- Use `help` for full list.
- Lines end with `\n` (newline).
### Core Commands
#### MLX90640 Image Commands
| Command | Description | Example |
|---------|-------------|---------|
| `ascii n` | Draw ASCII-art thermal map (16 grayscale levels) | `ascii 0` |
| `tempmap n` | Print numeric temperature grid (°C) | `tempmap 1` |
| `binary n` | Dump raw float array (768×4 bytes) | `binary 2` |
| `acqtime n` | Show last image acquisition timestamp (ms) | `acqtime 3` |
| `cartoon` | Toggle live ASCII animation over USB | `cartoon` |
#### Sensor Management
| Command | Description | Example |
|---------|-------------|---------|
| `listids` | List active I²C addresses of all sensors | `listids` |
| `mlxaddr n [= addr]` | Get/set I²C address for sensor n (04) | `mlxaddr 2 = 0x15` |
| `mlxdump n` | Dump all calibration parameters for sensor n | `mlxdump 0` |
| `state` | Show MLX90640 state machine status | `state` |
| `mlxpause` / `mlxcont` / `mlxstop` | Control acquisition | |
#### Environment
| Command | Description | Example |
|---------|-------------|---------|
| `environ` | Print T, P, H, dew point, Tsky | `environ` |
| `bmereinit` | Reinitialize BMP280 | |
| `ntc [n]` | Get NTC temperature (°C) for channel n (03) | `ntc 1` |
#### Heater Control
| Command | Description | Example |
|---------|-------------|---------|
| `autoheater [= 0/1]` | Enable/disable automatic dew avoidance | `autoheater = 1` |
| `setheater [= N]` | Set holding temperature (°C) | `setheater = 25` |
| `clearheater` | Disable holding, turn off heaters | |
| `pwm [n] [= val]` | Get/set PWM duty cycle (0100%) for channel n | `pwm 0 = 50` |
#### System & Debug
| Command | Description | Example |
|---------|-------------|---------|
| `adc [n]` | Get raw ADC value (04095) for channel n | `adc 4` |
| `dac [= val]` | Get/set DAC output (04095) | `dac = 2048` |
| `mcutemp` | Show MCU internal temperature (°C) | |
| `mcuvdd` | Show Vdd (V) | |
| `time` | Show SysTick counter (ms) | |
| `reset` | Software reset | |
| `sendstr = text` | Forward string to other interface | `sendstr = "hello"` |
#### Raw I²C (for debugging)
| Command | Description | Example |
|---------|-------------|---------|
| `iicscan` | Scan I²C bus, report found addresses | |
| `iicaddr [= addr]` | Get/set current I²C target address (non-shifted) | `iicaddr = 0x33` |
| `iicspeed [= n]` | Set I²C speed: 0=10k,1=100k,2=400k,3=1M,4=2M | |
| `readreg reg [= n]` | Read n 16-bit registers | `readreg 0x8000` |
| `writedata = v1 v2 ...` | Write 16-bit values | `writedata = 0x1234 0x5678` |
| `hwaddr addr` | Change hardware I²C address of MLX90640 (non-shifted) | `hwaddr 0x15` |
### Output Formats
#### ASCII Thermal Map (`ascii`)
```
RANGE=12.345
MIN=-5.67
MAX=6.78
.':;+*oxX#&%B$@
.':;+*oxX#&%B$@
...
```
Uses 16character grayscale ramp: space (coldest) → `@` (hottest).
#### Numeric Map (`tempmap`)
```
-2.3 1.2 3.4 ...
5.6 7.8 9.0 ...
...
```
#### Binary Image (`binary n`)
```
BINARY0=<768×4 bytes raw float array>ENDIMAGE\n
```
Little-endian IEEE 754 `float` values. Exact size: 3072 bytes per image.
#### Environment Output
```
TEMPERATURE=22.34
SKYTEMPERATURE=-15.67
PRESSURE_HPA=1013.25
PRESSURE_MM=759.98
HUMIDITY=65.20
TEMP_DEW=15.60
T_MEASUREMENT=12345678
```
### Sensors location
| N | ID | Cardinal direction |
|---|------|--------------------|
@@ -53,3 +281,130 @@ To call this help just print '?', 'h' or 'H' in terminal.
| 3 | 0x13 | West |
| 4 | 0x14 | North |
---------------------------------
---
## Building & Flashing
### Prerequisites
- ARM GCC toolchain (`arm-none-eabi-gcc`)
- Make
- [st-flash](https://github.com/texane/stlink), [stm32flash](https://sourceforge.net/projects/stm32flash/) or [OpenOCD](https://openocd.sourceforge.io) (for flashing MCU)
### Build
```bash
git clone --depth=1 https://github.com/eddyem/stm32samples.git
cd stm32samples/F3:F303/MLX90640-allsky
make
```
### Configuration
- `EBUG` flag in Makefile enables debug output (slower, but verbose).
- `NOCAN` define if CAN peripheral not used (increases USB buffer).
- `BUILD_NUMBER` and `BUILD_DATE` in `version.inc` are auto-generated.
### Flashing
```bash
make flash # for flashing over st-link
# make boot - for flashing over USART1 bootloader
# make dfuboot - for flashing over USB-DFU
```
or manually (over st-link):
```bash
openocd -f interface/stlink.cfg -f target/stm32f3x.cfg -c "program build/firmware.elf verify reset exit"
```
### udev Rule (Linux)
Create `/etc/udev/rules.d/99-USBiinterface.rules`:
```
ACTION=="add", ENV{USB_IDS}=="0483:5740", ATTRS{interface}=="?*", PROGRAM="/bin/bash -c \"ls /dev | grep $attr{interface} | wc -l \"", SYMLINK+="$attr{interface}%c", MODE="0666", GROUP="tty"
```
After replug, device appears as `/dev/ir-allsky0`.
---
## Calibration & Tuning
### NTC Thermistors
The firmware includes a **lookup table (LUT)** for NTC with B=3950, R25=1000Ω, covering -10..+59°C.
If a sensor reads `<5 ADC` → short circuit; `>4090 ADC` → open circuit.
To calibrate your NTCs, modify `Rlut[]` in `adc.c`.
### MLX90640
Calibration data is **per-sensor** and stored in EEPROM. The firmware reads it automatically on
startup.
No user calibration is required the factory data is used.
### Vdd Measurement
Internal Vrefint (1.2V typical) and factory calibration value `*VREFINT_CAL_ADDR` are used:
```
Vdd = (VREFINT_CAL * 3.3) / ADC_VREF
```
### MCU Temperature
Internal sensor (ADC1_IN16) uses factory calibration `TEMP30_CAL_ADDR` and `TEMP110_CAL_ADDR`.
---
## Troubleshooting
### No USB device detected
- Check `USBPU_ON()` in `main.c` some boards need pull-up control, others constant.
- Verify PA11/PA12 are configured as AF14.
- Try different USB cable / port.
### I²C communication errors
- Reduce speed: `iicspeed = 1` (100 kHz).
- Check pull-up resistors (2.2k10kΩ on SCL/SDA).
- Use `iicscan` to verify sensor addresses.
### BMP280 not responding
- Check SPI wiring (PB3PB5, PB9 CS).
- Try software reset: `bmereinit`.
- Verify chip ID: should be 0x58 (BMP280) or 0x60 (BME280).
### Heater not working
- Check `autoheater` status: `autoheater`.
- Verify NTC readings: `ntc`.
- For manual mode: `setheater = 25`, observe `pwm`.
### Cartoon mode stops updating
- Cartoon mode works **only over USB**, not UART.
- If no new images, check `state` may be paused or in error.
### Watchdog resets
- IWDG period is 2 seconds. Long operations (e.g., full calibration dump) may trigger reset.
- Disable in debug builds (remove `IWDG_REFRESH` calls or undefine `EBUG`).
---
## Performance & Limitations
| Parameter | Value |
|-----------|-------|
| Image update rate (5 sensors) | ~12 Hz (depends on I²C speed) |
| RAM usage | ~39 kB (image buffers + parameters) |
| Flash usage | ~26 kB |
| Maximum sensors | 5 (limited by I²C address space 0x100x14) |
| Temperature range | -40..+300°C (MLX90640) |
| Accuracy | ±1°C (typical after calibration) |
---
## License
All source files are licensed under **GNU General Public License v3.0** unless stated otherwise.
The BMP280 driver includes MIT-licensed code from sheinz (2016).
---
## Credits & References
- **Author:** Edward V. Emelianov <edward.emelianoff@gmail.com>
- **MLX90640 Datasheet:** Melexis (Document REV 10)
- **BMP280 Datasheet:** Bosch Sensortec
- **STM32F303 Reference Manual:** STMicroelectronics (RM0316)
For questions, bug reports, or contributions, please use the GitHub issue tracker.

Binary file not shown.

View File

@@ -22,8 +22,8 @@
#ifdef EBUG
#include "strfunc.h"
#include "usb_dev.h"
#endif
#include "usb_dev.h"
// turn on/off automatic cover heater in case of high humidity
uint8_t AutoHeater = 0;

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 19.0.1, 2026-05-20T22:25:52. -->
<!-- Written by QtCreator 19.0.2, 2026-05-29T11:48:44. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{7bd84e39-ca37-46d3-be9d-99ebea85bc0d}</value>
<value type="QByteArray">{cf63021e-ef53-49b0-b03b-2f2570cdf3b6}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
@@ -32,7 +32,7 @@
<value type="QByteArray" key="EditorConfiguration.Codec">KOI8-R</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">true</value>
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
@@ -40,9 +40,9 @@
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">false</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">1</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
@@ -51,10 +51,10 @@
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">false</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">true</value>
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
</valuemap>
@@ -79,8 +79,8 @@
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
<value type="int" key="ClangTools.ParallelJobs">2</value>
<value type="bool" key="ClangTools.PreferConfigFile">false</value>
<value type="int" key="ClangTools.ParallelJobs">4</value>
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
@@ -96,12 +96,12 @@
<value type="bool" key="HasPerBcDcs">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{65a14f9e-e008-4c1b-89df-4eaa4774b6e3}</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{91347f2c-5221-46a7-80b1-0a054ca02f79}</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Big/Data/00__Electronics/STM32/F303-nolib/blink</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/eddy/Yandex.Disk/Projects/stm32samples/F3:F303/MLX90640-allsky</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
@@ -153,8 +153,10 @@
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
<value type="QList&lt;int&gt;" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
@@ -167,6 +169,7 @@
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
@@ -187,8 +190,10 @@
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
<value type="QList&lt;int&gt;" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
@@ -201,6 +206,7 @@
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>

View File

@@ -1,5 +1,6 @@
BMP280.c
BMP280.h
Readme.md
adc.c
adc.h
commproto.cpp

Before

Width:  |  Height:  |  Size: 372 B

After

Width:  |  Height:  |  Size: 382 B

View File

@@ -1,2 +1,2 @@
#define BUILD_NUMBER "65"
#define BUILD_DATE "2026-05-06"
#define BUILD_NUMBER "67"
#define BUILD_DATE "2026-05-29"

106
Readme.md
View File

@@ -1,10 +1,104 @@
Some working code examples for STM32
====================================
# Repository Overview
Built without any third-party library.
The `stm32samples` repository is a collection of low-level, bare-metal code examples and complete
projects for various STM32 microcontroller series (F0, F1, F3, F4, G0). It uses CMSIS header files
from `modm-io/cmsis-header-stm32` for register definitions.
Supported F0, F1, F3, F4 and G0 series.
## Project Structure by MCU Series
### STM32F0 (F030, F042, F072)
- **3steppersLB** Controls 3 stepper motors with encoders via USB/CAN bus
- **blink** Simple LED toggling
- **CANbus4BTA** CAN replacement for PEP-CAN
- **CANBUS_SSI** Works with BTA SSI azimuth encoder
- **Chiller** Basic chiller temperature controller
- **F0_testbrd** Tests STM32F0x2 on custom board
- **htu21d_nucleo** Reads HTU-21D sensor on Nucleo-F042K
- **morze** Echoes USART1 data as Morse code on TIM3CH1 (PA6)
- **NUCLEO_SPI** SSI over SPI on Nucleo-F042K
- **PL2303_ringbuffer** USB CDC ACM with ring buffers
- **QuadEncoder** Quadrature encoder via timer
- **Servo** Controls SG-90 style servos
- **Socket_fans** Manages multiple fans
- **TM1637** Drives 7segment displays
- **tsys01_nucleo** Reads two TSYS01 sensors
- **uart_blink & uart_blink_dma** USART echo with DMA
- **usbcan_relay** Relay board over CAN bus
- **usbcan_ringbuffer** USBCAN adapter with ring buffers
- **USBHID** USB HID keyboard + mouse
CMSIS-headers:
https://github.com/modm-io/cmsis-header-stm32
### STM32F1 (F103)
- **BMP180, BMP280** I²C temperature/pressure sensors
- **Canon_managing_device** Controls Canon lenses
- **canUART** UARTCAN bridge
- **DHT22_DHT11** Humidity sensors using timer+DMA
- **DS18** DS18x20 temperature sensors
- **F1_testbrd** Test board for LQFP48 packages
- **I2Cscan** I²C scanner with register R/W
- **LED_Screen** Drives 32×16 LED matrices (P10)
- **MAX7219_screen** Controls 8×8 LED matrices
- **RGB_LED_Screen** HUB75E RGB panel with 8.8.4 color
- **SevenCDCs** Seven USBCDC ACM instances on one MCU (joke project)
- **shutter** Bistable shutter via USB/external signal
- **Tetris** Tetris on HUB75E panel
- **USB_HID** USB HID mouse+keyboard
- **ws2815** Rainbow effect on WS2815 strips
### STM32F3 (F303)
- **ADC** Works with ADC peripheral
- **blink** Toggles LEDs on PB0/PB1
- **CANusb** USBCAN adapter
- **floatPrintf** Converts floats to strings
- **Multistepper** Controls up to 64 multiplexed steppers
- **NitrogenFlooding** Automatic nitrogen flooding
- **PL2303** PL2303 emulator (old)
- **Seven_CDCs** Seven USB CDC ACM interfaces
- **usart1fullDMA** USART1 Rx/Tx DMA with match detection
- **USB_template_CDC** USBCDC template
### STM32F4 (F401)
- **blink** Simple LED toggling
### STM32G0 (G070, G0B1)
- **blink** Basic LED blink
- **RTC** Realtime clock
- **flash** Flash memory operations
- **g0b1** USBCDC working on G0B1
- **i2c** I²C operations
- **usart** USART communication
### Other Directories
- **deprecated** Archive of older, nolongermaintained code
- **snippets** Small reusable code fragments
- **testboard** KiCad 8 design files
## Development Environment
- **Toolchain**: arm-none-eabigcc with `-flto` optimisations
- **Build**: Structured Makefiles per series
- **Debug**: OpenOCD configuration files provided
- **Libraries**: No thirdparty libraries; only CMSISSVD headers
## Project Maturity
- **Alpha**: USB template for F303, MLX90640 allsky camera
- **Stable**: LED blink, UART echo, sensor interfaces, USBCDC
- **Draft**: CANbus4BTA, MLX90640multi
- **Deprecated**: Older code in `deprecated/`
## Summary
This repository is a valuable resource for learning lowlevel STM32 programming without vendor
libraries. It covers practical applications:
- **Industrial control**: Stepper motors, CAN bus, relay boards
- **Sensor interfacing**: Temperature, pressure, humidity, encoders
- **Humanmachine interfaces**: LED matrices, 7segment displays, USB HID
- **Communication**: UART, SPI, I²C, USBCDC, USBHID, CAN
- **Prototyping**: Test boards for F0, F1, F3, G0
For the latest updates, check the repository on GitHub.
## License
This repository is provided under the GNU General Public License v3 or later.
Full text of the GPLv3 is available at <https://www.gnu.org/licenses/gpl-3.0.html>.