From bf8c9f8441c5e9e802d82b26b48f62dd5143ede0 Mon Sep 17 00:00:00 2001 From: Joerg Lehmann Date: Mon, 18 May 2020 16:06:31 +0200 Subject: [PATCH] optimize power --- mini-beieli-node.ino | 96 +++++++++++++++++++++++++++++--------- mini_beieli_node.h | 15 +++--- mini_beieli_node_hx711.h | 5 ++ mini_beieli_node_nau7802.h | 25 +++++++++- 4 files changed, 110 insertions(+), 31 deletions(-) diff --git a/mini-beieli-node.ino b/mini-beieli-node.ino index 35ee056..86f40e1 100644 --- a/mini-beieli-node.ino +++ b/mini-beieli-node.ino @@ -253,6 +253,7 @@ void setup_platform(void) } gLoRaWAN.SetReceiveBufferBufferCb(receiveMessage); + setTxCycleTime(CATCFG_T_CYCLE_INITIAL, CATCFG_INTERVAL_COUNT_INITIAL); gCatena.registerObject(&gLoRaWAN); /* find the platform */ @@ -537,7 +538,6 @@ void ReadSensors(SENSOR_data &sensor_data) { long w2_0_real; // vBat - gCatena.poll(); int vbat_mv = (int)(gCatena.ReadVbat() * 1000.0f); res.vbat = GetVBatValue(vbat_mv); if (config_data.debug_level > 0) { @@ -551,7 +551,6 @@ void ReadSensors(SENSOR_data &sensor_data) { if (config_data.debug_level > 0) { gCatena.SafePrintf("%010d - LoadCell is ready.\n", millis()); } - gCatena.poll(); if (config_data.cal_w1_0 != NOT_ATTACHED) { res.weight1 = (int32_t)ReadScale('A'); if (config_data.debug_level > 0) { @@ -564,7 +563,6 @@ void ReadSensors(SENSOR_data &sensor_data) { gCatena.SafePrintf("%010d - Load_cell 1 is disabled\n", millis()); } } - gCatena.poll(); if (config_data.cal_w2_0 != NOT_ATTACHED) { res.weight2 = (int32_t)ReadScale('B'); if (config_data.debug_level > 0) { @@ -585,7 +583,6 @@ void ReadSensors(SENSOR_data &sensor_data) { } // Disable Power - gCatena.poll(); PowerdownScale(); // Gewicht berechnen @@ -605,11 +602,9 @@ void ReadSensors(SENSOR_data &sensor_data) { res.weight = (uint16_t)weight_current32; if (fBme) { - gCatena.poll(); /* warm up the BME280 by discarding a measurement */ (void)gBME280.readTemperature(); - gCatena.poll(); Adafruit_BME280::Measurements m = gBME280.readTemperaturePressureHumidity(); // temperature is 2 bytes from -0x80.00 to +0x7F.FF degrees C // pressure is 2 bytes, hPa * 10. @@ -695,9 +690,9 @@ void StartNewIteration() { if (config_data.debug_level > 0) { gCatena.SafePrintf("%010d - startSendingUplink(), my_position: %d, iteration: %d, package_counter: %d\n", millis(), my_position, iteration, package_counter); } - // the first 12 packets are "Init-Packets" or each INIT_PACKAGE_INTERVAL ... + // the first packets are "Init-Packets" or each INIT_PACKAGE_INTERVAL ... startSendingUplink(next_package_is_init_package); - next_package_is_init_package = ((iteration < 12) || ((package_counter % INIT_PACKAGE_INTERVAL) == 0)); + next_package_is_init_package = ((iteration < INIT_PACKETS) || ((package_counter % INIT_PACKAGE_INTERVAL) == 0)); if (config_data.debug_level > 1) { gLed.Set(LedPattern::TwoShort); @@ -732,8 +727,8 @@ void StartNewIteration() { sleep_time_sec = 5; } - // for the first 12 iterations, we set the sleep time to 10 seconds only... - if (iteration <= 12) { + // for the first iterations, we set the sleep time to 10 seconds only... + if (iteration <= INIT_PACKETS) { sleep_time_sec = 10; } @@ -1106,6 +1101,9 @@ static void startNewIterationCb(osjob_t* pJob) static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage, size_t nMessage) { + unsigned txCycle; + unsigned txCount; + long cal_w1_0; long cal_w2_0; float cal_w1_factor; @@ -1221,12 +1219,64 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage lora_data_first.cal_w2_factor = config_data.cal_w2_factor; } } + + if (port == 0) + { + return; + } + + else if (! (port == 1 && 2 <= nMessage && nMessage <= 3)) + { + if (config_data.debug_level > 0) { + gCatena.SafePrintf("invalid message port(%02x)/length(%x)\n", + port, nMessage + ); + } + return; + } + + txCycle = (pMessage[0] << 8) | pMessage[1]; + + if (txCycle < CATCFG_T_MIN || txCycle > CATCFG_T_MAX) + { + if (config_data.debug_level > 0) { + gCatena.SafePrintf("tx cycle time out of range: %u\n", txCycle); + } + return; + } + + // byte [2], if present, is the repeat count. + // explicitly sending zero causes it to stick. + txCount = CATCFG_INTERVAL_COUNT; + if (nMessage >= 3) + { + txCount = pMessage[2]; + } + + setTxCycleTime(txCycle, txCount); + } +void setTxCycleTime(unsigned txCycle, unsigned txCount) +{ + if (txCount > 0) { + if (config_data.debug_level > 0) { + gCatena.SafePrintf("message cycle time %u seconds for %u messages\n", txCycle, txCount); + } + } + else if (config_data.debug_level > 0) { + gCatena.SafePrintf("message cycle time %u seconds indefinitely\n", txCycle); + } + + gTxCycle = txCycle; + gTxCycleCount = txCount; +} + + /* process "application hello" -- args are ignored */ // argv[0] is "hello" // argv[1..argc-1] are the (ignored) arguments -cCommandStream::CommandStatus cmdHello(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdHello(cCommandStream * pThis, void *pContext, int argc, char **argv) { pThis->printf("Hello, world!\n"); @@ -1234,7 +1284,7 @@ cCommandStream::CommandStatus cmdHello(cCommandStream *pThis, void *pContext, in } -cCommandStream::CommandStatus cmdGetCalibrationSettings(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdGetCalibrationSettings(cCommandStream * pThis, void *pContext, int argc, char **argv) { pThis->printf("{\n"); pThis->printf(" \"cal_w1_0\": \"%d\",\n", config_data.cal_w1_0); @@ -1246,7 +1296,7 @@ cCommandStream::CommandStatus cmdGetCalibrationSettings(cCommandStream *pThis, v return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdGetSensorReadings(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdGetSensorReadings(cCommandStream * pThis, void *pContext, int argc, char **argv) { SENSOR_data temp_sensor_data; @@ -1264,21 +1314,21 @@ cCommandStream::CommandStatus cmdGetSensorReadings(cCommandStream *pThis, void * return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdGetScale1(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdGetScale1(cCommandStream * pThis, void *pContext, int argc, char **argv) { pThis->printf("getscale1\n"); return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdGetScale2(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdGetScale2(cCommandStream * pThis, void *pContext, int argc, char **argv) { pThis->printf("getscale2\n"); return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdCalibrateZeroScaleA(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdCalibrateZeroScaleA(cCommandStream * pThis, void *pContext, int argc, char **argv) { setup_scales(); config_data.cal_w1_0 = (int32_t)ReadScale('A'); @@ -1288,7 +1338,7 @@ cCommandStream::CommandStatus cmdCalibrateZeroScaleA(cCommandStream *pThis, void return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdCalibrateZeroScaleB(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdCalibrateZeroScaleB(cCommandStream * pThis, void *pContext, int argc, char **argv) { setup_scales(); config_data.cal_w2_0 = (int32_t)ReadScale('B'); @@ -1298,7 +1348,7 @@ cCommandStream::CommandStatus cmdCalibrateZeroScaleB(cCommandStream *pThis, void return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdCalibrateScaleA(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdCalibrateScaleA(cCommandStream * pThis, void *pContext, int argc, char **argv) { String w1_gramm(argv[1]); long weight1; @@ -1320,7 +1370,7 @@ cCommandStream::CommandStatus cmdCalibrateScaleA(cCommandStream *pThis, void *pC return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdCalibrateScaleB(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdCalibrateScaleB(cCommandStream * pThis, void *pContext, int argc, char **argv) { String w2_gramm(argv[1]); long weight2; @@ -1342,18 +1392,20 @@ cCommandStream::CommandStatus cmdCalibrateScaleB(cCommandStream *pThis, void *pC return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdSetDebugLevel(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdSetDebugLevel(cCommandStream * pThis, void *pContext, int argc, char **argv) { String s_debug_level(argv[1]); config_data.debug_level = s_debug_level.toInt(); gCatena.getFram()->saveField(cFramStorage::kAppConf, (const uint8_t *)&config_data, sizeof(config_data)); + SetScalesDebugLevel(config_data.debug_level); + pThis->printf("{ \"msg\": \"set_debug_level was successful\" }\n"); return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdGetDebugLevel(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdGetDebugLevel(cCommandStream * pThis, void *pContext, int argc, char **argv) { gCatena.getFram()->saveField(cFramStorage::kAppConf, (const uint8_t *)&config_data, sizeof(config_data)); @@ -1362,7 +1414,7 @@ cCommandStream::CommandStatus cmdGetDebugLevel(cCommandStream *pThis, void *pCon return cCommandStream::CommandStatus::kSuccess; } -cCommandStream::CommandStatus cmdStopIterations(cCommandStream *pThis, void *pContext, int argc, char **argv) +cCommandStream::CommandStatus cmdStopIterations(cCommandStream * pThis, void *pContext, int argc, char **argv) { stop_iterations = true; return cCommandStream::CommandStatus::kSuccess; diff --git a/mini_beieli_node.h b/mini_beieli_node.h index 33eaaa5..4cf0c64 100644 --- a/mini_beieli_node.h +++ b/mini_beieli_node.h @@ -14,11 +14,11 @@ enum { // 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 = 30, // 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 + CATCFG_T_CYCLE = 6 * 60, // every 6 minutes + //CATCFG_T_CYCLE = 30, // for Testing (Swisscom Compliance) + CATCFG_T_CYCLE_TEST = 30, // every 30 seconds + CATCFG_T_CYCLE_INITIAL = 30, // every 30 seconds initially + CATCFG_INTERVAL_COUNT_INITIAL = 10, // repeat for 5 minutes CATCFG_T_REBOOT = 30 * 24 * 60 * 60, // reboot every 30 days }; @@ -26,7 +26,7 @@ enum { enum { CATCFG_T_WARMUP = 1, CATCFG_T_SETTLE = 5, - CATCFG_T_OVERHEAD = (CATCFG_T_WARMUP + CATCFG_T_SETTLE), + CATCFG_T_OVERHEAD = (CATCFG_T_WARMUP + CATCFG_T_SETTLE + 4), 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, @@ -56,7 +56,7 @@ enum { | \****************************************************************************/ -static const int32_t fwVersion = 20200513; +static const int32_t fwVersion = 20200514; static const byte INIT_PACKAGE_INTERVAL = 100; // send an init package every 100 packages; static const byte MAX_VALUES_TO_SEND = 8; @@ -66,6 +66,7 @@ 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 static const long NOT_ATTACHED = -2147483648; +static const byte INIT_PACKETS = 5; // must be 64 bytes long (size of kAppConf) typedef struct { diff --git a/mini_beieli_node_hx711.h b/mini_beieli_node_hx711.h index 6341b9e..19fbc03 100644 --- a/mini_beieli_node_hx711.h +++ b/mini_beieli_node_hx711.h @@ -11,6 +11,11 @@ Q2HX711 hx711(A1, A0); byte debug_level; +void SetScalesDebugLevel(byte dbg_level) +{ + debug_level = dbg_level; +} + bool SetupScales(byte dbg_level) { debug_level = dbg_level; diff --git a/mini_beieli_node_nau7802.h b/mini_beieli_node_nau7802.h index 57a0dde..9d30e6b 100644 --- a/mini_beieli_node_nau7802.h +++ b/mini_beieli_node_nau7802.h @@ -7,6 +7,7 @@ #include "SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h" #define SAMPLES 10 +#define IGNORE_READINGS 8 NAU7802 myScale; //Create instance of the NAU7802 class @@ -14,6 +15,11 @@ byte debug_level; byte interruptPin = A0; +void SetScalesDebugLevel(byte dbg_level) +{ + debug_level = dbg_level; +} + bool SetupScales(byte dbg_level) { debug_level = dbg_level; @@ -60,11 +66,26 @@ long ReadScale(char channel) myScale.calibrateAFE(); long res; + long dummy; + int const ignore_readings = IGNORE_READINGS; // number of first readings to ignore int const num_scale_readings = SAMPLES; // number of instantaneous scale readings to calculate the median - // we use the median, not the average, see https://community.particle.io/t/boron-gpio-provides-less-current-than-electrons-gpio/46647/13 - long readings[num_scale_readings]; // create arry to hold readings + for (int i = 0; i < ignore_readings; i++) { + while (digitalRead(interruptPin) == LOW) { + if ((millis() - startTime) > 60000) { + if (debug_level > 0) { + gCatena.SafePrintf("Timeout while reading scale (dummy values)...\n"); + } + return 0; + } + delay(1); + } + dummy = myScale.getReading(); + } + // we use the median, not the average, see https://community.particle.io/t/boron-gpio-provides-less-current-than-electrons-gpio/46647/13 + startTime = millis(); + long readings[num_scale_readings]; // create arry to hold readings for (int i = 0; i < num_scale_readings; i++) { while (digitalRead(interruptPin) == LOW) { //while(! myScale.available()) {