Lmic, EmonLib and LowPower


(Esawyja) #1

Hi all,
I have a weird problem, when I follow this build https://learn.openenergymonitor.org/electricity-monitoring/ctac/how-to-build-an-arduino-energy-monitor and measure current, all works fine, below is the code and serial output

#include "EmonLib.h"
#include <LowPower.h>
EnergyMonitor emon1;
// Create an instance
void setup()
{
  while ((!Serial) && (millis() < 10000)){ }
  Serial.begin(9600);

      emon1.current(5, 115.1);             // Current: input pin, calibration.
    }

    void loop()
    {
    double et = emon();
    int16_t e = et * 100;
    Serial.print(et*230.0);           // Apparent power
      Serial.print(" ");
      Serial.println(et);             // Irms
      Serial.flush();
      LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);
    }

    double emon() {
      int sensorValue = analogRead(A5);
      Serial.println(sensorValue);
      double e = emon1.calcIrms(1480);  // Calculate Irms only
      return e;
    }

    513
    52.00 0.23
    514
    40.85 0.18
    514
    36.55 0.16
    514
    36.29 0.16
    514
    33.54 0.15
    515
    36.18 0.16
    514
    36.04 0.16

But as soon as I introduce the LMIC library, with LowPower and EmonLib, something goes horrible wrong, it seems that the analogRead is affected by one of the libraries

    Code below

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include "DHT.h"
#include <LowPower.h>
#include "EmonLib.h"
EnergyMonitor emon1;

static const PROGMEM u1_t NWKSKEY[16] = { xxx };
static const u1_t PROGMEM APPSKEY[16] = { xxx };
static const u4_t DEVADDR = 0xxxx; // <-- Change this address for every node!

void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }

static osjob_t sendjob;

const unsigned TX_INTERVAL = 30;

const lmic_pinmap lmic_pins = {
    .nss = 6,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 5,
    .dio = {2, 3, 4},
};

int ANALOGPIN = 3;

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"));
            break;
        case EV_RFU1:
            Serial.println(F("EV_RFU1"));
            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.println(F("Received "));
              Serial.println(LMIC.dataLen);
              Serial.println(F(" bytes of payload"));
            }
            for (int i=0; i<int(TX_INTERVAL/8); i++) {
              Serial.flush();
              LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);
            }
            do_send(&sendjob);
            break;
            // 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;
         default:
            Serial.println(F("Unknown event"));
            break;
    }
}

void do_send(osjob_t* j){
  int sensorValue = analogRead(ANALOGPIN);
  Serial.print("The analogRead output : - ");
  Serial.println(sensorValue);
  
  double Irms = emon1.calcIrms(1480);
  double et = emon1.calcIrms(1480);
  Serial.print("The Irms calculation output : - ");
  Serial.println(Irms); 
  
  
  Serial.print("This is et :- ");
  Serial.println(et);
  int16_t e = et * 100;
  Serial.print("This is e :- ");
  Serial.println(e);

  float Vcc=readVcc(); //value in mV
  Vcc=Vcc/1000;//value in V
  int16_t v = Vcc * 100;
  Serial.print("Voltage: ");
  Serial.print(v);
  Serial.println(" Volts");
 
  byte payloadA[2];
  payloadA[0] = highByte(e);
  payloadA[1] = lowByte(e);

  byte payloadB[2];
  payloadB[0] = highByte(v);
  payloadB[1] = lowByte(v);

int sizeofPayloadA = sizeof(payloadA);
int sizeofPayloadB = sizeof(payloadB);

for (int i=0; i<sizeofPayloadA; i++) {
  if (payloadA[i]<0x10) {
    Serial.print(F("0"));
    Serial.print(payloadA[i],HEX);
  } else {
        Serial.print(payloadA[i],HEX);
  }
}
Serial.println(F(""));

for (int i=0; i<sizeofPayloadB; i++) {
  if (payloadB[i]<0x10) {
    Serial.print(F("0"));
    Serial.print(payloadB[i],HEX);
  } else {
        Serial.print(payloadB[i],HEX);
  } 
}
Serial.println(F(""));

byte payload[sizeofPayloadA + sizeofPayloadB];

memcpy(payload, payloadA, sizeofPayloadA);
memcpy(payload + sizeofPayloadA, payloadB, sizeofPayloadB);

    if (LMIC.opmode & OP_TXRXPEND) {
        Serial.println(F("OP_TXRXPEND, not sending"));
    } else {
          LMIC_setTxData2(1, payload, sizeof(payload), 0);
        Serial.println(F("Packet queued"));
    }
}

void setup() {
    Serial.begin(9600);
    Serial.println(F("LoRaStarting"));
    analogReference(INTERNAL);
    emon1.current(5, 115.1);
    Serial.println(F("EMON Starting"));
    os_init();
    LMIC_reset();

    #ifdef PROGMEM
    uint8_t appskey[sizeof(APPSKEY)];
    uint8_t nwkskey[sizeof(NWKSKEY)];
    memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
    memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
   
    LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
    #else
    LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
    #endif

    #if defined(CFG_eu868)
    LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI);      // g-band
    LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK,  DR_FSK),  BAND_MILLI);      // g2-band
    #elif defined(CFG_us915)
    LMIC_selectSubBand(1);
    #endif
    LMIC_setLinkCheckMode(0);

    LMIC.dn2Dr = DR_SF9;

    LMIC_setDrTxpow(DR_SF7,14);

    do_send(&sendjob);
}

void loop() {
    os_runloop_once();
}

long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif 

  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH 
  uint8_t high = ADCH; // unlocks both

  long result = (high<<8) | low;
  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

And the serial output

LoRaStarting
EMON Starting
The analogRead output : - 377
The Irms calculation output : - 91.80
This is et :- 16.51
This is e :- 1651
Voltage: 328 Volts
0673
0148
Packet queued
185322: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 312
The Irms calculation output : - 8.79
This is et :- 10.20
This is e :- 1020
Voltage: 328 Volts
03FC
0148
Packet queued
506767: EV_TXCOMPLETE (includes waiting for RX windows)

No hardware was changed during the 2 tests
Has anyone seen this before please?
Sorry about the bad editing, the editor hates me


#2

and what happends if you // LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);


(Esawyja) #3

I get similar results

LoRaStarting
EMON Starting
1023
24721.80 107.49
Voltage: 328 Volts
29FC
0148
Packet queued
152182: EV_TXCOMPLETE (includes waiting for RX windows)
516
6161.23 26.79
Voltage: 328 Volts
0A76
0148
Packet queued
929642: EV_TXCOMPLETE (includes waiting for RX windows)
516
2649.04 11.52
Voltage: 328 Volts
047F
0148
Packet queued
1707505: EV_TXCOMPLETE (includes waiting for RX windows)
515
2344.39 10.19
Voltage: 328 Volts
03FB
0148
Packet queued
2485489: EV_TXCOMPLETE (includes waiting for RX windows)
516
2333.93 10.15
Voltage: 328 Volts
03F6
0148
Packet queued

This is after I set this

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.println(F("Received "));
              Serial.println(LMIC.dataLen);
              Serial.println(F(" bytes of payload"));
            }
            //for (int i=0; i<int(TX_INTERVAL/2); i++) {
            //  LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);
            //}
            //do_send(&sendjob);
            //break;
            // Schedule next transmission
            os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
            break;
        case EV_LOST_TSYNC:

With the “control” program, I get the correct value even with the sleep commented

>     > #include "EmonLib.h"
>     > #include <LowPower.h>
>     > EnergyMonitor emon1;
>     > // Create an instance
>     > void setup()
>     > {
>     >   while ((!Serial) && (millis() < 10000)){ }
>     >   Serial.begin(9600);
>     > 
>     >   emon1.current(5, 115.1);             // Current: input pin, calibration.
>     > }
>     > 
>     > void loop()
>     > {
>     > double et = emon();
>     > int16_t e = et * 100;
>     > Serial.print(et*230.0);           // Apparent power
>     >   Serial.print(" ");
>     >   Serial.println(et);             // Irms
>     >   Serial.flush();
>     >   //LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);
>     > }
>     > 
>     > double emon() {
>     >   int sensorValue = analogRead(A5);
>     >   Serial.println(sensorValue);
>     >   double e = emon1.calcIrms(1480);  // Calculate Irms only
>     >   return e;
>     > }

512
51.54 0.22
513
38.39 0.17
513
36.18 0.16
512
34.78 0.15
513
34.62 0.15
512
35.29 0.15
513
35.25 0.15
513
35.00 0.15
512
35.29 0.15
512
34.62 0.15
512
34.78 0.15
512
34.31 0.15
512
35.26 0.15
513
33.59 0.15
513
35.64 0.15
512
35.50 0.15

(Couin) #4

By any chance, aren’t you using pin 3 and 5 for more than one task?


#5

sharp !


(Esawyja) #6

Hi
Sorry I think that was a paste from while I was troubleshooting, the radio is connected to the digital pins as per
https://www.thethingsnetwork.org/labs/story/build-the-cheapest-possible-node-yourself
image

And the CT is connected to A5

Below is the code as I’m using it now

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include "DHT.h"
#include <LowPower.h>
#include "EmonLib.h"
EnergyMonitor emon1;

static const PROGMEM u1_t NWKSKEY[16] = { xxx };
static const u1_t PROGMEM APPSKEY[16] = { xxx };
static const u4_t DEVADDR = 0xxxx; // <-- Change this address for every node!

void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }

static osjob_t sendjob;

const unsigned TX_INTERVAL = 30;

const lmic_pinmap lmic_pins = {
    .nss = 6,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 5,
    .dio = {2, 3, 4},
};

int ANALOGPIN = A5;

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"));
            break;
        case EV_RFU1:
            Serial.println(F("EV_RFU1"));
            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.println(F("Received "));
              Serial.println(LMIC.dataLen);
              Serial.println(F(" bytes of payload"));
            }
            for (int i=0; i<int(TX_INTERVAL/8); i++) {
              Serial.flush();
              LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);
            }
            do_send(&sendjob);
            break;
            // 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;
         default:
            Serial.println(F("Unknown event"));
            break;
    }
}

void do_send(osjob_t* j){
  int sensorValue = analogRead(ANALOGPIN);
  Serial.print("The analogRead output : - ");
  Serial.println(sensorValue);
  
  double Irms = emon1.calcIrms(1480);
  double et = emon1.calcIrms(1480);
  Serial.print("The Irms calculation output : - ");
  Serial.println(Irms); 
  
  
  Serial.print("This is et :- ");
  Serial.println(et);
  int16_t e = et * 100;
  Serial.print("This is e :- ");
  Serial.println(e);

  float Vcc=readVcc(); //value in mV
  Vcc=Vcc/1000;//value in V
  int16_t v = Vcc * 100;
  Serial.print("Voltage: ");
  Serial.print(v);
  Serial.println(" Volts");
 
  byte payloadA[2];
  payloadA[0] = highByte(e);
  payloadA[1] = lowByte(e);

  byte payloadB[2];
  payloadB[0] = highByte(v);
  payloadB[1] = lowByte(v);

int sizeofPayloadA = sizeof(payloadA);
int sizeofPayloadB = sizeof(payloadB);

for (int i=0; i<sizeofPayloadA; i++) {
  if (payloadA[i]<0x10) {
    Serial.print(F("0"));
    Serial.print(payloadA[i],HEX);
  } else {
        Serial.print(payloadA[i],HEX);
  }
}
Serial.println(F(""));

for (int i=0; i<sizeofPayloadB; i++) {
  if (payloadB[i]<0x10) {
    Serial.print(F("0"));
    Serial.print(payloadB[i],HEX);
  } else {
        Serial.print(payloadB[i],HEX);
  } 
}
Serial.println(F(""));

byte payload[sizeofPayloadA + sizeofPayloadB];

memcpy(payload, payloadA, sizeofPayloadA);
memcpy(payload + sizeofPayloadA, payloadB, sizeofPayloadB);

    if (LMIC.opmode & OP_TXRXPEND) {
        Serial.println(F("OP_TXRXPEND, not sending"));
    } else {
          LMIC_setTxData2(1, payload, sizeof(payload), 0);
        Serial.println(F("Packet queued"));
    }
}

void setup() {
    Serial.begin(9600);
    Serial.println(F("LoRaStarting"));
    analogReference(INTERNAL);
    emon1.current(5, 115.1);
    Serial.println(F("EMON Starting"));
    os_init();
    LMIC_reset();

    #ifdef PROGMEM
    uint8_t appskey[sizeof(APPSKEY)];
    uint8_t nwkskey[sizeof(NWKSKEY)];
    memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
    memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
   
    LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
    #else
    LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
    #endif

    #if defined(CFG_eu868)
    LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI);      // g-band
    LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
    LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK,  DR_FSK),  BAND_MILLI);      // g2-band
    #elif defined(CFG_us915)
    LMIC_selectSubBand(1);
    #endif
    LMIC_setLinkCheckMode(0);

    LMIC.dn2Dr = DR_SF9;

    LMIC_setDrTxpow(DR_SF7,14);

    do_send(&sendjob);
}

void loop() {
    os_runloop_once();
}

long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif 

  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH 
  uint8_t high = ADCH; // unlocks both

  long result = (high<<8) | low;
  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

And the resulting output

LoRaStarting
EMON Starting
The analogRead output : - 1023
The Irms calculation output : - 107.49
This is et :- 26.80
This is e :- 2680
Voltage: 328 Volts
0A78
0148
Packet queued
176217: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 535
The Irms calculation output : - 11.49
This is et :- 10.22
This is e :- 1021
Voltage: 328 Volts
03FD
0148
Packet queued
497653: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 535
The Irms calculation output : - 10.13
This is et :- 10.21
This is e :- 1021
Voltage: 328 Volts
03FD
0148
Packet queued
888938: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 535
The Irms calculation output : - 10.14
This is et :- 10.18
This is e :- 1018
Voltage: 328 Volts
03FA
0148
Packet queued
1300284: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 535
The Irms calculation output : - 10.16
This is et :- 10.19
This is e :- 1018
Voltage: 328 Volts
03FA
0148
Packet queued
1724737: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 535
The Irms calculation output : - 10.08
This is et :- 10.23
This is e :- 1022
Voltage: 328 Volts
03FE
0148
Packet queued
2141547: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 535
The Irms calculation output : - 10.15
This is et :- 10.22
This is e :- 1021
Voltage: 328 Volts
03FD
0148
Packet queued
2510309: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 535
The Irms calculation output : - 10.15
This is et :- 10.21
This is e :- 1021
Voltage: 328 Volts
03FD
0148
Packet queued
2844020: EV_TXCOMPLETE (includes waiting for RX windows)
The analogRead output : - 535
The Irms calculation output : - 10.14
This is et :- 10.20
This is e :- 1020
Voltage: 328 Volts
03FC
0148
Packet queued
3270039: EV_TXCOMPLETE (includes waiting for RX windows)

Apologies for the confusion, If I use the program generator at https://lcd-web.nl/ttngenerator/

And generate a program using a moisture sensor and make some changes, see below

#include <SPI.h>
#define ACT_METHOD_ABP

static const uint8_t PROGMEM NWKSKEY[16] = {xxxxx };
static const uint8_t PROGMEM APPSKEY[16] = { xxxx };
static const uint32_t DEVADDR = 0xxxxxx;

#include <lmic.h>
#include <hal/hal.h>

static osjob_t sendjob;

#ifdef ACT_METHOD_ABP
  void os_getArtEui (u1_t* buf) { }
  void os_getDevEui (u1_t* buf) { }
  void os_getDevKey (u1_t* buf) { }
#else
  void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
  void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
  void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
#endif

const lmic_pinmap lmic_pins = {
    .nss = 6,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 5,
    .dio = {2, 3, 4},
};

#ifndef _Sodaq_RN2483_h
  #include "LowPower.h"
#endif

#define DEBUG

int ANALOGPIN = A5;
int readVal;

static uint8_t dataTX[3];

unsigned long cycle_length = 30 * 1 * 1000UL; // cycle * mins_or_secs * 1000;
unsigned long sense_every = 1;
unsigned long send_every = 1;

unsigned long cycle = -1;  //  init at -1, so first cycle starts as cycle 0 for 1st sense/send
unsigned long prevSleep = 0; 

void setup() {
  while ((!Serial) && (millis() < 10000)){ }

  Serial.begin(9600);
  Serial.println(F("emon (template version: 13Jan2017 generated: 10Jul2018)"));

  init_node();
  init_sensor();
}


void loop() {
  cycle += 1;
  if ( (cycle % sense_every) == 0 ) { do_sense(); }
  if ( (cycle % send_every) == 0 ) { build_data(); do_send(); }
  unsigned long current = millis();
  do_sleep(cycle_length - (current - prevSleep));  // sleep minus elapsed time
  prevSleep = current;
  #ifdef _Sodaq_RN2483_h
    prevSleep += cycle_length;
  #endif
}


void init_sensor() {
  Serial.println("");
  pinMode(ANALOGPIN, INPUT);
}

void do_sense() {
  delay(1000);
  readVal = analogRead(ANALOGPIN);

  #ifdef DEBUG 
    Serial.print(F(" readVal: "));
    Serial.print(readVal);
    Serial.println();
  #endif

}

/* **************************************************************
 * build data to transmit in dataTX
 * *************************************************************/
void build_data() {

  #ifdef DEBUG 
    Serial.print(F("Time:"));
    Serial.print(millis());
    Serial.print(F(" Send Value:"));
    Serial.print(readVal);
    Serial.println();
  #endif
    
  // map it to dataTX; 1 leading byte (0x01) plus 2 data bytes
  /* *************************************************
   * Suggested payload function for this data
   *
   * if (bytes[0] == 0x01) {
   *   var moisture = (bytes[1] << 8) | bytes[2];  
   *   return { payload: moisture };
   * }
   *
   * ************************************************/
  dataTX[0] = 0x01;     //first byte is send as 00 to recognise this is a temperature in our dashboard
  dataTX[1] = readVal >> 8;
  dataTX[2] = readVal & 0xFF;
}


/* **************************************************************
* sleep
* *************************************************************/
void do_sleep(float sleepTime) {

  #ifdef DEBUG
    Serial.print(F("Sleep for "));
    Serial.print(sleepTime/1000, 3);
    Serial.println(F(" seconds"));
  #endif

  Serial.flush();

  #ifndef _Sodaq_RN2483_h
    // sleep logic using LowPower library
    int delays[] = {8000, 4000, 2000, 1000, 500, 250, 120, 60, 30};
    period_t sleep[] = {SLEEP_8S, SLEEP_4S, SLEEP_2S, SLEEP_1S, SLEEP_500MS, SLEEP_250MS, SLEEP_120MS, SLEEP_60MS, SLEEP_30MS};

    // correction for overhead in this routine
    sleepTime = sleepTime * 0.93;

    float x;
    unsigned int i;
    for (i=0; i<=9; i++) {
      for (x=sleepTime; x>=delays[i]; x-=delays[i]) {
        LowPower.powerDown(sleep[i], ADC_OFF, BOD_OFF);
        sleepTime -= delays[i];
      } 
    }
  #else
    // no LowPower implemented yet, so just a delay
    delay(sleepTime);
  #endif

}

  
/* **************************************************************
 * radio code, typical would be init_node(), do_send(), etc
 * *************************************************************/
/* **************************************************************
 * init the Node
 * *************************************************************/
void init_node() {
  #ifdef VCC_ENABLE
     // For Pinoccio Scout boards
     pinMode(VCC_ENABLE, OUTPUT);
     digitalWrite(VCC_ENABLE, HIGH);
     delay(1000);
  #endif

  // LMIC init
  os_init();
  // Reset the MAC state. Session and pending data transfers will be discarded.
  LMIC_reset();

  #ifdef ACT_METHOD_ABP
    // Set static session parameters. Instead of dynamically establishing a session
    // by joining the network, precomputed session parameters are be provided.
    #ifdef PROGMEM
      // On AVR, these values are stored in flash and only copied to RAM
      // once. Copy them to a temporary buffer here, LMIC_setSession will
      // copy them into a buffer of its own again.
      uint8_t appskey[sizeof(APPSKEY)];
      uint8_t nwkskey[sizeof(NWKSKEY)];
      memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
      memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
      LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
    #else
      // If not running an AVR with PROGMEM, just use the arrays directly
      LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
    #endif

    #if defined(CFG_eu868)
      // Set up the channels used by the Things Network, which corresponds
      // to the defaults of most gateways. Without this, only three base
      // channels from the LoRaWAN specification are used, which certainly
      // works, so it is good for debugging, but can overload those
      // frequencies, so be sure to configure the full frequency range of
      // your network here (unless your network autoconfigures them).
      // Setting up channels should happen after LMIC_setSession, as that
      // configures the minimal channel set.
      // NA-US channels 0-71 are configured automatically
      LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
      LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI);      // g-band
      LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
      LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
      LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
      LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
      LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
      LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7),  BAND_CENTI);      // g-band
      LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK,  DR_FSK),  BAND_MILLI);      // g2-band
      // TTN defines an additional channel at 869.525Mhz using SF9 for class B
      // devices' ping slots. LMIC does not have an easy way to define set this
      // frequency and support for class B is spotty and untested, so this
      // frequency is not configured here.
    #elif defined(CFG_us915)
      // NA-US channels 0-71 are configured automatically
      // but only one group of 8 should (a subband) should be active
      // TTN recommends the second sub band, 1 in a zero based count.
      // https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json
      LMIC_selectSubBand(1);
    #endif

    // Disable link check validation
    LMIC_setLinkCheckMode(0);

    // TTN uses SF9 for its RX2 window.
    LMIC.dn2Dr = DR_SF9;

    // Set data rate and transmit power (note: txpow seems to be ignored by the library)
    LMIC_setDrTxpow(DR_SF7,14);
  #endif

  #ifdef ACT_METHOD_OTAA
    // got this fix from forum: https://www.thethingsnetwork.org/forum/t/over-the-air-activation-otaa-with-lmic/1921/36
    LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
  #endif

}

/* **************************************************************
 * send the message
 * *************************************************************/
void do_send() {

  Serial.print(millis());
  Serial.print(F(" Sending.. "));  

  send_message(&sendjob);

  // wait for send to complete
  Serial.print(millis());
  Serial.print(F(" Waiting.. "));  
 
  while ( (LMIC.opmode & OP_JOINING) or (LMIC.opmode & OP_TXRXPEND) ) { os_runloop_once();  }
  Serial.print(millis());
  Serial.println(F(" TX_COMPLETE"));
}
  
/* *****************************************************************************
* send_message
* ****************************************************************************/
void send_message(osjob_t* j) {
  // 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(1, dataTX, sizeof(dataTX), 0);
    Serial.println(F("Packet queued"));
  }
}

/*******************************************************************************/
void onEvent (ev_t ev) {
  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"));
      // Disable link check validation (automatically enabled
      // during join, but not supported by TTN at this time).
      LMIC_setLinkCheckMode(0);
      break;
    case EV_RFU1:
      Serial.println(F("EV_RFU1"));
      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.dataLen) {
        // data received in rx slot after tx
        Serial.print(F("Data Received: "));
        Serial.write(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
        Serial.println();
      }
      // schedule next transmission
      // os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), send_message);
      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;
    default:
      Serial.println(F("Unknown event"));
      break;
  }
    
}

It works for a while and then I get a failure

emon (template version: 13Jan2017 generated: 10Jul2018)

 readVal: 513
Time:1007 Send Value:513
1007 Sending.. Packet queued
1019 Waiting.. EV_TXCOMPLETE (includes waiting for RX windows)
3098 TX_COMPLETE
Sleep for 26.900 seconds
 readVal: 513
Time:4196 Send Value:513
4198 Sending.. Packet queued
4202 Waiting.. 4218 TX_COMPLETE
Sleep for 28.863 seconds
 readVal: 513
Time:5332 Send Value:513
5332 Sending.. Packet queued
5339 Waiting.. 5353 TX_COMPLETE
Sleep for 28.864 seconds
 readVal: 513
Time:6469 Send Value:513
6469 Sending.. Packet queued
6475 Waiting.. 6490 TX_COMPLETE
Sleep for 28.865 seconds
 readVal: 513
Time:7606 Send Value:513
7606 Sending.. Packet queued
7618 Waiting.. FAILURE 
C:\Users\xxx\Documents\Arduino\libraries\arduino-lmic-master\src\lmic\radio.c:660

I’m starting to pull my hair out… Please any suggestions will be appreciated!


(Esawyja) #7

Thanks all, I found the problem, badly soldered joint on A5