beegee-tokyo / SX126x-Arduino

Arduino library to use Semtech SX126x LoRa chips and modules to communicate
MIT License
226 stars 64 forks source link

SX126x-Arduino + Ethernet #3

Closed brolly759 closed 4 years ago

brolly759 commented 4 years ago

I have successfully used your library to communicate 2 modules together but seem to have an issue when I try to use Ethernet at the same time.

Here is the Ethernet, ESP32 I am using: https://www.amazon.com/Olimex-ESP32-POE-ISO-Espressif-Ethernet-Isolation/dp/B07R1ZMSG7/ref=sr_1_2?keywords=esp32+poe&qid=1572020502&sr=8-2

From what I can tell I need to use a different SPI pins, here is my configuration:

// ESP32 - SX126x pin configuration int PIN_LORA_RESET = 5; // LORA RESET int PIN_LORA_NSS = 15; // LORA SPI CS int PIN_LORA_SCLK = 0; // LORA SPI CLK int PIN_LORA_MISO = 2; // LORA SPI MISO int PIN_LORA_DIO_1 = 32; //21; // LORA DIO_1 int PIN_LORA_BUSY = 16; //22; // LORA SPI BUSY int PIN_LORA_MOSI = 4; // LORA SPI MOSI int RADIO_TXEN = -1; // 26; // LORA ANTENNA TX ENABLE int RADIO_RXEN = -1; //27; // LORA ANTENNA RX ENABLE

What I would really like to test is to remove somehow all the events / IRQ's and just check for a message coming in manually.

Side note, would be nice if this was ported to AVR also :)

brolly759 commented 4 years ago

to update, I got them both to work but I do see some timing issues. My original issue was int RADIO_TXEN and RADIO_RXEN set to 26,27 instead of -1. Now I just need to figure out the timing issue. Here is my code: `

define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT

define ETH_PHY_POWER 12

include

include

include

include

static bool eth_connected = false;

hw_config hwConfig; /* // ESP32 - SX126x pin configuration int PIN_LORA_RESET = 4; // LORA RESET int PIN_LORA_NSS = 3; // LORA SPI CS int PIN_LORA_SCLK = 18; // LORA SPI CLK int PIN_LORA_MISO = 19; // LORA SPI MISO int PIN_LORA_DIO_1 = 32; //21; // LORA DIO_1 int PIN_LORA_BUSY = 33; //22; // LORA SPI BUSY int PIN_LORA_MOSI = 23; // LORA SPI MOSI int RADIO_TXEN = 2; // 26; // LORA ANTENNA TX ENABLE int RADIO_RXEN = 1; //27; // LORA ANTENNA RX ENABLE

*/

// ESP32 - SX126x pin configuration int PIN_LORA_RESET = 5; // LORA RESET int PIN_LORA_NSS = 15; // LORA SPI CS int PIN_LORA_SCLK = 0; // LORA SPI CLK int PIN_LORA_MISO = 2; // LORA SPI MISO int PIN_LORA_DIO_1 = 32; //21; // LORA DIO_1 int PIN_LORA_BUSY = 16; //22; // LORA SPI BUSY int PIN_LORA_MOSI = 4; // LORA SPI MOSI int RADIO_TXEN = -1; // 26; // LORA ANTENNA TX ENABLE int RADIO_RXEN = -1; //27; // LORA ANTENNA RX ENABLE

// Function declarations void OnTxDone(void); void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); void OnTxTimeout(void); void OnRxTimeout(void); void OnRxError(void); void OnCadDone(bool cadResult);

//#define LED_BUILTIN

// Define LoRa parameters

define RF_FREQUENCY 915000000 // Hz

define TX_OUTPUT_POWER 22 // dBm

define LORA_BANDWIDTH 0 // [0: 125 kHz, 1: 250 kHz, 2: 500 kHz, 3: Reserved]

define LORA_SPREADING_FACTOR 7 // [SF7..SF12]

define LORA_CODINGRATE 1 // [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]

define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx

define LORA_SYMBOL_TIMEOUT 0 // Symbols

define LORA_FIX_LENGTH_PAYLOAD_ON false

define LORA_IQ_INVERSION_ON false

define RX_TIMEOUT_VALUE 3000

define TX_TIMEOUT_VALUE 3000

define BUFFER_SIZE 64 // Define the payload size here

static RadioEvents_t RadioEvents; static uint16_t BufferSize = BUFFER_SIZE; static uint8_t RcvBuffer[BUFFER_SIZE]; static uint8_t TxdBuffer[BUFFER_SIZE]; static bool isMaster = false; const uint8_t PingMsg[] = "PING"; const uint8_t PongMsg[] = "PONG";

time_t timeToSend;

time_t cadTime;

uint8_t pingCnt = 0; uint8_t pongCnt = 0;

void setup() { // pinMode(LED_BUILTIN, OUTPUT); // digitalWrite(LED_BUILTIN, LOW);

// Define the HW configuration between MCU and SX126x
hwConfig.CHIP_TYPE = SX1262_CHIP;         // Example uses an eByte E22 module with an SX1262
hwConfig.PIN_LORA_RESET = PIN_LORA_RESET; // LORA RESET
hwConfig.PIN_LORA_NSS = PIN_LORA_NSS;    // LORA SPI CS
hwConfig.PIN_LORA_SCLK = PIN_LORA_SCLK;   // LORA SPI CLK
hwConfig.PIN_LORA_MISO = PIN_LORA_MISO;   // LORA SPI MISO
hwConfig.PIN_LORA_DIO_1 = PIN_LORA_DIO_1; // LORA DIO_1
hwConfig.PIN_LORA_BUSY = PIN_LORA_BUSY;   // LORA SPI BUSY
hwConfig.PIN_LORA_MOSI = PIN_LORA_MOSI;   // LORA SPI MOSI
hwConfig.RADIO_TXEN = RADIO_TXEN;         // LORA ANTENNA TX ENABLE
hwConfig.RADIO_RXEN = RADIO_RXEN;         // LORA ANTENNA RX ENABLE
hwConfig.USE_DIO2_ANT_SWITCH = false;    // Example uses an eByte E22 module which uses RXEN and TXEN pins as antenna control
hwConfig.USE_DIO3_TCXO = true;            // Example uses an eByte E22 module which uses DIO3 to control oscillator voltage
hwConfig.USE_DIO3_ANT_SWITCH = false;    // Only Insight ISP4520 module uses DIO3 as antenna control

// Initialize Serial for debug output
Serial.begin(115200);

WiFi.onEvent(WiFiEvent); ETH.begin();

Serial.println("=====================================");
Serial.println("SX126x PingPong test");
Serial.println("=====================================");

Serial.println("MCU Espressif ESP32");

uint8_t deviceId[8];

BoardGetUniqueId(deviceId);
Serial.printf("BoardId: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
              deviceId[7],
              deviceId[6],
              deviceId[5],
              deviceId[4],
              deviceId[3],
              deviceId[2],
              deviceId[1],
              deviceId[0]);

// Initialize the LoRa chip
Serial.println("Starting lora_hardware_init");
lora_hardware_init(hwConfig);

// Initialize the Radio callbacks
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
RadioEvents.RxError = OnRxError;
RadioEvents.CadDone = OnCadDone;

// Initialize the Radio
Radio.Init(&RadioEvents);

// Set Radio channel
Radio.SetChannel(RF_FREQUENCY);

// Set Radio TX configuration
Radio.SetTxConfig(MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                  LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                  LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                  true, 0, 0, LORA_IQ_INVERSION_ON, TX_TIMEOUT_VALUE);

// Set Radio RX configuration
Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                  LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                  LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                  0, true, 0, 0, LORA_IQ_INVERSION_ON, true);

// Start LoRa
Serial.println("Starting Radio.Rx");
Radio.Rx(RX_TIMEOUT_VALUE);

timeToSend = millis();

} long lastSent = 0; void loop() { // Handle Radio events Radio.IrqProcess();

long current = millis(); if(current - lastSent > 3000){ if (eth_connected) { // Serial.println("testClient"); testClient("google.com", 80); lastSent = millis(); }

} // We are on FreeRTOS, give other tasks a chance to run // Serial.println("In Loop"); delay(100); yield(); }

/*@brief Function to be executed on Radio Tx Done event / void OnTxDone(void) { Serial.println("OnTxDone"); Radio.Rx(RX_TIMEOUT_VALUE); }

/*@brief Function to be executed on Radio Rx Done event / void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) { Serial.println("OnRxDone"); delay(10); BufferSize = size; memcpy(RcvBuffer, payload, BufferSize);

Serial.printf("RssiValue=%d dBm, SnrValue=%d\n", rssi, snr);

for (int idx = 0; idx < size; idx++)
{
    Serial.printf("%02X ", RcvBuffer[idx]);
}
Serial.println("");

// digitalWrite(LED_BUILTIN, HIGH);

if (isMaster == true)
{
    if (BufferSize > 0)
    {
        if (strncmp((const char *)RcvBuffer, (const char *)PongMsg, 4) == 0)
        {
            Serial.println("Received a PONG in OnRxDone as Master");

            // Wait 500ms before sending the next package
            delay(500);

            // Check if our channel is available for sending
            Radio.Standby();
            SX126xSetCadParams(LORA_CAD_08_SYMBOL, LORA_SPREADING_FACTOR + 13, 10, LORA_CAD_ONLY, 0);
            SX126xSetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                                  IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                                  IRQ_RADIO_NONE, IRQ_RADIO_NONE);
            cadTime = millis();
            Radio.StartCad();
            // Sending next Ping will be started when the channel is free
        }
        else if (strncmp((const char *)RcvBuffer, (const char *)PingMsg, 4) == 0)
        { // A master already exists then become a slave
            Serial.println("Received a PING in OnRxDone as Master");

            isMaster = true;
            Radio.Rx(RX_TIMEOUT_VALUE);
        }
        else // valid reception but neither a PING or a PONG message
        {   // Set device as master and start again
            isMaster = true;
            Radio.Rx(RX_TIMEOUT_VALUE);
        }
    }
}
else
{
    if (BufferSize > 0)
    {
        if (strncmp((const char *)RcvBuffer, (const char *)PingMsg, 4) == 0)
        {
            Serial.println("Received a PING in OnRxDone as Slave");

            // Check if our channel is available for sending
            Radio.Standby();
            SX126xSetCadParams(LORA_CAD_08_SYMBOL, LORA_SPREADING_FACTOR + 13, 10, LORA_CAD_ONLY, 0);
            SX126xSetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                                  IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                                  IRQ_RADIO_NONE, IRQ_RADIO_NONE);
            cadTime = millis();
            Radio.StartCad();
            // Sending Pong will be started when the channel is free
        }
        else // valid reception but not a PING as expected
        {   // Set device as master and start again
            Serial.println("Received something in OnRxDone as Slave");

            isMaster = true;
            Radio.Rx(RX_TIMEOUT_VALUE);
        }
    }
}

}

/*@brief Function to be executed on Radio Tx Timeout event / void OnTxTimeout(void) { // Radio.Sleep(); Serial.println("OnTxTimeout"); // digitalWrite(LED_BUILTIN, LOW);

Radio.Rx(RX_TIMEOUT_VALUE);

}

/*@brief Function to be executed on Radio Rx Timeout event / void OnRxTimeout(void) { Serial.println("OnRxTimeout");

//digitalWrite(LED_BUILTIN, LOW);

if (isMaster == true)
{
    // Wait 500ms before sending the next package
    delay(500);

    // Check if our channel is available for sending
    Radio.Standby();
    SX126xSetCadParams(LORA_CAD_08_SYMBOL, LORA_SPREADING_FACTOR + 13, 10, LORA_CAD_ONLY, 0);
    SX126xSetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                          IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                          IRQ_RADIO_NONE, IRQ_RADIO_NONE);
    cadTime = millis();
    Radio.StartCad();
    // Sending the ping will be started when the channel is free
}
else
{
    // No Ping received within timeout, switch to Master
    isMaster = true;
    // Check if our channel is available for sending
    Radio.Standby();
    SX126xSetCadParams(LORA_CAD_08_SYMBOL, LORA_SPREADING_FACTOR + 13, 10, LORA_CAD_ONLY, 0);
    SX126xSetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                          IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                          IRQ_RADIO_NONE, IRQ_RADIO_NONE);
    cadTime = millis();
    Radio.StartCad();
    // Sending the ping will be started when the channel is free
}

}

/*@brief Function to be executed on Radio Rx Error event / void OnRxError(void) { Serial.println("OnRxError");

// digitalWrite(LED_BUILTIN, LOW);

if (isMaster == true)
{
    // Wait 500ms before sending the next package
    delay(500);

    // Check if our channel is available for sending
    Radio.Standby();
    SX126xSetCadParams(LORA_CAD_08_SYMBOL, LORA_SPREADING_FACTOR + 13, 10, LORA_CAD_ONLY, 0);
    SX126xSetDioIrqParams(IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                          IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED,
                          IRQ_RADIO_NONE, IRQ_RADIO_NONE);
    cadTime = millis();
    Radio.StartCad();
    // Sending the ping will be started when the channel is free
}
else
{
    Radio.Rx(RX_TIMEOUT_VALUE);
}

}

/*@brief Function to be executed on Radio Rx Error event / void OnCadDone(bool cadResult) { time_t duration = millis() - cadTime; if (cadResult) { Serial.printf("CAD returned channel busy after %ldms\n", duration);

    Radio.Rx(RX_TIMEOUT_VALUE);
}
else
{
    Serial.printf("CAD returned channel free after %ldms\n", duration);

    if (isMaster)
    {
        Serial.println("Sending a PING in OnCadDone as Master");

        // Send the next PING frame
        TxdBuffer[0] = 'P';
        TxdBuffer[1] = 'I';
        TxdBuffer[2] = 'N';
        TxdBuffer[3] = 'G';
    }
    else
    {
        Serial.println("Sending a PONG in OnCadDone as Slave");

        // Send the reply to the PONG string
        TxdBuffer[0] = 'P';
        TxdBuffer[1] = 'O';
        TxdBuffer[2] = 'N';
        TxdBuffer[3] = 'G';
    }
    // We fill the buffer with numbers for the payload
    for (int i = 4; i < BufferSize; i++)
    {
        TxdBuffer[i] = i - 4;
    }

    Radio.Send(TxdBuffer, BufferSize);
}

}

void WiFiEvent(WiFiEvent_t event) { switch (event) { case SYSTEM_EVENT_ETH_START: Serial.println("ETH Started"); //set eth hostname here ETH.setHostname("esp32-ethernet"); break; case SYSTEM_EVENT_ETH_CONNECTED: Serial.println("ETH Connected"); break; case SYSTEM_EVENT_ETH_GOT_IP: Serial.print("ETH MAC: "); Serial.print(ETH.macAddress()); Serial.print(", IPv4: "); Serial.print(ETH.localIP()); if (ETH.fullDuplex()) { Serial.print(", FULL_DUPLEX"); } Serial.print(", "); Serial.print(ETH.linkSpeed()); Serial.println("Mbps"); eth_connected = true; break; case SYSTEM_EVENT_ETH_DISCONNECTED: Serial.println("ETH Disconnected"); eth_connected = false; break; case SYSTEM_EVENT_ETH_STOP: Serial.println("ETH Stopped"); eth_connected = false; break; default: break; } }

void testClient(const char * host, uint16_t port) { Serial.print("\nconnecting to "); Serial.println(host);

WiFiClient client; if (!client.connect(host, port)) { Serial.println("connection failed"); return; } client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host); while (client.connected() && !client.available()); while (client.available()) { Serial.write(client.read()); }

Serial.println("closing connection\n"); client.stop(); }`

beegee-tokyo commented 4 years ago

One problem could be in

void testClient(const char * host, uint16_t port)

You might need to move this to a separate task. Because while you are connecting to the client, the main loop() is blocked and the LoRa events are not handled.

Either put the LoRa stuff into a independant running task or the ETH stuff.

beegee-tokyo commented 4 years ago

Regarding AVR port, I use the Ticker library for timeouts and this is not available for AVR platform as far as I know.

brolly759 commented 4 years ago

You can close this for now, I changed the code a little and it seems to be working now so its not a hardware issue, I just need to code it better .

beegee-tokyo commented 4 years ago

Good.