I have a Rain Meter, based on a tilting bucket mechanism. So, on my view at least, it have to be very time critical, so I don’t lose a reading. But a the moment it’s not working properly, the LoRa send job is taking a good part of the runtime.
So, is there a tip that I could use for doing the measurement asynchronous?
Bellow is my code: (if there’s something wrong, please point out)
/* LoRa*/
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#ifdef COMPILE_REGRESSION_TEST
# define FILLMEIN 0
#else
# warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!"
# define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN)
#endif
static const u1_t PROGMEM APPEUI[8] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
void os_getArtEui (u1_t* buf) {
memcpy_P(buf, APPEUI, 8);
}
static const u1_t PROGMEM DEVEUI[8] = xxxxxxxxxxxxxxxx;
void os_getDevEui (u1_t* buf) {
memcpy_P(buf, DEVEUI, 8);
}
static const u1_t PROGMEM APPKEY[16] = xxxxxxxxxxxxxxxxxxxxxxxxx};
void os_getDevKey (u1_t* buf) {
memcpy_P(buf, APPKEY, 16);
}
uint8_t port = 2;
byte payload[6];
static osjob_t sendjob;
static osjob_t readjob;
int16_t sent_temperature;
uint16_t sent_rain_mm;
const unsigned TX_INTERVAL = 60;
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = 18,
.rxtx = LMIC_UNUSED_PIN,
.rst = LMIC_UNUSED_PIN,
.dio = {/*dio0*/ 26, /*dio1*/ 33, /*dio2*/ LMIC_UNUSED_PIN}
};
void printHex2(unsigned v) {
v &= 0xff;
if (v < 16)
Serial.print('0');
Serial.print(v, HEX);
}
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
switch (ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
break;
case EV_JOINED:
Serial.println(F("EV_JOINED"));
{
u4_t netid = 0;
devaddr_t devaddr = 0;
u1_t nwkKey[16];
u1_t artKey[16];
LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
Serial.print("netid: ");
Serial.println(netid, DEC);
Serial.print("devaddr: ");
Serial.println(devaddr, HEX);
Serial.print("AppSKey: ");
for (size_t i = 0; i < sizeof(artKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(artKey[i]);
}
Serial.println("");
Serial.print("NwkSKey: ");
for (size_t i = 0; i < sizeof(nwkKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(nwkKey[i]);
}
Serial.println();
}
LMIC_setLinkCheckMode(0);
break;
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen) {
Serial.print(F("Received "));
Serial.print(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
case EV_TXCANCELED:
Serial.println(F("EV_TXCANCELED"));
break;
case EV_RXSTART:
/* do not print anything -- it wrecks timing */
break;
case EV_JOIN_TXCOMPLETE:
Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
break;
default:
Serial.print(F("Unknown event: "));
Serial.println((unsigned) ev);
break;
}
}
/**************************************************************************/
/* DHT */
#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
int humidity;
float temperature;
void update_dht_readings()
{
humidity = int(dht.readHumidity());
temperature = dht.readTemperature();
}
void serial_print_dht()
{
Serial.println(String(humidity) + " %H | " + String(temperature) + " *C");
}
/**************************************************************************/
/* Photoressitor */
#define LDR_PIN 15
#define MAX_ADC_READING 4095
#define ADC_REF_VOLTAGE 3.3
#define REF_RESISTANCE 4860
#define LUX_CALC_SCALAR 12518931
#define LUX_CALC_EXPONENT -1.405
int ldrRawData;
float resistorVoltage, ldrVoltage;
float ldrResistance;
int ldrLux;
void update_ldr_readings()
{
ldrRawData = analogRead(LDR_PIN);
resistorVoltage = (float)ldrRawData / MAX_ADC_READING * ADC_REF_VOLTAGE;
ldrVoltage = ADC_REF_VOLTAGE - resistorVoltage;
ldrResistance = ldrVoltage / resistorVoltage * REF_RESISTANCE;
ldrLux = int(LUX_CALC_SCALAR * pow(ldrResistance, LUX_CALC_EXPONENT));
}
void serial_print_ldr()
{
Serial.println(String(ldrLux) + " lux");
}
/**************************************************************************/
/* Rainmeter */
#define RAIN_PIN 13
#define SCALAR_MM 0.3
float rain_mm;
void update_rain_mm_readings()
{
if (digitalRead(RAIN_PIN))
{
rain_mm += SCALAR_MM;
}
}
void reset_rain_mm_readings()
{
rain_mm = 0;
}
void serial_print_rain_mm()
{
Serial.println(String(rain_mm) + " mm");
}
/**************************************************************************/
#define ms_per_hour 3600000
#define ms_per_min 60000
#define ms_per_sec 1000
const long interval = ms_per_sec * 5;
unsigned long previousMillis;
unsigned long currentMillis;
void update_time_counter()
{
currentMillis = millis();
}
void(* reset_arduino) (void) = 0;
void setup() {
Serial.begin(9600);
Serial.println(F("Starting"));
pinMode(LDR_PIN, INPUT);
pinMode(RAIN_PIN, INPUT);
dht.begin();
#ifdef VCC_ENABLE
// For Pinoccio Scout boards
pinMode(VCC_ENABLE, OUTPUT);
digitalWrite(VCC_ENABLE, HIGH);
delay(1000);
#endif
os_init();
LMIC_reset();
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
do_read(&readjob);
// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
}
void do_read(osjob_t* j)
{
(currentMillis >= ms_per_hour) ? reset_arduino() : update_time_counter();
update_rain_mm_readings();
update_dht_readings();
update_ldr_readings();
if (currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
(isnan(temperature) || isnan(humidity)) ? void(Serial.println("Failed to read from DHT")) : serial_print_dht();
(isnan(ldrLux)) ? void(Serial.println("Failed to read from LDR")) : serial_print_ldr();
(isnan(rain_mm)) ? void(Serial.println("Failed to read from Rain Meter")) : serial_print_rain_mm();
}
sent_temperature = int(temperature);
sent_rain_mm = int((rain_mm * 100));
}
void do_send(osjob_t* j) {
payload[0] = sent_temperature >> 8;
payload[1] = sent_temperature;
payload[2] = humidity >> 8;
payload[3] = humidity;
payload[4] = ldrLux >> 8;
payload[5] = ldrLux;
payload[6] = sent_rain_mm >> 8;
payload[7] = sent_rain_mm;
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(port, payload, sizeof(payload), 0);
Serial.println(F("Packet queued"));
}
do_read(&readjob);
// Next TX is scheduled after TX_COMPLETE event.
}
void loop() {
os_runloop();
}
Thanks for all the help in advance!!
Best regards