LoRa Radio Node V1 (Hope RF96) Setup for TTN

Environment:

  • TTN Indoor Gateway
  • Arduino IDE
  • LMIC Library v1.5 (also tried v1.4)
  • LoRa Radio Node RF96 915Mhz (North America) with AT328 installed
  • Hardware configurations:
    DIO0 → D2
    DIO1 → 5

I have LoRa Radio Node which has installed Hope RF96 module(picture attached), I read its datasheet and also I found some very useful information to work with this module like mobilefish on Youtube and some web sites, I followed this example First steps with LoRa Radio Node to setup my module but when I downloaded the code from github, some important files were missing. I thought to use LMIC library as this is widely used. after completing the setup, when my LoRa node is running I get the message on Serial Monitor:

EV_JOINING then a long pause and then
EV_JOIN_FAILED and then this message keep repeating itself.

I tried to find the solution on TTN forum and checked/updated following:

Pin configuration 
// Pin mapping
 const lmic_pinmap lmic_pins = {
    .nss = 10,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 9,
    .dio = {2, 5, LMIC_UNUSED_PIN},  // DIO01 -> D5
};
  • I came to know in config.h I have to change frequency to 915Mhz, I did that,
  • I also read in some thread that module worked with separate USB power supply, so tried it.
  • Distance from Gateway, I tried it many way like Gateway in same room, or 20 feet away, upper floor etc.

My Setup on TTN is all good, I took care of LSB, MSB while copying AppEUI, DeviceEUI and AppKey

When we create an Application on TTN and add a device manually there are some fields:

LoRaWAN version: I set to MAC V1.0.2 as its most commonly used, but i could not find anything related to this in RF96 datasheet or TTN help. When I read module’s register value 0x42 (for version) I get 0x12. I tried many other LoRaWAN versions with Regional parameters.

Regional Parameters version: in this field I set PHY V1.0.2 REV B again I was not able to find any documentation about it. (Last night i was able to find in the datasheet register for PHY 0x11, still I need to read the value)

After all above updates I still get same messages on Serial Monitor except few times I received the message, on TTN console I can see that some messages received activity took place but no payload attached to it. (but again except those few messages were received correct and I was to see payload attached to them)

Whenever message is successfully delivered I can see following line on Serial Monitor,
EV_TXCOMPLETE (includes waiting for RX windows)

I want to know what else I should consider?

LoRa_RFM98_AT328PShield

Your LMIC version is outdated, please use a current version, like version 4.1 from here: GitHub - mcci-catena/arduino-lmic: LoraWAN-MAC-in-C library, adapted to run under the Arduino environment

Most likely the messages without payload are answers from your node to the network commands, send by the network to your node, but your LMIC version doesn’t understand/handle them correctly.

1 Like

I’m still getting same response on TTN consolde but bit different on Serial Monitor

I set lmic_project_config.h
#define CFG_us915 1
#define CFG_sx_1276_radio 1

On TTN Application device: manually created, LoRaWAN version & Regional Parameters are same as above, I want to know if those setting are correct for HopeRF96 module.

Here is serial log
17:11:07.685 → Starting
17:11:07.720 → Packet queued
17:11:07.754 → 2698: EV_JOINING
17:11:07.754 → 3198: EV_TXSTART
17:11:14.191 → 405005: EV_JOIN_TXCOMPLETE: no JoinAccept
17:11:14.564 → 428700: EV_TXSTART
17:11:20.655 → 809174: EV_JOIN_TXCOMPLETE: no JoinAccept
17:11:25.766 → 1126247: EV_TXSTART
17:11:32.201 → 1528070: EV_JOIN_TXCOMPLETE: no JoinAccept
17:11:32.535 → 1548420: EV_TXSTART

And that’s what I can see on TTN console.

lora_lmic_4

It might be that the oscillator of your device is not accurate enough to fit the RX windows to receive the join accept message. You could try to relax the timing by adjust the LMIC clock error setting with this API:

It did not work

    LMIC_reset();
    LMIC_setClockError(MAX_CLOCK_ERROR * 10 / 100);

I set clock error and put lots of different number to calculate percentage but it did not work

This modules has 8MHz crystal installed, is there some way to calculate what exactly number needed, or can i check the frequency at some point?

Or there could be some other reason?

Which console and can you provide one where the timestamp match.

Or put another way, is it getting to the gateway but not the application?

Here are log events from Serial Monitor, Gateway and Application (please note that I’m using two computers one for Serial Monitor and other for TTN web page, not sure if that can cause time difference)

19:58:38.017 → 405010: EV_JOIN_TXCOMPLETE: no JoinAccept
19:58:38.934 → 462411: EV_TXSTART
19:58:45.033 → 842898: EV_JOIN_TXCOMPLETE: no JoinAccept
19:58:55.172 → 1474295: EV_TXSTART
19:59:01.609 → 1876133: EV_JOIN_TXCOMPLETE: no JoinAccept
19:59:02.539 → 1934971: EV_TXSTART
19:59:08.636 → 2315466: EV_JOIN_TXCOMPLETE: no JoinAccept
19:59:16.444 → 2801927: EV_TXSTART
19:59:22.899 → 3203765: EV_JOIN_TXCOMPLETE: no JoinAccept
19:59:23.443 → 3238192: EV_TXSTART
19:59:29.547 → 3618685: EV_JOIN_TXCOMPLETE: no JoinAccept
19:59:37.098 → 4090297: EV_TXSTART

lora_lmic_4

What conclusions do YOU come to based on that information?

1 Like

I’m quite new to LoRa, I’m using LMIC library example so that I can see it working then add my own logic.

What conclusions do YOU come to based on that information?

It sounds bit confusing to me, on TTN log (as image attached) I can see message was received with correct DeviceEUI and AppKey but no payload, I don’t understand the point when Ids has been transmitted and received why not payload?

I can see SNR, RSSI and Frequency are in working range

There is one more important thing, I only want to transmit data, but its trying to receive something, that I do not understand, but as I do not have working example I do not want to edit the code.

I received my new MKR 1310 board, I bought original TTN gateway and Arduino MKR 1310 so that I can setup things quickly and it will help me to learn quickly without any road blocks.

But MKR 1310 is behaving same as I described about Radio Node, does it mean I have some issues with my gateway? TTN indoor gateway running with version 2.0.4 firmware, in case it could be gateway how can I figure out the problem?

Because that’s the Join Request.

It’s too loud, like SHOUTING - get 5-10m and a brick wall between the gateway & device or change the antenna for a 50Ω resistor. Aim for -75dB or less.

You’ve got the device setup, the Network Server has processed the join request and told the gateway to transmit a join accept. There is no indication that the gateway did not transmit it. Everything is working up to that point. What do you conclude from that?

You would really benefit from having a good grasp of LoRaWAN basics so you know what the interactions back & forth between device & the servers are:

https://www.thethingsnetwork.org/docs/lorawan/

1 Like

I love the way you explain things, I highly appreciate your help. I will further look on it a get back.

Hi, there! I’m having the same problem of sairfan1. Does anyone get this node up un running? I’ve try all the same options stated here. and the node is stuck in EV_JOIN_TXCOMPLETE: no JoinAccept.

You need to give us more details than “I have the same problem”

Did you try the solutions suggested?

What do you see on the debug port?
What do you see on the gateway console?
What do you see on the application console?
What sketch are you using?

Details or I can only guess.

You are wright i’ll try to do the point:
Last days I’ve made some improvements, now the node get connected send valid packet only once and get stuck on OP_TXRXPEND. Now the details:

1- Hardware Lora Node v1.0 Atmega328 with RFM95W radio 915 Mhz freq.
2- Node is 300 meters away from GW, GW mounted on FM radio antenna structure at 20 meters high aprox. GW using AU915 Freq. FSB2.
3- Skecth is the well known example from arduino-lmic lib which I’m using for project building, linking and finally load to MCU; note that I’ve change the message to “Hello” on the test, and tweak some SF. Finally reading some posts in the Forum I’ll try tomorrow to calculate airtime etc with online tools and give another try tomorrow. Here the source code being used:


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

//
// For normal use, we require that you edit the sketch to replace FILLMEIN
// with values assigned by the TTN console. However, for regression tests,
// we want to be able to compile these scripts. The regression tests define
// COMPILE_REGRESSION_TEST, and in that case we define FILLMEIN to a non-
// working but innocuous value.
//
#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

// This EUI must be in little-endian format, so least-significant-byte
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]={ 0xE0, 0x07, 0xD0, 0x50, 0x00, 0x5A, 0x40, 0x0A };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}

// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8]={ 0x40, 0x9D, 0x05, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}

// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
static const u1_t PROGMEM APPKEY[16] = { 0x46, 0x1A, 0x44, 0x8F, 0xE3, 0xD4, 0xF7, 0x3A, 0xBE, 0x8C, 0xA4, 0x64, 0x14, 0xF7, 0x4B, 0x6B};
void os_getDevKey (u1_t* buf) {  memcpy_P(buf, APPKEY, 16);}

static uint8_t mydata[] = "Hello";
static osjob_t sendjob;

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

// Pin mapping
const lmic_pinmap lmic_pins = {
    .nss = 10,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 9,
    .dio = {2, 5, LMIC_UNUSED_PIN},
};

/*
const lmic_pinmap lmic_pins = {
    .nss = 10,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 9,
    .dio = {2, 5, 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();
            }
            // Disable link check validation (automatically enabled
            // during join, but because slow data rates change max TX
	    // size, we don't use it in this example.
            LMIC_setLinkCheckMode(0);
            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)"));
            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;
        /*
        || 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;
        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;
    }
}

void do_send(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, mydata, sizeof(mydata)-1, 0);
        Serial.println(F("Packet queued"));
    }
    // Next TX is scheduled after TX_COMPLETE event.
}

void setup() {
  
    Serial.begin(115200);
    Serial.println(F("Starting"));

    // LMIC init
    os_init();
    // Reset the MAC state. Session and pending data transfers will be discarded.
    LMIC_reset();
    
    LMIC.dn2Dr = DR_SF9;
    LMIC_setClockError(MAX_CLOCK_ERROR * 6 / 100);
    
    //Para au915 habilito la subbanda 2 con los 8 canales de uplink y uno de downlink
    LMIC_enableSubBand(1);
    
    // Disable link check validation
    LMIC_setLinkCheckMode(0);

    // Set data rate and transmit power (note: txpow seems to be ignored by the library)
    LMIC_setDrTxpow(DR_SF10,14);
    // Start job (sending automatically starts OTAA too)
    do_send(&sendjob);
}

void loop() {
    os_runloop_once();
}

Some logs on next post

second post
4- Serial monitor log of the last try

14:41:27.225 -> Starting
14:41:27.273 -> Packet queued
14:41:27.273 -> 2570: EV_JOINING
14:41:27.273 -> 3151: EV_TXSTART
14:41:32.751 -> 343945: EV_JOINED
14:41:32.751 -> netid: 19
14:41:32.751 -> devaddr: 260C61B1
14:41:32.751 -> AppSKey: 5C-6A-79-E9-44-11-28-55-6F-D7-01-FD-7B-76-35-B6
14:41:32.751 -> NwkSKey: D9-D9-5C-E4-B9-C5-78-D3-D8-71-C0-8A-3A-2D-E8-26
14:41:32.751 -> 345392: EV_TXSTART
14:41:38.164 -> 684203: EV_TXCOMPLETE (includes waiting for RX windows)
14:41:38.681 -> 715342: EV_TXSTART
14:47:09.374 -> OP_TXRXPEND, not sending

Resuming at the moment the node get connected send one packet and stucks, this happened once or twice a day. after sending the packet and getting stuck if I reset the node to restart from beginning has no effect and the node did not connect anymore.

maximum Info I can collect by time being.

I´ve also a JSON for the live data from gateway but it’s impossible to paste here (too long).

thanks in advance.

Mauricio

It is stuck, how long did you wait before you reset it? As your TX intervals are 330sec

I have yet to see a json too long to post.

1 Like

I’ve waited hours…

Live data log exported is >36000 chars long! i cannot post it here. But here you can see some messages with payload reception etc. if you thinks to need some particular messages I can look and post them.

"rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01GR1WA6RCVN7F8T2XSCJYX3W0"
      ],
      "uplink_message": {
        "session_key_id": "AYYDxQXEU1Go0iUpHnqWag==",
        "f_port": 1,
        "frm_payload": "T9dbqoQ=",
        "rx_metadata": [
          {
            "gateway_ids": {
              "gateway_id": "eui-553232ff01d005c0",
              "eui": "553232FF01D005C0"
            },
            "time": "2023-01-30T17:41:33.025675Z",
            "timestamp": 4119273076,
            "rssi": -92,
            "channel_rssi": -92,
            "snr": -1,
            "location": {
              "latitude": -35.9152500363007,
              "longitude": -64.2932716012001,
              "altitude": 33,
              "source": "SOURCE_REGISTRY"
            },
            "uplink_token": "CiIKIAoUZXVpLTU1MzIzMmZmMDFkMDA1YzASCFUyMv8B0AXAEPS8nKwPGgwIzoLgngYQ1JLjnwIgoOq7vvHuAw==",
            "channel_index": 5,
            "received_at": "2023-01-30T17:41:34.481804132Z"
          }
        ],
        "settings": {
          "data_rate": {
            "lora": {
              "bandwidth": 125000,
              "spreading_factor": 10,
              "coding_rate": "4/5"
            }
          },
          "frequency": "917800000",
          "timestamp": 4119273076,
          "time": "2023-01-30T17:41:33.025675Z"
        },
        "received_at": "2023-01-30T17:41:34.604454944Z",
        "consumed_airtime": "0.329728s",
        "network_ids": {
          "net_id": "000013",
          "tenant_id": "ttn",
          "cluster_id": "nam1",
          "cluster_address": "nam1.cloud.thethings.network"
        }
      }
    },
    "correlation_ids": [
      "gs:conn:01GR1F2184287JNJ3471GDB546",
      "gs:up:host:01GR1F21CAWB2WANAYDDQYAX7E",
      "gs:uplink:01GR1WA6RB672N317W83XFNG4Q",
      "ns:uplink:01GR1WA6RCRWYEYTAEWD4S8CA3",
      "rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01GR1WA6RCVN7F8T2XSCJYX3W0"
    ],
    "origin": "ip-10-101-13-20.us-west-1.compute.internal",
    "context": {
      "tenant-id": "CgN0dG4="
    },
    "visibility": {
      "rights": [
        "RIGHT_APPLICATION_TRAFFIC_READ"
      ]
    },
    "unique_id": "01GR1WA6YXH56VKG6FJYSB1BD0"
  },
  {
    "name": "as.up.data.forward",
    "time": "2023-01-30T17:41:34.812526346Z",
    "identifiers": [
      {
        "device_ids": {
          "device_id": "eui-70b3d57ed0059d40",
          "application_ids": {
            "application_id": "los-leandros"
          },
          "dev_eui": "70B3D57ED0059D40",
          "join_eui": "0A405A0050D007E0",
          "dev_addr": "260C61B1"
        }
      }
    ],
    "data": {
      "@type": "type.googleapis.com/ttn.lorawan.v3.ApplicationUp",
      "end_device_ids": {
        "device_id": "eui-70b3d57ed0059d40",
        "application_ids": {
          "application_id": "los-leandros"
        },
        "dev_eui": "70B3D57ED0059D40",
        "join_eui": "0A405A0050D007E0",
        "dev_addr": "260C61B1"
      },
      "correlation_ids": [
        "as:up:01GR1WA6YSC4RQ3328ZRDSD9F6",
        "gs:conn:01GR1F2184287JNJ3471GDB546",
        "gs:up:host:01GR1F21CAWB2WANAYDDQYAX7E",
        "gs:uplink:01GR1WA6RB672N317W83XFNG4Q",
        "ns:uplink:01GR1WA6RCRWYEYTAEWD4S8CA3",
        "rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01GR1WA6RCVN7F8T2XSCJYX3W0",
        "rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01GR1WA6YRVX6RHQ05ZVSRJXZD"
      ],
      "received_at": "2023-01-30T17:41:34.808294901Z",
      "uplink_message": {
        "session_key_id": "AYYDxQXEU1Go0iUpHnqWag==",
        "f_port": 1,
        "frm_payload": "SGVsbG8=",
        "decoded_payload": {
          "bytes": [
            72,
            101,
            108,
            108,
            111
          ]
        },
        "rx_metadata": [
          {
            "gateway_ids": {
              "gateway_id": "eui-553232ff01d005c0",
              "eui": "553232FF01D005C0"
            },
            "time": "2023-01-30T17:41:33.025675Z",
            "timestamp": 4119273076,
            "rssi": -92,
            "channel_rssi": -92,
            "snr": -1,
            "location": {
              "latitude": -35.9152500363007,
              "longitude": -64.2932716012001,
              "altitude": 33,
              "source": "SOURCE_REGISTRY"
            },
            "uplink_token": "CiIKIAoUZXVpLTU1MzIzMmZmMDFkMDA1YzASCFUyMv8B0AXAEPS8nKwPGgwIzoLgngYQ1JLjnwIgoOq7vvHuAw==",
            "channel_index": 5,
            "received_at": "2023-01-30T17:41:34.481804132Z"
          }
        ],
        "settings": {
          "data_rate": {
            "lora": {
              "bandwidth": 125000,
              "spreading_factor": 10,
              "coding_rate": "4/5"
            }
          },
          "frequency": "917800000",
          "timestamp": 4119273076,
          "time": "2023-01-30T17:41:33.025675Z"
        },
        "received_at": "2023-01-30T17:41:34.604454944Z",
        "consumed_airtime": "0.329728s",
        "network_ids": {
          "net_id": "000013",
          "tenant_id": "ttn",
          "cluster_id": "nam1",
          "cluster_address": "nam1.cloud.thethings.network"
        }
      }
    },
    "correlation_ids": [
      "as:up:01GR1WA6YSC4RQ3328ZRDSD9F6",
      "gs:conn:01GR1F2184287JNJ3471GDB546",
      "gs:up:host:01GR1F21CAWB2WANAYDDQYAX7E",
      "gs:uplink:01GR1WA6RB672N317W83XFNG4Q",
      "ns:uplink:01GR1WA6RCRWYEYTAEWD4S8CA3",
      "rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01GR1WA6RCVN7F8T2XSCJYX3W0",
      "rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01GR1WA6YRVX6RHQ05ZVSRJXZD"
    ],

Here you can see part of the log. the best I can do.

thanks in advance
mauricio