Skip to content

Commit f7a5b83

Browse files
committed
MZTC: correct the driver against the camera protocol manual
Five points where the code disagreed with the BJ core serial protocol manual. The manual is the one shipped with the camera and it is the source for the class and subclass addresses the driver already used. Auto shutter wire values The camera defines 0x01 for temperature only, 0x02 for time only and 0x03 for time and temperature. It answers 0x00 with a threshold error. The driver sent the zero-based setting straight through. Every mode was off by one. The default sent an out of range value. The setting keeps its zero-based ordering for the settings.yaml lookup table. The driver adds MZTC_SHUTTER_WIRE_OFFSET on the way out. Shutter interval belongs to the camera 0x7C/0x05 is a read and write command taking two bytes of minutes. The camera runs the schedule from it. The driver ignored the command and ran its own timer, firing manual shutter commands that competed with the camera. The interval is now pushed on connect. mztcCheckCalibration only counts elapsed minutes for the status and OSD surfaces. mztc_ffc_interval now accepts 1 to 60. Zero no longer means disabled, because the camera owns the schedule. Selecting TEMP_ONLY is how time-driven correction is turned off. Initialization status reply address The host asks on 0x7C/0x14. The manual specifies the reply as class 0x7D subclass 0x06. The decoder matched on the request address. The reply was never decoded. Vignetting correction is an action 0x7C/0x0C with data 0x02, write only. The manual requires the lens to be pointed at a uniform surface first. Running it automatically would superimpose the current scene onto the correction. The boolean setting is removed. mztc_vignetting and MSP2_SET_MZTC_VIGNETTING at 0x224B replace it. Bad pixel removal is not a setting 0x78/0x1A drives an on-screen cursor through move, confirm and cancel steps. A flight controller cannot walk that cursor onto each bad pixel. The boolean setting is removed with nothing in its place. Both removed booleans were never transmitted. They did nothing. Contract changes The MSP config payload drops from 24 to 22 bytes. msp_messages.json moves to 2.3.0 and gains MSP2_SET_MZTC_VIGNETTING. docs/Settings.md is regenerated. The camera manual contradicts itself on the zoom labels. Its prose says 1x, 2x, 4x and 8x. Its value table for the same command says 1x, 2x, 3x and 4x. The wire values 0 to 3 are identical either way. The enum is unchanged and the ambiguity is documented. Validated on three builds. SPEEDYBEEF405AIO with MZTC on sits at 77.9% flash. MATEKF722SE with MZTC off sits at 95.1% flash. SITL builds too. All three compile with no warnings in any MZTC file. 543 of 543 unit tests pass.
1 parent da45c74 commit f7a5b83

10 files changed

Lines changed: 171 additions & 117 deletions

File tree

docs/MassZero_Thermal_Camera.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ set mztc_mirror_mode = NONE
148148

149149
Zoom accepts `1X`, `2X`, `4X` and `8X`. Mirror accepts `NONE`, `HORIZONTAL`, `VERTICAL` and `CENTRAL`. `mztc_zoom 2` applies a zoom level immediately by index.
150150

151+
The camera manual contradicts itself on the zoom labels. Its prose says 1x, 2x, 4x and 8x. Its value table for the same command says 1x, 2x, 3x and 4x. The wire values 0 to 3 are the same either way. The setting works regardless of which set of labels is right.
152+
151153
### Shutter and flat field correction
152154

153155
A manual shutter cycle on this camera performs a flat field correction. One command covers both:
@@ -163,7 +165,9 @@ set mztc_auto_shutter = TIME_AND_TEMP
163165
set mztc_ffc_interval = 5
164166
```
165167

166-
`mztc_auto_shutter` accepts `TEMP_ONLY`, `TIME_ONLY` and `TIME_AND_TEMP`. `mztc_ffc_interval` is in minutes. Setting it to 0 disables the time-driven correction. INAV issues its own timed correction unless `mztc_auto_shutter` is `TEMP_ONLY`. In that case the timing is left to the camera.
168+
`mztc_auto_shutter` accepts `TEMP_ONLY`, `TIME_ONLY` and `TIME_AND_TEMP`. `mztc_ffc_interval` is in minutes and accepts 1 to 60.
169+
170+
The camera runs the shutter schedule itself. INAV pushes both values to it on connect and then leaves it alone. Select `TEMP_ONLY` to stop the camera correcting on a timer, since it then reacts to temperature drift only.
167171

168172
### Temperature alerts
169173

@@ -177,11 +181,21 @@ Both thresholds accept -40 to 200 degrees Celsius. The low threshold must not ex
177181

178182
Alerts only fire once the camera reports a temperature. The published MassZero protocol document defines no temperature-read command. No build in this tree reports one yet. The alert state stays clear.
179183

180-
### Correction and display options
184+
### Vignetting correction
185+
186+
Vignetting correction is a one-shot action. There is no setting for it:
187+
188+
```
189+
mztc_vignetting
190+
```
191+
192+
Point the lens at a uniform surface before running it. The camera superimposes whatever it is looking at onto the correction. A cluttered scene makes the image worse.
193+
194+
Bad pixel removal is not exposed. The camera drives it through an on-screen cursor that has to be walked onto each bad pixel. A flight controller cannot do that usefully.
195+
196+
### Display options
181197

182198
```
183-
set mztc_bad_pixel_removal = ON
184-
set mztc_vignetting_correction = ON
185199
set mztc_crosshair_enabled = OFF
186200
set mztc_temperature_unit = CELSIUS
187201
set mztc_update_rate = 9
@@ -202,6 +216,7 @@ set mztc_update_rate = 9
202216
| `mztc_denoise <spatial> <temporal>` | Set both denoising levels |
203217
| `mztc_alerts <enabled> <high> <low>` | Configure the temperature alerts |
204218
| `mztc_calibrate` | Trigger a manual shutter cycle for a flat field correction |
219+
| `mztc_vignetting` | Run one vignetting correction |
205220
| `mztc_save` | Save the current image settings to the camera's own flash |
206221
| `mztc_defaults` | Restore the camera to its factory defaults |
207222
| `mztc_reconnect` | Close the port and restart the connection sequence |
@@ -214,17 +229,18 @@ The camera is reachable over MSP V2 in INAV's own command range. Full payload la
214229

215230
| Command | Code | Direction | Payload |
216231
| --- | --- | --- | --- |
217-
| `MSP2_MZTC_CONFIG` | 0x2240 | Out | 24 bytes |
232+
| `MSP2_MZTC_CONFIG` | 0x2240 | Out | 22 bytes |
218233
| `MSP2_MZTC_STATUS` | 0x2241 | Out | 19 bytes |
219234
| `MSP2_MZTC_FRAME_DATA` | 0x2242 | Out | 24 byte header plus thermal bytes |
220-
| `MSP2_SET_MZTC_CONFIG` | 0x2243 | In | 24 bytes |
235+
| `MSP2_SET_MZTC_CONFIG` | 0x2243 | In | 22 bytes |
221236
| `MSP2_SET_MZTC_MODE` | 0x2244 | In | 1 byte |
222237
| `MSP2_SET_MZTC_PALETTE` | 0x2245 | In | 1 byte |
223238
| `MSP2_SET_MZTC_ZOOM` | 0x2246 | In | 1 byte |
224239
| `MSP2_SET_MZTC_SHUTTER` | 0x2247 | In | 0 or 1 bytes |
225240
| `MSP2_SET_MZTC_ALERTS` | 0x2248 | In | 5 bytes |
226241
| `MSP2_SET_MZTC_IMAGE_PARAMS` | 0x2249 | In | 3 bytes |
227242
| `MSP2_SET_MZTC_CORRECTION` | 0x224A | In | 2 bytes |
243+
| `MSP2_SET_MZTC_VIGNETTING` | 0x224B | In | 0 or 1 bytes |
228244

229245
Temperatures cross as signed 16 bit deci-degrees Celsius. 25.5 degrees is 255. Every field is read and written individually. The wire layout never depends on compiler padding.
230246

docs/Settings.md

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3551,16 +3551,6 @@ Auto shutter calibration mode
35513551

35523552
---
35533553

3554-
### mztc_bad_pixel_removal
3555-
3556-
Enable bad pixel removal
3557-
3558-
| Default | Min | Max |
3559-
| --- | --- | --- |
3560-
| ON | OFF | ON |
3561-
3562-
---
3563-
35643554
### mztc_baudrate
35653555

35663556
Baud rate index for MassZero Thermal Camera. Index 8 is 115200. MassZero cameras ship at that rate.
@@ -3623,11 +3613,11 @@ Enable MassZero Thermal Camera
36233613

36243614
### mztc_ffc_interval
36253615

3626-
Flat Field Calibration interval in minutes (0=disabled)
3616+
Automatic shutter interval in minutes. The camera runs the schedule itself. Set mztc_auto_shutter to TEMP_ONLY to stop it correcting on a timer.
36273617

36283618
| Default | Min | Max |
36293619
| --- | --- | --- |
3630-
| 5 | 0 | 60 |
3620+
| 5 | 1 | 60 |
36313621

36323622
---
36333623

@@ -3746,16 +3736,6 @@ Frame update rate in Hz
37463736

37473737
---
37483738

3749-
### mztc_vignetting_correction
3750-
3751-
Enable vignetting correction
3752-
3753-
| Default | Min | Max |
3754-
| --- | --- | --- |
3755-
| ON | OFF | ON |
3756-
3757-
---
3758-
37593739
### mztc_zoom_level
37603740

37613741
Digital zoom level

docs/development/msp/msp_messages.json

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"version": {
33
"major": 2,
4-
"minor": 2,
4+
"minor": 3,
55
"patch": 0
66
},
77
"messages": {
@@ -11799,23 +11799,11 @@
1179911799
"name": "ffc_interval",
1180011800
"ctype": "uint8_t",
1180111801
"units": "minutes",
11802-
"desc": "Automatic flat field correction interval. 0-60, where 0 disables it."
11803-
},
11804-
{
11805-
"name": "bad_pixel_removal",
11806-
"ctype": "uint8_t",
11807-
"units": "",
11808-
"desc": "Bad pixel removal enabled. 0 or 1."
11809-
},
11810-
{
11811-
"name": "vignetting_correction",
11812-
"ctype": "uint8_t",
11813-
"units": "",
11814-
"desc": "Vignetting correction enabled. 0 or 1."
11802+
"desc": "Automatic shutter interval in minutes. 1-60. The camera runs the schedule itself."
1181511803
}
1181611804
]
1181711805
},
11818-
"notes": "Requires `USE_MZTC`. Fixed 24 byte reply. Each field is written with the `sbufWrite*` helpers. The layout never depends on compiler padding.",
11806+
"notes": "Requires `USE_MZTC`. Fixed 22 byte reply. Each field is written with the `sbufWrite*` helpers. The layout never depends on compiler padding.",
1181911807
"description": "Reads the MassZero thermal camera configuration."
1182011808
},
1182111809
"MSP2_MZTC_STATUS": {
@@ -12101,24 +12089,12 @@
1210112089
"name": "ffc_interval",
1210212090
"ctype": "uint8_t",
1210312091
"units": "minutes",
12104-
"desc": "Automatic flat field correction interval. 0-60, where 0 disables it."
12105-
},
12106-
{
12107-
"name": "bad_pixel_removal",
12108-
"ctype": "uint8_t",
12109-
"units": "",
12110-
"desc": "Bad pixel removal enabled. 0 or 1."
12111-
},
12112-
{
12113-
"name": "vignetting_correction",
12114-
"ctype": "uint8_t",
12115-
"units": "",
12116-
"desc": "Vignetting correction enabled. 0 or 1."
12092+
"desc": "Automatic shutter interval in minutes. 1-60. The camera runs the schedule itself."
1211712093
}
1211812094
]
1211912095
},
1212012096
"reply": null,
12121-
"notes": "Requires `USE_MZTC`. Expects 24 bytes. The whole request is validated against the `MZTC_*` limits before any field is applied. A rejected request leaves the running configuration untouched.",
12097+
"notes": "Requires `USE_MZTC`. Expects 22 bytes. The whole request is validated against the `MZTC_*` limits before any field is applied. A rejected request leaves the running configuration untouched.",
1212212098
"description": "Writes the MassZero thermal camera configuration."
1212312099
},
1212412100
"MSP2_SET_MZTC_MODE": {
@@ -12269,6 +12245,23 @@
1226912245
"reply": null,
1227012246
"notes": "Requires `USE_MZTC`. Expects 2 bytes. Returns an error if the camera is not connected.",
1227112247
"description": "Sets the MassZero thermal camera denoising parameters."
12248+
},
12249+
"MSP2_SET_MZTC_VIGNETTING": {
12250+
"code": 8779,
12251+
"mspv": 2,
12252+
"request": {
12253+
"payload": [
12254+
{
12255+
"name": "trigger",
12256+
"ctype": "uint8_t",
12257+
"units": "",
12258+
"desc": "Ignored. The command itself is the trigger."
12259+
}
12260+
]
12261+
},
12262+
"reply": null,
12263+
"notes": "Requires `USE_MZTC`. Accepts 0 or 1 bytes. The camera manual requires the lens to be pointed at a uniform surface before this runs, so it is an action and never a stored setting.",
12264+
"description": "Runs one vignetting correction on the camera."
1227212265
}
1227312266
}
1227412267
}

src/main/config/mztc_camera.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,28 @@ typedef enum {
7878
MZTC_MIRROR_CENTRAL = 3 // Both horizontal and vertical
7979
} mztcMirrorMode_e;
8080

81-
// MassZero Thermal Camera auto shutter modes
81+
// MassZero Thermal Camera auto shutter modes.
82+
//
83+
// The camera expects 0x01 to 0x03 on the wire and rejects 0x00 as out of
84+
// range, so the driver adds MZTC_SHUTTER_WIRE_OFFSET when it sends the value.
85+
// These enum values stay zero-based because settings.yaml indexes its lookup
86+
// table from zero.
8287
typedef enum {
83-
MZTC_SHUTTER_TEMP_ONLY = 0, // Based on temperature difference only
84-
MZTC_SHUTTER_TIME_ONLY = 1, // Based on time interval only
85-
MZTC_SHUTTER_TIME_AND_TEMP = 2 // Both time and temperature (default)
88+
MZTC_SHUTTER_TEMP_ONLY = 0, // Camera wire value 0x01
89+
MZTC_SHUTTER_TIME_ONLY = 1, // Camera wire value 0x02
90+
MZTC_SHUTTER_TIME_AND_TEMP = 2 // Camera wire value 0x03, the default
8691
} mztcShutterMode_e;
8792

93+
#define MZTC_SHUTTER_WIRE_OFFSET 1
94+
8895
// MassZero Thermal Camera limits.
8996
//
9097
// These are the single source of truth for the valid ranges. settings.yaml
9198
// references them for the CLI bounds. The MSP handlers validate against them.
9299
// A value the CLI rejects cannot be smuggled in over MSP.
93100
#define MZTC_MIN_UPDATE_RATE 1 // Minimum 1 Hz
94101
#define MZTC_MAX_UPDATE_RATE 30 // Maximum 30 Hz
95-
#define MZTC_MIN_FFC_INTERVAL 0 // 0 disables periodic FFC
102+
#define MZTC_MIN_FFC_INTERVAL 1 // Minimum 1 minute
96103
#define MZTC_MAX_FFC_INTERVAL 60 // Maximum 60 minutes
97104
#define MZTC_MIN_PERCENT 0
98105
#define MZTC_MAX_PERCENT 100
@@ -127,9 +134,7 @@ typedef struct mztcConfig_s {
127134
uint8_t temperature_alerts; // Enable temperature alerts
128135
float alert_high_temp; // High temperature alert threshold
129136
float alert_low_temp; // Low temperature alert threshold
130-
uint8_t ffc_interval; // Flat Field Calibration interval (minutes)
131-
uint8_t bad_pixel_removal; // Enable bad pixel removal
132-
uint8_t vignetting_correction; // Enable vignetting correction
137+
uint8_t ffc_interval; // Automatic shutter interval, in minutes
133138
} mztcConfig_t;
134139

135140
// MassZero Thermal Camera status structure
@@ -219,6 +224,7 @@ bool mztcIsConnected(void);
219224
void mztcRequestReconnect(void);
220225
bool mztcSaveConfiguration(void);
221226
bool mztcRestoreDefaults(void);
227+
bool mztcTriggerVignettingCorrection(void);
222228
bool mztcConfigIsValid(const mztcConfig_t *cfg);
223229

224230
// Serial framing helpers. Exposed so the unit test can exercise the wire

src/main/fc/cli.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ static void cliMztcCalibrate(char *cmdline);
170170
static void cliMztcReconnect(char *cmdline);
171171
static void cliMztcSave(char *cmdline);
172172
static void cliMztcDefaults(char *cmdline);
173+
static void cliMztcVignetting(char *cmdline);
173174
#endif
174175

175176
#ifdef USE_CLI_BATCH
@@ -5242,6 +5243,19 @@ static void cliMztcDefaults(char *cmdline)
52425243
cliPrintLine("Failed to restore camera defaults");
52435244
}
52445245
}
5246+
5247+
// Point the lens at a uniform surface before running this. The camera
5248+
// superimposes whatever it is looking at onto the correction otherwise.
5249+
static void cliMztcVignetting(char *cmdline)
5250+
{
5251+
UNUSED(cmdline);
5252+
5253+
if (mztcTriggerVignettingCorrection()) {
5254+
cliPrintLine("Vignetting correction triggered. Point the lens at a uniform surface first.");
5255+
} else {
5256+
cliPrintLine("Failed to trigger vignetting correction");
5257+
}
5258+
}
52455259
#endif // USE_MZTC
52465260

52475261
static void cliHelp(char *cmdline);
@@ -5332,6 +5346,7 @@ const clicmd_t cmdTable[] = {
53325346
CLI_COMMAND_DEF("mztc_mode", "set operating mode", "[mode]", cliMztcMode),
53335347
CLI_COMMAND_DEF("mztc_palette", "set color palette", "[palette]", cliMztcPalette),
53345348
CLI_COMMAND_DEF("mztc_save", "save the current settings to the camera flash", NULL, cliMztcSave),
5349+
CLI_COMMAND_DEF("mztc_vignetting", "run one vignetting correction", NULL, cliMztcVignetting),
53355350
CLI_COMMAND_DEF("mztc_zoom", "set zoom level", "[level]", cliMztcZoom),
53365351
#endif
53375352
CLI_COMMAND_DEF("mmix", "custom motor mixer", NULL, cliMotorMix),

src/main/fc/fc_msp.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,8 +2020,6 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
20202020
sbufWriteU16(dst, (uint16_t)MZTC_TEMP_TO_DECIDEG(cfg->alert_high_temp));
20212021
sbufWriteU16(dst, (uint16_t)MZTC_TEMP_TO_DECIDEG(cfg->alert_low_temp));
20222022
sbufWriteU8(dst, cfg->ffc_interval);
2023-
sbufWriteU8(dst, cfg->bad_pixel_removal);
2024-
sbufWriteU8(dst, cfg->vignetting_correction);
20252023
}
20262024
break;
20272025

@@ -4082,8 +4080,6 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
40824080
candidate.alert_high_temp = MZTC_DECIDEG_TO_TEMP((int16_t)sbufReadU16(src));
40834081
candidate.alert_low_temp = MZTC_DECIDEG_TO_TEMP((int16_t)sbufReadU16(src));
40844082
candidate.ffc_interval = sbufReadU8(src);
4085-
candidate.bad_pixel_removal = sbufReadU8(src);
4086-
candidate.vignetting_correction = sbufReadU8(src);
40874083

40884084
// This rejects an update_rate of zero. The camera task would
40894085
// otherwise use it as a divisor. It also rejects a baudrate that
@@ -4177,6 +4173,18 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
41774173
return MSP_RESULT_ERROR;
41784174
}
41794175
break;
4176+
4177+
case MSP2_SET_MZTC_VIGNETTING:
4178+
// An action, not a setting. The lens has to be pointed at a uniform
4179+
// surface before this is worth running.
4180+
if (dataSize <= 1) {
4181+
if (!mztcTriggerVignettingCorrection()) {
4182+
return MSP_RESULT_ERROR;
4183+
}
4184+
} else {
4185+
return MSP_RESULT_ERROR;
4186+
}
4187+
break;
41804188
#endif
41814189

41824190
case MSP2_INAV_SET_CRUISE_HEADING:

src/main/fc/settings.yaml

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ constants:
260260

261261
MZTC_MIN_UPDATE_RATE: 1
262262
MZTC_MAX_UPDATE_RATE: 30
263-
MZTC_MIN_FFC_INTERVAL: 0
263+
MZTC_MIN_FFC_INTERVAL: 1
264264
MZTC_MAX_FFC_INTERVAL: 60
265265
MZTC_MIN_PERCENT: 0
266266
MZTC_MAX_PERCENT: 100
@@ -4867,22 +4867,12 @@ groups:
48674867
min: MZTC_MIN_ALERT_TEMP
48684868
max: MZTC_MAX_ALERT_TEMP
48694869
- name: mztc_ffc_interval
4870-
description: "Flat Field Calibration interval in minutes (0=disabled)"
4870+
description: "Automatic shutter interval in minutes. The camera runs the schedule itself. Set mztc_auto_shutter to TEMP_ONLY to stop it correcting on a timer."
48714871
type: uint8_t
48724872
default_value: 5
48734873
field: ffc_interval
48744874
min: MZTC_MIN_FFC_INTERVAL
48754875
max: MZTC_MAX_FFC_INTERVAL
4876-
- name: mztc_bad_pixel_removal
4877-
description: "Enable bad pixel removal"
4878-
type: bool
4879-
default_value: ON
4880-
field: bad_pixel_removal
4881-
- name: mztc_vignetting_correction
4882-
description: "Enable vignetting correction"
4883-
type: bool
4884-
default_value: ON
4885-
field: vignetting_correction
48864876
- name: PG_GEOZONE_CONFIG
48874877
type: geozone_config_t
48884878
headers: ["navigation/navigation.h"]

0 commit comments

Comments
 (0)