Search code examples
esp32lora

Sending and receiving data using ESP32S3 with Ebyte Lora E22 is not working


I have wrote 2 simple programs receiver and transmitter in ESP32S3 connected to Lora EByte220 in a board using esp-idf, I can't see any packets receiver from receiver side and not sure how to fix/approach it

Lora transmitter program lora_transmitter.c:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "lora_transmitter.h"
#include <string.h>

#define TAG "LoRa Tranmitter"
#define UART_NUM UART_NUM_1
#define PIN_TX 21
#define PIN_RX 14
#define BAUD_RATE 9600

#define BUF_SIZE (1024)

void init_lora_module() {
    // Configure UART parameters
    const uart_config_t uart_config = {
        .baud_rate = BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };

    // Install UART driver and set up UART
    ESP_ERROR_CHECK(uart_driver_install(UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL,     0));
    ESP_ERROR_CHECK(uart_param_config(UART_NUM, &uart_config));
    ESP_ERROR_CHECK(uart_set_pin(UART_NUM, PIN_TX, PIN_RX, UART_PIN_NO_CHANGE,     UART_PIN_NO_CHANGE));

    ESP_LOGI(TAG, "LoRa module initialized");
}

void lora_transmit_task(void *pvParameters) {
    const char *data_to_send = "Hello, LoRa!";

    while (1) {
        // Send data over UART
        int len = uart_write_bytes(UART_NUM, data_to_send, strlen(data_to_send));
        if (len > 0) {
            ESP_LOGI(TAG, "Sent: %s", data_to_send);
        } else {
            ESP_LOGE(TAG, "Failed to send data");
        }

        vTaskDelay(pdMS_TO_TICKS(2000)); // Send data every 2 seconds
    }
}

where lora_transmitter.h is:

#ifndef LORA_SVC_H
#define LORA_SVC_H
#ifdef __cplusplus

// for C++ calls (main.cpp) in this case
extern "C" {
#endif


void lora_transmit_task(void *pvParameters);
void init_lora_module();

#ifdef __cplusplus
}
#endif

#endif // LORA_SVC_H

main.cpp:

extern "C" void app_main(void) {
    // Initialize the LoRa module
    init_lora_module();

    // Create a task to transmit data
    xTaskCreate(lora_transmit_task, "lora_transmit_task", 4096, NULL, 5, NULL);
}

in the other hand - the receiver is similar but transmit task and pins:

#define PIN_TX 4
#define PIN_RX 5

void lora_receive_task(void *pvParameters) {
    uint8_t rx_buffer[BUF_SIZE];

    while (1) {
        // Read data from UART
        int len = uart_read_bytes(UART_NUM, rx_buffer, BUF_SIZE - 1, pdMS_TO_TICKS(100));
        ESP_LOGI(TAG, "len is %d", len);
        if (len > 0) {
            rx_buffer[len] = '\0'; // Null-terminate the received data
            ESP_LOGI(TAG, "Received: %s", (char *)rx_buffer);
        }
    
        vTaskDelay(pdMS_TO_TICKS(2000));
        ESP_LOGI(TAG, "Waiting....");
    }
}

choosing the pins according to board schematic.

transmit program always prints: I (3026319) LoRa Tranmitter: Sent: Hello, LoRa! where receiver program always prints: I (1008539) LoRa Receiver: Waiting....

what did I miss in my code ? what is wrong with this UART program data packets transmitting and receiving?

I though at first it could be the pins, but reviewed the schematic of it many times even tried many pins combinations

receiver part:

enter image description here

enter image description here

enter image description here

transmitter part:

enter image description here

enter image description here


Solution

  • The issue was that I have assumed that M0, M1 defaults will be fine. apparently, I have to set them explicitly.

    in transmit part, M0, M1 were easy to set via GPIO config.

    in receiver part it was a bit harder since I had IO expander which I controlled via I2C.

    Setting M0, M1 to normal mode (0) solved the issue.

    here is how I did it in transmitter in init module function:

        // Configure M0 and M1 pins for mode selection
        gpio_config_t io_conf = {
            .pin_bit_mask = (1ULL << PIN_M0) | (1ULL << PIN_M1),
            .mode = GPIO_MODE_OUTPUT,
            .pull_up_en = GPIO_PULLUP_ENABLE,
        };
        gpio_config(&io_conf);
        
        // Set module to normal mode (M0 = 0, M1 = 0)
        gpio_set_level(PIN_M0, 0);
        gpio_set_level(PIN_M1, 0);
    

    and here is how I did it in receiver part:

    // I2C configuration
    #define I2C_MASTER_SCL_IO 2      // SCL pin
    #define I2C_MASTER_SDA_IO 1      // SDA pin
    #define I2C_MASTER_NUM I2C_NUM_1  // I2C port number
    #define I2C_FREQ_HZ          100000      // I2C frequency
    #define TCA9535_ADDR  0x24        // I2C address (A0=0, A1=0, A2=1)
    
    #define WRITE_BIT            I2C_MASTER_WRITE   /*!< I2C master write */
    #define READ_BIT             I2C_MASTER_READ    /*!< I2C master read */
    //I2C function
    esp_err_t i2c_master_init(void) {
        i2c_config_t conf = {
            .mode = I2C_MODE_MASTER,
            .sda_io_num = I2C_MASTER_SDA_IO,
            .scl_io_num = I2C_MASTER_SCL_IO,
            .sda_pullup_en = GPIO_PULLUP_ENABLE,
            .scl_pullup_en = GPIO_PULLUP_ENABLE,
            .master.clk_speed = I2C_FREQ_HZ,
        };
        ESP_ERROR_CHECK(i2c_param_config(I2C_MASTER_NUM, &conf));
        ESP_ERROR_CHECK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER, 0, 0, 0));
        return ESP_OK;
    }
    
    
    // Function to write data to a specific register
    esp_err_t tca9535_write_register(uint8_t reg, uint8_t value) {
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        i2c_master_start(cmd);
        i2c_master_write_byte(cmd, (TCA9535_ADDR << 1) | WRITE_BIT, true);
        i2c_master_write_byte(cmd, reg, true);  // Write to the register
        i2c_master_write_byte(cmd, value, true); // Write the value to the register
        i2c_master_stop(cmd);
        esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd);
        return ret;
    }
    
    // Function to configure P00 and P01 as outputs
    esp_err_t configure_p00_p01_as_output(void) {
        uint8_t iodir_value = 0xFC;  // 1111 1100, P00 and P01 set as outputs (0)
        return tca9535_write_register(0x06, iodir_value);  // 0x06 is IODIR register
    }
    
    // Function to configure P01 as an output
    esp_err_t configure_p01_as_output(void) {
        uint8_t iodir_value = 0xFD;  // 1111 1101, P01 set as output (0)
        return tca9535_write_register(0x06, iodir_value);  // 0x06 is IODIR register
    }
    
    // Function to set P00 and P01 to high or low
    esp_err_t set_p00_p01(uint8_t p00_state, uint8_t p01_state) {
        uint8_t gpio_value = (p00_state ? 0x01 : 0x00) | (p01_state ? 0x02 : 0x00);
        return tca9535_write_register(0x02, gpio_value);  // 0x02 is GPIO output register
    }
    // I2C functions end
    // I2C end
    

    and in init module:

       // I2C
        ESP_ERROR_CHECK(i2c_master_init());
        // Configure P00 as an output
        esp_err_t err = configure_p00_p01_as_output();
        ESP_LOGI(TAG, "err is %s", esp_err_to_name(err));
    
        // Set P00 and P01 to low
        err = set_p00_p01(0, 0);
        ESP_LOGI(TAG, "err is %s", esp_err_to_name(err));
        vTaskDelay(1000 / portTICK_PERIOD_MS);  // Wait for 1 second
    

    Thanks