Simple and lightweight library to work with LoRa sx1276
compatible modules on STM32 HAL.
It is really tiny, check this out:
$ arm-none-eabi-gcc -c -mcpu=cortex-m0plus -mthumb <other options stripped> lora_sx1276.c
$ size lora_sx1276.o
text data bss dec hex filename
1596 0 0 1596 63c lora_sx1276.o
It's just 1.5
Kb of compiled code! :)
Please be noticed - it does not implements LoRaWAN stack, it is pure LoRa - basically RADIO only.
Copy / add as submodule files under Src
directory to your STM32 HAL project, then:
- Include header:
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lora_sx1276.h"
// ...
/* USER CODE END Includes */
- Add module initialization somewhere in
main()
function like that:
/* USER CODE BEGIN 2 */
lora_sx1276 lora;
// SX1276 compatible module connected to SPI1, NSS pin connected to GPIO with label LORA_NSS
uint8_t res = lora_init(&lora, &hspi1, LORA_NSS_GPIO_Port, LORA_NSS_Pin, LORA_BASE_FREQUENCY_US);
if (res != LORA_OK) {
// Initialization failed
}
- Send packet:
// Send packet can be as simple as
uint8_t res = lora_send_packet(&lora, (uint8_t *)"test", 4);
if (res != LORA_OK) {
// Send failed
}
- Receive packet:
// Receive buffer
uint8_t buffer[32];
// Put LoRa modem into continuous receive mode
lora_mode_receive_continuous(&lora);
// Wait for packet up to 10sec
uint8_t res;
uint8_t len = lora_receive_packet_blocking(&lora, buffer, sizeof(buffer), 10000, &res);
if (res != LORA_OK) {
// Receive failed
}
buffer[len] = 0; // null terminate string to print it
printf("'%s'\n", buffer);
-
uint8_t lora_init(lora_sx1276 *lora, SPI_HandleTypeDef *spi, GPIO_TypeDef *nss_port, uint16_t nss_pin, uint64_t freq)
Initialize LoRa with default parameters:lora
LoRa definition to be initializedspi
SPI HAL bus (hspi1
,hspi2
, etc)nss_port
- GPIO port whereNSS
pin connected tonss_pin
- GPIO pin number innss_port
freq
- operating frequency. In Hz Returns:LORA_OK
- modem initialized successfullyLORA_ERROR
- initialization failed (e.g. no modem present on SPI bus / wrong NSS port/pin)
-
uint8_t lora_version(lora_sx1276 *lora)
Returns LoRa modem version number (usually0x12
)
-
void lora_mode_sleep(lora_sx1276 *lora)
Put radio into SLEEP mode: In this mode only SPI and configuration registers are accessible. LoRa FIFO is not accessible. -
void lora_mode_standby(lora_sx1276 *lora)
Put radio into standby (idle) mode: Both Crystal Oscillator and LoRa baseband blocks are turned on. RF part and PLLs are disabled. -
void lora_mode_receive_continuous(lora_sx1276 *lora)
Put radio into continuous receive mode: When activated the RFM95/96/97/98(W) powers all remaining blocks required for reception, processing all received data until a new user request is made to change operating mode. -
void lora_mode_receive_single(lora_sx1276 *lora)
Put radio into single receive mode: When activated the RFM95/96/97/98(W) powers all remaining blocks required for reception, remains in this state until a valid packet has been received and then returns to Standby mode.
-
void lora_set_tx_power(lora_sx1276 *lora, uint8_t level)
Sets LoRa transmit power.level
- TX power in dBm. Valid range from 2dBm to 20dBm
-
void lora_set_frequency(lora_sx1276 *lora, uint64_t freq);
Set operational frequency.freq
- frequency in Hz
-
void lora_set_signal_bandwidth(lora_sx1276 *lora, uint64_t bw)
Set signal bandwidth.bw
- desired bandwidth, fromLORA_BANDWIDTH_7_8_KHZ
toLORA_BANDWIDTH_500_KHZ
For more information refer to section 4.1 of datasheet.
-
void lora_set_spreading_factor(lora_sx1276 *lora, uint8_t sf)
Set signal spreading factor.sf
- spreading factor. Value from 6 to 12 For more information refer to section 4.1 of datasheet.
-
void lora_set_coding_rate(lora_sx1276 *lora, uint8_t rate)
Set coding rate.rate
- coding rate. Use any ofLORA_CODING_RATE*
constants. For more information refer to section 4.1 of datasheet.
-
void lora_set_crc(lora_sx1276 *lora, uint8_t enable)
Enable / disable CRCenable
- set to0
to disable CRC, any other value enables CRC.
-
void lora_set_preamble_length(lora_sx1276 *lora, uint16_t len)
Set length of packet preamble.len
- length of packet preamble For more information refer to section 4.1.1.6 of datasheet
-
void lora_set_implicit_header_mode(lora_sx1276 *lora)
Set "implicit header" mode, meaning no packet header at all. Refer to section 4.1.1.6 of datasheet -
void lora_set_explicit_header_mode(lora_sx1276 *lora)
Set "explicit", i.e. always add packet header with various system information. Refer to section 4.1.1.6 of datasheet -
void lora_enable_interrupt_rx_done(lora_sx1276 *lora)
Enables interrupt on DIO0 when packet received SX1276 module will pull DIO0 line high -
void lora_enable_interrupt_tx_done(lora_sx1276 *lora)
Enables interrupt on DIO0 when transmission is done SX1276 module will pull DIO0 line high -
void lora_clear_interrupt_tx_done(lora_sx1276 *lora)
Clears TX interrupt on DIO0
-
uint8_t lora_packet_rssi(lora_sx1276 *lora)
Returns RSSI of last received packet -
uint8_t lora_packet_snr(lora_sx1276 *lora)
Returns SNR of last received packet
-
uint8_t lora_is_transmitting(lora_sx1276 *lora)
Query modem for any ongoing packet transmission. Returns0
if no active transmission present -
uint8_t lora_send_packet_dma_start(lora_sx1276 *lora, uint8_t *data, uint8_t data_len)
Sends packet using DMA. You must calllora_send_packet_dma_complete()
when DMA is done.data
- pointer to buffer to be transmitteddata_len
- how many bytes to transmit fromdata
buffer. Returns:LORA_BUSY
in case of active transmission ongoingLORA_OK
packet scheduled to be sent.
-
void lora_send_packet_dma_complete(lora_sx1276 *lora);
Completes DMA based send packet initiated bylora_send_packet_dma_start()
-
uint8_t lora_send_packet_blocking(lora_sx1276 *lora, uint8_t *data, uint8_t data_len, uint32_t timeout)
Send packet in non-blocking modedata
- pointer to buffer to be transmitteddata_len
- how many bytes to transmit fromdata
buffer. Returns:LORA_BUSY
in case of active transmission ongoingLORA_OK
packet scheduled to be sent. Check state withlora_is_transmitting()
or by interrupt.
-
uint8_t lora_send_packet(lora_sx1276 *lora, uint8_t *data, uint8_t data_len)
Send packet and returns only when packet sent / error occured (blocking mode).data
- pointer to buffer to be transmitteddata_len
- how many bytes to transmit fromdata
buffer.timeout
- maximum wait time to finish transmission. Returns:LORA_BUSY
in case of active transmission ongoingLORA_TIMEOUT
packet wasn't transmitted in given time frame.LORA_OK
packet scheduled to be sent.
-
uint8_t lora_is_packet_available(lora_sx1276 *lora)
Checks if packet modem has packet awaiting to be received Returns0
if no packet is available, or any positive integer in case packet is ready -
uint8_t lora_pending_packet_length(lora_sx1276 *lora);
If modem has packet awaiting to be received - returns it's length. -
uint8_t lora_receive_packet(lora_sx1276 *lora, uint8_t *buffer, uint8_t buffer_len, uint8_t *error)
Receives packet from LoRa modembuffer
- pointer to buffer where copy packet to.buffer_len
- length ofbuffer
. If incoming packet greater thanbuffer_len
it will be truncated to fitbuffer_len
.error
- pointer touint8_t
to store error. Can beNULL
- so no error information will be stored. Returns actual packet length stored intobuffer
.
-
uint8_t lora_receive_packet_dma_start(lora_sx1276 *lora, uint8_t *buffer, uint8_t buffer_len, uint8_t *error);
Receives packet from LoRa modem using DMA mode. You must call `lora_receive_packet_dma_complete() from DMA receive done callbackbuffer
- pointer to buffer where copy packet to.buffer_len
- length ofbuffer
. If incoming packet greater thanbuffer_len
it will be truncated to fitbuffer_len
.error
- pointer touint8_t
to store error. Can beNULL
- so no error information will be stored. Returns actual packet length stored intobuffer
.
error
is one of:LORA_OK
- packet successfully received.LORA_EMPTY
- no packet received at the moment (check for packet bylora_is_packet_available()
before).LORA_TIMEOUT
- timeout while receiving packet (only for single receive mode).LORA_INVALID_HEADER
- packet with malformed header received.LORA_CRC_ERROR
- malformed packet received (CRC failed). Please note that you need to enable this functionality explicitly, it is disabled by default.
-
void lora_receive_packet_dma_complete(lora_sx1276 *lora);
Completes DMA based receive packet initiated bylora_receive_packet_dma_start()
-
uint8_t lora_receive_packet_blocking(lora_sx1276 *lora, uint8_t *buffer, uint8_t buffer_len, uint32_t timeout, uint8_t *error)
Receive packet in "blocking mode" i.e. function return only when packet:- In case of single receive mode: when packet arrived or timeout occurred.
Please note that it is not enough to set
timeout
to something positive - you also need to set timeout in LoRa modem by callinglora_set_rx_symbol_timeout
before. - For continuous receiving mode will wait until packet arrived / timeout occurred.
buffer
- pointer to buffer where copy packet to.buffer_len
- length ofbuffer
. If incoming packet greater thanbuffer_len
it will be truncated to fitbuffer_len
.error
- pointer touint8_t
to store error. Can beNULL
- so no error information will be stored. Returns actual packet length stored intobuffer
.
error
is one of:LORA_OK
- packet successfully received.LORA_EMPTY
- no packet received at the moment (check for packet bylora_is_packet_available()
before).LORA_TIMEOUT
- timeout while receiving packet (only for single receive mode).LORA_INVALID_HEADER
- packet with malformed header received.LORA_CRC_ERROR
- malformed packet received (CRC failed). Please note that you need to enable this functionality explicitly, it is disabled by default.
- In case of single receive mode: when packet arrived or timeout occurred.
Please note that it is not enough to set
-
void lora_set_rx_symbol_timeout(lora_sx1276 *lora, uint16_t symbols)
Sets timeout forlora_mode_receive_single()
in symbols.symbols
- timeout value. Valid from4
to1024
symbols. For more information refer to datasheet section 4.1.5