0
votes

I'm trying send data from Arduino to ESP32 through LoRa. I'm using 2 identical Ra-02 Aithinker modules with antennas. I use ususal library for Arduino "LoRa" and same one ported for ESP32. I didn't implemented all the functions because I need only the sipliest setup.

Here is the code of ported library:

LoRa.h:

#ifndef LORA_H
#define LORA_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"

#define PIN_NUM_MISO 25
#define PIN_NUM_MOSI 23
#define PIN_NUM_CLK  19
#define PIN_NUM_CS   22
#define PIN_NUM_RST  18

#define LORA_DEFAULT_DIO0_PIN  2

#define PA_OUTPUT_RFO_PIN      0
#define PA_OUTPUT_PA_BOOST_PIN 1

// registers
#define REG_FIFO                 0x00
#define REG_OP_MODE              0x01
#define REG_FRF_MSB              0x06
#define REG_FRF_MID              0x07
#define REG_FRF_LSB              0x08
#define REG_PA_CONFIG            0x09
#define REG_LNA                  0x0c
#define REG_FIFO_ADDR_PTR        0x0d
#define REG_FIFO_TX_BASE_ADDR    0x0e
#define REG_FIFO_RX_BASE_ADDR    0x0f
#define REG_FIFO_RX_CURRENT_ADDR 0x10
#define REG_IRQ_FLAGS            0x12
#define REG_RX_NB_BYTES          0x13
#define REG_PKT_RSSI_VALUE       0x1a
#define REG_PKT_SNR_VALUE        0x1b
#define REG_MODEM_CONFIG_1       0x1d
#define REG_MODEM_CONFIG_2       0x1e
#define REG_PREAMBLE_MSB         0x20
#define REG_PREAMBLE_LSB         0x21
#define REG_PAYLOAD_LENGTH       0x22
#define REG_MODEM_CONFIG_3       0x26
#define REG_RSSI_WIDEBAND        0x2c
#define REG_DETECTION_OPTIMIZE   0x31
#define REG_DETECTION_THRESHOLD  0x37
#define REG_SYNC_WORD            0x39
#define REG_DIO_MAPPING_1        0x40
#define REG_VERSION              0x42

// modes
#define MODE_LONG_RANGE_MODE     0x80
#define MODE_SLEEP               0x00
#define MODE_STDBY               0x01
#define MODE_TX                  0x03
#define MODE_RX_CONTINUOUS       0x05
#define MODE_RX_SINGLE           0x06

// PA config
#define PA_BOOST                 0x80

// IRQ masks
#define IRQ_TX_DONE_MASK           0x08
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
#define IRQ_RX_DONE_MASK           0x40

#define MAX_PKT_LENGTH           255

class LoRaClass{
public:
  LoRaClass();

  uint8_t begin(long frequency=0);

  void sleep();
  void setFrequency(long frequency);
  void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
  void idle();
  int parsePacket(int size = 0);
  virtual int available();
  virtual int read();
  int packetRssi();
  uint8_t beginPacket(uint8_t implicitHeader = false);
  uint8_t endPacket();
  size_t write(const uint8_t *buffer, size_t size);
  void setSpreadingFactor(int sf);
  void dumpRegisters();

private:
    uint8_t singleTransfer(uint8_t data);   
    uint8_t readRegister(uint8_t address);
    void writeRegister(uint8_t address, uint8_t value);
    void explicitHeaderMode();
    void implicitHeaderMode();
private:
  //SPISettings _spiSettings;
  spi_device_handle_t _spi;
  int _ss;
  int _reset;
  int _dio0;
  int _frequency;
  int _packetIndex;
  int _implicitHeaderMode;
  void (*_onReceive)(int);
};

extern LoRaClass LoRa;

#endif

LoRa.c:

#include "LoRa.h"

// registers
#define REG_FIFO                 0x00
#define REG_OP_MODE              0x01
#define REG_FRF_MSB              0x06
#define REG_FRF_MID              0x07
#define REG_FRF_LSB              0x08
#define REG_PA_CONFIG            0x09
#define REG_LNA                  0x0c
#define REG_FIFO_ADDR_PTR        0x0d
#define REG_FIFO_TX_BASE_ADDR    0x0e
#define REG_FIFO_RX_BASE_ADDR    0x0f
#define REG_FIFO_RX_CURRENT_ADDR 0x10
#define REG_IRQ_FLAGS            0x12
#define REG_RX_NB_BYTES          0x13
#define REG_PKT_RSSI_VALUE       0x1a
#define REG_PKT_SNR_VALUE        0x1b
#define REG_MODEM_CONFIG_1       0x1d
#define REG_MODEM_CONFIG_2       0x1e
#define REG_PREAMBLE_MSB         0x20
#define REG_PREAMBLE_LSB         0x21
#define REG_PAYLOAD_LENGTH       0x22
#define REG_MODEM_CONFIG_3       0x26
#define REG_RSSI_WIDEBAND        0x2c
#define REG_DETECTION_OPTIMIZE   0x31
#define REG_DETECTION_THRESHOLD  0x37
#define REG_SYNC_WORD            0x39
#define REG_DIO_MAPPING_1        0x40
#define REG_VERSION              0x42

// modes
#define MODE_LONG_RANGE_MODE     0x80
#define MODE_SLEEP               0x00
#define MODE_STDBY               0x01
#define MODE_TX                  0x03
#define MODE_RX_CONTINUOUS       0x05
#define MODE_RX_SINGLE           0x06

// PA config
#define PA_BOOST                 0x80

// IRQ masks
#define IRQ_TX_DONE_MASK           0x08
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
#define IRQ_RX_DONE_MASK           0x40

#define MAX_PKT_LENGTH           255


LoRaClass::LoRaClass() {
  //_spiSettings(8E6, MSBFIRST, SPI_MODE0),
  _ss = PIN_NUM_CS;
  _reset = PIN_NUM_RST;
  _dio0 = LORA_DEFAULT_DIO0_PIN;
  _frequency = 0;
  _packetIndex = 0;
  _implicitHeaderMode = 0;
  //_onReceive(NULL)

  // setup pins
    gpio_config_t io_conf;
    io_conf.intr_type =  GPIO_INTR_DISABLE  ;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = (uint64_t)(((uint64_t)(((uint64_t)1)<<_ss)) | ((uint64_t)(((uint64_t)1)<<_reset)));
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE ;
    gpio_config(&io_conf);

    // perform reset
    gpio_set_level((gpio_num_t)_reset, 0);
    vTaskDelay(10 / portTICK_RATE_MS);
    gpio_set_level((gpio_num_t)_reset, 1);
    vTaskDelay(10 / portTICK_RATE_MS);

    // set SS high
    gpio_set_level((gpio_num_t)_ss, 1);

    esp_err_t ret;

    //memset(_spi,0,sizeof(spi_device_handle_t));

    spi_bus_config_t buscfg;
    memset(&buscfg,0,sizeof(buscfg));
    buscfg.miso_io_num=PIN_NUM_MISO;
    buscfg.mosi_io_num=PIN_NUM_MOSI;
    buscfg.sclk_io_num=PIN_NUM_CLK;
    buscfg.quadwp_io_num=-1;
    buscfg.quadhd_io_num=-1;

    spi_device_interface_config_t devcfg;
    memset(&devcfg,0,sizeof(devcfg));
    devcfg.clock_speed_hz=2*1000*1000;               //Clock out at 10 MHz
    devcfg.mode=0;  
    devcfg.spics_io_num=-1;                     //CS pin
    devcfg.queue_size=7;                          //We want to be able to queue 7 transactions at a time

    ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1);
    if (ret != ESP_OK) {
        printf("Error: spi_bus_initialize: %0d",ret);
    }
    ret=spi_bus_add_device(HSPI_HOST, &devcfg, &_spi);
    if (ret != ESP_OK) {
        printf("Error: spi_bus_add_device: %0d",ret);
    }   
    printf("\n\nLoRa Initialized\n");
}

uint8_t LoRaClass::begin(long frequency) {
    uint8_t version = readRegister(REG_VERSION);
    if (version != 0x12) {
        return version;
    }

    sleep();
    if (frequency>0) setFrequency(frequency);
    writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
    writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
    writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
    writeRegister(REG_MODEM_CONFIG_3, 0x04);
    setTxPower(17);
    idle();
    printf("\n\nLoRa started\n");
    return 1;
}

uint8_t LoRaClass::singleTransfer(uint8_t data)
{
    uint32_t resp=0;
    esp_err_t ret;

    spi_transaction_t t;
    memset(&t, 0, sizeof(t));       //Zero out the transaction
    t.length=8;                     //Command is 8 bits
    t.tx_buffer=&data;               //The data is the cmd itself
    t.rx_buffer=&resp;

    ret = spi_device_transmit(_spi, &t);  //Transmit!
    if (ret != ESP_OK) printf("spi_device_transmit error: 0x%0x\n",ret);

    return resp;
}

uint8_t LoRaClass::readRegister(uint8_t address)
{
    gpio_set_level((gpio_num_t)_ss, 0);
    vTaskDelay(1 / portTICK_RATE_MS);   

    singleTransfer(address & 0x7f);
    //printf(".");
    uint8_t resp =  singleTransfer(0x00);

    vTaskDelay(1 / portTICK_RATE_MS);   
    gpio_set_level((gpio_num_t)_ss, 1);
    return resp;
}

void LoRaClass::writeRegister(uint8_t address, uint8_t value)
{
    gpio_set_level((gpio_num_t)_ss, 0);
    vTaskDelay(1 / portTICK_RATE_MS);   

    singleTransfer(address | 0x80);
    singleTransfer(value);

    vTaskDelay(1 / portTICK_RATE_MS);   
    gpio_set_level((gpio_num_t)_ss, 1);
}

void LoRaClass::sleep()
{
  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
}

void LoRaClass::setFrequency(long frequency)
{
  _frequency = frequency;

  long fstep = 61.03515625;
  long frfl = frequency/fstep;
  uint64_t frf = ((uint64_t)frfl);

  writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
  writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
  writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
}

void LoRaClass::setTxPower(int level, int outputPin)
{
  if (PA_OUTPUT_RFO_PIN == outputPin) {
    // RFO
    if (level < 0) {
      level = 0;
    } else if (level > 14) {
      level = 14;
    }

    writeRegister(REG_PA_CONFIG, 0x70 | level);
  } else {
    // PA BOOST
    if (level < 2) {
      level = 2;
    } else if (level > 17) {
      level = 17;
    }

    writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
  }
}

void LoRaClass::idle()
{
  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
}

int LoRaClass::parsePacket(int size)
{
    int packetLength = 0;
    int irqFlags = readRegister(REG_IRQ_FLAGS);

    if (size > 0) {
        implicitHeaderMode();   
        writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
    } else {
        explicitHeaderMode();
    }

    writeRegister(REG_IRQ_FLAGS, irqFlags);

    if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
        _packetIndex = 0;
        if (_implicitHeaderMode) {
            packetLength = readRegister(REG_PAYLOAD_LENGTH);
        } else {
            packetLength = readRegister(REG_RX_NB_BYTES);
        }
        writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
        idle();
    } else 
    if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) {
        writeRegister(REG_FIFO_ADDR_PTR, 0);
        writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
    }

    return packetLength;
}

void LoRaClass::explicitHeaderMode()
{
  _implicitHeaderMode = 0;

  writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe);
}

void LoRaClass::implicitHeaderMode()
{
  _implicitHeaderMode = 1;

  writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01);
}

int LoRaClass::available()
{
  return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
}

int LoRaClass::read()
{

  _packetIndex++;

  return readRegister(REG_FIFO);
}

int LoRaClass::packetRssi()
{
  return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < 868000000 ? 164 : 157));
}

uint8_t LoRaClass::beginPacket(uint8_t implicitHeader)
{
  idle();

  if (implicitHeader) {
    implicitHeaderMode();
  } else {
    explicitHeaderMode();
  }

  writeRegister(REG_FIFO_ADDR_PTR, 0);
  writeRegister(REG_PAYLOAD_LENGTH, 0);
  return 1;
}

uint8_t LoRaClass::endPacket()
{
  // put in TX mode
  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);

  // wait for TX done
  while((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0);

  // clear IRQ's
  writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);

  return 1;
}

size_t LoRaClass::write(const uint8_t *buffer, size_t size)
{
  int currentLength = readRegister(REG_PAYLOAD_LENGTH);

  // check size
  if ((currentLength + size) > MAX_PKT_LENGTH) {
    size = MAX_PKT_LENGTH - currentLength;
  }

  // write data
  for (size_t i = 0; i < size; i++) {
    writeRegister(REG_FIFO, buffer[i]);
  }

  // update length
  writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);

  return size;
}

void LoRaClass::setSpreadingFactor(int sf)
{
  if (sf < 6) {
    sf = 6;
  } else if (sf > 12) {
    sf = 12;
  }

  if (sf == 6) {
    writeRegister(REG_DETECTION_OPTIMIZE, 0xc5);
    writeRegister(REG_DETECTION_THRESHOLD, 0x0c);
  } else {
    writeRegister(REG_DETECTION_OPTIMIZE, 0xc3);
    writeRegister(REG_DETECTION_THRESHOLD, 0x0a);
  }

  writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0));
}

void LoRaClass::dumpRegisters()
{
  for (int i = 0; i < 128; i++) {
    printf("0x%02X=0x%02X\n",i,readRegister(i));
  }
}

On Arduino I send like this:

  LoRa.beginPacket();
  LoRa.write(0);
  LoRa.write(1);
  LoRa.write(2);
  LoRa.write(3);
  LoRa.endPacket();

  delay(3000);

On ESP32 I receive like this:

while (1) {     

            packetSize = LoRa.parsePacket();        
            if (packetSize>0) {
                printf("\nReceived: ");
                while (LoRa.available()) {
                    printf("%02X ",LoRa.read());
                }       
                printf(" (RSSI: %0d)\n", LoRa.packetRssi());

            }                       

        }

But problem is that I receive this:

Received: 99 CB 2B 0F  (RSSI: -89)
Received: 90 0D 2B 1F  (RSSI: -90)
Received: 9A 9D 2B 0F  (RSSI: -94)
Received: 00 01 2B 07  (RSSI: -87)
Received: 00 0D 2B 0F  (RSSI: -89)
Received: 9A 0B 2B 0F  (RSSI: -94)
Received: A8 C1 2B 0F  (RSSI: -90)
Received: 00 01 A3 03  (RSSI: -88)
Received: 00 07 2B 0F  (RSSI: -87)
Received: 00 0D 2B 0F  (RSSI: -89)
Received: 09 08 2B 5F  (RSSI: -89)
Received: 99 08 02 0A  (RSSI: -95)
Received: A9 0B 2B 0F  (RSSI: -95)

Could anybody please suggest waht to fix in order to receive data correct?

BTW, from ESP32 to ESP32 data comes correctly. I also dumped SX1278 registers on both sides - they are identical.

1

1 Answers

1
votes

Have you checked the SPI frequency on the Arduino side? The developer of the LoRa library says in the FAQ that 5v Arduinos might experience problems when using logic level converters to talk to the 3.3v LoRa module. You might need to slowdown the speed of the SPI bus in order to work.