Adafruit feather m0 with TTN

Hi,

I am using adafruit feather m0 Lora node, I am trying to connect it with the TTN but it could not send the payload. Could someone please assist me with how to fix it?

Sincerely
Junaid

Bit hard to say without any detail.

What makes you think it can’t send the payload? Error messages? Serial logs? Smoke?

How does this relate to the Dragino end node topic?

I am using it for temperature sensing. The serial log working fine. But the TTN console does not receive any payload. Below are the screenshots of my query.
image
image

Please do not post images of text when you can copy & paste the text.

What does the gateway think it is hearing from your Feather?

Thanks for your suggestion.

Yes the Gateway working fine and shows the Feather m0 details. Here below is the text copied from Gateway.

{
  "gw_id": "eui-a840411f58b04150",
  "payload": "QKP7oTCAGAkDaiYjxTU0+CbrKUR3QXx3qioAh8eh6Bd6u4HudB1TPR6Oz86J5mwb8xidWPxwEVkmHP2sxLwUT/TxcRzVvzlbsR/N0DGqMrcZlnruwIWq65o8LBQR1KALFZHM2NBHqVrGWz952Ktdwz3zPjAonSH7KvfqRQK9xW3jY75VNjFhy0uoCWpzVjwUa0DB0R/JDrr7Ya7OnAkV6NfHIUXeqw==",
  "f_cnt": 2328,
  "lora": {
    "spreading_factor": 7,
    "bandwidth": 125,
    "air_time": 266495999
  },
  "coding_rate": "4/5",
  "timestamp": "2021-05-16T20:29:11.524Z",
  "rssi": -113,
  "snr": 5.8,
  "dev_addr": "30A1FBA3",
  "frequency": 868300000
}

Please format your post, see How do I format my forum post? [HowTo]

That gateway entry is for DevAddr 30A1FBA3 and your serial log shows one starting FF (now you know why we like it as text). You need matching timestamps.

That doesnt look like a TTN device address…have you registered an application in TTN and registered a device against it? Has the device joined TTN? Also looks at odds with the Dev Addr in the picture above (FF110E1E) so what have you done to set up the adafruit? Are you trying ABP or OTAA?

I believe 30 xx xx xx is for a Loriot Network ID?

Sir,

Here I am going to mention what I did in detail. First of all, I connected the Dragino LPS8 Gateway with the TTN.

Gateway

Then I created an application on the things console. In this application, I registered my device as can be seen below. (ABP Activation mehtod)

application

After that, I copied the device address (DEVADDR), Network session key (NWKSKEY), and Application Session Key (APPSKEY) and paste them into the code.

keys

code

By compiling and uploading the sketch, the serial monitor shows the sensed data. However, there is no data on application data on TTN.

image

As you can see, there is no data

image

@descartes Sorry I posted a few snapshots, without them I could not explain my message to experts like you.

I hope my question is now cleared to you.

Note: I am sorry I am extremely beginner in this field. Your assistance will be highly appreciated.

Yours sincerely
Junaid

Yup, understood all that.

The serial log from the Feather needs a matching gateway log for the same time for us to see if the Feather is being heard by the gateway.

But then your Feather’s serial log’s DevAddr doesn’t match the DevAddr in your screenshot and none of TTN’s start FF. So you may need to check the keys are copied over correctly.

I am very thankful to you. I deleted the registered device and trying to add it correctly but unable to fix the issue. Would you be kind enough to supervise me on Skype or Microsoft Team? As I guess the only problem is in the device address, I am new so don’t know how to add correctly. I searched a lot of tutorials and google for the last 3 weeks but found no helpful stuff.

Whilst monitoring your GW’s traffic page live (historic data isnt shown) can you reset/restart your device and capture what the GW sees…and post back

This rarely solves the problem.

We are all volunteers here, it’s not feasible to do this.

I don’t recognise the firmware from the Arduino screen shot above (which could still have been text) - what is it and where did you get it from?

And

This is key. Check your code as this needs to match.

Please show (in formatted text) the part of the code where you set the DevAddr and keys. Did you base your code on an example from the internet? If so please also post a link to that code.

After discussing it with you all experts @kersing @descartes @Jeff-UK, now I am confident the problem is in devaddr.

In the IDE, I clicked tools>get board info> SN: 3739FC93504E514E34202020FF110E1E and paste it in the device EUI option in the register device. Now further I don’t know what to do.

board info

image

The Gateway traffic shows the following information

image

Why? Where does it say to do that? It’s not how you generate a DevEUI and it isn’t how you setup a device for ABP. DevAddr is not DevEUI.

It’s clear that the DevAddr you are entering in to the code is somehow being turned in to FF110E1E and that your gateway is hearing the uplink but as that DevAddr doesn’t match anything for TTN, it won’t be transferred over to your application. But as you haven’t you answered either myself or @kersing about which code you are using, we can’t move forward.

If you keep changing things, we will be trying to hit a moving target.

@descartes @kersing @Jeff-UK : Thanks for your kind help. Here I uploaded the code and the method that I am trying to connect the node to google drive. The code is in this link named as SRSSensor-lorawan. Please let me know if doesn’t work I will re-send it via email or any other method.

https://drive.google.com/drive/folders/1aY8BLin8-PVVEi0HzLH9UzLtSaYYA7AU?usp=sharing

Thank you
Yours sincerely
Junaid

Just post it here or, as actually requested, tell us where you got it from, or both.

You can use the </> tool to format code.

Or make it public on Google. But you aren’t getting my email address so I can get your code. I have working code for the Feather, which is why I am just about barely hanging in here as there is a possibility I can help you.

Thank you for your response. The code is given by my Professor and is working fine I have tested on ResIOT platform. Here its my first time on TTN. You can see the code below.


    /*******************************************************************************
  ARTYS - SRS Smart Rainfall System


 *******************************************************************************/

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <SRSPacket.h>
#include <ArduinoUniqueID.h> // libs to extract Serial Number from SAMD21

/*
 * SW:00-FF
 * 
 * HW:
 *  01 : Adafruit feather M0 LoraWan + Sense
 *  02 : AckeeG + LORAWAN + Sense
 *
 * TX :
 * 0 : ETH
 * 1 :  ETH WIFI
 * 2 : GSM
 * 3 : LoRAWAN
 *
 * SW + HW + TX MUST be UNIQUE
 * Single fields aren't unique
 */
#define FW_VERSION "00013"
#define ARTYS43 // FeatherM0-ARTYS43 configuration

// LoRaWAN NwkSKey, network session key
 u1_t NWKSKEY[16] = { 0x89, 0xA2, 0xC0, 0xA5, 0x1B, 0x88, 0x7E, 0x9D, 0xAD, 0xD0, 0x24, 0x90, 0x6D, 0xA9, 0x90, 0xCB };

// LoRaWAN AppSKey, application session key
static const u1_t PROGMEM APPSKEY[16] = { 0x98, 0xB6, 0xB3, 0x97, 0x41, 0x77, 0xCE, 0x49, 0xAC, 0x50, 0x76, 0x39, 0x4B, 0x70, 0x63, 0x66 };

typedef struct {
  boolean valid;
  u1_t NWKSKEY[16];
  u1_t APPSKEY[16];
  u1_t APPEUI[8];
  u4_t DEVADDR;
} LORAWAN_CONFIG_t;


// LoRaWAN end-device address (DevAddr)
// See http://thethingsnetwork.org/wiki/AddressSpace
// The library converts the address to network byte order as needed.
u4_t DEVADDR = 0x26013BCD; //= *( 0x0080A048); // word #3 Serial Number see 9.3.3 Serial Number Samd21 datasheet


// These callbacks are only used in over-the-air activation, so they are
// left empty here (we cannot leave them out completely unless
// DISABLE_JOIN is set in arduino-lmic/project_config/lmic_project_config.h,
// otherwise the linker will complain).
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }

// payload to send to TTN gateway
//static uint8_t payload[51];
static osjob_t sendjob;

// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 60;

// Pin mapping for Adafruit Feather M0 LoRa
const lmic_pinmap lmic_pins = {
  .nss = 8, // PA06
  .rxtx = LMIC_UNUSED_PIN,
  .rst = 4,
  .dio = {3, 6, LMIC_UNUSED_PIN},
  .rxtx_rx_active = 0,
  .rssi_cal = 8,              // LBT cal for the Adafruit Feather M0 LoRa, in dB
  .spi_freq = 8000000,
};

SRSData srsData; // packet to send data acquired

SRSConf srsConf; // packet to send configuration Data

unsigned long millis2Acquire = 0;
unsigned long millis2SendData = 0;
unsigned long millis2SendConf = 0;

unsigned long A0cumulativeValue = 0;
unsigned long A1cumulativeValue = 0;
unsigned long A2cumulativeValue = 0;
unsigned long A3cumulativeValue = 0;
unsigned long A4cumulativeValue = 0;
unsigned long A5cumulativeValue = 0;
unsigned long A7cumulativeValue = 0;

int noOfSampleAcquired = 0;

#define ADC_ACQ_INTERVAL     900 // we need to acquire 64 samples every 60 seconds

#define SEND_DATA_INTERVAL  60000 // 60 seconds

#define SEND_CONF_INTERVAL  900000 // 15 minutes seconds

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;
    /*
      || This event is defined but not used in the code. No
      || point in wasting codespace on it.
      ||
      || 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)"));
      digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
      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"));
      }
      // 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;
    /*
      || This event is defined but not used in the code. No
      || point in wasting codespace on it.
      ||
      || case EV_SCAN_FOUND:
      ||    Serial.println(F("EV_SCAN_FOUND"));
      ||    break;
    */
    case EV_TXSTART:
      Serial.println(F("EV_TXSTART"));
      break;
    default:
      Serial.print(F("Unknown event: "));
      Serial.println((unsigned) ev);
      break;
  }
}

/**
 * convert ADC value to microvolt
 * ADV range 0 1.65
 * ADC resolution = 4096
 * each unit correspond to 403 uV 1650000/4096
 */
int adc2Microvolt(int adcValue)
{
  return adcValue * 403;
}

void
printADCValue(char *label, int value)
{
  int uV = adc2Microvolt(value);

  Serial.print(label);
  Serial.print(value, DEC);
  Serial.print("(Dec) ");
  Serial.print(value, HEX);
  Serial.print("(Hex) ");
  Serial.print(value, BIN);
  Serial.print("(Bin) ");
  Serial.print(uV, DEC);
  Serial.println("(uV) ");
}

/**
 * 
 */
void do_send(int dataType) {
  if (noOfSampleAcquired == 0) {
    Serial.println("No data acquired");
    return;
  }

  Serial.print("DEVADDR : ");
  Serial.println(DEVADDR, HEX);

  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)

  //digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  // Check if there is not a current TX/RX job running
  if (LMIC.opmode & OP_TXRXPEND) {
    Serial.println(F("OP_TXRXPEND, not sending"));
  } else {
    //String payloadString = srsData.toJson();

    if (dataType == SRSPacketHeader::SRS_DATA) {
      int A0Value = A0cumulativeValue / noOfSampleAcquired;
      int A1Value = A1cumulativeValue / noOfSampleAcquired;
      int A2Value = A2cumulativeValue / noOfSampleAcquired;
      int A3Value = A3cumulativeValue / noOfSampleAcquired;
      int A4Value = A4cumulativeValue / noOfSampleAcquired;
      int A5Value = A5cumulativeValue / noOfSampleAcquired;
      int A7Value = A7cumulativeValue / noOfSampleAcquired;

      // we send ADC value in order to save bytes
      // server have to convert ADC value into uV
      srsData.CH_A = A0Value;
      srsData.CH_B = A1Value;
  
      srsData.S2_A = A2Value;
      srsData.S2_B = A3Value;

      srsData.S1_A = A4Value;
      srsData.S1_B = A5Value;

      srsData.temperature = A7Value;
  
      srsData.updateSequence();
      srsData.calculateCRC();

      A0cumulativeValue = A1cumulativeValue = A2cumulativeValue = noOfSampleAcquired = 0;
      A3cumulativeValue = A4cumulativeValue = A5cumulativeValue = A7cumulativeValue;

      printADCValue("A0 : ", A0Value);
      printADCValue("A1 : ", A1Value);
      printADCValue("A2 : ", A2Value);
      printADCValue("A3 : ", A3Value);
      printADCValue("A4 : ", A4Value);
      printADCValue("A5 : ", A5Value);
      printADCValue("A7 : ", A7Value);
      LMIC_setTxData2(1, (unsigned char *) &srsData, sizeof(srsData), 0);
      Serial.println(F("Data sent"));
      Serial.println(srsData.toJson());
    } else {
      srsConf.setUptime(millis());
      srsConf.updateSequence();
      srsConf.calculateCRC();
      LMIC_setTxData2(1, (unsigned char *) &srsConf, sizeof(srsConf), 0);
      Serial.println(F("Conf sent"));
      Serial.println(srsConf.toJson());
    }
  }
  //digitalWrite(LED_BUILTIN, LOW);   // turn the LED OFF (HIGH is the voltage level)
  // Next TX is scheduled after TX_COMPLETE event.
}

void setup() {

  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);    // turn the LED ON by making the voltage HIGH
  
  delay(15000);
  //while (!Serial);
  Serial.begin(115200);
  Serial.println("#1 serial initialized");

  Serial.print("NWKSKEY : ");
  for (size_t i = 0; i < UniqueIDsize; i++) {
     NWKSKEY[i] = UniqueID[i];
     Serial.print(UniqueID[i], HEX);
     Serial.print(" ");
  }
  Serial.println("");


  memcpy((void *)&DEVADDR, (void *)0x0080A048, sizeof(DEVADDR)); // word #3 Serial Number see 9.3.3 Serial Number Samd21 datasheet

  srsData.setDeviceId((const char *)NWKSKEY, sizeof(NWKSKEY));
#ifdef notdef
  // Create a "LORAWAN_CONFIG_t" variable and call it "lorawanConfig"
  LORAWAN_CONFIG_t lorawanConfig;

  // Read the content of "my_flash_store" into the "lorawanConfig" variable
  lorawanConfig = my_flash_store.read();
  if (lorawanConfig.valid == false) {
    memcpy(lorawanConfig.NWKSKEY, NWKSKEY, sizeof(lorawanConfig.NWKSKEY));
    memcpy(lorawanConfig.APPSKEY, APPSKEY, sizeof(lorawanConfig.APPSKEY));
    lorawanConfig.DEVADDR = DEVADDR;
    memset(lorawanConfig.APPEUI, '*', sizeof(lorawanConfig.APPEUI));
    lorawanConfig.valid = true;
    // ...and finally save everything into "my_flash_store"
    my_flash_store.write(lorawanConfig);
    Serial.println("save lorawanConfig to my_flash_store");
  } else {
    Serial.println("flash data valid!");
  }
#endif

  // In Zero board, the default analogRead() resolution for these boards is 10 bits, for compatibility. You need to use analogReadResolution() to change it to 12 bits.
  analogReadResolution(12);
  // Configures the reference voltage used for analog input (i.e. the value used as the top of the input range)
  analogReference(AR_INTERNAL1V65); // a built-in 1.65V reference

  //reading analog input set automatically pin as analog input
  int sensorValue;
  sensorValue = analogRead(A0);
  sensorValue = analogRead(A1);
  sensorValue = analogRead(A2);
  sensorValue = analogRead(A3);
  sensorValue = analogRead(A4);
  sensorValue = analogRead(A5);
  sensorValue = analogRead(A6);
  sensorValue = analogRead(A7);
  Serial.println("#2 ADCs initialized");

  
  delay(100);
  Serial.println(F("Starting"));

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

   Serial.println("#4 LMIC initialized");
  // Set static session parameters. Instead of dynamically establishing a session
  // by joining the network, precomputed session parameters are be provided.
  // 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);

  // We'll disable all 72 channels used by TTN
  //for (int c = 0; c < 72; c++){
  //  LMIC_disableChannel(c);
  //}

  // We'll only enable Channel 16 (905.5Mhz) since we're transmitting on a single-channel
  LMIC_enableChannel(16);

  // Disable link check validation
  LMIC_setLinkCheckMode(0);

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

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

  // srsConf initialization
  Serial.println(FW_VERSION); // XXXDBG
  srsConf.setFirmwareVersion(FW_VERSION);
  
  // Start job
  //do_send(&sendjob);
  millis2Acquire = millis() ;
  millis2SendData = millis() + SEND_DATA_INTERVAL;
  millis2SendConf = millis() + (SEND_DATA_INTERVAL/2); //SEND_DATA_INTERVAL/2) added to avoid
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW

  Serial.println(F("SETUP DONE"));
}

bool ledBuiltinOn = false;

void loop() {

  if (((long)(millis() - millis2Acquire)) >= 0)  {
    if (ledBuiltinOn == false) {
      digitalWrite(LED_BUILTIN, HIGH);
      ledBuiltinOn = true;
    } else {
      digitalWrite(LED_BUILTIN, LOW);
      ledBuiltinOn = false;
    }

    if (noOfSampleAcquired < 64) {
      noOfSampleAcquired++;
      int value = analogRead(A0);
      A0cumulativeValue +=  value;
      value = analogRead(A1);
      A1cumulativeValue +=  value;
      value = analogRead(A2);
      A2cumulativeValue +=  value;
      value = analogRead(A3);
      A3cumulativeValue +=  value;
      value = analogRead(A4);
      A4cumulativeValue +=  value;
      value = analogRead(A5);
      A5cumulativeValue +=  value;
      value = analogRead(A7);
      A7cumulativeValue +=  value;
    }

    millis2Acquire += ADC_ACQ_INTERVAL;
    printf("%d %d %d %d\n", digitalRead(13), digitalRead(40), digitalRead(41), digitalRead(43));

  }
  if (((long)(millis() - millis2SendData)) >= 0) {
    millis2SendData += SEND_DATA_INTERVAL;
    printf("It would be time to send ACQUIRED data");
    do_send(SRSPacketHeader::SRS_DATA);
  }

  if (((long)(millis() - millis2SendConf)) >= 0) {
    millis2SendConf += SEND_CONF_INTERVAL;
    printf("It would be time to send configuration data ");
    do_send(SRSPacketHeader::SRS_CONF);
  }

  os_runloop_once();
}

Why are you changing the DEVADDR in setup?

This code does not make sense because TTN uses only 8 channels in EU868. (The frequency listed in a previous message shows you are using EU868).

I would suggest you start by cleaning up the code or you could check LMIC-node (search the forum) as a starting point for better structured code.

BTW we explicitly asked to format the code. Is it that hard to add [ code ] before and [ /code ] (without the spaces) after your code block?

Sorry sir, I am new here and didn’t know how to format the code.