I don’t think the police or the courts care, and you end up with an asymmetric radio system and you end up needing a lot of them for your devices. Just use a normal stubby antenna or piece of wire.
Where does it suggest that then?
It looks like in Sandeep’s porting of LMn, both the
APP_KEY
andNWK_KEY
are already passedLoRaMacMibSetRequestConfirm()
, which seems to eventually set the secure element keys defined in the file you linked.
Meh! Layers of code to drill through - good spot.
Maybe you could try RadioLib - people have got the Pico working, I have a Pico + radio combo on my bench (somewhere) to test it for the official RadioLib docs so there will be some sorting out as we don’t have it gift wrapped just yet but it should be simpler than unravelling the abandonware that is the port - looks like someone got a Pico when they first came out, did the port, realised that battery life was going to be poor and just left it on the 3 year old release of LoRaMAC-node.
Radiolib really good! I’ll give it a try. Defentitely seems like a better solution compared to the port as you said.
Out of interest, what MCUs would you suggest that are more power efficient?
Out of interest, what MCUs would you suggest that are more power efficient?
Not so much efficiency, it’s more about the sleep current which for the Pico is in mA’s and for pretty much everything else is in uA.
For RadioLib which needs more Flash than AVR normally offers, I’d go with SAMD or STM32. ESP32 does do low power sleep - which is what a LW device normally spends a lot of time doing - but has a longer restart time from deep sleep.
Ok I’ve basically just spliced together bits from the Arduino OTAA example and tweaked it to work with the Pico. Here’s what Ive got so far:
// main.cpp
#include <string.h>
#include <stdio.h>
#include <pico/stdlib.h>
#include "tusb.h"
#include "config.h"
int uplinkDelay = 3600; // 1 hour
int main() {
// Init serial and wait for a connection:
stdio_init_all();
while (!tud_cdc_connected()) {
tight_loop_contents();
}
printf("Radiolib LoRaWAN example for Raspberry Pi Pico\n");
// Initialise the radio
int16_t state = radio.begin();
debug(state != RADIOLIB_ERR_NONE, "Initialise radio failed", state, true);
// Initialise the LoRaWAN node and try to join the network
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
printf("Joining LoRaWAN network...\n");
state = node.activateOTAA();
debug(state != RADIOLIB_ERR_NONE, "Join failed", state, true);
printf("Joined LoRaWAN network successfully!\n");
while(true) {
// Send uplink every uplinkDelay seconds
printf("Sending uplink...\n");
uint8_t value1 = radio.random(100);
uint16_t value2 = radio.random(2000);
uint8_t uplinkPayload[3];
uplinkPayload[0] = value1;
uplinkPayload[1] = highByte(value2);
uplinkPayload[2] = lowByte(value2);
int16_t state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), "Error in sendReceive", state, false);
printf("Uplink complete, next in ");
printf("%d", uplinkDelay);
printf(" seconds. \n");
// Sleep until next uplink
sleep_ms(uplinkDelay * 1000UL);
}
}
//config.h
#pragma once
#include <RadioLib.h>
#include "PicoHal.h"
// Pin definitions:
#define SPI_PORT spi0
#define SPI_MISO 16
#define SPI_MOSI 19
#define SPI_SCK 18
#define RFM_NSS 8
#define RFM_RST 9
#define RFM_DIO0 7
#define RFM_DIO1 10
// LoRaWAN keys:
#define RADIOLIB_LORAWAN_JOIN_EUI 0x0000000000000000
#ifndef RADIOLIB_LORAWAN_DEV_EUI
#define RADIOLIB_LORAWAN_DEV_EUI 0x70B3D57ED0069153
#endif
#ifndef RADIOLIB_LORAWAN_APP_KEY
#define RADIOLIB_LORAWAN_APP_KEY 0xE1, 0x03, 0x8F, 0x0B, 0xF6, 0x3D, 0x80, 0x80, 0x3D, 0x3B, 0xC6, 0x15, 0xA5, 0x24, 0x58, 0xD4
#endif
#ifndef RADIOLIB_LORAWAN_NWK_KEY
#define RADIOLIB_LORAWAN_NWK_KEY 0xC8, 0x7F, 0xC4, 0xFA, 0xF7, 0xD6, 0xFB, 0x72, 0x3E, 0x94, 0x0A, 0x7A, 0x33, 0xE0, 0x46, 0xC7
#endif
// Region and sub-band:
const LoRaWANBand_t Region = AU915;
const uint8_t subBand = 2; // TTN uses FSB 2 in Australia so I'm assuming 2 here
// Create the hardware abstraction layer:
PicoHal* hal = new PicoHal(SPI_PORT, SPI_MISO, SPI_MOSI, SPI_SCK);
// Create the radio module:
SX1276 radio = new Module(hal, RFM_NSS, RFM_DIO0, RFM_RST, RFM_DIO1);
// Init the lorawan keys:
uint64_t joinEUI = RADIOLIB_LORAWAN_JOIN_EUI;
uint64_t devEUI = RADIOLIB_LORAWAN_DEV_EUI;
uint8_t appKey[] = { RADIOLIB_LORAWAN_APP_KEY };
uint8_t nwkKey[] = { RADIOLIB_LORAWAN_NWK_KEY };
// create the LoRaWAN node
LoRaWANNode node(&radio, &Region, subBand);
// Error code helpers
// I pasted this from arduino example and changed a few things to make it work with the Pico. Probably not the most elegant but it works for now.
const char* stateDecode(const int16_t result) {
switch (result) {
case RADIOLIB_ERR_NONE:
return "ERR_NONE";
case RADIOLIB_ERR_CHIP_NOT_FOUND:
return "ERR_CHIP_NOT_FOUND";
case RADIOLIB_ERR_PACKET_TOO_LONG:
return "ERR_PACKET_TOO_LONG";
case RADIOLIB_ERR_RX_TIMEOUT:
return "ERR_RX_TIMEOUT";
case RADIOLIB_ERR_CRC_MISMATCH:
return "ERR_CRC_MISMATCH";
case RADIOLIB_ERR_INVALID_BANDWIDTH:
return "ERR_INVALID_BANDWIDTH";
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
return "ERR_INVALID_SPREADING_FACTOR";
case RADIOLIB_ERR_INVALID_CODING_RATE:
return "ERR_INVALID_CODING_RATE";
case RADIOLIB_ERR_INVALID_FREQUENCY:
return "ERR_INVALID_FREQUENCY";
case RADIOLIB_ERR_INVALID_OUTPUT_POWER:
return "ERR_INVALID_OUTPUT_POWER";
case RADIOLIB_ERR_NETWORK_NOT_JOINED:
return "RADIOLIB_ERR_NETWORK_NOT_JOINED";
case RADIOLIB_ERR_DOWNLINK_MALFORMED:
return "RADIOLIB_ERR_DOWNLINK_MALFORMED";
case RADIOLIB_ERR_INVALID_REVISION:
return "RADIOLIB_ERR_INVALID_REVISION";
case RADIOLIB_ERR_INVALID_PORT:
return "RADIOLIB_ERR_INVALID_PORT";
case RADIOLIB_ERR_NO_RX_WINDOW:
return "RADIOLIB_ERR_NO_RX_WINDOW";
case RADIOLIB_ERR_INVALID_CID:
return "RADIOLIB_ERR_INVALID_CID";
case RADIOLIB_ERR_UPLINK_UNAVAILABLE:
return "RADIOLIB_ERR_UPLINK_UNAVAILABLE";
case RADIOLIB_ERR_COMMAND_QUEUE_FULL:
return "RADIOLIB_ERR_COMMAND_QUEUE_FULL";
case RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND:
return "RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND";
case RADIOLIB_ERR_JOIN_NONCE_INVALID:
return "RADIOLIB_ERR_JOIN_NONCE_INVALID";
case RADIOLIB_ERR_N_FCNT_DOWN_INVALID:
return "RADIOLIB_ERR_N_FCNT_DOWN_INVALID";
case RADIOLIB_ERR_A_FCNT_DOWN_INVALID:
return "RADIOLIB_ERR_A_FCNT_DOWN_INVALID";
case RADIOLIB_ERR_DWELL_TIME_EXCEEDED:
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
case RADIOLIB_LORAWAN_NO_DOWNLINK:
return "RADIOLIB_LORAWAN_NO_DOWNLINK";
case RADIOLIB_LORAWAN_SESSION_RESTORED:
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
case RADIOLIB_LORAWAN_NEW_SESSION:
return "RADIOLIB_LORAWAN_NEW_SESSION";
case RADIOLIB_LORAWAN_NONCES_DISCARDED:
return "RADIOLIB_LORAWAN_NONCES_DISCARDED";
case RADIOLIB_LORAWAN_SESSION_DISCARDED:
return "RADIOLIB_LORAWAN_SESSION_DISCARDED";
}
return "See https://jgromes.github.io/RadioLib/group__status__codes.html";
}
// helper function to display any issues
void debug(bool failed, const char* message, int state, bool halt) {
if(failed) {
printf("%s", message);
printf(" - ");
printf("%s", stateDecode(state));
printf(" (");
printf("%d", state);
printf(") \n");
while(halt) { sleep_ms(1); }
}
}
// helper function to display a byte array
void arrayDump(uint8_t *buffer, uint16_t len) {
for(uint16_t c = 0; c < len; c++) {
char b = buffer[c];
if(b < 0x10) { printf("0"); }
printf("%d",b);
}
printf(" ");
}
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
The library seems really nice but I’ve got a new problem - After sending a join request, it looks like TTN rejects it and and the error “Devnonce is too small” is listed in the console. This is with version 1.1.0 and RP001 revision A.
I’ve still got a few things to try and it seems like a fairly common problem so I I’ll do some searching on the forum and the github discussions. But I’m guessing I should start a new thread with this?
After sending a join request, it looks like TTN rejects it and and the error “Devnonce is too small” is listed in the console. This is with version 1.1.0 and RP001 revision A.
Read the notes in the starter - they are totally comphrehensive written by @AwesomeDude. You will in fact be the first person to ask about this because, well, the notes are so awesome.
Simpler to carry on with this thread.