Replies: 5 comments 1 reply
-
Withtout sharing that program, it is not possible for me to tell you why is it behaving in this way. The library is just a tool, CPU utilization is a direct result of how that tool is being used. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the quick reply. Details
/*
RadioLib SX126x Receive with Interrupts Example
This example listens for LoRa transmissions and tries to
receive them. Once a packet is received, an interrupt is
triggered. To successfully receive data, the following
settings have to be the same on both transmitter
and receiver:
- carrier frequency
- bandwidth
- spreading factor
- coding rate
- sync word
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// include the hardware abstraction layer
#include "PiHal.h"
#include <cstring>
#include <cstdlib>
//#include <stdio.h>
//#include <string.h>
//#include <stdlib.h>
#include <time.h>
#include <curl/curl.h>
#define FREQUENCY 868.0
#define BANDWIDTH 125.0
#define SPREADING_FACTOR 7
#define TRANSMIT_POWER 0
#define CODING_RATE 5
// ------------------- LoRa Sending & Receiving Paramaters --------------------------
#define OWNID 0xAA
#define SRCAUSSEN 0xB1 // Sender 1 Aussen Süd
#define SRCBAD 0xB2 // Sender 2 Bad
#define SRCVERONIKA 0xB3 // Sender 3 Veronika
#define SRCALENA 0xB4 // Sender 4 Alena
#define SRCSZ 0xB5 // Sender 5 Schlafzimmer
#define SRCNORD 0xB6 // Sender 6 Aussen Nord
#define ACKNOWLEDGE 0x414B
static const uint8_t PH_packetSize = 20;
static const uint8_t PH_ackPacketSize = 6;
union PH_dataPacket {
uint8_t packetByte[PH_packetSize];
struct packetContent {
uint8_t dest; // B // 1 byte
uint8_t source; // B // 1 byte
uint16_t sequenceNumber; // H // 2 bytes
int16_t temperature; // h // 2 bytes Temperature x 100, °C 2 decimal digits
uint16_t humidity; // H // 2 bytes % x 100, °C 2 decimal digits
uint32_t pressure; // I // 4 bytes kPa x 100, 2 decimal digits
uint32_t gas; // I // 4 bytes unknown x 100, °C 2 decimal digits
uint16_t voltage; // H // 2 bytes V x 100, °C 2 decimal digits
} content;
};
union PH_ackPacket {
uint8_t packetByte[PH_ackPacketSize];
struct packetContent {
uint8_t dest; // B // 1 byte
uint8_t source; // B // 1 byte
uint16_t acknowledge; // H // 2 bytes AK as acharcters
uint16_t sequenceNumber; // H // 2 bytes
} ackcont;
};
PH_dataPacket packet;
PH_ackPacket ackpacket;
char token[200];
char org[200];
char bucket[200];
float myRSSI = 0;
float mySNR = 0;
float myFQE = 0;
// create a new instance of the HAL class
PiHal* hal = new PiHal(1);
// now we can create the radio module
SX1262 radio = new Module(hal, 21, 16, 18, 20);
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void printRawPacket() {
for (int i = 0; i < sizeof(packet); i++) {
printf("0x%02x ", packet.packetByte[i]);
}
printf("\n");
}
void printPacket() {
printf("Dest: 0x%02x %d\n", packet.content.dest, (uint8_t)packet.content.dest); // B // 1 byte
printf("Source: 0x%02x %d\n", packet.content.source, (uint8_t)packet.content.source);
printf("Seq: 0x%04x %d\n", packet.content.sequenceNumber, (uint16_t)packet.content.sequenceNumber); // H // 2 bytes
printf("Temp: 0x%04x %02f C\n", packet.content.temperature, (float((int16_t)packet.content.temperature) / 100)); // h // 2 bytes Temperature x 100, °C 2 decimal digits
printf("Hum: 0x%04x %02f %\n", packet.content.humidity, (float((uint16_t)packet.content.humidity) / 100)); // H // 2 bytes % x 100, °C 2 decimal digits
printf("Pres: 0x%08x %02f hPa\n", packet.content.pressure, (float((uint32_t)packet.content.pressure) / 100)); // I // 4 bytes kPa x 100, 2 decimal digits
printf("Gas: 0x%08x %02f\n", packet.content.gas, (float((uint32_t)packet.content.gas) / 100)); // I // 4 bytes unknown x 100, °C 2 decimal digits
printf("Volt: 0x%04x %02f V\n", packet.content.voltage, (float((uint16_t)packet.content.voltage) / 100)); // H // 2 bytes V x 100, °C 2 decimal digits
}
int sendAcknowledge() {
// Cleanup the packet
for (int i = 0; i < sizeof(ackpacket); i++) {
ackpacket.packetByte[i] = 0x0;
}
ackpacket.ackcont.dest = packet.content.source;
ackpacket.ackcont.source = OWNID;
ackpacket.ackcont.acknowledge = ACKNOWLEDGE;
ackpacket.ackcont.sequenceNumber = packet.content.sequenceNumber;
// wait half a second before transmitting
hal->delay(500);
int transstate = radio.transmit((uint8_t*)&ackpacket, sizeof(ackpacket));
// printf("ACK To: 0x%02x with State: %d\n", ackpacket.ackcont.dest, transstate);
return transstate;
}
void saveData(float rssi, float snr, float error) {
CURL *curl;
CURLcode res;
struct curl_slist *headers= NULL;
char *content = (char*) malloc(1024);
char *urlStr = (char*) malloc(1024);
char *authStr = (char*) malloc(1024);
char *tempStr = (char*) malloc(255);
strcpy(urlStr, "http://localhost:8086/api/v2/write?org=");
strcat(urlStr, org);
strcat(urlStr, "&bucket=");
strcat(urlStr, bucket);
strcat(urlStr, "&precision=s");
// printf("URL String: %s\n", urlStr);
switch (packet.content.source) {
case SRCAUSSEN:
strcpy(content, "Wetterdaten,Location=AUSSEN ");
break;
case SRCBAD:
strcpy(content, "Wetterdaten,Location=BAD ");
break;
case SRCVERONIKA:
strcpy(content, "Wetterdaten,Location=VERONIKA ");
break;
case SRCALENA:
strcpy(content, "Wetterdaten,Location=ALENA ");
break;
case SRCSZ:
strcpy(content, "Wetterdaten,Location=SCHLAFZIMMER ");
break;
case SRCNORD:
strcpy(content, "Wetterdaten,Location=AUSSENNORD ");
break;
default:
strcpy(content, "Wetterdaten,Location=AUSSEN ");
}
sprintf(tempStr, "Temperatur=%.2f,", float((int16_t)packet.content.temperature) / 100);
strcat(content, tempStr);
sprintf(tempStr, "Luftfeuchtigkeit=%.2f,", float((uint16_t)packet.content.humidity) / 100);
strcat(content, tempStr);
sprintf(tempStr, "Luftdruck=%.2f,", float((uint32_t)packet.content.pressure) / 100);
strcat(content, tempStr);
sprintf(tempStr, "Luftqualität=%.2f,", float((uint32_t)packet.content.gas) / 100);
strcat(content, tempStr);
sprintf(tempStr, "Batterie=%.2f,", float((uint16_t)packet.content.voltage) / 100);
strcat(content, tempStr);
sprintf(tempStr, "RSSI=%.2f,", rssi);
strcat(content, tempStr);
sprintf(tempStr, "SNR=%.2f,", snr);
strcat(content, tempStr);
sprintf(tempStr, "FreqError=%.2f", error);
strcat(content, tempStr);
// printf(content);
// printf("\n");
strcpy(authStr, "Authorization: Token ");
strcat(authStr, token);
// printf("Authentication: %s\n", authStr);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, urlStr);
headers = curl_slist_append(headers, authStr);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
headers = curl_slist_append(headers, "Accept: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
headers = curl_slist_append(headers, "Content-Type: text/plain; charset=utf-8");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
/* Get size of the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(content));
/* Pass in a pointer of data - libcurl will not copy */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, content);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
/* always cleanup */
curl_easy_cleanup(curl);
}
free(content);
free(urlStr);
free(authStr);
free(tempStr);
}
int main(int argc, char** argv) {
if(argc != 4){
fprintf(stderr, "Incorrect Paramters, need TOKEN, ORGANISATION and BUCKET as three parameters for InfluxDB!!!\n");
return (1);
}
printf("Paramaters: %d\n", argc);
for (int i=0; i< argc; i++) {
printf("Parameter %d = %s\n", i, argv [i]);
}
strcpy(token, argv[1]);
strcpy(org, argv[2]);
strcpy(bucket, argv[3]);
printf("[SX1262] Initializing ... \n");
radio.setDio1Action(setFlag);
int state = radio.begin(FREQUENCY, BANDWIDTH, SPREADING_FACTOR, CODING_RATE, 0x12, 10, 8, 0.0, false);
if (state != RADIOLIB_ERR_NONE) {
printf("Radio.begin failed, code %d\n", state);
return (1);
}
// set the function that will be called
// when new packet is received
radio.setPacketReceivedAction(setFlag);
// start listening for LoRa packets
printf("[SX1262] Starting to listen ... \n");
state = radio.startReceive();
if (state == RADIOLIB_ERR_NONE) {
printf("success!");
} else {
printf("Radio.startReceive failed, code #%d\n", state);
while (true) { hal->delay(10); }
}
for (;;) {
// check if the flag is set
if (receivedFlag) {
// reset flag
receivedFlag = false;
int numBytes = radio.getPacketLength();
printf("PacketSize: %d\n", numBytes);
state = radio.readData((uint8_t*)&packet, numBytes);
printRawPacket();
printPacket();
if (state == RADIOLIB_ERR_NONE) {
// packet was successfully received
// printf("Received packet!\n");
if (packet.content.dest != OWNID) {
printf("Not for me, continue.....\n");
continue;
} else {
myRSSI = radio.getRSSI();
mySNR = radio.getSNR();
myFQE = radio.getFrequencyError();
// printf("From: 0x%02x To: 0x%02x\n", packet.content.source, packet.content.dest);
sendAcknowledge();
// Continue receiving or listening
state = radio.startReceive();
saveData(myRSSI, mySNR, myFQE);
// printf("Radio.startTransmit with code #%d\n", state);
// Just for me to see something
// printRawPacket();
// printPacket();
// print RSSI (Received Signal Strength Indicator)
printf("RSSI:\t\t%0.2f dBm\n", radio.getRSSI());
// print SNR (Signal-to-Noise Ratio)
printf("SNR:\t\t%0.2f dB\n", radio.getSNR());
// print frequency error
printf("Frequency error:\t%0.2f Hz\n", radio.getFrequencyError());
}
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
// packet was received, but is malformed
fprintf(stderr, "CRC error!\n");
}
}
}
} It is just a receiver running on the PI with an endless loop. I used your examples/NonArduino/Raspberry example to set it up. As mentioned bevor, It works really good. |
Beta Was this translation helpful? Give feedback.
-
Hi @longtomin I believe that the reason is the difference in pooling between ESP32 and Raspberry. adding something like hal->delay(1000); to your endless loop should solve your issue. take a look at "examples/NonArduino/Raspberry/main.cpp" line 60 |
Beta Was this translation helpful? Give feedback.
-
@longtomin now it's clear, you have an infinite loop which can always execute (since the only thing it does is check the flag set from ISR), there is no point at which the thread the proggram is running in stops being able to execute. And since the RPi has nothing else to do, that loop is always being run. PS: I edited your post so the comment isn't that long. Feel free to take a look how I did that. The solution is to adapt your program to take into account the fact that you are now running in Unix-based OS instead of an MCU like ESP32. For example, by using threads from the POSIX
That's not a good idea. It will appear to help, since the thread running the program will now stop itself for 1000 ms (approximately, sicne we're in non-realtime OS). But it will also mean that you will always have at least 1 second delay before each packet is received. This is not an issue in the library, but rather a question about usage, hence I will convert it to discussion now. |
Beta Was this translation helpful? Give feedback.
-
Thanks for your help. |
Beta Was this translation helpful? Give feedback.
-
Hello,
I found this Lib because I use it at the ESP32S3 Boards and was thinking why nor use it at the Raspberry PI as well.
Good work and it is working without any bigger issue and long explanations.
I wrote a receiver program for the PI using cmake and the libs. Everything is working find.
The only thing is, I use the PI for other things as well and I recognized 60° C or more.
So I found that the Receiver is running with 100% or a little bit more CPU usage, see:
Question: Is it possible to send the program into a sleep mode which is just processing when data is arrived?
I looked for the radio.sleep and radio.standby functions.
I have this hat for the PI: WaveShare Lora Hat
Beta Was this translation helpful? Give feedback.
All reactions