|
1 | | -# MaixCAM Thermal 160 Real-time Thermal Imaging Monitoring |
| 1 | +# MaixCAM Thermal160 Real-time Thermal Imaging |
2 | 2 |
|
3 | | -This is a real-time thermal imaging monitoring application developed based on the MaixPy v4 framework, specifically designed for MaixCAM2 (and future supported models). The application receives raw thermal imaging data at 160x120 resolution via UART and renders it as a real-time video stream with Ironbow pseudo-color mapping. |
| 3 | +This is a MaixPy v4 Thermal160 live-view app for MaixCAM2. It receives 160x120 thermal frames over UART, parses the tail telemetry, and renders pseudo-color live video with center temperature, min/max markers, and NUC status. The 24-hour history recorder is now built into this app, so no separate history app is required. |
4 | 4 |
|
5 | 5 | ## Hardware Requirements |
6 | 6 |
|
7 | | -* Device: MaixCAM2, code can be ported to other platforms that support UART peripherals |
8 | | -* Sensor: Thermal imaging module with PMOD interface or UART output supporting 160x120 pixels. |
9 | | -* Connection method: |
10 | | - * MaixCAM2 defaults to /dev/ttyS2. |
11 | | - * Baud rate: Initial 2,000,000, can jump to up to 4,000,000 after handshake. |
| 7 | +* Device: MaixCAM2. |
| 8 | +* Sensor: Thermal160 / TN160 160x120 thermal imaging module. |
| 9 | +* Connections: |
| 10 | + * UART: MaixCAM2 uses `/dev/ttyS2` by default. |
| 11 | + * Baud rate: starts at `2,000,000`, then switches to `4,000,000` after sending the `0x44` handshake. |
| 12 | + * Reset: MaixCAM2 `A9` is configured as `GPIOA9` and used as the Thermal160 software reset pin. |
| 13 | + |
| 14 | +## Startup Behavior |
| 15 | + |
| 16 | +When MaixCAM2 is powered from battery, Thermal160 may not automatically enter a usable powered/reset state. Before opening UART, the app sends one A9 reset pulse: |
| 17 | + |
| 18 | +1. `pinmap.set_pin_function("A9", "GPIOA9")` |
| 19 | +2. Release `GPIOA9` high by default |
| 20 | +3. Pull it low for about `120ms` |
| 21 | +4. Release it high and wait about `400ms` |
| 22 | + |
| 23 | +The current implementation assumes an active-low reset. If your hardware reset is active-high, swap these constants: |
| 24 | + |
| 25 | +```python |
| 26 | +THERMAL_RESET_IDLE_LEVEL = 0 |
| 27 | +THERMAL_RESET_ACTIVE_LEVEL = 1 |
| 28 | +``` |
| 29 | + |
| 30 | +During startup, the UI shows `Initializing thermal160` with a progress bar for 3 seconds. It only shows `thermal160 device not found` if no valid frame is received after that grace period. |
12 | 31 |
|
13 | 32 | ## Configuration |
14 | 33 |
|
15 | 34 | Adjust the following constants at the top of the code as needed: |
16 | 35 |
|
17 | | -* CMAP = True: Set to True to display color thermal imaging, False to display original grayscale (zero-copy, higher performance). |
18 | | -* SKIP_COUNT = 10: Number of initial frames to skip on startup, used to stabilize sensor data. |
| 36 | +* `SKIP_COUNT = 10`: Initial frames skipped after startup. |
| 37 | +* `STARTUP_GRACE_SEC = 3.0`: Delay before showing `Device not found`. |
| 38 | +* `LONG_PRESS_SEC = 0.8`: Long-press time for entering the history screen from the lower-right button. |
| 39 | +* `SAMPLE_INTERVAL_SEC = 1.0`: History sampling interval. |
| 40 | +* `THERMAL_RESET_ASSERT_SEC = 0.12`: A9 reset assert time. |
| 41 | +* `THERMAL_RESET_RELEASE_DELAY_SEC = 0.40`: Delay after releasing reset. |
19 | 42 |
|
20 | 43 | ## Protocol Overview |
21 | 44 |
|
22 | 45 | The expected UART data format is: |
23 | 46 |
|
24 | | -* Header: 0xFF |
25 | | -* Payload: 19,200 bytes (160 * 120) of single-byte grayscale data. |
26 | | -* Checksum: Payload does not contain 0xFF. |
27 | | -* Total packet size: 19201 bytes |
| 47 | +* Header: `0xFF` |
| 48 | +* Pixels: `160 * 120 = 19200` bytes of 8-bit temperature-linear grayscale data |
| 49 | +* Telemetry: 30 bytes, including `VTEMP / t_lo / t_hi / anchor / smooth / mean_diff / NTC / NUC` runtime state |
| 50 | +* Total size: `1 + 19200 + 30 = 19231` bytes |
28 | 51 |
|
29 | | -## Notes |
| 52 | +Note: valid pixel data may contain `0xFF`. The parser must not resync only because `0xFF` appears in the pixel payload. It validates frame alignment using telemetry plausibility and the next-frame header position. |
| 53 | + |
| 54 | +## History Mode |
30 | 55 |
|
31 | | -* MaixCAM2 Compatibility: The program includes baud rate switching commands (0x44) specifically for MaixCAM2. When using other UART devices, please modify the HardwareHAL class according to the actual communication protocol. |
32 | | -* Resource Release: The program ensures safe UART resource release on exit through the finally block. |
| 56 | +On the live-view screen: |
| 57 | + |
| 58 | +* Short-press the lower-right button: switch color map. |
| 59 | +* Long-press the lower-right button for about `0.8s`: enter the history screen. |
| 60 | + |
| 61 | +On the history screen: |
| 62 | + |
| 63 | +* `BACK` in the upper-left corner: return to live view. |
| 64 | +* `SAVE` in the upper-right corner: save a full-history trend PNG. |
| 65 | + |
| 66 | +The app records one sample per second to CSV in the background. Entering the history screen does not stop UART reading. |
| 67 | + |
| 68 | +Output files are stored under this installed app directory: |
| 69 | + |
| 70 | +* MaixCam2 installed app output directory: `/maixapp/apps/thermal160_camera/output/` |
| 71 | +* CSV: `/maixapp/apps/thermal160_camera/output/history_YYYYmmdd_HHMMSS.csv` |
| 72 | +* PNG: `/maixapp/apps/thermal160_camera/output/trend_YYYYmmdd_HHMMSS.png` |
| 73 | + |
| 74 | +## Notes |
33 | 75 |
|
| 76 | +* A9 is only a reset control signal. Do not power Thermal160 directly from a MaixCAM2 GPIO. |
| 77 | +* Reset polarity and timing still need validation on real hardware. |
| 78 | +* UART resources are released in the `finally` block on exit. |
0 commit comments