Heltec LoRa (V3) with W5500 Ethernet Module

Hi All,

Was wondering if anyone has successfully got a Heltec LoRa (V3) board working together with a W5500 Ethernet Module using VSPI for the LoRa and HSPI for the W5500 ?
The aim being to have the LoRa radio working at the same time as the wired ethernet connection, and with the WiFi reading data from devices as well.

There is plenty of sample code for these individually but not integrated and operating at the same time.

If anyone has an example would be much appreciated.

Thanks

the following uses a W5500 connected to a Heltec LoRa V3 to transmit data over LoRa P2P and over Ethernet using UDP datagrams
file main.ino

// Heltec LoRa SX1262 transmit test

// File>Examples>RadioLib>SX126x>SX126x_Transmit_Interrupt

// EDITs:
//  radio.begin frequency set to 868.0
//  transmitting byte array and printing it

/*
  RadioLib SX126x Transmit with Interrupts Example

  This example transmits LoRa packets with one second delays
  between them. Each packet contains up to 256 bytes
  of data, in the form of:
  - Arduino String
  - null-terminated char array (C-string)
  - arbitrary binary data (byte array)

  Other modules from SX126x family can also be used.

  For default module settings, see the wiki page
  https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem

  For full API reference, see the GitHub Pages
  https://jgromes.github.io/RadioLib/
*/

// include the library
#include <RadioLib.h>
#include "ESP32_UDP_transmit.h"

// Heltec LoRa V3  SX1262 has the following connections:
// NSS pin:   8
// DIO1 pin:  14
// NRST pin:  12
// BUSY pin:  13
SX1262 radio = new Module(8, 14, 12, 13);

// or detect the pinout automatically using RadioBoards
// https://github.com/radiolib-org/RadioBoards
/*
#define RADIO_BOARD_AUTO
#include <RadioBoards.h>
Radio radio = new RadioModule();
*/

// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;

// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;

// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
//            and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
  // we sent a packet, set the flag
  transmittedFlag = true;
}

void setup() {
  Serial.begin(115200);
  delay(2000);
  W5500setup();    // setup W5500 Erthernet
  // initialize SX1262 with default settings
  Serial.print(F("\n\nHeltec LoRa V3 [SX1262] Initializing ... "));
  int state = radio.begin(868.0);
  if (state == RADIOLIB_ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true) { delay(10); }
  }

  // set the function that will be called
  // when packet transmission is finished
  radio.setPacketSentAction(setFlag);

  // start transmitting the first packet
  Serial.print(F("[SX1262] Sending first packet ... "));

  // you can transmit C-string or Arduino string up to
  // 256 characters long
  transmissionState = radio.startTransmit("Hello World!");

  // you can also transmit byte array up to 256 bytes long
  /*
    byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
                      0x89, 0xAB, 0xCD, 0xEF};
    state = radio.startTransmit(byteArr, 8);
  */
}

// counter to keep track of transmitted packets
int count = 0;

void loop() {

  // check if the previous LoRa transmission finished
  if (transmittedFlag) {
    // reset flag
    transmittedFlag = false;

    if (transmissionState == RADIOLIB_ERR_NONE) {
      // packet was successfully sent
      Serial.println(F("transmission finished!"));

      // NOTE: when using interrupt-driven transmit method,
      //       it is not possible to automatically measure
      //       transmission data rate using getDataRate()

    } else {
      Serial.print(F("failed, code "));
      Serial.println(transmissionState);
    }

    // clean up after transmission is finished
    // this will ensure transmitter is disabled,
    // RF switch is powered down etc.
    radio.finishTransmit();

    // wait  before transmitting again
    delay(5000);

    // send another one
    Serial.print(F("[SX1262] Sending another packet ... "));

    // you can transmit C-string or Arduino string up to
    // 256 characters long
    //String str = "Hello World! #" + String(count++);
    //transmissionState = radio.startTransmit(str);

    // you can also transmit byte array up to 256 bytes long
    static byte byteArr[] = { 0x01, 0x23, 0x45, 0x67,
                              0x89, 0xAB, 0xCD, 0xEF };
    for (int i = 0; i < sizeof(byteArr); i++)
      Serial.printf("0x%02X ", byteArr[i]);
    transmissionState = radio.startTransmit(byteArr, 8);
    byteArr[0]++;
    W5500loop(byteArr);  // transmit W5500 Ethernet
  }
}

file ESP32_UDP_transmit.h (in same directory as main.ino)

// ESP32_UDP_transmit.h UDP ESP32 W5500 ethernet transmit test data

#ifndef ESP32_UDP_TRANSMIT
#define ESP32_UDP_TRANSMIT

// function prototypes
void W5500setup(void);
void W5500loop(byte *byteArr);
void displayIPaddress(const IPAddress address, unsigned int port);
void displayMACaddress(byte address[]);

#endif


file ESP32_UDP_transmit.cpp (in same directory as main.ino)

// ESP32_UDP_transmit.cpp UDP ESP32 W5500 ethernet transmit test data

// UDP chat program using  ESP32-ETH01  tested on UNO and Nano
// **** change IP addresses and ports to suit requirements *****

#include <EthernetESP32.h>
#include <EthernetUdp.h>  // for UDP

#include "ESP32_UDP_transmit.h"  // include W5500 ethernet header file

// define Heltec LoRa V3 W5500 SPI pins
#define W5500_SCK 40
#define W5500_MISO 42
#define W5500_MOSI 39
#define W5500_CS 41

W5500Driver driver(W5500_CS);  // SPI SS is GPIO34

SPIClass hspi(HSPI);  // HSPI object used by W5500

// *****   IP of this machine and remote machine *********
IPAddress localIP(192, 168, 1, 167);  // local static localIP address
IPAddress remoteIP(192, 168, 1, 65);  // local static localIP address

// Enter a MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x32 };

unsigned int localPort = 999;   //10000;   // local port to listen on
unsigned int remotePort = 999;  //10000;  // remote port to transmiit too

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void W5500setup(void) {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  delay(2000);
  while (!Serial)
    ;
  Serial.println("\n\nUDP ESP32 ethernet transmit test data ");

  hspi.begin(W5500_SCK, W5500_MISO, W5500_MOSI, W5500_CS);
  driver.setSPI(hspi);    // specify driver SPI interface
  Ethernet.init(driver);  // for ESP32-ETH01
  Serial.println("Initialize Ethernet with DHCP:");
  if (Ethernet.begin()) {
    Serial.print("  DHCP assigned IP ");
    Serial.println(Ethernet.localIP());
  } else {
    Serial.println("Failed to configure Ethernet using DHCP");
    Ethernet.begin(localIP);
    Serial.print("configured Ethernet static IP ");
    Serial.println(Ethernet.localIP());
    // while (true) {
    // delay(1);
  }
  if (Udp.begin(localPort))  // start UDP
    Serial.print("Ethernet UDP started ");
  else Serial.println("UDP begin() failed!");
  displayIPaddress(Ethernet.localIP(), localPort);
}

void W5500loop(byte* byteArr) {
   Serial.print("\n   Transmitting datagram to ");
  displayIPaddress(remoteIP, remotePort);
  Udp.beginPacket(remoteIP, remotePort);  // send to remote localIP and port 999
  Udp.write((const uint8_t*)byteArr, 8);
  Udp.endPacket();
  delay(10);
}

// read IP address from keyboard and check it
IPAddress getIPaddress(const char* prompt) {
  IPAddress ip;
  while (1) {  // read  IP (end with new line)
    Serial.print(prompt);
    while (Serial.available() == 0) delay(10);
    char text[40] = { 0 };
    Serial.readBytesUntil('\n', (char*)text, 40);
    for (int i = 0; i < 40; i++)
      if (text[i] < ' ') text[i] = 0;  // remove CR or LF
    Serial.print(text);
    if (ip.fromString(text)) break;  // if IP OK break while
    Serial.println(" invalid IP try again");
  }
  return ip;
}


// print IPAdress and port
void displayIPaddress(const IPAddress address, unsigned int port) {
  Serial.print(" IP ");
  Serial.print(address);
  Serial.print(" port ");
  Serial.println(port);
}

void displayMACaddress(byte address[]) {
  Serial.print("MAC address ");
  for (int i = 0; i < 6; i++) {
    Serial.print("0x");
    Serial.print(address[i], HEX);
    if (i < 5) Serial.print(".");
  }
  Serial.println();
}


Heltec serial monitor output

UDP ESP32 ethernet transmit test data 
Initialize Ethernet with DHCP:
  DHCP assigned IP 192.168.1.245
Ethernet UDP started  IP 192.168.1.245 port 999


Heltec LoRa V3 [SX1262] Initializing ... success!
[SX1262] Sending first packet ... transmission finished!
[SX1262] Sending another packet ... 0x01 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF 
   Transmitting datagram to  IP 192.168.1.65 port 999
transmission finished!
[SX1262] Sending another packet ... 0x02 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF 
   Transmitting datagram to  IP 192.168.1.65 port 999
transmission finished!
[SX1262] Sending another packet ... 0x03 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF 
   Transmitting datagram to  IP 192.168.1.65 port 999
transmission finished!
[SX1262] Sending another packet ... 0x04 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF 
   Transmitting datagram to  IP 192.168.1.65 port 999
transmission finished!
[SX1262] Sending another packet ... 0x05 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF 
   Transmitting datagram to  IP 192.168.1.65 port 999
transmission finished!
[SX1262] Sending another packet ... 0x06 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF 
   Transmitting datagram to  IP 192.168.1.65 port 999
transmission finished!
[SX1262] Sending another packet ... 0x07 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF 
   Transmitting datagram to  IP 192.168.1.65 port 999

Java program to receive and display UDP datagrams

// UDPchat.java - simple peer-to-peer chat program using UDP
//           - given remote IP address can send strings using UDP datagrams 
//           - will also wait for datagrams and display contents
// remote IP and port are specified via command line - default IP is 127.0.0.1 (i.e. localhost) and port is 1000  
//
// e.g. to send datagrams to IP 146.227.59.130 port 1006
// java chat 146.227.59.130 1006

import java.io.*;
import java.util.*;
import java.net.*;

public class UDPchat extends Thread
{
   private final static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
   int port=10000;//999;//10001;// 100006                             // port to send/receive datagrams on
   String remoteIPaddress= "192.168.1.176";//"169.254.144.20";//("192.168.1.8");//127.0.0.1");      // IP to send datagrams

   // constructor, parameter is command line parameters
   public UDPchat(String args[]) throws Exception
    {
    // get remote IP address and port from command line parameters
    if (args.length > 0)    remoteIPaddress =  (args[0]);           // get IPaddress
    if (args.length > 1)    port = Integer.parseInt(args[1]);        // get port number
    System.out.println("chat program: IP address " + InetAddress.getLocalHost().toString() + " port " + port );
    
    start();        // start thread to receive and display datagrams

    // loop waiting for keyboard input, send datagram to remote IP                
    while(true)
      try
        {
        String s = in.readLine();                       // read a String
        System.out.println("Sending to " + remoteIPaddress + " socket " + port + " data: " + s);
        byte[] data = s.getBytes();                                     // convert to byte array
        DatagramSocket theSocket = new DatagramSocket();                // create datagram socket and the datagram
        DatagramPacket   theOutput = new DatagramPacket(data, data.length, InetAddress.getByName(remoteIPaddress), port);
        theSocket.send(theOutput);                                      // and send the datagram
       }
      catch (Exception e) {System.out.println("Eroor sending datagram " + e);}
    }

   // thread run method, receives datagram and display contents as a string and HEX
   public void run()                
        {
          try
              {
              // open DatagramSocket to receive 
              DatagramSocket ds = new DatagramSocket(port);
              // loop forever reading datagrams from the DatagramSocket
              while (true)
                 {
                 byte[] buffer = new byte[65507];                       // array to put datagrams in
                 DatagramPacket dp = new DatagramPacket(buffer, buffer.length); // DatagramPacket to hold the datagram
                 ds.receive(dp);                                     // wait for next datagram
                 String s = new String(dp.getData(),0,dp.getLength());        // get contenets as a String
                 System.out.println("UDP datagram length " + s.length()+ "  from IP " + dp.getAddress() + " received: " + s );
                 // and display HEX values
                 System.out.print("   in HEX ");
                 for(int i=0;i<dp.getLength();i++)
                     System.out.printf("0x%02X ", buffer[i]);
                 System.out.println();
                 }
              }
          catch (SocketException se) {System.err.println("chat error " + se); }
          catch (IOException se) {System.err.println("chat error " + se);}
          System.exit(1);                                                       // exit on error
        }


public static void main(String args[]) throws Exception
{
   UDPchat c=new UDPchat(args);
}

Java console output

E:\temp>java UDPchat.java 192.168.1.245 999
chat program: IP address DELL_win_11/192.168.1.65 port 999
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x02 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x03 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x04 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x05 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x06 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x07 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x08 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x09 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x0A 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received: #Eg????
   in HEX 0x0B 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
UDP datagram length 8  from IP /192.168.1.245 received:  #Eg????
   in HEX 0x0C 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF

photo of test setup
image

Heltec LoRa V2 P2P receiver output

Heltec LoRa V2  SX1276  [SX1276] Initializing ... success!
[SX1276] Starting to listen ... success!
[SX1276] Received packet!
[SX1276] Data:		3 35 69 103 137 171 205 239 
[SX1276] RSSI:		-50.00 dBm
[SX1276] SNR:		12.00 dB
[SX1276] Frequency error:	-2149.58 Hz
[SX1276] Received packet!
[SX1276] Data:		4 35 69 103 137 171 205 239 
[SX1276] RSSI:		-49.00 dBm
[SX1276] SNR:		10.00 dB
[SX1276] Frequency error:	-2153.78 Hz
[SX1276] Received packet!
[SX1276] Data:		5 35 69 103 137 171 205 239 
[SX1276] RSSI:		-50.00 dBm
[SX1276] SNR:		12.25 dB
[SX1276] Frequency error:	-2162.16 Hz
[SX1276] Received packet!
[SX1276] Data:		6 35 69 103 137 171 205 239 
[SX1276] RSSI:		-51.00 dBm
[SX1276] SNR:		9.50 dB
[SX1276] Frequency error:	-2170.55 Hz
2 Likes

Thanks horace, that’s awesome.