Files
Edward Emelianov f6178a8b84 add plot script
2026-07-23 22:29:10 +03:00
..
2026-07-23 22:29:10 +03:00
2026-06-24 22:56:04 +03:00
2026-06-01 09:34:53 +03:00
2026-06-01 09:34:53 +03:00
2025-10-05 00:10:02 +03:00
2025-10-05 00:10:02 +03:00
2026-06-01 09:34:53 +03:00
2026-06-01 09:34:53 +03:00
2026-05-20 22:28:01 +03:00
2026-05-29 11:49:55 +03:00
2026-05-20 22:28:01 +03:00
2026-06-01 09:34:53 +03:00
2026-06-01 09:34:53 +03:00
2026-05-29 11:49:55 +03:00
2026-06-01 09:34:53 +03:00
2026-06-01 09:34:53 +03:00
2026-05-20 22:28:01 +03:00
2026-06-01 09:34:53 +03:00
2025-10-05 00:10:02 +03:00
2025-10-05 00:10:02 +03:00
2025-10-06 23:27:30 +03:00
2026-06-01 09:34:53 +03:00
2026-06-01 09:34:53 +03:00
2025-10-05 00:10:02 +03:00
2025-10-05 00:10:02 +03:00
2026-06-01 09:34:53 +03:00

IR All-Sky Camera Documentation

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.

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


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 (0–3.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
PA0–PA3 NTC1–NTC4 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 0–100
  • ch3 – Proportional to (35°C – T_ambient + T_sky) × 2.5 %, clamped 0–100

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 (0–4) 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 (0–3) 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 (0–100%) for channel n pwm 0 = 50

System & Debug

Command Description Example
adc [n] Get raw ADC value (0–4095) for channel n adc 4
dac [= val] Get/set DAC output (0–4095) 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 16‑character 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
0 0x10 Zenith
1 0x11 East
2 0x12 South
3 0x13 West
4 0x14 North


Building & Flashing

Prerequisites

Build

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

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):

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.2k–10kΩ on SCL/SDA).
  • Use iicscan to verify sensor addresses.

BMP280 not responding

  • Check SPI wiring (PB3–PB5, 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) ~1–2 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 0x10–0x14)
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.