Dragino+pi3 node transmission problems


#8

Q ’ how do you plan to power this setup… battery / solar or a combination ?

The less data you transmit, the longer your setup will work on a battery, thats why its important that you processor goes to ‘sleep’ in between transmissions.

Problem is… how and when do you wake up the mcu (hence start using a lot more energy+transmit data)
So you figured that out yet, ultra sound /weight / light , how do you trigger a transmission ?

I don’t know how often these ‘chicadees’ will enter your setup, but its probably better to think of a system that collect data during a certain time , format that data and transmits in a clever packet once an hour/day whatever and not everytime a bird comes in.
for that to work you’ll need a 'preprocessor+some fram+RTC


(Arjan) #9

Oh, actually, the image shows two packets. Also, they might be anyone’s LoRa transmission if they’re not yours. Given the first bytes, 0xDA985AA0 and 0x66A58D15 I don’t think these are LoRaWAN uplinks. The CRC_BAD indicates problems also. Anyway, we need to see the code, and know what you see in TTN Console.

(Make sure to keep at least a few meters between node and gateway.)


(Chickadee) #10

We registered our gateway, not the node. In order to see the Decrypted message does each individual node need to be registered to the TTN console?

We see nothing, so far we have not gotten any traffic from the gateway, even though we have been logging packets from the nodes. Leading me to believe its because the packets being sent using this repo are not using the LoRaWAN protocol.

From our last development meeting we assumed that the rpi-lora-tranceiver repository was the reason we were not able to see any traffic on the TTN. Leading me to shift to using a new repository for our nodes. I am somewhat positive that this repository: lmic-rpi-lora-gps-hat will allow us to register our nodes and send out LoRaWAN protocols to our GW. Have you ever worked with this repository?


(Chickadee) #11

@arjanvanb

Thank you for these suggestions! I totally agree with them and will present them to the group. Really appreciate the help.


(Chickadee) #12

@BoRRoZ

For right now we are going to use a 12V battery to power these setups. We plan to only have them collecting RFID tags from sunrise to sunset using a daylight sensor. We are considering implementing a solar trickle charger that will use the power it collects to slowly recharge each one of our batteries. Using the solar trickle charger will not keep each battery charged continuously but it will extend the time in which our setup will be running.

We have been discussing this for some time now. The professor who initially brought us in to work on this project wants the updates to be as fast as possible, ideally instantaneous. We explained to him that in order to achieve that it comes down to the power supply we choose to implement. With the batteries we are using we will be able to get 7 to 8 days running this setup for 12 hours a day at idle. That being said we are still trying to find the best way to send the data while still being conscious of our battery consumption. We are leaning towards logging each RFID tag into a file that we only transmit a few times each day. Or possibly every hour. That is still to be determined.


(Chickadee) #13

Although I do have a general question. When we started out this project we were planning to use raspberry pi 3’s for our host device on each node. Once we began considering power consumption it became obvious that the raspberry pi zero W is a better option for us to go with.

although someone just brought to my attention that the raspberry Pi Zero W is single core and will not be capable of running multiple programs at once. Is this true? I dont believe that it is from what I have been reading on other forms but can anyone confirm if this is true or not.

The reason this would be a problem is that in order to use our current setup we need the LoRa program (whatever program that will be responsible for transmitting our data) and the Master Code program ( the main program that will be running to control the RFID reader and collect the data from the read tags to be pushed to a log file for transmission) running at the same time.


(Arjan) #14

Yes.

Without registering the devices (and an application for the devices) you should still see the packets in the gateway’s Traffic page in TTN Console though; you should even see packets for non-TTN users.

But given the CRC_BAD errors, I guess you should indeed focus on the gateway. I’ve not worked with your hardware. (And again: keep a few meters, say 10, between nodes and gateway.) Maybe post a longer log?

The LoRaWAN software on the device/node does not need to run all the time, but really only when it needs to transmit something. (It’s not some WiFi-like connection with the gateway that it needs to keep running.)

You might also run into Limitations: data rate, packet size, 30 seconds uplink and 10 messages downlink per day Fair Access Policy then.

Oh, and show us some code!


The hard RAK831 cafe part 3
(Chickadee) #15

This is true, but is it still possible to run both at the same time? We plan to only activate our LoRa board a few times each day in order to save power, but when we start transmitting the LoRa packets will we be able to continue reading tags with our “master code” program running simultaneously alongside the LoRa program?


(Arjan) #16

Actually I wonder if you even need a Pi. Maybe some ESP suffices already, but that depends on the software you need to read that RFID tag and to get the weight.


(Chickadee) #17

Its just a simple python program. Same thing for the Weight sensor. But right now we are just using the RFID sensor until we are able to get everything deployed and verify that its a functioning system. Once that happens we will calibrate and begin reprogramming the weight sensor to start functioning.


(Chickadee) #19
Click to see the full code
#include <string>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>

#include <sys/ioctl.h>

#include <wiringPi.h>
#include <wiringPiSPI.h>


// #############################################
// #############################################

#define REG_FIFO                    0x00
#define REG_OPMODE                  0x01
#define REG_FIFO_ADDR_PTR           0x0D
#define REG_FIFO_TX_BASE_AD         0x0E
#define REG_FIFO_RX_BASE_AD         0x0F
#define REG_RX_NB_BYTES             0x13
#define REG_FIFO_RX_CURRENT_ADDR    0x10
#define REG_IRQ_FLAGS               0x12
#define REG_DIO_MAPPING_1           0x40
#define REG_DIO_MAPPING_2           0x41
#define REG_MODEM_CONFIG            0x1D
#define REG_MODEM_CONFIG2           0x1E
#define REG_MODEM_CONFIG3           0x26
#define REG_SYMB_TIMEOUT_LSB  		0x1F
#define REG_PKT_SNR_VALUE			0x19
#define REG_PAYLOAD_LENGTH          0x22
#define REG_IRQ_FLAGS_MASK          0x11
#define REG_MAX_PAYLOAD_LENGTH 		0x23
#define REG_HOP_PERIOD              0x24
#define REG_SYNC_WORD				0x39
#define REG_VERSION	  				0x42

#define PAYLOAD_LENGTH              0x40

// LOW NOISE AMPLIFIER
#define REG_LNA                     0x0C
#define LNA_MAX_GAIN                0x23
#define LNA_OFF_GAIN                0x00
#define LNA_LOW_GAIN		    	0x20

#define RegDioMapping1                             0x40 // common
#define RegDioMapping2                             0x41 // common

#define RegPaConfig                                0x09 // common
#define RegPaRamp                                  0x0A // common
#define RegPaDac                                   0x5A // common

#define SX72_MC2_FSK                0x00
#define SX72_MC2_SF7                0x70
#define SX72_MC2_SF8                0x80
#define SX72_MC2_SF9                0x90
#define SX72_MC2_SF10               0xA0
#define SX72_MC2_SF11               0xB0
#define SX72_MC2_SF12               0xC0

#define SX72_MC1_LOW_DATA_RATE_OPTIMIZE  0x01 // mandated for SF11 and SF12

// sx1276 RegModemConfig1
#define SX1276_MC1_BW_125                0x70
#define SX1276_MC1_BW_250                0x80
#define SX1276_MC1_BW_500                0x90
#define SX1276_MC1_CR_4_5            0x02
#define SX1276_MC1_CR_4_6            0x04
#define SX1276_MC1_CR_4_7            0x06
#define SX1276_MC1_CR_4_8            0x08

#define SX1276_MC1_IMPLICIT_HEADER_MODE_ON    0x01

// sx1276 RegModemConfig2
#define SX1276_MC2_RX_PAYLOAD_CRCON        0x04

// sx1276 RegModemConfig3
#define SX1276_MC3_LOW_DATA_RATE_OPTIMIZE  0x08
#define SX1276_MC3_AGCAUTO                 0x04

// preamble for lora networks (nibbles swapped)
#define LORA_MAC_PREAMBLE                  0x34

#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1 0x0A
#ifdef LMIC_SX1276
#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x70
#elif LMIC_SX1272
#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74
#endif

// FRF
#define        REG_FRF_MSB              0x06
#define        REG_FRF_MID              0x07
#define        REG_FRF_LSB              0x08

#define        FRF_MSB                  0xD9 // 868.1 Mhz
#define        FRF_MID                  0x06
#define        FRF_LSB                  0x66

// ----------------------------------------
// Constants for radio registers
#define OPMODE_LORA      0x80
#define OPMODE_MASK      0x07
#define OPMODE_SLEEP     0x00
#define OPMODE_STANDBY   0x01
#define OPMODE_FSTX      0x02
#define OPMODE_TX        0x03
#define OPMODE_FSRX      0x04
#define OPMODE_RX        0x05
#define OPMODE_RX_SINGLE 0x06
#define OPMODE_CAD       0x07

// ----------------------------------------
// Bits masking the corresponding IRQs from the radio
#define IRQ_LORA_RXTOUT_MASK 0x80
#define IRQ_LORA_RXDONE_MASK 0x40
#define IRQ_LORA_CRCERR_MASK 0x20
#define IRQ_LORA_HEADER_MASK 0x10
#define IRQ_LORA_TXDONE_MASK 0x08
#define IRQ_LORA_CDDONE_MASK 0x04
#define IRQ_LORA_FHSSCH_MASK 0x02
#define IRQ_LORA_CDDETD_MASK 0x01

// DIO function mappings                D0D1D2D3
#define MAP_DIO0_LORA_RXDONE   0x00  // 00------
#define MAP_DIO0_LORA_TXDONE   0x40  // 01------
#define MAP_DIO1_LORA_RXTOUT   0x00  // --00----
#define MAP_DIO1_LORA_NOP      0x30  // --11----
#define MAP_DIO2_LORA_NOP      0xC0  // ----11--

// #############################################
// #############################################
//
typedef bool boolean;
typedef unsigned char byte;

static const int CHANNEL = 0;

char message[256];

bool sx1272 = true;

byte receivedbytes;

enum sf_t { SF7=7, SF8, SF9, SF10, SF11, SF12 };

/*******************************************************************************
 *
 * Configure these values!
 *
 *******************************************************************************/

// SX1272 - Raspberry connections
int ssPin = 6;
int dio0  = 7;
int RST   = 0;

// Set spreading factor (SF7 - SF12)
sf_t sf = SF7;

// Set center frequency
uint32_t  freq = 868100000; // in Mhz! (868.1)

byte hello[32] = "HELLO";

void die(const char *s)
{
    perror(s);
    exit(1);
}

void selectreceiver()
{
    digitalWrite(ssPin, LOW);
}

void unselectreceiver()
{
    digitalWrite(ssPin, HIGH);
}

byte readReg(byte addr)
{
    unsigned char spibuf[2];

    selectreceiver();
    spibuf[0] = addr & 0x7F;
    spibuf[1] = 0x00;
    wiringPiSPIDataRW(CHANNEL, spibuf, 2);
    unselectreceiver();

    return spibuf[1];
}

void writeReg(byte addr, byte value)
{
    unsigned char spibuf[2];

    spibuf[0] = addr | 0x80;
    spibuf[1] = value;
    selectreceiver();
    wiringPiSPIDataRW(CHANNEL, spibuf, 2);

    unselectreceiver();
}

static void opmode (uint8_t mode) {
    writeReg(REG_OPMODE, (readReg(REG_OPMODE) & ~OPMODE_MASK) | mode);
}

static void opmodeLora() {
    uint8_t u = OPMODE_LORA;
    if (sx1272 == false)
        u |= 0x8;   // TBD: sx1276 high freq
    writeReg(REG_OPMODE, u);
}


void SetupLoRa()
{
    
    digitalWrite(RST, HIGH);
    delay(100);
    digitalWrite(RST, LOW);
    delay(100);

    byte version = readReg(REG_VERSION);

    if (version == 0x22) {
        // sx1272
        printf("SX1272 detected, starting.\n");
        sx1272 = true;
    } else {
        // sx1276?
        digitalWrite(RST, LOW);
        delay(100);
        digitalWrite(RST, HIGH);
        delay(100);
        version = readReg(REG_VERSION);
        if (version == 0x12) {
            // sx1276
            printf("SX1276 detected, starting.\n");
            sx1272 = false;
        } else {
            printf("Unrecognized transceiver.\n");
            //printf("Version: 0x%x\n",version);
            exit(1);
        }
    }

    opmode(OPMODE_SLEEP);

    // set frequency
    uint64_t frf = ((uint64_t)freq << 19) / 32000000;
    writeReg(REG_FRF_MSB, (uint8_t)(frf>>16) );
    writeReg(REG_FRF_MID, (uint8_t)(frf>> 8) );
    writeReg(REG_FRF_LSB, (uint8_t)(frf>> 0) );

    writeReg(REG_SYNC_WORD, 0x34); // LoRaWAN public sync word

    if (sx1272) {
        if (sf == SF11 || sf == SF12) {
            writeReg(REG_MODEM_CONFIG,0x0B);
        } else {
            writeReg(REG_MODEM_CONFIG,0x0A);
        }
        writeReg(REG_MODEM_CONFIG2,(sf<<4) | 0x04);
    } else {
        if (sf == SF11 || sf == SF12) {
            writeReg(REG_MODEM_CONFIG3,0x0C);
        } else {
            writeReg(REG_MODEM_CONFIG3,0x04);
        }
        writeReg(REG_MODEM_CONFIG,0x72);
        writeReg(REG_MODEM_CONFIG2,(sf<<4) | 0x04);
    }

    if (sf == SF10 || sf == SF11 || sf == SF12) {
        writeReg(REG_SYMB_TIMEOUT_LSB,0x05);
    } else {
        writeReg(REG_SYMB_TIMEOUT_LSB,0x08);
    }
    writeReg(REG_MAX_PAYLOAD_LENGTH,0x80);
    writeReg(REG_PAYLOAD_LENGTH,PAYLOAD_LENGTH);
    writeReg(REG_HOP_PERIOD,0xFF);
    writeReg(REG_FIFO_ADDR_PTR, readReg(REG_FIFO_RX_BASE_AD));

    writeReg(REG_LNA, LNA_MAX_GAIN);

}

boolean receive(char *payload) {
    // clear rxDone
    writeReg(REG_IRQ_FLAGS, 0x40);

    int irqflags = readReg(REG_IRQ_FLAGS);

    //  payload crc: 0x20
    if((irqflags & 0x20) == 0x20)
    {
        printf("CRC error\n");
        writeReg(REG_IRQ_FLAGS, 0x20);
        return false;
    } else {

        byte currentAddr = readReg(REG_FIFO_RX_CURRENT_ADDR);
        byte receivedCount = readReg(REG_RX_NB_BYTES);
        receivedbytes = receivedCount;

        writeReg(REG_FIFO_ADDR_PTR, currentAddr);

        for(int i = 0; i < receivedCount; i++)
        {
            payload[i] = (char)readReg(REG_FIFO);
        }
    }
    return true;
}

void receivepacket() {

    long int SNR;
    int rssicorr;

    if(digitalRead(dio0) == 1)
    {
        if(receive(message)) {
            byte value = readReg(REG_PKT_SNR_VALUE);
            if( value & 0x80 ) // The SNR sign bit is 1
            {
                // Invert and divide by 4
                value = ( ( ~value + 1 ) & 0xFF ) >> 2;
                SNR = -value;
            }
            else
            {
                // Divide by 4
                SNR = ( value & 0xFF ) >> 2;
            }
            
            if (sx1272) {
                rssicorr = 139;
            } else {
                rssicorr = 157;
            }

            printf("Packet RSSI: %d, ", readReg(0x1A)-rssicorr);
            printf("RSSI: %d, ", readReg(0x1B)-rssicorr);
            printf("SNR: %li, ", SNR);
            printf("Length: %i", (int)receivedbytes);
            printf("\n");
            printf("Payload: %s\n", message);

        } // received a message

    } // dio0=1
}

static void configPower (int8_t pw) {
    if (sx1272 == false) {
        // no boost used for now
        if(pw >= 17) {
            pw = 15;
        } else if(pw < 2) {
            pw = 2;
        }
        // check board type for BOOST pin
        writeReg(RegPaConfig, (uint8_t)(0x80|(pw&0xf)));
        writeReg(RegPaDac, readReg(RegPaDac)|0x4);

    } else {
        // set PA config (2-17 dBm using PA_BOOST)
        if(pw > 17) {
            pw = 17;
        } else if(pw < 2) {
            pw = 2;
        }
        writeReg(RegPaConfig, (uint8_t)(0x80|(pw-2)));
    }
}


static void writeBuf(byte addr, byte *value, byte len) {                                                       
    unsigned char spibuf[256];                                                                          
    spibuf[0] = addr | 0x80;                                                                            
    for (int i = 0; i < len; i++) {                                                                         
        spibuf[i + 1] = value[i];                                                                       
    }                                                                                                   
    selectreceiver();                                                                                   
    wiringPiSPIDataRW(CHANNEL, spibuf, len + 1);                                                        
    unselectreceiver();                                                                                 
}

void txlora(byte *frame, byte datalen) {

    // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
    writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP);
    // clear all radio IRQ flags
    writeReg(REG_IRQ_FLAGS, 0xFF);
    // mask all IRQs but TxDone
    writeReg(REG_IRQ_FLAGS_MASK, ~IRQ_LORA_TXDONE_MASK);

    // initialize the payload size and address pointers
    writeReg(REG_FIFO_TX_BASE_AD, 0x00);
    writeReg(REG_FIFO_ADDR_PTR, 0x00);
    writeReg(REG_PAYLOAD_LENGTH, datalen);

    // download buffer to the radio FIFO
    writeBuf(REG_FIFO, frame, datalen);
    // now we actually start the transmission
    opmode(OPMODE_TX);

    printf("send: %s\n", frame);
}

int main (int argc, char *argv[]) {

    if (argc < 2) {
        printf ("Usage: argv[0] sender|rec [message]\n");
        exit(1);
    }

    wiringPiSetup () ;
    pinMode(ssPin, OUTPUT);
    pinMode(dio0, INPUT);
    pinMode(RST, OUTPUT);

    wiringPiSPISetup(CHANNEL, 500000);

    SetupLoRa();

    if (!strcmp("sender", argv[1])) {
        opmodeLora();
        // enter standby mode (required for FIFO loading))
        opmode(OPMODE_STANDBY);

        writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec

        configPower(23);

        printf("Send packets at SF%i on %.6lf Mhz.\n", sf,(double)freq/1000000);
        printf("------------------\n");

        if (argc > 2)
            strncpy((char *)hello, argv[2], sizeof(hello));

        while(1) {
            txlora(hello, strlen((char *)hello));
            delay(5000);
        }
    } else {

        // radio init
        opmodeLora();
        opmode(OPMODE_STANDBY);
        opmode(OPMODE_RX);
        printf("Listening at SF%i on %.6lf Mhz.\n", sf,(double)freq/1000000);
        printf("------------------\n");
        while(1) {
            receivepacket(); 
            delay(1);
        }

    }

    return (0);
}

I attached the entire code file but I am pretty sure this is the only part you need to see. Its the portion of the code where you can change what the payload is, set the freq, SF, and channel.

typedef bool boolean;
typedef unsigned char byte;

static const int CHANNEL = 0;

char message[256];

bool sx1272 = true;

byte receivedbytes;

enum sf_t { SF7=7, SF8, SF9, SF10, SF11, SF12 };

/*******************************************************************************
 *
 * Configure these values!
 *
 *******************************************************************************/

// SX1272 - Raspberry connections
int ssPin = 6;
int dio0  = 7;
int RST   = 0;

// Set spreading factor (SF7 - SF12)
sf_t sf = SF7;

// Set center frequency
uint32_t  freq = 915100000; // in Mhz! (868.1)

byte hello[32] = "HELLO";

Is this helpful?


(Arjan) #20

…so you’re still using some peer-to-peer bare LoRa software for the device?

You’ll need some LoRaWAN library for the device/node, in which you will also need to configure the device’s DevEUI, AppEUI and AppKey (for OTAA) or DevAddr, NwkSKey and AppSKey (for ABP).

Ah, you already wrote that:

This might help, but I’ve not used it: https://github.com/wklenk/lmic-rpi-lora-gps-hat

(Oh, you mentioned that one too :joy: Time to get away from the keyboard for me. So, yes: try that!)


(Chickadee) #21

Haha no worries. We are meeting tonight to work on it as a group, hopefully We are able to make some progress.


(Chickadee) #22

Successes! we were able to receive packets on the TTN console! Now that we have gotten packets sent to us from one of our nodes. We are attempting to change the payload to unique values.
The%20Things%20Network%20Console


(Arjan) #23

Nice. Your next problem: you’ve got the AppEUI in the wrong order. And you might have made the same mistake for the DevEUI. You’re seeing OTAA Join Requests, but TTN does not recognize these values and does not create an OTAA Join Accept.

See Hex, lsb or msb? (When indeed using LMIC, scroll to my answer at the end.)


(Chickadee) #24

image

@arjanvanb

You were right about the keys being switched around. We got those fixed and have now successfully got a join accepted. The nodes have been seen by the TTN. But we are not able to see any decoded data. How do we actually see the data?


(Arjan) #25

What are you seeing?

When an OTAA Join succeeds then you’re sure that the configuration is okay. Next, if the device is transmitting any data, and one or more gateways receive that, then you should see the decrypted application data in both the application’s Data page and the specific device’s Data page in TTN Console. You should also see the full LoRaWAN packet in the gateway’s Traffic page (if one has access to that, which you do), which includes the encrypted application payload (plus the LoRaWAN header, the MIC and possibly some MAC commands, all shown as a single sequence of hexadecimal values).

So, is the device sending any uplink at all, after the join?

If you define a Decoder in the application’s Payload Format, and if that does not throw any errors, then TTN can also decode the application data for you, and show that on the same Data pages.

Do you have any Decoder defined? (Not mandatory, of course. You can also decode in your own application, fed by the MQTT Data API or some integration.)


(Chickadee) #26

We have not defined a decoder, no. We are looking at the ‘integration’ tab though. From what we can gather, if we were to setup an http integration then we would be able to send the (decryped)data directly to wherever we determine, right? Does the decryption only happen if we define a decoder in the applications payload format or through our own application. I guess what I am asking is if we decide to setup an http integration, would that handle the decryption for us or would we need to define it in the payload as well?

2019-02-12%2019_46_23-The%20Things%20Network%20Console

this is an example of an up-link we received after the join. We also noticed our RSSI is very low. This might be because of the building we are testing in. This particular packet was sent from a node located approximately 30 to 40 meters away. Although we are right next to a massive cluster computer, which I assume would probably interfere with the signal strength. We are planning to take our devices outside for a better testing environment.


(Arjan) #27

In your current setup, TTN knows all secrets and will indeed always decrypt for you. See the documentation. (In theory you could also have your own Handler.)

If you also define a Decoder then both the MQTT Data API and the HTTP Integration will give you both the Base64 encoded raw application payload, and whatever fields that are returned by the Decoder.

(As an aside, as you showed another screenshot of the gateway’s Traffic page: be sure to also peek into what the application’s and device’s Data pages give you if you didn’t do that already.)


(Chickadee) #28

Hi,

We’ve been able to send configurable payloads, verified by a decoder. However, it seems that our maximum range is 2.5 feet for acknowledgements and payloads(uplinks). We’ve done multiple tests at 50 and 100 meters but to no avail. What troubleshooting steps do you recommend to fix the range?

-Chickadee - J