jgromes / radiolib Goto Github PK
View Code? Open in Web Editor NEWUniversal wireless communication library for embedded devices
Home Page: https://jgromes.github.io/RadioLib/
License: MIT License
Universal wireless communication library for embedded devices
Home Page: https://jgromes.github.io/RadioLib/
License: MIT License
This can be considered bug or feature, so I'll leave it as a general question.
Is there a reason why whitening on SX126x defaults to ON? This got me stuck for few days until I found it, now I'm finally receiving some data that starts to make sense (I'm missing first byte of data, but that may be another issue).
Can we add a method that sets the whitening? Something like:
int16_t setWhitening(bool whiteningEnabled);
I'm also not sure about other default values defined by:
int16_t setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t payloadLength = 0xFF, uint8_t packetType = SX126X_GFSK_PACKET_VARIABLE, uint8_t preambleDetectorLength = SX126X_GFSK_PREAMBLE_DETECT_16, uint8_t whitening = SX126X_GFSK_WHITENING_ON);
Doesn't it work the way that whenever the
setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);
is used in code (setCRC(), disableAddressFiltering(), setSyncWord() etc.), it will actually use those defaults?
EDIT: And the missing first byte is because of SX126X_GFSK_PACKET_VARIABLE. So I guess we should think about how to implement these settings too.
Is your feature request related to a problem? Please describe.
No, pure enhancement.
Describe the solution you'd like
The transmit
blocks the core until TX is fully completed. Is this based on the assumption that the WiFi (for instance) and other tasks will run independently on CPU0? Have you considered reading the radio state before starting a transmission and don't block but use IRQs to mark a successfull TX?
Describe alternatives you've considered
Using ESP8266 and some of Arduino's yield
.
Example: Example: https://github.com/trendmicro/RadioHAL/blob/master/src/RH_CC1120.cpp#L274
What do you think? My apologies if there is a discussion board/ML/chat to discuss this prior to open an issue: I haven't found any. In that case, please point me there and just close this issue.
I'm using a ESP32 and a RFM69. I saw something about use the receiveDirect() for this. But I dont know how to use. When I try to see the DIO1 there is the clock (I guess). But in the DIO2 there is noise.
My goal is capture the signal of a RF garage control or similar devices.
Hi,
I'm trying to extend the timeout for the receive function by putting it in a for loop. It can receive the first message fine, but in the next loops, it receives garbage?
Receiver
int state = 0;
String str = "";
for (int i = 0; i < 10; i++)
{
state = LORA.receive(str);
if (state == ERR_NONE)
{
Serial.println(str);
}
}
Transmitter
void loop()
{
int state = LORA.transmit("hello world!");
if (state == ERR_NONE) Serial.println("Success");
}
Thanks,
Richard
I am connecting a eByte E22-900M22 module with the SX1262 chip. This module has DIO1 and DIO2 exposed, but DIO2 (in my setup) is used to control the RX/TX direction of the antenna. DIO3 is not available.
The initialization routine for the SX1262 module asks for 2 interrupt inputs. But I can only assign DIO1.
Questions:
The code is based on the SX126x_Receive.ino and SX126x_Transmit.ino examples:
#include <Arduino.h>
#include <SPI.h>
#include <RadioLib.h>
// SX1262 module is in slot A on the shield
SX1262 lora = new Module(5, 25, 25, 22, SPI);
void setFlag(void);
void printError(int errNo);
#define LED_RED 16
#define RADIO_RXEN 27
#define RADIO_TXEN 26
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// disable interrupt when it's not needed
volatile bool enableInterrupt = true;
uint8_t dataBuffer[1024];
void setup()
{
pinMode(LED_RED, OUTPUT);
pinMode(RADIO_RXEN, OUTPUT);
pinMode(RADIO_TXEN, INPUT);
digitalWrite(LED_RED, HIGH);
digitalWrite(RADIO_RXEN, HIGH);
// digitalWrite(RADIO_TXEN, LOW);
SPI.begin(18, 19, 23, 5);
Serial.begin(115200);
Serial.println("=====================================");
Serial.println("SX126x receiver test");
Serial.println("=====================================");
int state = lora.begin(915.0, 125.0, 6, 5, 0x3444, 22, 8);
// int state = lora.begin();
if (state == ERR_NONE)
{
Serial.println("success!");
}
else
{
Serial.print("failed: ");
printError(state);
}
// set the function that will be called
// when new packet is received
lora.setDio1Action(setFlag);
lora.setDio2Action(setFlag);
digitalWrite(RADIO_RXEN, HIGH);
// start listening for LoRa packets
// Serial.print("[SX1262] Starting to listen ... ");
// state = lora.startReceive();
// if (state == ERR_NONE)
// {
// Serial.println("success!");
// }
// else
// {
// Serial.print("failed: ");
// printError(state);
// }
/// \todo add WiFi connection here
}
void loop()
{
// put your main code here, to run repeatedly:
digitalWrite(LED_RED, !digitalRead(LED_RED));
delay(500);
int result = lora.receive(dataBuffer, 1024);
if ((result != ERR_NONE) && (result != ERR_RX_TIMEOUT))
{
Serial.print("Receive error: ");
printError(result);
}
else if (result == ERR_NONE)
{
Serial.println("Received==>");
Serial.println(String((char *)dataBuffer));
}
// check if the flag is set
if (receivedFlag)
{
// disable the interrupt service routine while
// processing the data
enableInterrupt = false;
// reset flag
receivedFlag = false;
// you can read received data as an Arduino String
String str;
int state = lora.readData(str);
// you can also read received data as byte array
/*
byte byteArr[8];
int state = lora.receive(byteArr, 8);
*/
if (state == ERR_NONE)
{
// packet was successfully received
Serial.println("[SX1262] Received packet!");
// print data of the packet
Serial.print("[SX1262] Data:\t\t");
Serial.println(str);
// print RSSI (Received Signal Strength Indicator)
Serial.print("[SX1262] RSSI:\t\t");
Serial.print(lora.getRSSI());
Serial.println(" dBm");
// print SNR (Signal-to-Noise Ratio)
Serial.print("[SX1262] SNR:\t\t");
Serial.print(lora.getSNR());
Serial.println(F(" dBm"));
}
else if (state == ERR_CRC_MISMATCH)
{
// packet was received, but is malformed
Serial.println(F("CRC error!"));
}
// we're ready to receive more packets,
// enable interrupt service routine
enableInterrupt = true;
}
}
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void)
{
// check if the interrupt is enabled
if (!enableInterrupt)
{
return;
}
// we got a packet, set the flag
receivedFlag = true;
}
void printError(int errNo)
{
switch (errNo)
{
case ERR_NONE:
Serial.println("Success!");
break;
case ERR_UNKNOWN:
Serial.println("Unknown error");
break;
case ERR_CHIP_NOT_FOUND:
Serial.println("SX127x not found");
break;
case ERR_EEPROM_NOT_INITIALIZED:
Serial.println("EEPROM not initialized");
break;
case ERR_PACKET_TOO_LONG:
Serial.println("TX packet too long");
break;
case ERR_TX_TIMEOUT:
Serial.println("TX timeout");
break;
case ERR_RX_TIMEOUT:
Serial.println("RX timeout");
break;
case ERR_CRC_MISMATCH:
Serial.println("CRC error");
break;
case ERR_INVALID_BANDWIDTH:
Serial.println("Invalid bandwidth");
break;
case ERR_INVALID_SPREADING_FACTOR:
Serial.println("Invalid spreading factor");
break;
case ERR_INVALID_CODING_RATE:
Serial.println("Invalid coding rate");
break;
case ERR_INVALID_BIT_RANGE:
Serial.println("Invalid bit range (internal error)");
break;
case ERR_INVALID_FREQUENCY:
Serial.println("Invalid frequence value");
break;
case ERR_INVALID_OUTPUT_POWER:
Serial.println("Invalid output power");
break;
case PREAMBLE_DETECTED:
Serial.println("Channel is in use");
break;
case CHANNEL_FREE:
Serial.println("Channel is free");
break;
case ERR_SPI_WRITE_FAILED:
Serial.println("SPI write error");
break;
case ERR_INVALID_CURRENT_LIMIT:
Serial.println("Invalid current limit");
break;
case ERR_INVALID_PREAMBLE_LENGTH:
Serial.println("Invalid preamble length");
break;
case ERR_INVALID_GAIN:
Serial.println("Invalid gain");
break;
case ERR_WRONG_MODEM:
Serial.println("Wrong modem command");
break;
case ERR_INVALID_BIT_RATE:
Serial.println("Invalid bit rate");
break;
case ERR_INVALID_FREQUENCY_DEVIATION:
Serial.println("Invalid frequence deviation");
break;
case ERR_INVALID_BIT_RATE_BW_RATIO:
Serial.println("Invalid bit rate bandwidth ratio");
break;
case ERR_INVALID_RX_BANDWIDTH:
Serial.println("Invalid RX bandwidth");
break;
case ERR_INVALID_SYNC_WORD:
Serial.println("FSK sync word invalid");
break;
case ERR_INVALID_DATA_SHAPING:
Serial.println("Invalid FSK data shaping");
break;
case ERR_INVALID_MODULATION:
Serial.println("Invalid modulation");
break;
case ERR_AT_FAILED:
Serial.println("AT command failed");
break;
case ERR_URL_MALFORMED:
Serial.println("Invalid URL");
break;
case ERR_RESPONSE_MALFORMED_AT:
Serial.println("Malformed AT command");
break;
case ERR_RESPONSE_MALFORMED:
Serial.println("Malformed response");
break;
case ERR_MQTT_CONN_VERSION_REJECTED:
Serial.println("MQTT connection rejected due to version mismatch");
break;
case ERR_MQTT_CONN_ID_REJECTED:
Serial.println("MQTT connection rejected due to unknown ID");
break;
case ERR_MQTT_CONN_SERVER_UNAVAILABLE:
Serial.println("MQTT server unavailable");
break;
case ERR_MQTT_CONN_BAD_USERNAME_PASSWORD:
Serial.println("MQTT username/password incorrect");
break;
// case ERR_MQTT_CONN_NOT_AUTHORIZED:
// Serial.println("Unauthorized connection to MQTT broker");
// break;
case ERR_MQTT_UNEXPECTED_PACKET_ID:
Serial.println("Unexpected MQTT packet ID");
break;
case ERR_MQTT_NO_NEW_PACKET_AVAILABLE:
Serial.println("No packet available");
break;
// case MQTT_SUBS_SUCCESS_QOS_0:
// Serial.println("MQTT QoS 0 subscription success");
// break;
case MQTT_SUBS_SUCCESS_QOS_1:
Serial.println("MQTT QoS 1 subscription success");
break;
case MQTT_SUBS_SUCCESS_QOS_2:
Serial.println("MQTT QoS 2 subscription success");
break;
case ERR_MQTT_SUBS_FAILED:
Serial.println("MQTT subscription failed");
break;
case ERR_CMD_MODE_FAILED:
Serial.println("Command failure");
break;
case ERR_FRAME_MALFORMED:
Serial.println("Frame malformed");
break;
case ERR_FRAME_INCORRECT_CHECKSUM:
Serial.println("Frame checksum error");
break;
case ERR_FRAME_UNEXPECTED_ID:
Serial.println("Unexpected ID");
break;
case ERR_FRAME_NO_RESPONSE:
Serial.println("Frame timeout");
break;
case ERR_INVALID_RTTY_SHIFT:
Serial.println("Invalid RTTY shift");
break;
case ERR_UNSUPPORTED_ENCODING:
Serial.println("Unsupported encoding");
break;
case ERR_INVALID_DATA_RATE:
Serial.println("Invalid data rate");
break;
case ERR_INVALID_ADDRESS_WIDTH:
Serial.println("Invalid address width");
break;
case ERR_INVALID_PIPE_NUMBER:
Serial.println("Invalid pipe number");
break;
case ERR_INVALID_NUM_BROAD_ADDRS:
Serial.println("Invalid broadcast address");
break;
case ERR_INVALID_CRC_CONFIGURATION:
Serial.println("Invalid CRC configuration");
break;
case LORA_DETECTED:
Serial.println("Scan found LoRa transmission");
break;
case ERR_INVALID_TCXO_VOLTAGE:
Serial.println("Invalid TCXO voltage");
break;
case ERR_INVALID_MODULATION_PARAMETERS:
Serial.println("Invalid modulation parameter");
break;
case ERR_SPI_CMD_TIMEOUT:
Serial.println("SPI timeout");
break;
case ERR_SPI_CMD_INVALID:
Serial.println("SPI received invalid command");
break;
case ERR_SPI_CMD_FAILED:
Serial.println("SPI CMD failed");
break;
}
}
Hey Jgromes,
I seem to be having a runtime error when I try to use the Kitelibe Library with RTTY instead of LoRaLib. It is the same exact piece of code and the only difference is the library and the Lora module declaration
#include <SoftwareSerial.h>
#include <KiteLib.h>
#include <TinyGPS.h>
TinyGPS gps;
SoftwareSerial ss(6, 5);
SX1278 lora = new Module(7, 3, 2);
void setup()
{
Serial.begin(115200);
ss.begin(9600);
int state = lora.begin(434.0, 62.5, 12, 8, 0x13, 10);
if (state == ERR_NONE)
{
Serial.println(F("success!"));
}
else
{
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
}
void loop()
{
bool newData = false;
unsigned long chars;
unsigned short sentences, failed;
for (unsigned long start = millis(); millis() - start < 1000;)
{
while (ss.available())
{
char c = ss.read();
if (gps.encode(c))
newData = true;
}
}
if (newData)
{
float flat, flon;
unsigned long age;
gps.f_get_position(&flat, &flon, &age);
Serial.print("LAT=");
Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.00 : flat, 7);
Serial.print(" LON=");
Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.00 : flon, 6);
Serial.print(" ALT=");
Serial.print(gps.f_altitude() == TinyGPS::GPS_INVALID_F_ALTITUDE ? 0.00 : gps.f_altitude());
String transmissionMessage = String("");
transmissionMessage += String(";");
if (0==1)
{
transmissionMessage += String("0.0");
}
else
{
transmissionMessage += String(flat, 4);
}
transmissionMessage += String(";");
if (0==1)
{
transmissionMessage += String("0.0");
}
else
{
transmissionMessage += String(flon,4);
}
transmissionMessage += String(";");
if (0==1)
{
transmissionMessage += String("0.0");
}
else
{
transmissionMessage += String(gps.f_altitude());
}
int state = lora.transmit(transmissionMessage);
if (state == ERR_NONE) {
// the packet was successfully transmitted
Serial.println(" success!");
// print measured data rate
Serial.print("Datarate:\t");
Serial.print(lora.dataRate);
Serial.println(" bps");
} else if (state == ERR_PACKET_TOO_LONG) {
// the supplied packet was longer than 256 bytes
Serial.println(" too long!");
} else if (state == ERR_TX_TIMEOUT) {
// timeout occured while transmitting packet
Serial.println(" timeout!");
}
}
}
This code shown above transmits once and then locks up the loop.
#include <SoftwareSerial.h>
#include <KiteLib.h>
#include <TinyGPS.h>
TinyGPS gps;
SoftwareSerial ss(6, 5);
SX1278 lora = new Module(7, 3, 2);
RTTYClient rtty(&lora);
void setup()
{
Serial.begin(115200);
ss.begin(9600);
int state = lora.begin(434.0, 62.5, 12, 8, 0x13, 10);
if (state == ERR_NONE)
{
Serial.println(F("success!"));
}
else
{
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
}
void loop()
{
bool newData = false;
unsigned long chars;
unsigned short sentences, failed;
for (unsigned long start = millis(); millis() - start < 1000;)
{
while (ss.available())
{
char c = ss.read();
if (gps.encode(c))
newData = true;
}
}
if (newData)
{
float flat, flon;
unsigned long age;
gps.f_get_position(&flat, &flon, &age);
Serial.print("LAT=");
Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.00 : flat, 7);
Serial.print(" LON=");
Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.00 : flon, 6);
Serial.print(" ALT=");
Serial.print(gps.f_altitude() == TinyGPS::GPS_INVALID_F_ALTITUDE ? 0.00 : gps.f_altitude());
String transmissionMessage = String("");
transmissionMessage += String(";");
if (0==1)
{
transmissionMessage += String("0.0");
}
else
{
transmissionMessage += String(flat, 4);
}
transmissionMessage += String(";");
if (0==1)
{
transmissionMessage += String("0.0");
}
else
{
transmissionMessage += String(flon,4);
}
transmissionMessage += String(";");
if (0==1)
{
transmissionMessage += String("0.0");
}
else
{
transmissionMessage += String(gps.f_altitude());
}
int state = lora.begin(434.0, 62.5, 12, 8, 0x13, 10);
state = lora.transmit(transmissionMessage);
if (state == ERR_NONE) {
// the packet was successfully transmitted
Serial.println(" success!");
// print measured data rate
Serial.print("Datarate:\t");
Serial.print(lora.dataRate);
Serial.println(" bps");
} else if (state == ERR_PACKET_TOO_LONG) {
// the supplied packet was longer than 256 bytes
Serial.println(" too long!");
} else if (state == ERR_TX_TIMEOUT) {
// timeout occured while transmitting packet
Serial.println(" timeout!");
rtty.begin(434, 183, 45, 5);
rtty.println(transmissionMessage);
lora.standby();
Serial.println(F("done!"));
// wait for a second before transmitting again
delay(1000);
}
}
}
This is ultimately what I am trying to achieve but it gets locked after the LoRa transmission.
Thank you very much Jgromes, hope I'm not disturbing too much with these questions :)
Best Regards,
Julian
Will RadioLib support ESP32 in the near future?
Can this function be implemented in the SX1262 module? Looks like DIO2 is already occupied by the RF switch.
Not sure if it is a bug or a limitation.
I send a structure with the size of 34 bytes
struct dataPckg
{
char rcvAddr[8];
char sendAddr[8];
char type;
char data[16];
char term = 0;
} dataPckgStruct;
from a nRF52 with a SX1262 attached with
int state = lora.startTransmit((const char *)&outPckg, 34);
or from an ESP32 with a SX1262 attached with
lora.transmit((const char *)&outPckg, 34);
Log output of the data sent looks like this:
Sending Package:
Rcv: FF FF FF FF FF FF FF FF
Sender: F7 BC C6 FA A5 6C CB 4E
Type: 0
Data:
12 00 00 00
00 00 00 00
00 00 00 00
00 00 00 ED
Inside the library when the data is written to the SX1262 buffer I put an additional debug output with the buffer content:
FF FF FF FF
FF FF FF FF
F7 BC C6 FA
A5 6C CB 4E
00
12 00 00 00
00 00 00 00
00 00 00 00
00 00 00 ED
So at that point the data is still complete.
CAD is done before sending and the channel is available.
For receiving I use interrupt driven method and then
int state = lora.readData((uint8_t *)&inPckg, 34);
to get the data.
For the receiving side I added some debug output into SX126x.cpp into readData()
size_t length = rxBufStatus[0];
Serial.printf("Receiving %d bytes, wanted %d\n", length, len);
// read packet data
if(len == 0) {
// argument 'len' equal to zero indicates String call, which means dynamically allocated data array
// dispose of the original and create a new one
delete[] data;
data = new uint8_t[length + 1];
}
state = readBuffer(data, length);
for(int idx=0; idx<length; idx++)
{
Serial.printf("%02X ", data[idx]);
}
Serial.println("\n===================");
On the ESP32 I receive
Receiving 16 bytes, wanted 34
FF FF FF FF FF FF FF FF F7 BC C6 FA A5 6C CB 4E
===================
On the nRF52 I receive
Receiving 17 bytes, wanted 34
F7 BC C6 FA A5 6C CB 4E FF FF FF FF FF FF FF FF 01
===================
And it is always 16 bytes on the ESP32 and 17 bytes on the nRF52.
Kind of lost here. What could be the cause. I know from the datasheet that the Data buffer of the SX1262 is 256 byte large. But I do not know how it is setup by the library. Maybe the RX buffer is set too small???
Hey do you have a forum or discussion page someplace for your library and user code discussions ?
Hi,
I have switched to using char*'s instead of String objects. But the function provided as
for (int i = 0; i < 25; i++)
{
char rxTransmission[20];
int state = LORA.receive(rxTransmission, 20);
if (state == ERR_NONE)
{
Serial.println(rxTransmission);
}
}
returns data like this:
HELLOWORLDโ?โ?
when sent transmissions of:
HELLOWORLD
Any ideas?
Thanks,
Richard
-- edit --
When using it in this mode:
char rxTransmission[64];
for (int i = 0; i < 25; i++)
{
int state = lora.receive(rxTransmission, 20);
if (state == ERR_NONE)
{
Serial.println(rxTransmission)
}
}
The result is "HELLOWORLDD"
We are trying to use task scheduler in our application. However, the blocking functions like delay() and tone() cause problems in timing. Can the morse protocol be remade using millis or some other non-blocking function?
Looks like SX126x datasheets were changed quite a bit since SX126x was implemented - thanks a lot, Semtech. This includes previously undocumented registers, fixes to errata and possibly some other things.
Current SX126x driver should be revised to make sure it's up-to-date with the latest datasheet revision.
Docs claim that Semetech chips have capabilities for MSK and GMSK. Can those be invoked using some settings in code?
Is your feature request related to a problem? Please describe.
The radios don't wait until the channel is clear before transmitting. If a unit starts to transmit halfway through a packet directed to it, it will miss that packet. It might also cause other stations to miss the packet it interrupts, or its packet might not be heard (or both).
Describe the solution you'd like
An implementation of p-persistence CSMA:
Configuration parameters might include:
Describe alternatives you've considered
The isChannelBusy()
proposed in #67 could be the standard function that physical layers expose if they are able to be used with feature. This can be implemented without the complex functionality described there, it just won't be as good.
Additional context
https://en.wikipedia.org/wiki/Carrier-sense_multiple_access
I'm going to write this code anyway, if there's interest in including it in this library we can figure out a good interface before I get started.
Hi, and thanks for a nice library!
I'm have very few pins to spare on my ESP32, I need to run SPI with the fewest pins possible.
I need to find pins for MOSI, MISO, SCK, but the RST I'm connecting to the ESP32 "Reset" pin.
And what about the "SS" ("CS"), since I'm only running ONE device on my SPI bus, do I really need to set this?? Can't I hardwire SS to VCC or GND on the SX1278 module and enter SS=-1 when initializing the library? All feedback is welcome since I'm a total newbee on LoRa.
Hi jgromes! we are actually using the sx1278 for 433MHz FSK with RadioLib, but we need the signal strength information, we have already check the register map for FSK in the sx1278 and RSSI value and RSSI configuration is available. Do you have a function to read this in the receiver? or can you make that available? The parameters related to RSSI available from the register map are:
Regards
Where do you have the pin connection info for non KiteShield hook ups ?
I'm trying to use the RFM69_receive example, with an Arduino UNO pinout compatible board (a Wemos D1) and a RFM69 breakout board to suit (but not your shield).
What Arduino pins go to the SPI pins on the RFM69 module for your code examples ?
I looked over all the files but came up blank...
Thanks,
Martin
(A newbie RF module user :)
Add SX1262/68 support to RadioLib.
Main issues:
Originated in https://github.com/jgromes/LoRaLib/issues/53
Hi, i am using a sx1272 module (ra-01) with a esp12f as microcontroller.
I tried to compile a simple code but the ARDUINO IDE gave me this error:
command-line>:0:9: error: expected identifier before numeric constant
/home/alexis/Arduino/libraries/RadioLib/src/modules/ESP8266.h:13:7: note: in expansion of macro 'ESP8266'
class ESP8266: public TransportLayer {
^
command-line>:0:9: error: expected unqualified-id before numeric constant
/home/alexis/Arduino/libraries/RadioLib/src/modules/ESP8266.h:13:7: note: in expansion of macro 'ESP8266'
class ESP8266: public TransportLayer {
^
exit status 1
Error compilando para la tarjeta Generic ESP8266 Module.
Code: (reduced for simplicity)
#include <RadioLib.h>
void setup() {
}void loop() {
}
Any ideas? Thank you
Bought 3 units with the same radio label:TTGO 433 470 MHz Modle LoRa32 radio module, SX1278
I have one unit which gives error -12 when I set the LoRa frequency to anything between 432 and 470 MHz and no error when I set 868 - 880 MHz however it does not transmit on that 868 MHz frequency.
The code sends RTTY and LoRa alternating (for radiotracker under a balloon) and RTTY does transmit on 432 MHz without problems.
`// Default RTTY settings. Change when needed
#define RTTY_FREQUENCY 432.762
#define RTTY_SHIFT 600
#define RTTY_BAUD 75
#define RTTY_STOPBITS 1
// Default LORA settings. Change when needed
#define LORA_FREQUENCY 869.662
#define LORA_BANDWIDTH 125.0
#define LORA_SPREADFACTOR 9
#define LORA_CODERATE 7`
I have no clue why this does happen.
The first hardware board from the same seller does not give this error and does transmit on 432.762 if I set that frequency.
Running the same board with Stuart Robinson tracker software does do tranmist both LoRa and RTTY on 432.762 if I set that frequency.
Any idea what could be the issue ?
Hi Jan,
I've a question about the implementation of the CC1101 receive flow,
Why does the readData() method put the radio back in idle mode after a packet is read from RX FIFO?
I think this way the example will not work properly since the radio is put in receive mode only once , then data is read using readData whose side effect is to put radio back in IDLE. This way (I suppose) no other packet will be received.
Unfortunately I cannot test it with a real radio at the moment.
Thankyou
It will be nice to have support in RadioLib POCSAG protocol
https://www.raveon.com/pdfiles/AN142(POCSAG).pdf
https://habr.com/en/post/438906/
examples sound recorded POCSAG:
https://www.sigidwiki.com/wiki/POCSAG
At current exist big project which use PAGERS with 1200 bps POCSAG protocol DAPNET
With RadioLib and if you add support POCSAG protocol, we can build own small pagers with Arduino or ESP32 +OLED display and any board supported by RadioLib.
Hope I am not getting annoying with my issues.
I got my Insight DSP4520 modules. These modules combines a nRF52 and a SX1262 into one package.
Unfortunately on these boards the DIO2 is used as RF switch control and this cannot be changed.
Is there any hope that I can change the library to setup DIO2 as RF switch control?
I found in SX126x.cpp this:
int16_t SX126x::config(uint8_t modem) {
// set DIO2 as IRQ
uint8_t* data = new uint8_t[1];
data[0] = SX126X_DIO2_AS_IRQ;
Serial.println("Setting DIO2 as RF switch control");
int16_t state = SPIwriteCommand(SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL, data, 1);
if(state != ERR_NONE) {
return(state);
}
...
and
int16_t SX126x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) {
uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
(uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
(uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
(uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)};
return(SPIwriteCommand(SX126X_CMD_SET_DIO_IRQ_PARAMS, data, 8));
}
I changed it to
int16_t SX126x::config(uint8_t modem) {
// set DIO2 as IRQ
uint8_t* data = new uint8_t[1];
#ifdef DSP4520
data[0] = SX126X_DIO2_AS_RF_SWITCH;
#else
data[0] = SX126X_DIO2_AS_IRQ;
Serial.println("Setting DIO2 as RF switch control");
#endif
int16_t state = SPIwriteCommand(SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL, data, 1);
if(state != ERR_NONE) {
return(state);
}
...
and
int16_t SX126x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) {
#ifdef DSP4520
// This will break the CAD functionality
dio2Mask = dio2Mask = SX126X_IRQ_NONE;
Serial.println("Setting DIO2 to SX126X_IRQ_NONE");
uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
(uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
(uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
(uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)};
#else
uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
(uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
(uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
(uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)};
#endif
return(SPIwriteCommand(SX126X_CMD_SET_DIO_IRQ_PARAMS, data, 8));
}
Just for testing.
But that might not be the only functions that needs to be changed. Can you point me to where I should search for additional locations that needs to be changed.
I know that this will break the CAD function, but I really would like to use your library, because it is much easier to setup than the SEMTECH example library for the SX126x chips.
If I get it to work, I will think about how to make this configurable (e.g. in the begin() function) and prepare a pull-request.
Describe the bug
I'm not sure if this is a bug or I'm missing something. However, when I use the SX1262 module and try to setup a receving example, the begin returns an error code of -20. From what I read on the wiki pages, this error is happening because "User tried to execute modem-exclusive method on a wrong modem." But, I know that the SX1262 supports both Lora mode and FSK mode, and therefore that should just work.
To Reproduce
Use the Example code from SX1262_Receive.
Expected behavior
I should be able to recevie stuff.
Screenshots
If applicable, add screenshots to help explain your problem.
Additional info (please complete):
Thanks for your help!
Describe the bug
SX126x modules cannot be woken with the library, instead one must manually wake the unit with a digital write to its select pin.
It looks like in SX126x::SPItransfer
, moving the line digitalWrite(_mod->getCs(), LOW);
to run before the Wait for BUSY
loop will fix this (first sentence in datasheet section 8.2.2) but I'm not sure if there's a reason it needs to be where it is.
To Reproduce
#include <RadioLib.h>
#define LORA_CHECK(A) { auto res = A; if(res) { Serial.print("FAILED " #A ": "); Serial.println(res); } } while(0)
#define BUSY 4
#define DIO1 2
#define DIO2 -1
#define SELECT 9
SX1262 lora = new Module(SELECT, DIO1, DIO2, BUSY);
void setup() {
Serial.begin(9600);
delay(10);
LORA_CHECK(lora.begin());
LORA_CHECK(lora.sleep());
//digitalWrite(SELECT, LOW); //Uncomment this and everything works
LORA_CHECK(lora.standby()); //Fails with -705
Serial.println("Setup done. If no errors show, everything worked.");
}
void loop() {}
Expected behavior
The module can be woken from sleep by asking it to return to standby
Additional info (please complete):
Issue: When using the SX126x receive interrupt example, the received data is incorrect and repeats for 3 to 20 seconds. Below is a snippit of the transmitted and received data. Is there something I am doing wrong to cause this?
Setup:
Some other facts:
Transmitter:
/*
RadioLib SX126x Receive Example
This example listens for LoRa transmissions using SX126x Lora modules.
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
- preamble length
Other modules from SX126x family can also be used.
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
void enableRX(void);
void enableTX(void);
#define RADIO_RXEN 11
#define RADIO_TXEN 12
SX1262 lora = new Module(10, 2, -1, 5);
void setup() {
Serial.begin(115200);
delay(1000);
pinMode(13, OUTPUT);
Serial.println("Tets");
Serial.print(F("[SX1262] Initializing ... "));
int state = lora.begin(915.0, 125.0, 7, 5, 0x1424, 22, 8);
//lora.setCurrentLimit(65);
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
if (lora.setTCXO(2.4) == ERR_INVALID_TCXO_VOLTAGE)
{
Serial.println(F("Selected TCXO voltage is invalid for this module!"));
}
enableTX();
}
void loop() {
unsigned long p = millis();
String k = String(p);
int state = lora.transmit(k);
Serial.println("Transmitting: " + String(p));
delay(1000);
}
void enableRX(void)
{
digitalWrite(RADIO_RXEN, HIGH);
digitalWrite(RADIO_TXEN, LOW);
delay(100);
}
void enableTX(void)
{
digitalWrite(RADIO_RXEN, LOW);
digitalWrite(RADIO_TXEN, HIGH);
delay(100);
}
Receiver:
/*
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
Other modules from SX126x/RFM9x family can also be used.
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
void enableRX(void);
void enableTX(void);
// GPIOs to control E22 RX_EN and TX_EN
#define RADIO_RXEN 4
#define RADIO_TXEN 7
// SX1262 has the following connections:
// NSS pin: 10
// DIO1 pin: 2
// DIO2 pin: 3
// BUSY pin: 9
SX1262 lora = new Module(10, 2, -1, 5);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1262 lora = RadioShield.ModuleA;
void setup() {
Serial.begin(115200);
Serial.print(F("[SX1262] Initializing ... "));
int state = lora.begin(915.0, 125.0, 7, 5, 0x1424, 22, 8);
//lora.setCurrentLimit(11.9);
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
if (lora.setTCXO(2.4) == ERR_INVALID_TCXO_VOLTAGE)
{
Serial.println(F("Selected TCXO voltage is invalid for this module!"));
}
enableRX();
lora.setDio1Action(setFlag);
// start listening for LoRa packets
Serial.print(F("[SX1262] Starting to listen ... "));
state = lora.startReceive();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// disable interrupt when it's not needed
volatile bool enableInterrupt = true;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// check if the interrupt is enabled
if(!enableInterrupt) {
return;
}
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {
// disable the interrupt service routine while
// processing the data
enableInterrupt = false;
// reset flag
receivedFlag = false;
// you can read received data as an Arduino String
String str = "";
int state = lora.readData(str);
if (state == ERR_NONE) {
// packet was successfully received
// Serial.println(F("[SX1262] Received packet!"));
// print data of the packet
Serial.print(F("Receiving:\t"));
Serial.println(str);
} else if (state == ERR_CRC_MISMATCH) {
// packet was received, but is malformed
Serial.println(F("CRC error!"));
} else {
// some other error occurred
Serial.print(F("failed, code "));
Serial.println(state);
}
// we're ready to receive more packets,
// enable interrupt service routine
enableInterrupt = true;
}
}
void enableRX(void)
{
digitalWrite(RADIO_RXEN, HIGH);
digitalWrite(RADIO_TXEN, LOW);
delay(100);
}
void enableTX(void)
{
digitalWrite(RADIO_RXEN, LOW);
digitalWrite(RADIO_TXEN, HIGH);
delay(100);
}
Is your feature request related to a problem? Please describe.
The SX126x scanChannel
function will interrupt a receive in progress that might have been started with startReceive
, causing the packet that is being received to be dropped.
Describe the solution you'd like
A method isChannelBusy()
that, if in receive mode, will query whether a preamble has been recently detected (see additional context below) and return that there is traffic without interrupting the receive.
If the unit is not in receive mode, isChannelBusy()
will return the result of scanChannel()
.
Describe alternatives you've considered
Can't really think of much.
Additional context
CSMA #68 is the motivation for this.
I've already got this written: In startReceive
, an additonal IRQ flag is set up so we get notification of Preamble Detected
. A custom ISR is attached to DIO1 that tracks the preamble, and calls the consumer defined function when Rx Done
is signalled.
isChannelBusy
looks if a preamble has been detected without a Rx Done recently (there's a timeout for in case we get a false preamble detection or never get Rx Done), and returns that the channel is busy if that's the case.
To avoid breaking existing code, an optional parameter can be added to startReceive
to indicate whether to attach our own ISR to track preamble detection. I would like to add two other new functions too: setRxDoneAction
and setTxDoneAction
; these would supersede setDio1Action
(maybe that could be declared deprecated?).
Let me know if there's interest and I'll spend the time polishing up my code to put it into a PR.
I couldnยดt use RTTY with RFM69 Module.
From the example code (https://github.com/jgromes/RadioLib/blob/master/examples/RTTY/RTTY_Transmit/RTTY_Transmit.ino ) i change to:
RF69 fsk = new Module(10,2 ,3 );
'get error in compilation:
radiolib_rtty:46: error: 'class RF69' has no member named 'beginFSK'
int state = fsk.beginFSK();
exit status 1
'class RF69' has no member named 'beginFSK''
Documentation say:
RTTY for modules: SX127x, RFM9x, SX126x, RF69, SX1231, CC1101 and nRF24L01
Iยดm doing something wrong?
Can i listen 433MHz RF (cheap 433mhz door - motion sensors) or send (cheap on-off switches - outlets) with TTGO or Heltec Lora ESP32? Because RF Receive/send Modules are really crappy..
Hello!
I have a Dorji DRF1268 module but somehow, Arduino doesn't "discover" it.
I keep getting these 2 error codes: -20 and -707
I have another weird module, a combined nRF52832 and SX1262 module named Insight ISP4520.
This module uses DIO3 as a power supply for the antenna switch:
They have a sample code how to set DIO3 as output and put it to high level:
static void SX126xDio3Control (bool state)
{
uint8_t reg_0x0580;
uint8_t reg_0x0583;
uint8_t reg_0x0584;
uint8_t reg_0x0585;
uint8_t reg_0x0920;
if (state)
{
// Configure DIO3 as output
// Read 0x0580
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0580 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0580 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0580 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
// Read 0x0583
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0583 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0583 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0583 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
// Read 0x0584
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0584 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0584 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0584 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
// Read 0x0585
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0585 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0585 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0585 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
// Write 0x0580
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0580 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0580 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0580 | 0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
// Write 0x0583
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0583 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0583 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0583 & ~0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
// Write 0x0584
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0584 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0584 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0584 & ~0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
// Write 0x0585
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0585 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0585 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0585 & ~0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
// Write 0x0920
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, 0x06);
GpioWrite (&SX126x.Spi.Nss, 1);
// Set DIO3 High
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0920 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0920 | 0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
}
else
{
// Set DIO3 Low
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, 0);
reg_0x0920 = SpiInOut(&SX126x.Spi, 0);
GpioWrite(&SX126x.Spi.Nss, 1);
SX126xWaitOnBusy();
GpioWrite(&SX126x.Spi.Nss, 0);
SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
SpiInOut(&SX126x.Spi, reg_0x0920 & ~0x08);
GpioWrite (&SX126x.Spi.Nss, 1);
}
}
but I have problems to transform this to work within your library.
I didn't find a readRegister()
only a writeRegister()
function. So I tried to write readRegister()
, but found that the SPItransfer
when in read mode only transfers the command, but for reading the registers after the command it is required to send the register address.
So I needed to write a SPItransferAddr(uint8_t cmd, uint8_t addr1, uint8_t addr2, bool write, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes, bool waitForBusy)
functions that sends the two address bytes after the command and then reads the register values.
After I got that to work I changed above code to work with your library and added it as a function setDio3AsOutput(bool enable)
.
Not sure if others need something like that, but here are the functions I added:
SX126x::readRegister
int16_t SX126x::readRegister(uint16_t addr, uint8_t *data, uint8_t numBytes)
{
uint8_t *dat = new uint8_t[numBytes];
int16_t state = SPItransferAddr(SX126X_CMD_READ_REGISTER,
(uint8_t)((addr >> 8) & 0xFF),
(uint8_t)(addr & 0xFF),
false,
NULL,
dat,
numBytes,
true);
memcpy(data, dat, numBytes);
delete[] dat;
return (state);
}
int16_t SX126x::SPItransferAddr
int16_t SX126x::SPItransferAddr(uint8_t cmd, uint8_t addr1, uint8_t addr2, bool write, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes, bool waitForBusy)
{
// get pointer to used SPI interface and the settings
SPIClass *spi = _mod->getSpi();
SPISettings spiSettings = _mod->getSpiSettings();
// ensure BUSY is low (state meachine ready)
// TODO timeout
while (digitalRead(_mod->getRx()))
;
// start transfer
digitalWrite(_mod->getCs(), LOW);
spi->beginTransaction(spiSettings);
// send command byte
spi->transfer(cmd);
DEBUG_PRINT(cmd, HEX);
DEBUG_PRINT('\t');
// send addr byte 1
spi->transfer(addr1);
DEBUG_PRINT(addr1, HEX);
DEBUG_PRINT('\t');
// send addr byte 2
spi->transfer(addr2);
DEBUG_PRINT(addr2, HEX);
DEBUG_PRINT('\t');
// variable to save error during SPI transfer
uint8_t status = 0;
// send/receive all bytes
if (write)
{
for (uint8_t n = 0; n < numBytes; n++)
{
// send byte
uint8_t in = spi->transfer(dataOut[n]);
DEBUG_PRINT(dataOut[n], HEX);
DEBUG_PRINT('\t');
DEBUG_PRINT(in, HEX);
DEBUG_PRINT('\t');
// check status
if (((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
((in & 0b00001110) == SX126X_STATUS_CMD_FAILED))
{
status = in;
}
}
DEBUG_PRINTLN();
}
else
{
// skip the first byte for read-type commands (status-only)
uint8_t in = spi->transfer(SX126X_CMD_NOP);
DEBUG_PRINT(SX126X_CMD_NOP, HEX);
DEBUG_PRINT('\t');
DEBUG_PRINT(in, HEX);
DEBUG_PRINT('\t')
// check status
if (((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
((in & 0b00001110) == SX126X_STATUS_CMD_FAILED))
{
status = in;
}
for (uint8_t n = 0; n < numBytes; n++)
{
dataIn[n] = spi->transfer(SX126X_CMD_NOP);
DEBUG_PRINT(SX126X_CMD_NOP, HEX);
DEBUG_PRINT('\t');
DEBUG_PRINT(dataIn[n], HEX);
DEBUG_PRINT('\t');
}
DEBUG_PRINTLN();
}
// stop transfer
spi->endTransaction();
digitalWrite(_mod->getCs(), HIGH);
// wait for BUSY to go high and then low
// TODO timeout
if (waitForBusy)
{
delayMicroseconds(1);
while (digitalRead(_mod->getRx()))
;
}
// parse status
switch (status)
{
case SX126X_STATUS_CMD_TIMEOUT:
return (ERR_SPI_CMD_TIMEOUT);
case SX126X_STATUS_CMD_INVALID:
return (ERR_SPI_CMD_INVALID);
case SX126X_STATUS_CMD_FAILED:
return (ERR_SPI_CMD_FAILED);
default:
return (ERR_NONE);
}
}
SX126x::setDio3AsOutput
int16_t SX126x::setDio3AsOutput(bool enable)
{
uint8_t reg_0x0580;
uint8_t reg_0x0583;
uint8_t reg_0x0584;
uint8_t reg_0x0585;
uint8_t reg_0x0920;
int state;
if (enable)
{
state = readRegister(0x0580, ®_0x0580, 1);
if (state != ERR_NONE)
{
return state;
}
state = readRegister(0x0583, ®_0x0583, 1);
if (state != ERR_NONE)
{
return state;
}
state = readRegister(0x0584, ®_0x0584, 1);
if (state != ERR_NONE)
{
return state;
}
state = readRegister(0x0585, ®_0x0585, 1);
if (state != ERR_NONE)
{
return state;
}
// Set the register values
reg_0x0580 = reg_0x0580 | 0x08;
reg_0x0583 = reg_0x0583 & ~0x08;
reg_0x0584 = reg_0x0584 & ~0x08;
reg_0x0585 = reg_0x0585 & ~0x08;
reg_0x0920 = 0x08;
state = writeRegister(0x0580, ®_0x0580, 1);
if (state != ERR_NONE)
{
return state;
}
state = writeRegister(0x0583, ®_0x0583, 1);
if (state != ERR_NONE)
{
return state;
}
state = writeRegister(0x0584, ®_0x0584, 1);
if (state != ERR_NONE)
{
return state;
}
state = writeRegister(0x0585, ®_0x0585, 1);
if (state != ERR_NONE)
{
return state;
}
state = writeRegister(0x0920, ®_0x0920, 1);
if (state != ERR_NONE)
{
return state;
}
return ERR_NONE;
}
else
{
{
state = readRegister(0x0920, ®_0x0920, 1);
if (state != ERR_NONE)
{
return state;
}
reg_0x0920 = reg_0x0920 & ~0x08;
state = writeRegister(0x0920, ®_0x0920, 1);
if (state != ERR_NONE)
{
return state;
}
}
}
return ERR_NONE;
}
PS: I have no idea where Insight got the register addresses 0x0580, 0x0583, 0x0584, 0x0585 and 0x0920 from. They are not in the datasheets. I guess they got it from Semtech directly.
Hi there,
Trying to work out how to use a Semtech DRF1278DM http://www.dorji.com/products-detail.php?ProId=34 with an Arduino Nano, I've read the other posts on here regarding how LoRaLib won't do UART and only SPI but the KiteLib link just redirects to the main LoRaLib page!
So if the LoRaLib library now supports the DRF1278DM module and not just the raw SX1278 board, how would you go about connecting it up, as it doesn't have the standard SCK and MOSI pins?
Would it just be like this?
SX1278 lora = new LoRa(11, 10); // RX-TX
or
SX1278 lora = new LoRa(11, 10, 9); // RX-TX+Enable
Cheers Benjamin!
How can I change decode model for FSK transmition in SX127X? Because, I need to transmit data with Manchester decode
I want to use recieve with interrupt on SX1268 however I am constrained by the no. Of pins I have available. So can I just put DIO2 pin as -1 and still use the recieve interrupt feature?
Using SparkFun LoRa Gateway - 1-Channel (ESP32)
NSS = 16, DIO0 = 26, DIO1 = 33, DIO2 = 32 according to schematic
Setting up the connection to the RFM95 module:
RFM95 lora = new Module(16, 26, 33, 32);
void setup() {
int state = lora.begin(868.0, 125.0, 9, 5, 0x3444, 22, 8);
if (state == ERR_NONE)
{
Serial.println("success!");
}
else
{
Serial.print("failed: ");
printError(state);
return false;
}
...
}
fails with
=====================================
RFM95 sender test
=====================================
DeviceID: 84 0D 8E 0C 56 3C 00 00
Initialize RFM95
SX127x not found! (1 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (2 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (3 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (4 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (5 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (6 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (7 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (8 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (9 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (10 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
No SX127x found!
failed: SX127x not found
Using the abandoned library RadioHead
Setup with
// Singleton instance of the radio driver
RH_RF95 rf95(16, 26);
// 16 = NSS, 26 = INT
void setup() {
// Init the RFM95 module
if (!rf95.init())
{
Serial.println("[RFM95] init failed");
delay(500);
}
}
works perfect, log output:
RH_RF95::init() started
RH_RF95::init() success
Any idea?
I have a Dorji SX1262 (868) I can't make it work in RX mode. The TX is working "SX126x_Transmit.ino" using "lora.setTCXO(1.6);"
ESP32 with Dorji DRF1262 (DIO2 not connected)
My RX sketch (not working):
#include <Arduino.h>
#include <WiFi.h>
#include <RadioLib.h>
time_t updateTime;
// Flag for sending finished
bool sendDone = false;
SPIClass *loraSPI = new SPIClass(HSPI);
// NSS DIO1 DIO2 BUSY
SX1262 lora = new Module(15, 22, -1, 21, *loraSPI);
int PIN_LORA_RESET = 19;
#define ssid = "MyWiFi"
#define pass = "qwerty123"
WiFiClient client;
struct tm timeinfo;
uint8_t dataMsg[6];
char ackMsg[] = "ACK";
long timeSinceLastPacket = 0;
uint16_t nodeId = 0;
char timeStamp[32];
void setup()
{
pinMode(PIN_LORA_RESET, OUTPUT);
digitalWrite(PIN_LORA_RESET, LOW);
delay(100);
digitalWrite(PIN_LORA_RESET, HIGH);
Serial.begin(115200);
// initialize SX1262
// carrier frequency: 868.0 MHz
// bandwidth: 125.0 kHz
// spreading factor: 7
// coding rate: 5
// sync word: 0x1424 (private network)
// output power: 22 dBm
// current limit: 60 mA
// preamble length: 8 symbols
// CRC: enabled
// Initialize LoRa
Serial.println(F("[SX1262] Initializing ... "));
int state = lora.begin(868.0, 125.0, 7); //SF7
if (state == ERR_NONE) {
Serial.println(F("LORA init success!"));
} else {
Serial.print(F("init failed, code "));Serial.println(state);
}
if (lora.setTCXO(1.6) == ERR_INVALID_TCXO_VOLTAGE)
{
Serial.println(F("Selected TCXO voltage is invalid for this module!"));
}
}
void loop() {
Serial.print(F("[SX1262] Waiting for incoming transmission ... "));
String str;
int state = lora.receive(str);
if (state == ERR_NONE) {
// packet was successfully received
Serial.println(F("success!"));
// print the data of the packet
Serial.print(F("[SX1262] Data:\t\t")); Serial.println(str);
// print the RSSI (Received Signal Strength Indicator)
// of the last received packet
Serial.print(F("[SX1262] RSSI:\t\t")); Serial.print(lora.getRSSI()); Serial.println(F(" dBm"));
// print the SNR (Signal-to-Noise Ratio)
// of the last received packet
Serial.print(F("[SX1262] SNR:\t\t")); Serial.print(lora.getSNR()); Serial.println(F(" dB"));
} else if (state == ERR_RX_TIMEOUT) {
// timeout occurred while waiting for a packet
Serial.println(F("timeout!"));
} else if (state == ERR_CRC_MISMATCH) {
// packet was received, but is malformed
Serial.println(F("CRC error!"));
} else {
// some other error occurred
Serial.print(F("failed, code ")); Serial.println(state);
}
}
Output of that sketch:
[SX1262] Waiting for incoming transmission ... timeout!
[SX1262] Waiting for incoming transmission ... timeout!
[SX1262] Waiting for incoming transmission ... timeout!
...
By the way I have another device transmitting over 868Mhz SF7 "helloworld" (tested and working)
Any Idea how to fix it?
Length of SyncWord on SX126x radios is being set as a value in bits, which is solved in library simply by:
// update packet parameters
_syncWordLength = len * 8;
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);
As I would like to use this feature, I would consider changing:
int16_t SX126x::setSyncWord(uint8_t* syncWord, uint8_t len)
to:
int16_t SX126x::setSyncWord(uint8_t* syncWord, uint8_t len, bool lenInBits)
for example. Then do obvious things in the code (I'll try to write up actual code later on today).
What do you think?
Is your feature request related to a problem? Please describe.
Pure enhancement.
Describe the solution you'd like
As for the filter
byte, the length
byte should be optional, as stated in the specs: it's written only if the application protocol is in variable-length mode. Also, is there any reason why the filter
reg value is not cached on the MCU memory? It would save one SPI read, and in high throughput transmissions it may make a difference.
I'm talking about CC1101 or RFM69, and similar modules.
RadioLib could be extended to provide hardware-agnostic AX.25 driver, which is currently not available.
Add parameter for SX126x::sleep(void)
to skip waiting for BUSY line of SX126x chip.
In battery powered systems you don't want to wait for the SX126x chip to go to sleep and instead just send the command and then put yourself to sleep.
I am working on a code for a battery powered sensor node.
The node wakes up every 30 seconds, reads a sensor, sends the sensor values over LoRa and goes to sleep again.
Right now I am measuring the time that the node is awake and found something strange.
void goToSleep(void)
{
time_t sendToSleep = millis();
// Send the LoRa module to sleep
lora.sleep();
Serial.printf("Set Lora to sleep took %ldms\n", (millis() - sendToSleep));
Serial.printf("Sleeping after %ldms\n", (millis() - wakeup));
// Go back to bed
time_t awakeTime = millis() - wakeup;
esp_sleep_enable_timer_wakeup((sleepForMillis - awakeTime) * uS_TO_mS_FACTOR);
esp_deep_sleep_start();
}
where wakeup = millis()
is done as first thing when entering setup()
.
The output is always
=====================================
LoRa sensor node test
=====================================
Temp 29.89
Humid 98.50
Finished reading sensor after 1010ms
CAD finished after 24ms
Transmit finished after 70ms
Set Lora to sleep took 5000ms
Sleeping after 6104ms
So putting the SX126x to sleep takes nearly 5 times as long as reading the sensors and sending the data.
I tried to track down why it takes so long and found that in sleep()
the command is waiting for BUSY line to go low before returning.
When I change the sleep()
function to
int16_t SX126x::sleep() {
uint8_t data[] = {SX126X_SLEEP_START_COLD | SX126X_SLEEP_RTC_OFF};
int16_t state = SPIwriteCommand(SX126X_CMD_SET_SLEEP, data, 1, true);
// wait for SX126x to safely enter sleep mode
delayMicroseconds(500);
return(state);
}
forcing the SPIwriteCommand to NOT wait for BUSY going low, I can reduce my awake time by 4 seconds to
=====================================
LoRa sensor node test
=====================================
Temp 30.0
Humid 98.50
Finished reading sensor after 1010ms
CAD finished after 24ms
Transmit finished after 70ms
Set Lora to sleep took 0ms
Sleeping after 1104ms
Change
int16_t SX126x::sleep() {
uint8_t data[] = {SX126X_SLEEP_START_COLD | SX126X_SLEEP_RTC_OFF};
int16_t state = SPIwriteCommand(SX126X_CMD_SET_SLEEP, data, 1);
// wait for SX126x to safely enter sleep mode
delayMicroseconds(500);
return(state);
}
to
int16_t SX126x::sleep(bool waitForBusy) {
uint8_t data[] = {SX126X_SLEEP_START_COLD | SX126X_SLEEP_RTC_OFF};
int16_t state = SPIwriteCommand(SX126X_CMD_SET_SLEEP, data, 1, waitForBusy);
// wait for SX126x to safely enter sleep mode
delayMicroseconds(500);
return(state);
}
with a declaration as
/*!
\brief Sets the module to sleep mode.
\returns \ref status_codes
*/
int16_t sleep(bool waitForBusy = true);
If you agree that this makes sense, I can submit a pull request for it.
RadioLib could be extended to support LoRaWAN networks (and it's been on the TODO/WIP list for quite a while now).
Hi,
is it possible to decode RTTY directly? I have a module with sx1276, esp32 and oled display. I would like to receive and decode itty directly on board and show messages on display. Can you explain how to make it with your library? rtty.read() is not implemented.
Thanks
Hi
I can't for the life of me get the Transmit or Interrupt examples working. Seems the library is not firing the interrupt.
This is what I am using:
https://www.mouser.com/ProductDetail/Semtech/SX1262MB2CAS?qs=qSfuJ%252Bfl%2Fd69tTGSeW1ezg%3D%3D&gclid=CjwKCAjwyqTqBRAyEiwA8K_4O7C7a8jZO-cE0LqnMlDPHCW88X2zbjaKHPTFOQHc3fD0QoWU1JnpBhoCh3AQAvD_BwE
The regular examples work fine.
I am on an Arduino Uno and the initialization I am using is as follows:
SX1262 lora = new Module(7, 5, -1, 3);
int state = lora.begin(915.0, 125.0, 9, 5, SX126X_SYNC_WORD_PRIVATE, 22);
Any help will be greatly appreciated.
I just didn't see Software Serial. h in the project. I guess it was uploaded or something. I compiled it using Arduino platform. Look forward to it. Thank you.
Hey, I am trying to decode the RTTY example using MMTTY and FLDigi but I cannot seem to get it to successfully decode. I suspect this is due to it being ASCII and not Baudot ITA2, do you have an implementation for ITA2 or can you share how to decode the rtty? thanks!
As on some modules DIO2 is not available because it is used to switch the RF antenna between RX and TX.
This means scanChannel()
function cannot be used.
As simple workaround could be to change scanChannel()
to use only DIO1 as IRQ input.
Example code how it works (tested on eByte E22 module which uses DIO2 as RF antenna switch):
int16_t SX126x::scanChannel()
{
// check active modem
if (getPacketType() != SX126X_PACKET_TYPE_LORA)
{
return (ERR_WRONG_MODEM);
}
// set mode to standby
int16_t state = standby();
if (state != ERR_NONE)
{
return (state);
}
// set DIO pin mapping
// state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED);
// Use DIO1 only for both CAD DONE and CAD DETECTED interrupts
state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE);
if (state != ERR_NONE)
{
return (state);
}
// clear interrupt flags
state = clearIrqStatus();
if (state != ERR_NONE)
{
return (state);
}
// set mode to CAD
state = setCad();
if (state != ERR_NONE)
{
return (state);
}
// wait for channel activity detected or timeout
while (!digitalRead(_mod->getInt0()))
{
// No need to check DIO2
// if(digitalRead(_mod->getInt1())) {
// clearIrqStatus();
// return(LORA_DETECTED);
// }
}
// Get the CAD result
uint16_t cadResult = getIrqStatus();
if (cadResult == 0x8000)
{
clearIrqStatus();
return (CHANNEL_FREE);
}
else // cadResult == 0x8001
{
clearIrqStatus();
return (LORA_DETECTED);
}
return (CHANNEL_FREE);
}
Hi,
I am using arduino pro micro - atmega32u4 (INT0 and INT1 are pins exchanged in relation to arduino uno) and in scanChannel the code gets stuck in while waiting for an activity in INT0. In the comment says have timeout but do not have, should not have a timout? I am only with a radio and now I have no way to test if with channel activity it would pass this condition.
thank you! and congratulations to cubeSat
int16_t SX126x::scanChannel()
{
// check active modem
if (getPacketType() != SX126X_PACKET_TYPE_LORA)
{
return (ERR_WRONG_MODEM);
}
// set mode to standby
int16_t state = standby();
if (state != ERR_NONE)
{
return (state);
}
// set DIO pin mapping
// state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED);
// Use DIO1 only for both CAD DONE and CAD DETECTED interrupts
state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE);
if (state != ERR_NONE)
{
return (state);
}
// clear interrupt flags
state = clearIrqStatus();
if (state != ERR_NONE)
{
return (state);
}
// set mode to CAD
state = setCad();
if (state != ERR_NONE)
{
return (state);
}
// wait for channel activity detected or timeout
while (!digitalRead(_mod->getInt0()))
{
// No need to check DIO2
// if(digitalRead(_mod->getInt1())) {
// clearIrqStatus();
// return(LORA_DETECTED);
// }
}
// Get the CAD result
uint16_t cadResult = getIrqStatus();
if (cadResult == 0x8000)
{
clearIrqStatus();
return (CHANNEL_FREE);
}
else // cadResult == 0x8001
{
clearIrqStatus();
return (LORA_DETECTED);
}
return (CHANNEL_FREE);
}
Hi! I'm looking for a solution to transmit RTTY teletype telemetry through a CC1101 equipped shield. I see that you're working on something that might satisfy my needs. What's the outlook and is there maybe an ETA?
Also, is KiteShield needed to use your library?
Hi friends
I have been paying attention to your project! When I used the SX1261, I encountered such a problem: when the parameters are set, the CAD is turned on, and the CAD Detect interrupt occurs to enable the receiving mode.
If I use CAD Only mode, it will receive normally, but the packet loss rate is very high;
If you are using the CAD Rx mode, rxtimeout will be generated continuously.
I hope to seek some help, thank you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.