From da5e52a0336db6026968dd110d30141f789089b4 Mon Sep 17 00:00:00 2001 From: Joerg Lehmann Date: Fri, 15 Nov 2019 22:03:55 +0100 Subject: [PATCH] refactor sending code --- mini-beieli-node.ino | 411 +++++++++++++++++-------------------------- mini_beieli_node.h | 107 +++++++++++ 2 files changed, 265 insertions(+), 253 deletions(-) create mode 100644 mini_beieli_node.h diff --git a/mini-beieli-node.ino b/mini-beieli-node.ino index fcb1b4c..0ff2014 100644 --- a/mini-beieli-node.ino +++ b/mini-beieli-node.ino @@ -26,59 +26,14 @@ #include #include +#include "mini_beieli_node.h" using namespace McciCatena; -/****************************************************************************\ - | - | MANIFEST CONSTANTS & TYPEDEFS - | - \****************************************************************************/ - -constexpr uint8_t kUplinkPort = 2; - -/* how long do we wait between transmissions? (in seconds) */ -enum { - // set this to interval between transmissions, in seconds - // Actual time will be a little longer because have to - // add measurement and broadcast time, but we attempt - // to compensate for the gross effects below. - CATCFG_T_CYCLE = 6 * 60, // every 6 minutes - CATCFG_T_CYCLE_TEST = 30, // every 10 seconds - CATCFG_T_CYCLE_INITIAL = 30, // every 30 seconds initially - CATCFG_INTERVAL_COUNT_INITIAL = 30, // repeat for 15 minutes -}; - -/* additional timing parameters; ususually you don't change these. */ -enum { - CATCFG_T_WARMUP = 1, - CATCFG_T_SETTLE = 5, - CATCFG_T_OVERHEAD = (CATCFG_T_WARMUP + CATCFG_T_SETTLE), - CATCFG_T_MIN = CATCFG_T_OVERHEAD, - CATCFG_T_MAX = CATCFG_T_CYCLE < 60 * 60 ? 60 * 60 : CATCFG_T_CYCLE, // normally one hour max. - CATCFG_INTERVAL_COUNT = 30, -}; - -constexpr uint32_t CATCFG_GetInterval(uint32_t tCycle) -{ - return (tCycle < CATCFG_T_OVERHEAD) - ? CATCFG_T_OVERHEAD - : tCycle - CATCFG_T_OVERHEAD; -} - -enum { - CATCFG_T_INTERVAL = CATCFG_GetInterval(CATCFG_T_CYCLE), -}; - -enum { - PIN_ONE_WIRE = A2, // XSDA1 == A2 - PIN_SHT10_CLK = 8, // XSCL0 == D8 - PIN_SHT10_DATA = 12, // XSDA0 == D12 -}; - // forwards static void settleDoneCb(osjob_t* pSendJob); static void warmupDoneCb(osjob_t* pSendJob); +static void startNewIterationCb(osjob_t* pJob); static void txNotProvisionedCb(osjob_t *pSendJob); static void sleepDoneCb(osjob_t* pSendJob); static Arduino_LoRaWAN::SendBufferCbFn sendBufferDoneCb; @@ -123,69 +78,12 @@ sMyExtraCommands_top( ); -/****************************************************************************\ - | - | READ-ONLY DATA - | - \****************************************************************************/ - -static const int32_t fwVersion = 20191004; -static const byte MAX_VALUES_TO_SEND = 8; -static const uint8_t LORA_DATA_VERSION = 1; -static const uint8_t LORA_DATA_VERSION_FIRST_PACKAGE = 129; -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 - /****************************************************************************\ | | VARIABLES | \****************************************************************************/ -// must be 139 bytes long (size of kBme680Cal) -typedef struct { - 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 - byte debug_level; // 0 => no debugging, 1 => infos, 2 => error, 3 => highest level - byte fill[122]; -} __attribute__((packed)) CONFIG_data; - -typedef struct { - uint8_t version; // Version of Packet Format (must be increased every time format changes...) - uint8_t vbat; // Batteriespannung (0: <= 2510mV, 70: 3000mV, 170: 3700mV, 255: >= 4295mV [1 Einheit => 7mV]) - uint8_t humidity[MAX_VALUES_TO_SEND]; // Luftfeuchtigkeit in Prozent - int16_t temperature; // Temperatur (Startwert) in 1/10 Grad Celsius - int8_t temperature_change[MAX_VALUES_TO_SEND - 1]; // Unterschied Temperatur seit letztem Messwert in 1/10 Grad Celsius - uint8_t pressure[MAX_VALUES_TO_SEND]; // Luftdruck in Hekto-Pascal (0 entspricht 825 hPa) - uint16_t weight[MAX_VALUES_TO_SEND]; // Waegezelle Gesamtgewicht, in 5g - uint8_t offset_last_reading; // Zeitunterschied letzte zu erste Messung (in Minuten) -} __attribute__((packed)) LORA_data; - -typedef struct { - uint8_t version; // Version of Packet Format (must be increased every time format changes...) - int32_t fw_version; // Version of Firmware, Nummer entspricht YYYYMMDD - uint8_t vbat; // Batteriespannung (0: <= 2510mV, 70: 3000mV, 170: 3700mV, 255: >= 4295mV [1 Einheit => 7mV]) - uint8_t humidity; // Luftfeuchtigkeit in Prozent - int16_t temperature; // Temperatur in 1/10 Grad Celsius - 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 -} __attribute__((packed)) LORA_data_first; - -typedef struct { - uint8_t vbat; // Batteriespannung (0: <= 2510mV, 70: 3000mV, 170: 3700mV, 255: >= 4295mV [1 Einheit => 7mV]) - uint8_t humidity; // Luftfeuchtigkeit in Prozent - int16_t temperature; // Temperatur in 1/10 Grad Celsius - 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 -} SENSOR_data; - - byte my_position = 0; // what is our actual measurement, starts with 0 long timer_pos0; @@ -194,6 +92,7 @@ LORA_data lora_data; LORA_data_first lora_data_first; CONFIG_data config_data; SENSOR_data last_sensor_reading; +long iteration = 0; // what iteration number do we have, starts with 0 // generic timer long t_cur; @@ -234,9 +133,9 @@ bool fUsbPower; // have we printed the sleep info? bool g_fPrintedSleeping = false; -// tFhe job that's used to synchronize us with the LMIC code +// the job that's used to synchronize us with the LMIC code static osjob_t sensorJob; -void sensorJob_cb(osjob_t* pJob); +static osjob_t iterationJob; void setup(void) { @@ -276,6 +175,8 @@ void setup_platform(void) gCatena.SafePrintf("cal_w2_factor: %d.%03d\n", (int)config_data.cal_w2_factor, (int)(config_data.cal_w2_factor * 1000) % 1000); gCatena.SafePrintf("debug_level: %d\n", (int)config_data.debug_level); gCatena.SafePrintf("Size of config_data: %d\n", sizeof(config_data)); + gCatena.SafePrintf("Size of lora_data_first: %d\n", sizeof(lora_data_first)); + gCatena.SafePrintf("Size of lora_data: %d\n", sizeof(lora_data)); } @@ -441,7 +342,7 @@ void setup_uplink(void) gLed.Set(LedPattern::Joining); /* trigger a join by sending the first packet */ - ReadSensors(true, false); + StartNewIteration(); } } } @@ -565,7 +466,6 @@ uint8_t GetVBatValue(int millivolts) return res; } - void DoDeepSleep() { if (config_data.debug_level > 0) { @@ -595,51 +495,30 @@ void DoDeepSleep() } } - -void ReadSensors(bool firstTime, bool readOnly) -{ - int16_t temp_current; - uint8_t humidity_current; - uint8_t pressure_current; - int32_t weight1_current; - int32_t weight2_current; - int16_t temp_change; +void ReadSensors(SENSOR_data &sensor_data) { + SENSOR_data res; int32_t weight_current32; - uint16_t weight_current; // vBat - float vBat = gCatena.ReadVbat(); + res.vbat = (uint8_t)(gCatena.ReadVbat() * 1000.0f); if (config_data.debug_level > 0) { - gCatena.SafePrintf("vBat: %d mV\n", (int)(vBat * 1000.0f)); + gCatena.SafePrintf("vBat: %d mV\n", res.vbat); } - // vBus - float vBus = gCatena.ReadVbus(); - if (config_data.debug_level > 0) { - gCatena.SafePrintf("vBus: %d mV\n", (int)(vBus * 1000.0f)); - } - fUsbPower = (vBus > 4.3) ? true : false; - - // Setup Scales - // Read Scales if (setup_scales()) { if (config_data.debug_level > 0) { gCatena.SafePrintf("HX711 LoadCell is ready.\n"); } LoadCell.set_gain(128); - long w1 = LoadCell.read_average(5); - weight1_current = (int32_t)w1; + res.weight1 = (int32_t)LoadCell.read_average(5); if (config_data.debug_level > 0) { - gCatena.SafePrintf("Load_cell 1 output val: %ld\n", w1); - gCatena.SafePrintf("Load_cell 1 weight1_current: %ld\n", weight1_current); + gCatena.SafePrintf("Load_cell 1 weight1_current: %ld\n", res.weight1); } LoadCell.set_gain(32); - long w2 = LoadCell.read_average(5); - weight2_current = (int32_t)w2; + res.weight2 = (int32_t)LoadCell.read_average(5); if (config_data.debug_level > 0) { - gCatena.SafePrintf("Load_cell 2 output val: %ld\n", w2); - gCatena.SafePrintf("Load_cell 2 weight2_current: %ld\n", weight2_current); + gCatena.SafePrintf("Load_cell 2 weight2_current: %ld\n", res.weight2); } } else { @@ -652,13 +531,13 @@ void ReadSensors(bool firstTime, bool readOnly) digitalWrite(D10, LOW); // Gewicht berechnen - weight_current32 = (int32_t)((((weight1_current - config_data.cal_w1_0) / config_data.cal_w1_factor) + ((weight2_current - config_data.cal_w2_0) / config_data.cal_w2_factor)) / 5.0); + weight_current32 = (int32_t)((((res.weight1 - config_data.cal_w1_0) / config_data.cal_w1_factor) + ((res.weight2 - config_data.cal_w2_0) / config_data.cal_w2_factor)) / 5.0); if (weight_current32 < 0) { weight_current32 = 0; } else if (weight_current32 > UINT16_MAX) { weight_current32 = UINT16_MAX; } - weight_current = (uint16_t)weight_current32; + res.weight = (uint16_t)weight_current32; if (fBme) { /* warm up the BME280 by discarding a measurement */ @@ -675,108 +554,119 @@ void ReadSensors(bool firstTime, bool readOnly) (int)m.Pressure, (int)m.Humidity); } - temp_current = (int16_t)((m.Temperature) * 10); - humidity_current = (uint8_t)m.Humidity; - pressure_current = (uint8_t)((m.Pressure / 100) - PRESSURE_OFFSET); + res.temperature = (int16_t)((m.Temperature) * 10); + res.humidity = (uint8_t)m.Humidity; + res.pressure = (uint8_t)((m.Pressure / 100) - PRESSURE_OFFSET); if (config_data.debug_level > 0) { - gCatena.SafePrintf("pressure_current: %d\n", pressure_current); + gCatena.SafePrintf("pressure_current: %d\n", res.pressure); } } - if (not(readOnly)) { + sensor_data = res; +} - if (firstTime) { - lora_data_first.vbat = GetVBatValue((int)(vBat * 1000.0f)); - lora_data_first.weight1 = weight1_current; - lora_data_first.weight2 = weight2_current; - lora_data_first.weight = weight_current; - lora_data_first.temperature = temp_current; - lora_data_first.humidity = humidity_current; - lora_data_first.pressure = pressure_current; - } else { - lora_data.vbat = GetVBatValue((int)(vBat * 1000.0f)); - lora_data.weight[my_position] = weight_current; - if (my_position == 0) { - lora_data.temperature = temp_current; - } else { - temp_change = temp_current - last_sensor_reading.temperature; - if (temp_change > 127) { - temp_change = 127; - } - if (temp_change < -128) { - temp_change = -128; - } +void StartNewIteration() { + // we increment the iteration counter + iteration++; - lora_data.temperature_change[my_position - 1] = (uint8_t)temp_change; - } - lora_data.humidity[my_position] = humidity_current; - lora_data.pressure[my_position] = pressure_current; - } + SENSOR_data current_sensor_reading; + ReadSensors(current_sensor_reading); + int16_t temp_change; + // vBus + float vBus = gCatena.ReadVbus(); + if (config_data.debug_level > 0) { + gCatena.SafePrintf("vBus: %d mV\n", (int)(vBus * 1000.0f)); + } + fUsbPower = (vBus > 4.3) ? true : false; + + if (iteration == 1) { + 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; + } else { + lora_data.vbat = current_sensor_reading.vbat; + lora_data.weight[my_position] = current_sensor_reading.weight; if (my_position == 0) { - timer_pos0 = millis(); - } - - if (config_data.debug_level > 0) { - ShowLORAData(firstTime); - } - my_position++; - - // Should we send the Data? - // 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 (firstTime || (my_position >= MAX_VALUES_TO_SEND) || ((last_sensor_reading.weight - weight_current) > 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("startSendingUplink()\n"); - } - startSendingUplink(firstTime); - gLed.Set(LedPattern::TwoShort); - - uint32_t deepSleepDelay = 10; - for (auto n = deepSleepDelay; n > 0; --n) - { - uint32_t tNow = millis(); - - while (uint32_t(millis() - tNow) < 1000) - { - gCatena.poll(); - yield(); - } - } + lora_data.temperature = current_sensor_reading.temperature; } else { - if (config_data.debug_level > 0) { - gCatena.SafePrintf("now going to sleep for 6 minutes...\n"); - if (fUsbPower) { - gCatena.SafePrintf("USB Power is on\n"); - } else { - gCatena.SafePrintf("USB Power is off\n"); - } - //Serial.flush(); + temp_change = current_sensor_reading.temperature - last_sensor_reading.temperature; + if (temp_change > 127) { + temp_change = 127; } - gLed.Set(LedPattern::Sleeping); - if (!fUsbPower) { - DoDeepSleep(); - sleepDoneCb(&sensorJob); - } else { - os_setTimedCallback( - &sensorJob, - os_getTime() + sec2osticks(CATCFG_T_INTERVAL), - sleepDoneCb); + if (temp_change < -128) { + temp_change = -128; + } + lora_data.temperature_change[my_position - 1] = (uint8_t)temp_change; + } + lora_data.humidity[my_position] = current_sensor_reading.humidity; + lora_data.pressure[my_position] = current_sensor_reading.pressure; + } + if (my_position == 0) { + timer_pos0 = millis(); + } + + if (config_data.debug_level > 0) { + ShowLORAData(iteration == 1); + } + my_position++; + + // Should we send the Data? + // 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)) { + lora_data.offset_last_reading = (uint8_t)((millis() - timer_pos0) / 1000 / 60); + if (config_data.debug_level > 0) { + gCatena.SafePrintf("startSendingUplink(), my_position: %d\n",my_position); + } + startSendingUplink(iteration == 1); + gLed.Set(LedPattern::TwoShort); + + // we allow 10 seconds for RX1 and RX2 to complete... + uint32_t deepSleepDelay = 10; + for (auto n = deepSleepDelay; n > 0; --n) + { + uint32_t tNow = millis(); + + while (uint32_t(millis() - tNow) < 1000) + { + gCatena.poll(); + yield(); } } } - last_sensor_reading.vbat = GetVBatValue((int)(vBat * 1000.0f)); + if (iteration > 1) { + // we make the current sensor reading to the last one... + last_sensor_reading = current_sensor_reading; + } - last_sensor_reading.weight1 = weight1_current; - last_sensor_reading.weight2 = weight2_current; - last_sensor_reading.weight = weight_current; - last_sensor_reading.temperature = temp_current; - last_sensor_reading.humidity = humidity_current; - last_sensor_reading.pressure = pressure_current; + if (config_data.debug_level > 0) { + gCatena.SafePrintf("now going to sleep for %d seconds...\n",CATCFG_T_INTERVAL); + if (fUsbPower) { + gCatena.SafePrintf("USB Power is on\n"); + } else { + gCatena.SafePrintf("USB Power is off\n"); + } + //Serial.flush(); + } + gLed.Set(LedPattern::Sleeping); + if (!fUsbPower) { + DoDeepSleep(); + startNewIterationCb(&iterationJob); + } else { + gCatena.SafePrintf("os_setTimedCallback for startNewIterationCb in %d...\n",CATCFG_T_INTERVAL); + os_setTimedCallback( + &iterationJob, + os_getTime() + sec2osticks(CATCFG_T_INTERVAL), + startNewIterationCb); + } } void startSendingUplink(bool firstTime) @@ -884,13 +774,20 @@ static void sleepDoneCb(osjob_t* pJob) static void warmupDoneCb(osjob_t* pJob) { - ReadSensors(false, false); + gCatena.SafePrintf("warmupDoneCb\n"); +} + +static void startNewIterationCb(osjob_t* pJob) +{ + gCatena.SafePrintf("startNewIterationCb\n"); + StartNewIteration(); } static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage, size_t nMessage) { uint32_t gram_A; uint32_t gram_B; + SENSOR_data temp_sensor_data; if (config_data.debug_level > 0) { gCatena.SafePrintf("receiveMessage was called!!!\n"); @@ -921,7 +818,7 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage port, nMessage ); // we print out the received message... - gCatena.SafePrintf("Current LMIC.seqnoUp: %d\n",LMIC.seqnoUp); + gCatena.SafePrintf("Current LMIC.seqnoUp: %d\n", LMIC.seqnoUp); gCatena.SafePrintf("Received Data (Payload): \n"); for (byte i = 0; i < nMessage; i++) { gCatena.SafePrintf("%02x", pMessage[i]); @@ -929,12 +826,12 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage gCatena.SafePrintf("\n"); } - if (LMIC.seqnoUp > 2) { + if (LMIC.seqnoUp > 2) { if (config_data.debug_level > 0) { gCatena.SafePrintf("tare with downlink is only possible within first two uplink packets!\n"); return; } - + } if (port == 1 && nMessage == 1) { @@ -942,9 +839,9 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage if (config_data.debug_level > 0) { gCatena.SafePrintf("reset both scales to zero\n"); } - ReadSensors(false, true); - config_data.cal_w1_0 = last_sensor_reading.weight1; - config_data.cal_w2_0 = last_sensor_reading.weight2; + ReadSensors(temp_sensor_data); + config_data.cal_w1_0 = temp_sensor_data.weight1; + config_data.cal_w2_0 = temp_sensor_data.weight2; gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); } } @@ -956,7 +853,7 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage gram_A += (long)pMessage[2] << 16; gram_A += (long)pMessage[3] << 8; gram_A += (long)pMessage[4]; - + gram_B = 0; gram_B += (long)pMessage[5] << 24; gram_B += (long)pMessage[6] << 16; @@ -966,9 +863,9 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage if (config_data.debug_level > 0) { gCatena.SafePrintf("tare scales, A: %d, B: %d\n", gram_A, gram_B); } - ReadSensors(false, true); - config_data.cal_w1_factor = (((float)last_sensor_reading.weight1 - config_data.cal_w1_0) / gram_A); - config_data.cal_w2_factor = (((float)last_sensor_reading.weight2 - config_data.cal_w2_0) / gram_B); + 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); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); } } @@ -1000,15 +897,17 @@ cCommandStream::CommandStatus cmdGetCalibrationSettings(cCommandStream *pThis, v cCommandStream::CommandStatus cmdGetSensorReadings(cCommandStream *pThis, void *pContext, int argc, char **argv) { - ReadSensors(false, true); + SENSOR_data temp_sensor_data; + + ReadSensors(temp_sensor_data); pThis->printf("{\n"); - pThis->printf(" \"weight\": \"%d\",\n", last_sensor_reading.weight); - pThis->printf(" \"weight1_raw\": \"%d\",\n", last_sensor_reading.weight1); - pThis->printf(" \"weight2_raw\": \"%d\",\n", last_sensor_reading.weight2); - pThis->printf(" \"temperature\": \"%d\",\n", last_sensor_reading.temperature); - pThis->printf(" \"humidity\": \"%d\",\n", last_sensor_reading.humidity); - pThis->printf(" \"pressure\": \"%d\",\n", last_sensor_reading.pressure); - pThis->printf(" \"batt\": \"%d\",\n", last_sensor_reading.vbat); + pThis->printf(" \"weight\": \"%d\",\n", temp_sensor_data.weight); + pThis->printf(" \"weight1_raw\": \"%d\",\n", temp_sensor_data.weight1); + pThis->printf(" \"weight2_raw\": \"%d\",\n", temp_sensor_data.weight2); + pThis->printf(" \"temperature\": \"%d\",\n", temp_sensor_data.temperature); + pThis->printf(" \"humidity\": \"%d\",\n", temp_sensor_data.humidity); + pThis->printf(" \"pressure\": \"%d\",\n", temp_sensor_data.pressure); + pThis->printf(" \"batt\": \"%d\",\n", temp_sensor_data.vbat); pThis->printf("}\n"); return cCommandStream::CommandStatus::kSuccess; @@ -1030,8 +929,10 @@ cCommandStream::CommandStatus cmdGetScale2(cCommandStream *pThis, void *pContext cCommandStream::CommandStatus cmdCalibrateZeroScaleA(cCommandStream *pThis, void *pContext, int argc, char **argv) { - ReadSensors(false, true); - config_data.cal_w1_0 = last_sensor_reading.weight1; + SENSOR_data temp_sensor_data; + + ReadSensors(temp_sensor_data); + config_data.cal_w1_0 = temp_sensor_data.weight1; gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); pThis->printf("{ \"msg\": \"calibrate_zero_scale_a was successful\" }\n"); @@ -1041,8 +942,10 @@ cCommandStream::CommandStatus cmdCalibrateZeroScaleA(cCommandStream *pThis, void cCommandStream::CommandStatus cmdCalibrateZeroScaleB(cCommandStream *pThis, void *pContext, int argc, char **argv) { - ReadSensors(false, true); - config_data.cal_w2_0 = last_sensor_reading.weight2; + SENSOR_data temp_sensor_data; + + ReadSensors(temp_sensor_data); + config_data.cal_w2_0 = temp_sensor_data.weight2; gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); pThis->printf("{ \"msg\": \"calibrate_zero_scale_b was successful\" }\n"); @@ -1052,14 +955,15 @@ cCommandStream::CommandStatus cmdCalibrateZeroScaleB(cCommandStream *pThis, void cCommandStream::CommandStatus cmdCalibrateScaleA(cCommandStream *pThis, void *pContext, int argc, char **argv) { - ReadSensors(false, true); + SENSOR_data temp_sensor_data; + ReadSensors(temp_sensor_data); String w1_gramm(argv[1]); - config_data.cal_w1_factor = (((float)last_sensor_reading.weight1 - config_data.cal_w1_0) / w1_gramm.toFloat()); + config_data.cal_w1_factor = (((float)temp_sensor_data.weight1 - config_data.cal_w1_0) / w1_gramm.toFloat()); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); - gCatena.SafePrintf("last_sensor_reading.weight1: %ld\n", last_sensor_reading.weight1); + gCatena.SafePrintf("temp_sensor_data.weight1: %ld\n", temp_sensor_data.weight1); gCatena.SafePrintf("config_data.cal_w1_0: %ld\n", config_data.cal_w1_0); gCatena.SafePrintf("w1_gramm: %s\n", w1_gramm); gCatena.SafePrintf("w1_gramm (float): %d\n", (int)w1_gramm.toFloat()); @@ -1072,10 +976,11 @@ cCommandStream::CommandStatus cmdCalibrateScaleA(cCommandStream *pThis, void *pC cCommandStream::CommandStatus cmdCalibrateScaleB(cCommandStream *pThis, void *pContext, int argc, char **argv) { - ReadSensors(false, true); + SENSOR_data temp_sensor_data; + ReadSensors(temp_sensor_data); String w2_gramm(argv[1]); - config_data.cal_w2_factor = (((float)last_sensor_reading.weight2 - config_data.cal_w2_0) / w2_gramm.toFloat()); + config_data.cal_w2_factor = (((float)temp_sensor_data.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 new file mode 100644 index 0000000..cde9d3e --- /dev/null +++ b/mini_beieli_node.h @@ -0,0 +1,107 @@ +// mini_beieli_node.h + +/****************************************************************************\ + | + | MANIFEST CONSTANTS & TYPEDEFS + | + \****************************************************************************/ + +constexpr uint8_t kUplinkPort = 2; + +/* how long do we wait between transmissions? (in seconds) */ +enum { + // set this to interval between transmissions, in seconds + // Actual time will be a little longer because have to + // add measurement and broadcast time, but we attempt + // to compensate for the gross effects below. + CATCFG_T_CYCLE = 6 * 60, // every 6 minutes + //CATCFG_T_CYCLE = 60, // for Testing + CATCFG_T_CYCLE_TEST = 30, // every 10 seconds + CATCFG_T_CYCLE_INITIAL = 30, // every 30 seconds initially + CATCFG_INTERVAL_COUNT_INITIAL = 30, // repeat for 15 minutes +}; + +/* additional timing parameters; ususually you don't change these. */ +enum { + CATCFG_T_WARMUP = 1, + CATCFG_T_SETTLE = 5, + CATCFG_T_OVERHEAD = (CATCFG_T_WARMUP + CATCFG_T_SETTLE), + CATCFG_T_MIN = CATCFG_T_OVERHEAD, + CATCFG_T_MAX = CATCFG_T_CYCLE < 60 * 60 ? 60 * 60 : CATCFG_T_CYCLE, // normally one hour max. + CATCFG_INTERVAL_COUNT = 30, +}; + +constexpr uint32_t CATCFG_GetInterval(uint32_t tCycle) +{ + return (tCycle < CATCFG_T_OVERHEAD) + ? CATCFG_T_OVERHEAD + : tCycle - CATCFG_T_OVERHEAD; +} + +enum { + CATCFG_T_INTERVAL = CATCFG_GetInterval(CATCFG_T_CYCLE), +}; + +enum { + PIN_ONE_WIRE = A2, // XSDA1 == A2 + PIN_SHT10_CLK = 8, // XSCL0 == D8 + PIN_SHT10_DATA = 12, // XSDA0 == D12 +}; + + +/****************************************************************************\ + | + | READ-ONLY DATA + | + \****************************************************************************/ + +static const int32_t fwVersion = 20191115; +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 uint32_t PRESSURE_OFFSET = 825; +static const uint16_t SEND_DIFF_THRESHOLD_5GRAMS = 10; // when weight value drops by 50g, then send data + +// must be 139 bytes long (size of kBme680Cal) +typedef struct { + 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 + byte debug_level; // 0 => no debugging, 1 => infos, 2 => error, 3 => highest level + byte fill[122]; +} __attribute__((packed)) CONFIG_data; + +typedef struct { + uint8_t version; // Version of Packet Format (must be increased every time format changes...) + uint8_t vbat; // Batteriespannung (0: <= 2510mV, 70: 3000mV, 170: 3700mV, 255: >= 4295mV [1 Einheit => 7mV]) + uint8_t humidity[MAX_VALUES_TO_SEND]; // Luftfeuchtigkeit in Prozent + int16_t temperature; // Temperatur (Startwert) in 1/10 Grad Celsius + int8_t temperature_change[MAX_VALUES_TO_SEND - 1]; // Unterschied Temperatur seit letztem Messwert in 1/10 Grad Celsius + uint8_t pressure[MAX_VALUES_TO_SEND]; // Luftdruck in Hekto-Pascal (0 entspricht 825 hPa) + uint16_t weight[MAX_VALUES_TO_SEND]; // Waegezelle Gesamtgewicht, in 5g + uint8_t offset_last_reading; // Zeitunterschied letzte zu erste Messung (in Minuten) +} __attribute__((packed)) LORA_data; + +typedef struct { + uint8_t version; // Version of Packet Format (must be increased every time format changes...) + int32_t fw_version; // Version of Firmware, Nummer entspricht YYYYMMDD + uint8_t vbat; // Batteriespannung (0: <= 2510mV, 70: 3000mV, 170: 3700mV, 255: >= 4295mV [1 Einheit => 7mV]) + uint8_t humidity; // Luftfeuchtigkeit in Prozent + int16_t temperature; // Temperatur in 1/10 Grad Celsius + 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 +} __attribute__((packed)) LORA_data_first; + +typedef struct { + uint8_t vbat; // Batteriespannung (0: <= 2510mV, 70: 3000mV, 170: 3700mV, 255: >= 4295mV [1 Einheit => 7mV]) + uint8_t humidity; // Luftfeuchtigkeit in Prozent + int16_t temperature; // Temperatur in 1/10 Grad Celsius + 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 +} SENSOR_data;