HelTecAutomation / ESP32_LoRaWAN

Transplanted from Semtech LoRaWAN(https://github.com/Lora-net/LoRaMac-node) protocol to "ESP32 + Arduino" platform. Use RTC, support deep sleep, only working with ESP32 + LoRa boards made by HelTec Automation(TM). Need a unique license to use it.
333 stars 108 forks source link

no data reception, only join #99

Closed DerMerten closed 1 month ago

DerMerten commented 1 month ago

Hello, I am very doubtful right now, I am sending data with LoRaWAN via TTN Gateway, but it only comes that it join. I want to send data from DHT11 and from a load cell. below is my code and below is the payload decorder. Can someone please help? Thank you edit: that's the only thing i get: grafik

Code:

#include "LoRaWan_APP.h"

uint8_t appEui[] = { something };
uint8_t devEui[] = { something };
uint8_t appKey[] = { something };

uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda, 0x85 };
uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef, 0x67 };
uint32_t devAddr = (uint32_t)0x007e6ae1;

uint16_t userChannelsMask[6] = { 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };

LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;
DeviceClass_t loraWanClass = CLASS_A;

uint32_t appTxDutyCycle = 240000;
bool overTheAirActivation = true;
bool loraWanAdr = true;
bool isTxConfirmed = true;
uint8_t appPort = 2;
uint8_t confirmedNbTrials = 4;

#include "HX711.h"
HX711 scale;

uint8_t dataPin = 26;
uint8_t clockPin = 48;
int int_nestweight = 0;

#define VBAT_PIN 1
#define VBAT_READ_CNTRL_PIN 37
#define ADC_READ_STABILIZE 10

int int_readBatLevel = 0;
float readBatLevel() {
  int analogValue = analogRead(VBAT_PIN);
  float voltage = 0.004376 * analogValue;
  return voltage;
}

#include <DHT.h>

#define DHTPIN 2
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);
int int_readhumidity = 0;
int int_readtemperature = 0;

static void prepareTxFrame(uint8_t port) {
  Serial.begin(115200);
  Serial.println("wakeup scale");
  scale.begin(dataPin, clockPin);
  scale.set_scale(1000.795471);
  scale.set_offset(4294624289);
  delay(5000);

  if (scale.is_ready()) {
    Serial.println("scale is ready");
    Serial.println(scale.get_units(1));
    int_nestweight = (scale.get_units(1) * 10);
    int_nestweight = 890;

    if (int_nestweight > 9000) {
      int_nestweight = 9999;
    }
  } else {
    int_nestweight = 8888;
    Serial.println("scale not ready");
  }

  Serial.println(int_nestweight);

  float v = readBatLevel();
  int_readBatLevel = abs(v * 100);
  Serial.print("Batterielevel ");
  Serial.println(int_readBatLevel);

  float humidity = dht.readHumidity();
  int_readhumidity = abs(humidity * 100);
  float temperature = dht.readTemperature();
  int_readtemperature = abs(temperature * 100);

  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("Error reading DHT sensor!");
    return;
  }

  Serial.print("Humidity: ");
  Serial.println(humidity);
  Serial.print("Temperature: ");
  Serial.println(temperature);

  appDataSize = 16;
  appData[0] = int_nestweight >> 8;
  appData[1] = int_nestweight & 0xFF;
  appData[2] = int_readBatLevel >> 8;
  appData[3] = int_readBatLevel & 0xFF;
  appData[4] = int_readhumidity >> 8;
  appData[5] = int_readhumidity & 0xFF;
  appData[6] = int_readtemperature >> 8;
  appData[7] = int_readtemperature & 0xFF;
}

void setup() {
  Serial.begin(115200);
  Mcu.begin();
  deviceState = DEVICE_STATE_INIT;
  scale.begin(dataPin, clockPin);
  scale.set_scale(1000.795471);
  scale.set_offset(4294624289);
  pinMode(VBAT_READ_CNTRL_PIN, OUTPUT);
  digitalWrite(VBAT_READ_CNTRL_PIN, LOW);
  dht.begin();
}

void loop() {
  switch (deviceState) {
    case DEVICE_STATE_INIT: {
#if (LORAWAN_DEVEUI_AUTO)
      LoRaWAN.generateDeveuiByChipID();
#endif
      LoRaWAN.init(loraWanClass, loraWanRegion);
      break;
    }
    case DEVICE_STATE_JOIN: {
      LoRaWAN.join();
      break;
    }
    case DEVICE_STATE_SEND: {
      prepareTxFrame(appPort);
      LoRaWAN.send();
      deviceState = DEVICE_STATE_CYCLE;
      break;
    }
    case DEVICE_STATE_CYCLE: {
      txDutyCycleTime = appTxDutyCycle + randr(-APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND);
      LoRaWAN.cycle(txDutyCycleTime);
      deviceState = DEVICE_STATE_SLEEP;
      break;
    }
    case DEVICE_STATE_SLEEP: {
      LoRaWAN.sleep(loraWanClass);
      break;
    }
    default: {
      deviceState = DEVICE_STATE_INIT;
      break;
    }
  }
}

Payload Decorder:

function decodeUplink(input) {
  var nestWeight = (input.bytes[0] << 8) | input.bytes[1];
  var batteryVoltage = (input.bytes[2] << 8) | input.bytes[3];
  var humidity = (input.bytes[4] << 8) | input.bytes[5];
  var temperature = (input.bytes[6] << 8) | input.bytes[7];

  var errorMessage = 'measurement_error';

  if (nestWeight < 1000) {
    return {
      data: {
        nest_weight_in_grams: nestWeight / 10,
        battery_status_in_volts: batteryVoltage / 100,
        humidity_in_percent: humidity / 100,
        temperature_in_degrees_celsius: temperature / 100
      }
    };
  } else {
    return {
      data: {
        error_message: errorMessage
      } 
    };
  }
}
BNNorman commented 1 month ago

Don't you need to change the state to DEVICE_STATE_SEND after the join() call?

    case DEVICE_STATE_JOIN: {
      LoRaWAN.join();
      break;
    }
DerMerten commented 1 month ago

Don't you need to change the state to DEVICE_STATE_SEND after the join() call?

    case DEVICE_STATE_JOIN: {
      LoRaWAN.join();
      break;
    }

should I delete this case or what do you mean?

BNNorman commented 1 month ago

No, try changing it to this..

case DEVICE_STATE_JOIN: {
      LoRaWAN.join();
      deviceState = DEVICE_STATE_SEND;
      break;
    }
DerMerten commented 1 month ago

No, try changing it to this..

case DEVICE_STATE_JOIN: {
      LoRaWAN.join();
      deviceState = DEVICE_STATE_SEND;
      break;
    }

so, now the Serial Monitor shows this: grafik but on the live Date from TTN still nothing: grafik

BNNorman commented 1 month ago

Possibly you are sending before the join has completed (race condition)

I don't know if LoRaWAN.join() on Heltec waits till it gets a message to say it has joined - that can take several seconds.

I would change the DEVICE_STATE_SEND code block to check devAddr before sending.

    case DEVICE_STATE_SEND: {
      # valid TTN devAddr begins with 0x26 or 0x27
      if (devAddr[0]==0x26 || devAddr[0]==0x27){
        prepareTxFrame(appPort);
        LoRaWAN.send();
       deviceState = DEVICE_STATE_CYCLE;
      }
      break;
    }
DerMerten commented 1 month ago

Possibly you are sending before the join has completed (race condition)

I don't know if LoRaWAN.join() on Heltec waits till it gets a message to say it has joined - that can take several seconds.

I would change the DEVICE_STATE_SEND code block to check devAddr before sending.

    case DEVICE_STATE_SEND: {
      # valid TTN devAddr begins with 0x26 or 0x27
      if (devAddr[0]==0x26 || devAddr[0]==0x27){
        prepareTxFrame(appPort);
        LoRaWAN.send();
       deviceState = DEVICE_STATE_CYCLE;
      }
      break;
    }

i have an error: Compilation error: invalid types 'uint32_t {aka unsigned int}[int]' for array subscript

DerMerten commented 1 month ago

Possibly you are sending before the join has completed (race condition)

I don't know if LoRaWAN.join() on Heltec waits till it gets a message to say it has joined - that can take several seconds.

I would change the DEVICE_STATE_SEND code block to check devAddr before sending.

    case DEVICE_STATE_SEND: {
      # valid TTN devAddr begins with 0x26 or 0x27
      if (devAddr[0]==0x26 || devAddr[0]==0x27){
        prepareTxFrame(appPort);
        LoRaWAN.send();
       deviceState = DEVICE_STATE_CYCLE;
      }
      break;
    }

so i ask ChatGPT and got this

if (((devAddr >> 24) & 0xFF) == 0x26 || ((devAddr >> 24) & 0xFF) == 0x27)

if this is correct, it is a different question, but the Heltec ESP no longer sends anything or the console no longer displays anything

BNNorman commented 1 month ago

It's basically the same thing but looks like the Heltec code is treating devAddr as a 32bit int and not a bytearray, so go with the chatGPT version.

If the code no longer sends anything then it can only be, from what I can see, that this test

if (  ((devAddr >> 24) & 0xFF) == 0x26 || ((devAddr >> 24) & 0xFF) == 0x27)

is returning false.

it might be an idea to put a print statement in there, before the if, to see what devAddr is. Something like:-

Serial.print("devAddr"); Serial.println(devAddr,HEX);

I'm assuming you are connected to the Heltec via a USB serial cable.

BNNorman commented 1 month ago

Another possibility. LoRaWAN.send() appears to get here and if NextTx is false it won't send anything.

void LoRaWanClass::send(DeviceClass_t classMode)
{
    if( NextTx == true )
    {   
        NextTx = SendFrame( );
    }
}

Possibly, somewhere, this flag is set to prevent you exceeding the legal duty cycle limit. It might be worth making yourself a hot drink and waiting to see if your data is eventually sent. With a 1% duty cycle in EU for every 1s transmission you need to wait 99s before you can transmit again. That's the law.

That's as far as I can go.

DerMerten commented 1 month ago

I'm assuming you are connected to the Heltec via a USB serial cable.

hello, sorry for replying so late had a lot to do. Yes, for now, the Heltec is connected via USB later on it will be connect only with a battery. The output from the print is "devAddr7E6AE1" and with the new if statement:

 if (  ((devAddr >> 24) & 0xFF) == 0x26 || ((devAddr >> 24) & 0xFF) == 0x27)

no data is send

DerMerten commented 1 month ago

Another possibility. LoRaWAN.send() appears to get here and if NextTx is false it won't send anything.

void LoRaWanClass::send(DeviceClass_t classMode)
{
  if( NextTx == true )
  {   
      NextTx = SendFrame( );
  }
}

Possibly, somewhere, this flag is set to prevent you exceeding the legal duty cycle limit. It might be worth making yourself a hot drink and waiting to see if your data is eventually sent. With a 1% duty cycle in EU for every 1s transmission you need to wait 99s before you can transmit again. That's the law.

That's as far as I can go.

I have heard about this regulation, so I have set the appTxDutyCycle to 240,000 and that results in 4 minutes and that is the 1%. Where exactly should I paste your code?

BNNorman commented 1 month ago

That code is already in the LoRaWAN.cpp which you are using. I was just pointing out that receiving a devAddr might take some seconds and that the NextTX time slot might be the reason nothing was sent but it should be sent as soon as the 4 minute duty cycle has expired.

However, look at your devAddr:-

The output from the print is "devAddr7E6AE1"

and compare it with your console join devAddr :-

329838919-14a00b83-ee49-47f2-96ad-d1c178c84feb

It should be 4 bytes - possibly the print(devAddr,HEX) has dropped off the leading byte in which case it would be 007E6AE1 which is NOT a valid TTN devAddr. It should begin with 0x26 or 0x27 which is why nothing is being sent. It it was sent the TTN server would ignore it anyway because the devAddr is wrong.

I notice that your console display showed two different devAddr (look at the middle one). That is very weird and don't ask me why. I don't know. One for the TTN community (assunming it's always like that - mine never was)

You need to find out why your device/code is receiving an invalid devAddr.

Remember that radio signals can be swamped. Right clicking the console messages would show detailed messages which should help to identify the RSSI and SNR of what you are sending. How far away is your gateway? Or are your signals picked up by someone else's gateway?

If you are using your own gateway it may be too close - strong signals can swamp your device which might corrupt the received devAddr.

Brian

DerMerten commented 1 month ago

That code is already in the LoRaWAN.cpp which you are using. I was just pointing out that receiving a devAddr might take some seconds and that the NextTX time slot might be the reason nothing was sent but it should be sent as soon as the 4 minute duty cycle has expired.

However, look at your devAddr:-

The output from the print is "devAddr7E6AE1"

and compare it with your console join devAddr :-

329838919-14a00b83-ee49-47f2-96ad-d1c178c84feb

It should be 4 bytes - possibly the print(devAddr,HEX) has dropped off the leading byte in which case it would be 007E6AE1 which is NOT a valid TTN devAddr. It should begin with 0x26 or 0x27 which is why nothing is being sent. It it was sent the TTN server would ignore it anyway because the devAddr is wrong.

I notice that your console display showed two different devAddr (look at the middle one). That is very weird and don't ask me why. I don't know. One for the TTN community (assunming it's always like that - mine never was)

You need to find out why your device/code is receiving an invalid devAddr.

Remember that radio signals can be swamped. Right clicking the console messages would show detailed messages which should help to identify the RSSI and SNR of what you are sending. How far away is your gateway? Or are your signals picked up by someone else's gateway?

If you are using your own gateway it may be too close - strong signals can swamp your device which might corrupt the received devAddr.

Brian

yes a modifit version from the LoRaWAN.cpp. To be honest, everything worked with the load cell, but when I connected the DHT11, problems started to occur or are still occurring. i think it could be the appDataSize but i don't know exactly. i read the documentation and didn't understand much or tried out a few things and then i came up with something like this. If I set the appDataSize back to 4 and comment out the humidity & temperature from the DHT11, then everything works, or rather everything had worked. the RSSI value is -115 / -114 and why devAddr have a different value I can't tell you either. It have different values. grafik

I also asked in the TTN forum but till now nobody has answered me.

DerMerten commented 1 month ago

That code is already in the LoRaWAN.cpp which you are using. I was just pointing out that receiving a devAddr might take some seconds and that the NextTX time slot might be the reason nothing was sent but it should be sent as soon as the 4 minute duty cycle has expired.

However, look at your devAddr:-

The output from the print is "devAddr7E6AE1"

and compare it with your console join devAddr :-

329838919-14a00b83-ee49-47f2-96ad-d1c178c84feb

It should be 4 bytes - possibly the print(devAddr,HEX) has dropped off the leading byte in which case it would be 007E6AE1 which is NOT a valid TTN devAddr. It should begin with 0x26 or 0x27 which is why nothing is being sent. It it was sent the TTN server would ignore it anyway because the devAddr is wrong.

I notice that your console display showed two different devAddr (look at the middle one). That is very weird and don't ask me why. I don't know. One for the TTN community (assunming it's always like that - mine never was)

You need to find out why your device/code is receiving an invalid devAddr.

Remember that radio signals can be swamped. Right clicking the console messages would show detailed messages which should help to identify the RSSI and SNR of what you are sending. How far away is your gateway? Or are your signals picked up by someone else's gateway?

If you are using your own gateway it may be too close - strong signals can swamp your device which might corrupt the received devAddr.

Brian

I use the gateway in my city and it is within a radius of 5 km maybe more or less idk.

BNNorman commented 1 month ago

Every new join will mean a new devAddr (TTN/LoRaWAN security) but they all begin with 0x26 in your case. Perhaps the middle devAddr is internal to TTN servers IDK.

RSSI of -115 means you are unlikely to be swamped by strong reply transmissions so I think we can rule that out.

Why are you sending confirmed uplinks? Those required a downlink response which uses up some of your valuable duty cycle time and , also, TTN recommends a max of 10 per day and a total transmission time of 30s (Fair use policy) which includes uplinks and downlinks.

I was looking for a place to put some print statements to catch the LoRaWAN downlink packet but can't see any. What, exactly, is your device and especially the Radio module it is using?

I'm out of ideas now - I would urge you to use the Heltec forums. Point out that you appear to receive an invalid TTN devAddr after a successful join.

DerMerten commented 1 month ago

Every new join will mean a new devAddr (TTN/LoRaWAN security) but they all begin with 0x26 in your case. Perhaps the middle devAddr is internal to TTN servers IDK.

RSSI of -115 means you are unlikely to be swamped by strong reply transmissions so I think we can rule that out.

Why are you sending confirmed uplinks? Those required a downlink response which uses up some of your valuable duty cycle time and , also, TTN recommends a max of 10 per day and a total transmission time of 30s (Fair use policy) which includes uplinks and downlinks.

I was looking for a place to put some print statements to catch the LoRaWAN downlink packet but can't see any. What, exactly, is your device and especially the Radio module it is using?

I'm out of ideas now - I would urge you to use the Heltec forums. Point out that you appear to receive an invalid TTN devAddr after a successful join.

i use the following heltec esp, i have been searching for a long time and found nothing, so i decided to create a new issue. something unexpected just happened and i received something but without any values grafik

DerMerten commented 1 month ago

Every new join will mean a new devAddr (TTN/LoRaWAN security) but they all begin with 0x26 in your case. Perhaps the middle devAddr is internal to TTN servers IDK. RSSI of -115 means you are unlikely to be swamped by strong reply transmissions so I think we can rule that out. Why are you sending confirmed uplinks? Those required a downlink response which uses up some of your valuable duty cycle time and , also, TTN recommends a max of 10 per day and a total transmission time of 30s (Fair use policy) which includes uplinks and downlinks. I was looking for a place to put some print statements to catch the LoRaWAN downlink packet but can't see any. What, exactly, is your device and especially the Radio module it is using? I'm out of ideas now - I would urge you to use the Heltec forums. Point out that you appear to receive an invalid TTN devAddr after a successful join.

i use the following heltec esp, i have been searching for a long time and found nothing, so i decided to create a new issue. something unexpected just happened and i received something but without any values grafik

for some inexplicable reason unknown to me, it worked, then i rebooted it and the old state is back. i would let him send a bit now and then i want to see if he sends something, do you have an idea why he sends 0 as data?

battery_status_in_volts: 0, humidity_in_percent: 0, nest_weight_in_grams: 0, temperature_in_degrees_celsius: 0
BNNorman commented 1 month ago

0 would indicate incorrect wiring connection. The DHT11 is a one-wire device which requires VCC, GND and a pulled up signal. I would guess the pullup resistor has disconnected so no data would be received hence 0.

DerMerten commented 1 month ago

0 would indicate incorrect wiring connection. The DHT11 is a one-wire device which requires VCC, GND and a pulled up signal. I would guess the pullup resistor has disconnected so no data would be received hence 0.

okay and what about the rest? any idea?

BNNorman commented 1 month ago
for some inexplicable reason unknown to me, it worked,

If it worked you should have received a valid devAddr - and it might have taken a while due to duty cycle so possibly a duty cycle restriction expired allowing the data to be sent.

Have you used the TTN airtime calculator to work out what your transmit time would be for the data you are, hopefully, sending?

As I said before. If it's 1s then you would have to wait 99s before the next send and with confirmed uplinks that would be longer since TotalTxTime=(UplinkTxTime+DownlinkTxTime) and your system would wait 99*TotalTxTime before it would send another uplink.. Since I don't know your numbers that's all I can say.

However, the TTN console should indicate actual air time consumed sending your uplinks.

DerMerten commented 1 month ago
for some inexplicable reason unknown to me, it worked,

If it worked you should have received a valid devAddr - and it might have taken a while due to duty cycle so possibly a duty cycle restriction expired allowing the data to be sent.

Have you used the TTN airtime calculator to work out what your transmit time would be for the data you are, hopefully, sending?

As I said before. If it's 1s then you would have to wait 99s before the next send and with confirmed uplinks that would be longer since TotalTxTime=(UplinkTxTime+DownlinkTxTime) and your system would wait 99*TotalTxTime before it would send another uplink.. Since I don't know your numbers that's all I can say.

However, the TTN console should indicate actual air time consumed sending your uplinks.

so then when it worked, the devAddr was 260B68A6. No I have not use it. But thank you. I will try and try and wait, if it works I will let you know. If you have any ideas, you are welcome to write them.

BNNorman commented 1 month ago

That's a valid devAddr so the code would accept it and transmit. Be aware that there are probably other transmitters in your area. I have seen numerous transmissions on my gateway log from other people in my area but the devAddr filter blocks them on my devices which use a raspberry Pi and Python (https://github.com/BNNorman/dragino-1)

DerMerten commented 1 month ago

That's a valid devAddr so the code would accept it and transmit. Be aware that there are probably other transmitters in your area. I have seen numerous transmissions on my gateway log from other people in my area but the devAddr filter blocks them on my devices which use a raspberry Pi and Python (https://github.com/BNNorman/dragino-1)

should your code act as a gateway? If yes, is it possible to send the incoming data to to a MQTT? If no, what does it do then? i only skimmed your description a bit

BNNorman commented 1 month ago

No, it's just a device node. Look at Test.py - that's an example of how it might be used. It joins TTN and uplinks data to the app.

You can use MQTT to send data to TTN - if you have WiFi. Quite easy to do.

DerMerten commented 1 month ago

No, it's just a device node. Look at Test.py - that's an example of how it might be used. It joins TTN and uplinks data to the app.

You can use MQTT to send data to TTN - if you have WiFi. Quite easy to do.

yeah, thx. the heltec is running since a while and still the same (nothing). I will now see if this is due to the code

BNNorman commented 1 month ago

ok

DerMerten commented 1 month ago

ok

So, I think I've got it right. The problem was that the gateway I had was on the hill and the signals didn't reach it properly. I now have another one that is “flat” or on the same level as my LoRaWAN and now it works. grafik