firmware: add pH calibration NVS, protocol, and dispatch
This commit is contained in:
parent
3c33c7806d
commit
5b051cfa20
36
main/eis.c
36
main/eis.c
|
|
@ -26,6 +26,8 @@ static struct {
|
||||||
/* cell constant K (cm⁻¹), cached from NVS */
|
/* cell constant K (cm⁻¹), cached from NVS */
|
||||||
static float cell_k_cached;
|
static float cell_k_cached;
|
||||||
static float cl_factor_cached;
|
static float cl_factor_cached;
|
||||||
|
static float ph_slope_cached;
|
||||||
|
static float ph_offset_cached;
|
||||||
|
|
||||||
/* open-circuit calibration data */
|
/* open-circuit calibration data */
|
||||||
static struct {
|
static struct {
|
||||||
|
|
@ -594,8 +596,10 @@ int eis_has_open_cal(void)
|
||||||
return ocal.valid;
|
return ocal.valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NVS_CELLK_KEY "cell_k"
|
#define NVS_CELLK_KEY "cell_k"
|
||||||
#define NVS_CLFACTOR_KEY "cl_factor"
|
#define NVS_CLFACTOR_KEY "cl_factor"
|
||||||
|
#define NVS_PH_SLOPE_KEY "ph_slope"
|
||||||
|
#define NVS_PH_OFFSET_KEY "ph_offset"
|
||||||
|
|
||||||
void eis_set_cell_k(float k)
|
void eis_set_cell_k(float k)
|
||||||
{
|
{
|
||||||
|
|
@ -646,3 +650,31 @@ void eis_load_cl_factor(void)
|
||||||
cl_factor_cached = 0.0f;
|
cl_factor_cached = 0.0f;
|
||||||
nvs_close(h);
|
nvs_close(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void eis_set_ph_cal(float slope, float offset)
|
||||||
|
{
|
||||||
|
ph_slope_cached = slope;
|
||||||
|
ph_offset_cached = offset;
|
||||||
|
nvs_handle_t h;
|
||||||
|
if (nvs_open(NVS_OCAL_NS, NVS_READWRITE, &h) != ESP_OK) return;
|
||||||
|
nvs_set_blob(h, NVS_PH_SLOPE_KEY, &slope, sizeof(slope));
|
||||||
|
nvs_set_blob(h, NVS_PH_OFFSET_KEY, &offset, sizeof(offset));
|
||||||
|
nvs_commit(h);
|
||||||
|
nvs_close(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
float eis_get_ph_slope(void) { return ph_slope_cached; }
|
||||||
|
float eis_get_ph_offset(void) { return ph_offset_cached; }
|
||||||
|
|
||||||
|
void eis_load_ph_cal(void)
|
||||||
|
{
|
||||||
|
nvs_handle_t h;
|
||||||
|
if (nvs_open(NVS_OCAL_NS, NVS_READONLY, &h) != ESP_OK) return;
|
||||||
|
size_t len = sizeof(ph_slope_cached);
|
||||||
|
if (nvs_get_blob(h, NVS_PH_SLOPE_KEY, &ph_slope_cached, &len) != ESP_OK || len != sizeof(ph_slope_cached))
|
||||||
|
ph_slope_cached = 0.0f;
|
||||||
|
len = sizeof(ph_offset_cached);
|
||||||
|
if (nvs_get_blob(h, NVS_PH_OFFSET_KEY, &ph_offset_cached, &len) != ESP_OK || len != sizeof(ph_offset_cached))
|
||||||
|
ph_offset_cached = 0.0f;
|
||||||
|
nvs_close(h);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,4 +71,9 @@ void eis_set_cl_factor(float f);
|
||||||
float eis_get_cl_factor(void);
|
float eis_get_cl_factor(void);
|
||||||
void eis_load_cl_factor(void);
|
void eis_load_cl_factor(void);
|
||||||
|
|
||||||
|
void eis_set_ph_cal(float slope, float offset);
|
||||||
|
float eis_get_ph_slope(void);
|
||||||
|
float eis_get_ph_offset(void);
|
||||||
|
void eis_load_ph_cal(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
11
main/eis4.c
11
main/eis4.c
|
|
@ -57,6 +57,7 @@ void app_main(void)
|
||||||
eis_load_open_cal();
|
eis_load_open_cal();
|
||||||
eis_load_cell_k();
|
eis_load_cell_k();
|
||||||
eis_load_cl_factor();
|
eis_load_cl_factor();
|
||||||
|
eis_load_ph_cal();
|
||||||
temp_init();
|
temp_init();
|
||||||
|
|
||||||
esp_netif_init();
|
esp_netif_init();
|
||||||
|
|
@ -225,6 +226,16 @@ void app_main(void)
|
||||||
send_cl_factor(eis_get_cl_factor());
|
send_cl_factor(eis_get_cl_factor());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CMD_SET_PH_CAL:
|
||||||
|
eis_set_ph_cal(cmd.ph_cal.slope, cmd.ph_cal.offset);
|
||||||
|
send_ph_cal(cmd.ph_cal.slope, cmd.ph_cal.offset);
|
||||||
|
printf("pH cal set: slope=%.4f offset=%.4f\n", cmd.ph_cal.slope, cmd.ph_cal.offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_GET_PH_CAL:
|
||||||
|
send_ph_cal(eis_get_ph_slope(), eis_get_ph_offset());
|
||||||
|
break;
|
||||||
|
|
||||||
case CMD_START_CL: {
|
case CMD_START_CL: {
|
||||||
ClConfig cl_cfg;
|
ClConfig cl_cfg;
|
||||||
cl_cfg.v_cond = cmd.cl.v_cond;
|
cl_cfg.v_cond = cmd.cl.v_cond;
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,19 @@ int send_cl_end(void)
|
||||||
return send_sysex(sx, sizeof(sx));
|
return send_sysex(sx, sizeof(sx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- outbound: pH calibration ---- */
|
||||||
|
|
||||||
|
int send_ph_cal(float slope, float offset)
|
||||||
|
{
|
||||||
|
uint8_t sx[16];
|
||||||
|
uint16_t p = 0;
|
||||||
|
sx[p++] = 0xF0; sx[p++] = 0x7D; sx[p++] = RSP_PH_CAL;
|
||||||
|
encode_float(slope, &sx[p]); p += 5;
|
||||||
|
encode_float(offset, &sx[p]); p += 5;
|
||||||
|
sx[p++] = 0xF7;
|
||||||
|
return send_sysex(sx, p);
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- outbound: pH ---- */
|
/* ---- outbound: pH ---- */
|
||||||
|
|
||||||
int send_ph_result(float v_ocp_mv, float ph, float temp_c)
|
int send_ph_result(float v_ocp_mv, float ph, float temp_c)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@
|
||||||
#define CMD_CLEAR_REFS 0x32
|
#define CMD_CLEAR_REFS 0x32
|
||||||
#define CMD_SET_CL_FACTOR 0x33
|
#define CMD_SET_CL_FACTOR 0x33
|
||||||
#define CMD_GET_CL_FACTOR 0x34
|
#define CMD_GET_CL_FACTOR 0x34
|
||||||
|
#define CMD_SET_PH_CAL 0x35
|
||||||
|
#define CMD_GET_PH_CAL 0x36
|
||||||
|
|
||||||
/* Session sync commands (0x4x) */
|
/* Session sync commands (0x4x) */
|
||||||
#define CMD_SESSION_CREATE 0x40
|
#define CMD_SESSION_CREATE 0x40
|
||||||
|
|
@ -59,6 +61,7 @@
|
||||||
#define RSP_REFS_DONE 0x22
|
#define RSP_REFS_DONE 0x22
|
||||||
#define RSP_REF_STATUS 0x23
|
#define RSP_REF_STATUS 0x23
|
||||||
#define RSP_CL_FACTOR 0x24
|
#define RSP_CL_FACTOR 0x24
|
||||||
|
#define RSP_PH_CAL 0x25
|
||||||
|
|
||||||
/* Session sync responses (0x4x) */
|
/* Session sync responses (0x4x) */
|
||||||
#define RSP_SESSION_CREATED 0x40
|
#define RSP_SESSION_CREATED 0x40
|
||||||
|
|
@ -85,6 +88,7 @@ typedef struct {
|
||||||
struct { float v_mv; float duration_s; } clean;
|
struct { float v_mv; float duration_s; } clean;
|
||||||
float cell_k;
|
float cell_k;
|
||||||
float cl_factor;
|
float cl_factor;
|
||||||
|
struct { float slope; float offset; } ph_cal;
|
||||||
struct { uint8_t name_len; char name[MAX_SESSION_NAME]; } session_create;
|
struct { uint8_t name_len; char name[MAX_SESSION_NAME]; } session_create;
|
||||||
struct { uint8_t id; } session_switch;
|
struct { uint8_t id; } session_switch;
|
||||||
struct { uint8_t id; uint8_t name_len; char name[MAX_SESSION_NAME]; } session_rename;
|
struct { uint8_t id; uint8_t name_len; char name[MAX_SESSION_NAME]; } session_rename;
|
||||||
|
|
@ -139,6 +143,9 @@ int send_cell_k(float k);
|
||||||
/* outbound: chlorine factor */
|
/* outbound: chlorine factor */
|
||||||
int send_cl_factor(float f);
|
int send_cl_factor(float f);
|
||||||
|
|
||||||
|
/* outbound: pH calibration */
|
||||||
|
int send_ph_cal(float slope, float offset);
|
||||||
|
|
||||||
/* outbound: reference collection */
|
/* outbound: reference collection */
|
||||||
int send_ref_frame(uint8_t mode, uint8_t rtia_idx);
|
int send_ref_frame(uint8_t mode, uint8_t rtia_idx);
|
||||||
int send_ref_lp_range(uint8_t mode, uint8_t low_idx, uint8_t high_idx);
|
int send_ref_lp_range(uint8_t mode, uint8_t low_idx, uint8_t high_idx);
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,11 @@ static void parse_udp_sysex(const uint8_t *data, uint16_t len)
|
||||||
if (len < 8) return;
|
if (len < 8) return;
|
||||||
cmd.cl_factor = decode_float(&data[3]);
|
cmd.cl_factor = decode_float(&data[3]);
|
||||||
break;
|
break;
|
||||||
|
case CMD_SET_PH_CAL:
|
||||||
|
if (len < 13) return;
|
||||||
|
cmd.ph_cal.slope = decode_float(&data[3]);
|
||||||
|
cmd.ph_cal.offset = decode_float(&data[8]);
|
||||||
|
break;
|
||||||
case CMD_SESSION_CREATE:
|
case CMD_SESSION_CREATE:
|
||||||
if (len < 5) return;
|
if (len < 5) return;
|
||||||
cmd.session_create.name_len = data[3] & 0x7F;
|
cmd.session_create.name_len = data[3] & 0x7F;
|
||||||
|
|
@ -197,6 +202,7 @@ static void parse_udp_sysex(const uint8_t *data, uint16_t len)
|
||||||
case CMD_GET_TEMP:
|
case CMD_GET_TEMP:
|
||||||
case CMD_GET_CELL_K:
|
case CMD_GET_CELL_K:
|
||||||
case CMD_GET_CL_FACTOR:
|
case CMD_GET_CL_FACTOR:
|
||||||
|
case CMD_GET_PH_CAL:
|
||||||
case CMD_START_REFS:
|
case CMD_START_REFS:
|
||||||
case CMD_GET_REFS:
|
case CMD_GET_REFS:
|
||||||
case CMD_CLEAR_REFS:
|
case CMD_CLEAR_REFS:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue