refactor sending code

This commit is contained in:
Joerg Lehmann 2019-11-15 22:03:55 +01:00
parent 9be03ea5c2
commit da5e52a033
2 changed files with 265 additions and 253 deletions

View File

@ -26,59 +26,14 @@
#include <type_traits> #include <type_traits>
#include <HX711.h> #include <HX711.h>
#include "mini_beieli_node.h"
using namespace McciCatena; 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 // forwards
static void settleDoneCb(osjob_t* pSendJob); static void settleDoneCb(osjob_t* pSendJob);
static void warmupDoneCb(osjob_t* pSendJob); static void warmupDoneCb(osjob_t* pSendJob);
static void startNewIterationCb(osjob_t* pJob);
static void txNotProvisionedCb(osjob_t *pSendJob); static void txNotProvisionedCb(osjob_t *pSendJob);
static void sleepDoneCb(osjob_t* pSendJob); static void sleepDoneCb(osjob_t* pSendJob);
static Arduino_LoRaWAN::SendBufferCbFn sendBufferDoneCb; 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 | 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 byte my_position = 0; // what is our actual measurement, starts with 0
long timer_pos0; long timer_pos0;
@ -194,6 +92,7 @@ LORA_data lora_data;
LORA_data_first lora_data_first; LORA_data_first lora_data_first;
CONFIG_data config_data; CONFIG_data config_data;
SENSOR_data last_sensor_reading; SENSOR_data last_sensor_reading;
long iteration = 0; // what iteration number do we have, starts with 0
// generic timer // generic timer
long t_cur; long t_cur;
@ -234,9 +133,9 @@ bool fUsbPower;
// have we printed the sleep info? // have we printed the sleep info?
bool g_fPrintedSleeping = false; 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; static osjob_t sensorJob;
void sensorJob_cb(osjob_t* pJob); static osjob_t iterationJob;
void setup(void) 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("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("debug_level: %d\n", (int)config_data.debug_level);
gCatena.SafePrintf("Size of config_data: %d\n", sizeof(config_data)); 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); gLed.Set(LedPattern::Joining);
/* trigger a join by sending the first packet */ /* trigger a join by sending the first packet */
ReadSensors(true, false); StartNewIteration();
} }
} }
} }
@ -565,7 +466,6 @@ uint8_t GetVBatValue(int millivolts)
return res; return res;
} }
void DoDeepSleep() void DoDeepSleep()
{ {
if (config_data.debug_level > 0) { if (config_data.debug_level > 0) {
@ -595,51 +495,30 @@ void DoDeepSleep()
} }
} }
void ReadSensors(SENSOR_data &sensor_data) {
void ReadSensors(bool firstTime, bool readOnly) SENSOR_data res;
{
int16_t temp_current;
uint8_t humidity_current;
uint8_t pressure_current;
int32_t weight1_current;
int32_t weight2_current;
int16_t temp_change;
int32_t weight_current32; int32_t weight_current32;
uint16_t weight_current;
// vBat // vBat
float vBat = gCatena.ReadVbat(); res.vbat = (uint8_t)(gCatena.ReadVbat() * 1000.0f);
if (config_data.debug_level > 0) { 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 // Read Scales
if (setup_scales()) { if (setup_scales()) {
if (config_data.debug_level > 0) { if (config_data.debug_level > 0) {
gCatena.SafePrintf("HX711 LoadCell is ready.\n"); gCatena.SafePrintf("HX711 LoadCell is ready.\n");
} }
LoadCell.set_gain(128); LoadCell.set_gain(128);
long w1 = LoadCell.read_average(5); res.weight1 = (int32_t)LoadCell.read_average(5);
weight1_current = (int32_t)w1;
if (config_data.debug_level > 0) { 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", res.weight1);
gCatena.SafePrintf("Load_cell 1 weight1_current: %ld\n", weight1_current);
} }
LoadCell.set_gain(32); LoadCell.set_gain(32);
long w2 = LoadCell.read_average(5); res.weight2 = (int32_t)LoadCell.read_average(5);
weight2_current = (int32_t)w2;
if (config_data.debug_level > 0) { 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", res.weight2);
gCatena.SafePrintf("Load_cell 2 weight2_current: %ld\n", weight2_current);
} }
} }
else { else {
@ -652,13 +531,13 @@ void ReadSensors(bool firstTime, bool readOnly)
digitalWrite(D10, LOW); digitalWrite(D10, LOW);
// Gewicht berechnen // 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) { if (weight_current32 < 0) {
weight_current32 = 0; weight_current32 = 0;
} else if (weight_current32 > UINT16_MAX) { } else if (weight_current32 > UINT16_MAX) {
weight_current32 = UINT16_MAX; weight_current32 = UINT16_MAX;
} }
weight_current = (uint16_t)weight_current32; res.weight = (uint16_t)weight_current32;
if (fBme) { if (fBme) {
/* warm up the BME280 by discarding a measurement */ /* warm up the BME280 by discarding a measurement */
@ -675,108 +554,119 @@ void ReadSensors(bool firstTime, bool readOnly)
(int)m.Pressure, (int)m.Pressure,
(int)m.Humidity); (int)m.Humidity);
} }
temp_current = (int16_t)((m.Temperature) * 10); res.temperature = (int16_t)((m.Temperature) * 10);
humidity_current = (uint8_t)m.Humidity; res.humidity = (uint8_t)m.Humidity;
pressure_current = (uint8_t)((m.Pressure / 100) - PRESSURE_OFFSET); res.pressure = (uint8_t)((m.Pressure / 100) - PRESSURE_OFFSET);
if (config_data.debug_level > 0) { 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) { void StartNewIteration() {
lora_data_first.vbat = GetVBatValue((int)(vBat * 1000.0f)); // we increment the iteration counter
lora_data_first.weight1 = weight1_current; iteration++;
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;
}
lora_data.temperature_change[my_position - 1] = (uint8_t)temp_change; SENSOR_data current_sensor_reading;
} ReadSensors(current_sensor_reading);
lora_data.humidity[my_position] = humidity_current; int16_t temp_change;
lora_data.pressure[my_position] = pressure_current;
}
// 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) { if (my_position == 0) {
timer_pos0 = millis(); lora_data.temperature = current_sensor_reading.temperature;
}
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();
}
}
} else { } else {
if (config_data.debug_level > 0) { temp_change = current_sensor_reading.temperature - last_sensor_reading.temperature;
gCatena.SafePrintf("now going to sleep for 6 minutes...\n"); if (temp_change > 127) {
if (fUsbPower) { temp_change = 127;
gCatena.SafePrintf("USB Power is on\n");
} else {
gCatena.SafePrintf("USB Power is off\n");
}
//Serial.flush();
} }
gLed.Set(LedPattern::Sleeping); if (temp_change < -128) {
if (!fUsbPower) { temp_change = -128;
DoDeepSleep(); }
sleepDoneCb(&sensorJob); lora_data.temperature_change[my_position - 1] = (uint8_t)temp_change;
} else { }
os_setTimedCallback( lora_data.humidity[my_position] = current_sensor_reading.humidity;
&sensorJob, lora_data.pressure[my_position] = current_sensor_reading.pressure;
os_getTime() + sec2osticks(CATCFG_T_INTERVAL), }
sleepDoneCb);
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; if (config_data.debug_level > 0) {
last_sensor_reading.weight2 = weight2_current; gCatena.SafePrintf("now going to sleep for %d seconds...\n",CATCFG_T_INTERVAL);
last_sensor_reading.weight = weight_current; if (fUsbPower) {
last_sensor_reading.temperature = temp_current; gCatena.SafePrintf("USB Power is on\n");
last_sensor_reading.humidity = humidity_current; } else {
last_sensor_reading.pressure = pressure_current; 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) void startSendingUplink(bool firstTime)
@ -884,13 +774,20 @@ static void sleepDoneCb(osjob_t* pJob)
static void warmupDoneCb(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) static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage, size_t nMessage)
{ {
uint32_t gram_A; uint32_t gram_A;
uint32_t gram_B; uint32_t gram_B;
SENSOR_data temp_sensor_data;
if (config_data.debug_level > 0) { if (config_data.debug_level > 0) {
gCatena.SafePrintf("receiveMessage was called!!!\n"); gCatena.SafePrintf("receiveMessage was called!!!\n");
@ -921,7 +818,7 @@ static void receiveMessage(void *pContext, uint8_t port, const uint8_t *pMessage
port, nMessage port, nMessage
); );
// we print out the received message... // 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"); gCatena.SafePrintf("Received Data (Payload): \n");
for (byte i = 0; i < nMessage; i++) { for (byte i = 0; i < nMessage; i++) {
gCatena.SafePrintf("%02x", pMessage[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"); gCatena.SafePrintf("\n");
} }
if (LMIC.seqnoUp > 2) { if (LMIC.seqnoUp > 2) {
if (config_data.debug_level > 0) { if (config_data.debug_level > 0) {
gCatena.SafePrintf("tare with downlink is only possible within first two uplink packets!\n"); gCatena.SafePrintf("tare with downlink is only possible within first two uplink packets!\n");
return; return;
} }
} }
if (port == 1 && nMessage == 1) { 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) { if (config_data.debug_level > 0) {
gCatena.SafePrintf("reset both scales to zero\n"); gCatena.SafePrintf("reset both scales to zero\n");
} }
ReadSensors(false, true); ReadSensors(temp_sensor_data);
config_data.cal_w1_0 = last_sensor_reading.weight1; config_data.cal_w1_0 = temp_sensor_data.weight1;
config_data.cal_w2_0 = last_sensor_reading.weight2; config_data.cal_w2_0 = temp_sensor_data.weight2;
gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data)); 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[2] << 16;
gram_A += (long)pMessage[3] << 8; gram_A += (long)pMessage[3] << 8;
gram_A += (long)pMessage[4]; gram_A += (long)pMessage[4];
gram_B = 0; gram_B = 0;
gram_B += (long)pMessage[5] << 24; gram_B += (long)pMessage[5] << 24;
gram_B += (long)pMessage[6] << 16; 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) { if (config_data.debug_level > 0) {
gCatena.SafePrintf("tare scales, A: %d, B: %d\n", gram_A, gram_B); gCatena.SafePrintf("tare scales, A: %d, B: %d\n", gram_A, gram_B);
} }
ReadSensors(false, true); ReadSensors(temp_sensor_data);
config_data.cal_w1_factor = (((float)last_sensor_reading.weight1 - config_data.cal_w1_0) / gram_A); config_data.cal_w1_factor = (((float)temp_sensor_data.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); 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)); 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) 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("{\n");
pThis->printf(" \"weight\": \"%d\",\n", last_sensor_reading.weight); pThis->printf(" \"weight\": \"%d\",\n", temp_sensor_data.weight);
pThis->printf(" \"weight1_raw\": \"%d\",\n", last_sensor_reading.weight1); pThis->printf(" \"weight1_raw\": \"%d\",\n", temp_sensor_data.weight1);
pThis->printf(" \"weight2_raw\": \"%d\",\n", last_sensor_reading.weight2); pThis->printf(" \"weight2_raw\": \"%d\",\n", temp_sensor_data.weight2);
pThis->printf(" \"temperature\": \"%d\",\n", last_sensor_reading.temperature); pThis->printf(" \"temperature\": \"%d\",\n", temp_sensor_data.temperature);
pThis->printf(" \"humidity\": \"%d\",\n", last_sensor_reading.humidity); pThis->printf(" \"humidity\": \"%d\",\n", temp_sensor_data.humidity);
pThis->printf(" \"pressure\": \"%d\",\n", last_sensor_reading.pressure); pThis->printf(" \"pressure\": \"%d\",\n", temp_sensor_data.pressure);
pThis->printf(" \"batt\": \"%d\",\n", last_sensor_reading.vbat); pThis->printf(" \"batt\": \"%d\",\n", temp_sensor_data.vbat);
pThis->printf("}\n"); pThis->printf("}\n");
return cCommandStream::CommandStatus::kSuccess; 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) cCommandStream::CommandStatus cmdCalibrateZeroScaleA(cCommandStream *pThis, void *pContext, int argc, char **argv)
{ {
ReadSensors(false, true); SENSOR_data temp_sensor_data;
config_data.cal_w1_0 = last_sensor_reading.weight1;
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)); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data));
pThis->printf("{ \"msg\": \"calibrate_zero_scale_a was successful\" }\n"); 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) cCommandStream::CommandStatus cmdCalibrateZeroScaleB(cCommandStream *pThis, void *pContext, int argc, char **argv)
{ {
ReadSensors(false, true); SENSOR_data temp_sensor_data;
config_data.cal_w2_0 = last_sensor_reading.weight2;
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)); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data));
pThis->printf("{ \"msg\": \"calibrate_zero_scale_b was successful\" }\n"); 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) 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]); 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.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("config_data.cal_w1_0: %ld\n", config_data.cal_w1_0);
gCatena.SafePrintf("w1_gramm: %s\n", w1_gramm); gCatena.SafePrintf("w1_gramm: %s\n", w1_gramm);
gCatena.SafePrintf("w1_gramm (float): %d\n", (int)w1_gramm.toFloat()); 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) 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]); 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)); gCatena.getFram()->saveField(cFramStorage::kBme680Cal, (const uint8_t *)&config_data, sizeof(config_data));

107
mini_beieli_node.h Normal file
View File

@ -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;