From a991af0cd3093d32e55cd26a759612c040244df5 Mon Sep 17 00:00:00 2001 From: Joerg Lehmann Date: Thu, 12 Dec 2019 20:35:51 +0100 Subject: [PATCH] calibrate with downlink --- mini-beieli-node.ino | 138 ++++++++++++++++++++++++++++++------------- mini_beieli_node.h | 9 ++- 2 files changed, 102 insertions(+), 45 deletions(-) diff --git a/mini-beieli-node.ino b/mini-beieli-node.ino index 67248e1..723d3d9 100644 --- a/mini-beieli-node.ino +++ b/mini-beieli-node.ino @@ -141,12 +141,12 @@ static osjob_t sendJob; void setup(void) { gCatena.begin(); - ClearLoraData(); // Use D10 to regulate power pinMode(D10, OUTPUT); setup_platform(); + ClearLoraData(); setup_bme280(); //setup_scales(); @@ -176,8 +176,8 @@ void setup_platform(void) gCatena.SafePrintf("%010d - setup_platform, this is the configuration\n", millis()); gCatena.SafePrintf("cal_w1_0: %d\n", config_data.cal_w1_0); gCatena.SafePrintf("cal_w2_0: %d\n", config_data.cal_w2_0); - gCatena.SafePrintf("cal_w1_factor: %d.%03d\n", (int)config_data.cal_w1_factor, (int)(config_data.cal_w1_factor * 1000) % 1000); - gCatena.SafePrintf("cal_w2_factor: %d.%03d\n", (int)config_data.cal_w2_factor, (int)(config_data.cal_w2_factor * 1000) % 1000); + gCatena.SafePrintf("cal_w1_factor: %d.%03d\n", (int)config_data.cal_w1_factor, (int)abs(config_data.cal_w1_factor * 1000) % 1000); + gCatena.SafePrintf("cal_w2_factor: %d.%03d\n", (int)config_data.cal_w2_factor, (int)abs(config_data.cal_w2_factor * 1000) % 1000); gCatena.SafePrintf("debug_level: %d\n", (int)config_data.debug_level); } @@ -402,7 +402,10 @@ void ClearLoraData(void) lora_data_first.pressure = 0; lora_data_first.weight1 = 0; lora_data_first.weight2 = 0; - lora_data_first.weight = 0; + lora_data_first.cal_w1_0 = config_data.cal_w1_0; + lora_data_first.cal_w2_0 = config_data.cal_w2_0; + lora_data_first.cal_w1_factor = config_data.cal_w1_factor; + lora_data_first.cal_w2_factor = config_data.cal_w2_factor; lora_data_first.temperature = 0; my_position = 0; @@ -431,7 +434,10 @@ void ShowLORAData(bool firstTime) gCatena.SafePrintf(" \"pressure\": \"%u\",\n", lora_data_first.pressure); gCatena.SafePrintf(" \"weight1\": \"%ld\",\n", lora_data_first.weight1); gCatena.SafePrintf(" \"weight2\": \"%ld\",\n", lora_data_first.weight2); - gCatena.SafePrintf(" \"weight\": \"%u\",\n", lora_data_first.weight); + gCatena.SafePrintf(" \"cal_w1_0\": \"%ld\",\n", lora_data_first.cal_w1_0); + gCatena.SafePrintf(" \"cal_w2_0\": \"%ld\",\n", lora_data_first.cal_w2_0); + gCatena.SafePrintf(" \"cal_w1_factor\": \"%d.%03d\",\n", (int)lora_data_first.cal_w1_factor, (int)abs(lora_data_first.cal_w1_factor * 1000) % 1000); + gCatena.SafePrintf(" \"cal_w2_factor\": \"%d.%03d\",\n", (int)lora_data_first.cal_w2_factor, (int)abs(lora_data_first.cal_w2_factor * 1000) % 1000); gCatena.SafePrintf(" \"temperature\": \"%u\",\n", lora_data_first.temperature); gCatena.SafePrintf("}\n"); @@ -537,13 +543,13 @@ long my_read_average(byte gain, byte times) { gCatena.SafePrintf("%010d - my_read_average, measurements: ", millis()); } for (byte i = 0; i < times; i++) { - delay(WAITTIMELOADSAMPLES * 1000); + delay(WAITTIMELOADSAMPLES * 1000); LoadCell.power_up(); LoadCell.set_gain(gain); delay(2); // wait for stabilizing v = LoadCell.read(); LoadCell.power_down(); - + if (L > v) L = v; // find lowest value if (H < v) H = v; // find highest value sum += v; @@ -556,7 +562,7 @@ long my_read_average(byte gain, byte times) { if (config_data.debug_level > 0) { gCatena.SafePrintf("; average (without highest [%d] and lowest [%d] value): %d\n", H, L, res); } - + return res; } @@ -569,7 +575,7 @@ void ReadSensors(SENSOR_data &sensor_data) { int vbat_mv = (int)(gCatena.ReadVbat() * 1000.0f); res.vbat = GetVBatValue(vbat_mv); if (config_data.debug_level > 0) { - gCatena.SafePrintf("%010d - vBat: %d mV\n", vbat_mv); + gCatena.SafePrintf("%010d - vBat: %d mV\n", millis(), vbat_mv); } // Read Scales @@ -578,12 +584,12 @@ void ReadSensors(SENSOR_data &sensor_data) { gCatena.SafePrintf("%010d - HX711 LoadCell is ready.\n", millis()); } gCatena.poll(); - res.weight1 = (int32_t)my_read_average(32,7); + res.weight1 = (int32_t)my_read_average(32, 7); if (config_data.debug_level > 0) { gCatena.SafePrintf("%010d - Load_cell 1 weight1_current: %ld\n", millis(), res.weight1); } gCatena.poll(); - res.weight2 = (int32_t)my_read_average(128,7); + res.weight2 = (int32_t)my_read_average(128, 7); if (config_data.debug_level > 0) { gCatena.SafePrintf("%010d - Load_cell 2 weight2_current: %ld\n", millis(), res.weight2); } @@ -638,6 +644,7 @@ void ReadSensors(SENSOR_data &sensor_data) { void StartNewIteration() { uint32_t wait_time; + wait_time = 0; // we increment the iteration counter iteration++; @@ -653,11 +660,10 @@ void StartNewIteration() { } fUsbPower = (vBus > 4.3) ? true : false; - if (iteration == 1) { + if (iteration <= 3) { lora_data_first.vbat = current_sensor_reading.vbat; lora_data_first.weight1 = current_sensor_reading.weight1; lora_data_first.weight2 = current_sensor_reading.weight2; - lora_data_first.weight = current_sensor_reading.weight; lora_data_first.temperature = current_sensor_reading.temperature; lora_data_first.humidity = current_sensor_reading.humidity; lora_data_first.pressure = current_sensor_reading.pressure; @@ -685,7 +691,7 @@ void StartNewIteration() { } if (config_data.debug_level > 0) { - ShowLORAData(iteration == 1); + ShowLORAData(iteration <= 3); } my_position++; @@ -693,12 +699,13 @@ void StartNewIteration() { // we send data the first time the system is started, when the array is full // or when the weight has fallen more than threshold or the first measurement is // more than one hour old (which should not happen :-) ) - if ( (iteration == 1) || (my_position >= MAX_VALUES_TO_SEND) || ((last_sensor_reading.weight - current_sensor_reading.weight) > SEND_DIFF_THRESHOLD_5GRAMS) || ((millis() - timer_pos0) > 3600000)) { + if ( (iteration <= 3) || (my_position >= MAX_VALUES_TO_SEND) || ((last_sensor_reading.weight - current_sensor_reading.weight) > SEND_DIFF_THRESHOLD_5GRAMS) || ((millis() - timer_pos0) > 3600000)) { lora_data.offset_last_reading = (uint8_t)((millis() - timer_pos0) / 1000 / 60); if (config_data.debug_level > 0) { gCatena.SafePrintf("%010d - startSendingUplink(), my_position: %d, iteration: %d\n", millis(), my_position, iteration); } - startSendingUplink(iteration == 1); + // the first 3 packets are "Init-Packets"... + startSendingUplink(iteration <= 3); if (config_data.debug_level > 1) { gLed.Set(LedPattern::TwoShort); } @@ -719,7 +726,7 @@ void StartNewIteration() { } } - if (iteration > 1) { + if (iteration > 3) { // we make the current sensor reading to the last one... last_sensor_reading = current_sensor_reading; } @@ -732,6 +739,11 @@ void StartNewIteration() { sleep_time_sec = 5; } + // for the first 3 iterations, we set the sleep time to 10 seconds only... + if (iteration <= 3) { + sleep_time_sec = 10; + } + if (config_data.debug_level > 0) { gCatena.SafePrintf("%010d - now going to sleep for %d seconds...\n", millis(), sleep_time_sec); if (fUsbPower) { @@ -903,8 +915,16 @@ static void startNewIterationCb(osjob_t* pJob) static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage, size_t nMessage) { - uint32_t gram_A; - uint32_t gram_B; + long cal_w1_0; + long cal_w2_0; + float cal_w1_factor; + float cal_w2_factor; + + union u_tag { + byte b[4]; + float fval; + } u; + SENSOR_data temp_sensor_data; if (config_data.debug_level > 0) { @@ -944,9 +964,9 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage gCatena.SafePrintf("\n"); } - if (LMIC.seqnoUp > 2) { + if (LMIC.seqnoUp > 3) { if (config_data.debug_level > 0) { - gCatena.SafePrintf("tare with downlink is only possible within first two uplink packets!\n"); + gCatena.SafePrintf("setting calibration config with downlink is only possible within first three uplink packets!\n"); return; } @@ -964,30 +984,64 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage } } - if (port == 1 && nMessage == 9) { - if (pMessage[0] == 1) { - gram_A = 0; - gram_A += (long)pMessage[1] << 24; - gram_A += (long)pMessage[2] << 16; - gram_A += (long)pMessage[3] << 8; - gram_A += (long)pMessage[4]; + if (port == 1 && nMessage == 17) { + cal_w1_0 = 0; + cal_w1_0 += (long)pMessage[1] << 24; + cal_w1_0 += (long)pMessage[2] << 16; + cal_w1_0 += (long)pMessage[3] << 8; + cal_w1_0 += (long)pMessage[4]; - gram_B = 0; - gram_B += (long)pMessage[5] << 24; - gram_B += (long)pMessage[6] << 16; - gram_B += (long)pMessage[7] << 8; - gram_B += (long)pMessage[8]; + cal_w2_0 = 0; + cal_w2_0 += (long)pMessage[5] << 24; + cal_w2_0 += (long)pMessage[6] << 16; + cal_w2_0 += (long)pMessage[7] << 8; + cal_w2_0 += (long)pMessage[8]; + + u.b[0] = pMessage[12]; + u.b[1] = pMessage[11]; + u.b[2] = pMessage[10]; + u.b[3] = pMessage[9]; + cal_w1_factor = u.fval; + + u.b[0] = pMessage[16]; + u.b[1] = pMessage[15]; + u.b[2] = pMessage[14]; + u.b[3] = pMessage[13]; + cal_w2_factor = u.fval; + + if (pMessage[0] == 0) { + // set both scales to 0, use transmitted values (offset only) if (config_data.debug_level > 0) { - gCatena.SafePrintf("tare scales, A: %d, B: %d\n", gram_A, gram_B); + gCatena.SafePrintf("set calibration to zero, cal_w1_0: %d, cal_w2_0: %d\n", cal_w1_0, cal_w2_0); } - ReadSensors(temp_sensor_data); - config_data.cal_w1_factor = (((float)temp_sensor_data.weight1 - config_data.cal_w1_0) / gram_A); - config_data.cal_w2_factor = (((float)temp_sensor_data.weight2 - config_data.cal_w2_0) / gram_B); + + config_data.cal_w1_0 = cal_w1_0; + config_data.cal_w2_0 = cal_w2_0; gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); + lora_data_first.cal_w1_0 = config_data.cal_w1_0; + lora_data_first.cal_w2_0 = config_data.cal_w2_0; + } + + if (pMessage[0] == 1) { + // update calibration config with transmitted values + + if (config_data.debug_level > 0) { + gCatena.SafePrintf("update calibration config, cal_w1_0: %d, cal_w2_0: %d, cal_w1_factor: %d.%03d, cal_w2_factor: %d.%03d\n", cal_w1_0, cal_w2_0, (int)cal_w1_factor, (int)abs(cal_w1_factor * 1000) % 1000, (int)cal_w2_factor, (int)abs(cal_w2_factor * 1000) % 1000); + } + + config_data.cal_w1_0 = cal_w1_0; + config_data.cal_w2_0 = cal_w2_0; + config_data.cal_w1_factor = cal_w1_factor; + config_data.cal_w2_factor = cal_w2_factor; + gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); + + lora_data_first.cal_w1_0 = config_data.cal_w1_0; + lora_data_first.cal_w2_0 = config_data.cal_w2_0; + lora_data_first.cal_w1_factor = config_data.cal_w1_factor; + lora_data_first.cal_w2_factor = config_data.cal_w2_factor; } } - } /* process "application hello" -- args are ignored */ @@ -1048,7 +1102,7 @@ cCommandStream::CommandStatus cmdGetScale2(cCommandStream *pThis, void *pContext cCommandStream::CommandStatus cmdCalibrateZeroScaleA(cCommandStream *pThis, void *pContext, int argc, char **argv) { setup_scales(); - config_data.cal_w1_0 = (int32_t)my_read_average(32,10); + config_data.cal_w1_0 = (int32_t)my_read_average(32, 10); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); pThis->printf("{ \"msg\": \"calibrate_zero_scale_a was successful\" }\n"); @@ -1058,7 +1112,7 @@ cCommandStream::CommandStatus cmdCalibrateZeroScaleA(cCommandStream *pThis, void cCommandStream::CommandStatus cmdCalibrateZeroScaleB(cCommandStream *pThis, void *pContext, int argc, char **argv) { setup_scales(); - config_data.cal_w2_0 = (int32_t)my_read_average(128,10); + config_data.cal_w2_0 = (int32_t)my_read_average(128, 10); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); pThis->printf("{ \"msg\": \"calibrate_zero_scale_b was successful\" }\n"); @@ -1070,7 +1124,7 @@ cCommandStream::CommandStatus cmdCalibrateScaleA(cCommandStream *pThis, void *pC String w1_gramm(argv[1]); long weight1; setup_scales(); - weight1 = my_read_average(32,10); + weight1 = my_read_average(32, 10); config_data.cal_w1_factor = (float)((weight1 - config_data.cal_w1_0) / w1_gramm.toFloat()); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); @@ -1085,7 +1139,7 @@ cCommandStream::CommandStatus cmdCalibrateScaleB(cCommandStream *pThis, void *pC String w2_gramm(argv[1]); long weight2; setup_scales(); - weight2 = my_read_average(128,10); + weight2 = my_read_average(128, 10); config_data.cal_w2_factor = (float)((weight2 - config_data.cal_w2_0) / w2_gramm.toFloat()); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); diff --git a/mini_beieli_node.h b/mini_beieli_node.h index a303b93..9caf45b 100644 --- a/mini_beieli_node.h +++ b/mini_beieli_node.h @@ -55,7 +55,7 @@ enum { | \****************************************************************************/ -static const int32_t fwVersion = 20191209; +static const int32_t fwVersion = 20191212; // wait between samples // 3 sec is a good delay so that load cell did not warm up @@ -66,7 +66,7 @@ const int WAITTIMELOADSAMPLES = 3; static const byte MAX_VALUES_TO_SEND = 8; //static const byte MAX_VALUES_TO_SEND = 1; // Testing static const uint8_t LORA_DATA_VERSION = 1; -static const uint8_t LORA_DATA_VERSION_FIRST_PACKAGE = 129; +static const uint8_t LORA_DATA_VERSION_FIRST_PACKAGE = 128; static const uint32_t PRESSURE_OFFSET = 825; static const uint16_t SEND_DIFF_THRESHOLD_5GRAMS = 10; // when weight value drops by 50g, then send data @@ -100,7 +100,10 @@ typedef struct { uint8_t pressure; // Luftdruck in Hekto-Pascal (0 entspricht 825 hPa) int32_t weight1; // Waegezelle 1, Raw Value int32_t weight2; // Waegezelle 2, Raw Value - uint16_t weight; // Waegezelle Gesamtgewicht, in 5g + long cal_w1_0; // 4 Bytes, Wert Waegezelle 1 ohne Gewicht + long cal_w2_0; // 4 Bytes, Wert Waegezelle 2 ohne Gewicht + float cal_w1_factor; // 4 Bytes, Kalibrationsfaktor Waegezelle 1 + float cal_w2_factor; // 4 Bytes, Kalibrationsfaktor Waegezelle 2 } __attribute__((packed)) LORA_data_first; typedef struct {