TTGO LORA32 V2.0 - Peer to Peer

Bevor wir in die Welt von Lorawan einsteigen, testen wir unsere Hardware. Ich habe zwei TTGO LORA32 V2.0 angeschafft.  Mit denen baue ich im ersten Schritt eine Peer to Peer Verbindung auf.

Zu den TTGO LORA32 V2.0 Modulen gibts eine Stummelantene, eine Pigtail IPEX-SMA und ein LiPo Anschlusskabel. Der SMA Anschluss war dann schlussendlich auch der Grund, warum ich mich für den Kauf dieser Module entschieden habe.

Der SMA Stecker ermöglicht das Testen verschiedener Antennen und die Pigtail erleichtert die Unterbringung in einem Gehäuse. Mein Lieferant hat die Module in kleinen Kunststoff-Behältern geliefert. Diese lassen sich nach bohren einiger Löcher auch gleich als Gehäuse verwenden, die Antenne lässt sich montieren und entlastet mechanisch den IPEX Anschluss ein wenig.

Software

Zunächst muss man mit dem Library Manager eine LMIC Library installieren. Ich habe mich für die MCCI LoRaWan LMIC Library entschieden da diese auch für spätere Sketches verwendet werden wird.

Wichtig: Im Library Unterverzeichnis project_config gibt es eine Datei lmic_project_config.h - in dieser Datei ist für Europa der richtige Eintrag zu wählen:

// project-specific definitions
#define CFG_eu868 1
//#define CFG_us915 1
//#define CFG_au921 1
//#define CFG_as923 1
// #define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */
//#define CFG_in866 1
#define CFG_sx1276_radio 1
//#define LMIC_USE_INTERRUPTS

Auf Github gibt es die ersten brauchbaren Sketche (Link unten). Ich habe diese nur ein wenig adaptiert, damit man das OLED besser ablesen kann.

Mein Sender-Sketch

/*******************************************************************************
TTGO LORA32 V2.0 - SENDER

This is a simple example for
peer to peer communication of two TTGO LORA32 V2.0 modules.

No Hardware-Wiring needed.

adopted by (c) 2019 noiasca

based on the work of
https://github.com/LilyGO/TTGO-LORA32-V2.0

credits to
name=MCCI LoRaWAN LMIC library
version=2.3.2
author=IBM, Matthis Kooijman, Terry Moore, ChaeHee Won, Frank Rose

*******************************************************************************/

#include <SPI.h>
#include <LoRa.h> // install MCCI LoRaWAN LMIC library 2.3.2 by IBM
#include <Wire.h>
#include "SSD1306.h"
//#include "images.h"

#define SCK 5 // GPIO5 -- SX1278's SCK
#define MISO 19 // GPIO19 -- SX1278's MISnO
#define MOSI 27 // GPIO27 -- SX1278's MOSI
#define SS 18 // GPIO18 -- SX1278's CS
#define RST 14 // GPIO14 -- SX1278's RESET
#define DI0 26 // GPIO26 -- SX1278's IRQ(Interrupt Request)
#define BAND 868E6
const int OLED_RST_PIN = 16; 
const int LED_PIN = 2; // a LED on a free GPIO. don't use 22 as we need it for SCL
unsigned int counter = 0;

SSD1306 display(0x3c, 21, 22); // SDA 21, SCL 22, - BULITIN_LED 22 not usable
String rssi = "RSSI --";
String packSize = "--";
String packet;


void setup() {
pinMode(LED_PIN, OUTPUT); 
pinMode(OLED_RST_PIN, OUTPUT);
digitalWrite(OLED_RST_PIN, LOW); // set GPIO low to reset OLED
delay(50);
digitalWrite(OLED_RST_PIN, HIGH); // while OLED is running, must set GPIO in high

Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println(F("LoRa Sender Test"));

SPI.begin(SCK, MISO, MOSI, SS);
LoRa.setPins(SS, RST, DI0);
if (!LoRa.begin(BAND)) {
Serial.println(F("Starting LoRa failed!"));
while (1);
}
//LoRa.onReceive(cbk);
// LoRa.receive();
Serial.println(F("init ok"));
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);

display.drawString(0, 0, "init ok");
display.display();

delay(1500);
}

void loop() {
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);

display.drawString(0, 0, "Sending packet: ");
display.drawString(90, 0, String(counter));
Serial.println(String(counter));
display.display();

// send packet
LoRa.beginPacket();
LoRa.print("hello ");
LoRa.print(counter); // 
LoRa.endPacket();

counter++;
digitalWrite(LED_PIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_PIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}

Mein Empfänger Sketch

/*******************************************************************************
TTGO LORA32 V2.0 - RECEIVER

This is a simple example for 
peer to peer communication of two TTGO LORA32 V2.0 modules.

The sender caculates the quality based on packet loss.
The first packet received from sender will be used as reference value
Each packet increments the counter totalPackets

No Hardware-Wiring needed. Don't forget to connect the antenna before you suply the module with power

adopted by (c) 2019 noiasca

based on the work of
https://github.com/LilyGO/TTGO-LORA32-V2.0

credits to
name=MCCI LoRaWAN LMIC library
version=2.3.2
author=IBM, Matthis Kooijman, Terry Moore, ChaeHee Won, Frank Rose

*******************************************************************************/

#include <SPI.h>
#include <LoRa.h> // install MCCI LoRaWAN LMIC library 2.3.2 by IBM, Matthis Kooijman, 
#include <Wire.h>
#include "SSD1306.h"
//#include "images.h"

#define SCK 5 // GPIO5 -- SX1278's SCK
#define MISO 19 // GPIO19 -- SX1278's MISO
#define MOSI 27 // GPIO27 -- SX1278's MOSI
#define SS 18 // GPIO18 -- SX1278's CS
#define RST 14 // GPIO14 -- SX1278's RESET
#define DI0 26 // GPIO26 -- SX1278's IRQ(Interrupt Request)
#define BAND 868E6
const int OLED_RST_PIN = 16; 

SSD1306 display(0x3c, 21, 22); // SDA 21, SCL 22, - BULITIN_LED 22 not usable
String rssi = "RSSI --";
String packSize = "--";
String packet ;


void loraData() {
const uint8_t rowheight = 11;
static uint32_t totalPackets;
static uint16_t firstNumber;

totalPackets++;

uint16_t thisNumber = packet.substring(6).toInt();
uint16_t quality = 100;

if (totalPackets == 1)
firstNumber = thisNumber;
else
quality = totalPackets * 100 / (thisNumber - firstNumber+1); // simple "Send - Received Quote"

String strTotalPackets = String(totalPackets, DEC);
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(0, 0, rssi + " / " + quality + "%");

display.setFont(ArialMT_Plain_10);
display.drawString(0 , rowheight , "Received " + packSize + "bytes");
display.drawStringMaxWidth(0 , rowheight * 2 , 128, packet);

display.setFont(ArialMT_Plain_24);
display.drawString(0 , 40 , "Total " + strTotalPackets);
display.write(totalPackets);

display.display();

// Debug Output to Serial
Serial.print(F("RSSI:")); Serial.print(rssi);
Serial.print(F(" Total:")); Serial.print(totalPackets);
Serial.print(F(" Packet:")); Serial.print(packet);
Serial.print(F(" ThisNumber:")); Serial.print(thisNumber);
Serial.print(F(" Quality:")); Serial.print(quality);
Serial.println();
}

void cbk(int packetSize) {
packet = "";
packSize = String(packetSize, DEC);
for (int i = 0; i < packetSize; i++) {
packet += (char) LoRa.read();
}
rssi = "RSSI " + String(LoRa.packetRssi(), DEC) ;
loraData();
}

void setup() {
pinMode(OLED_RST_PIN, OUTPUT);
digitalWrite(OLED_RST_PIN, LOW); // set GPIO low to reset OLED
delay(50);
digitalWrite(OLED_RST_PIN, HIGH); // while OLED is running, must set GPIO in high、

Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println(F("LoRa Receiver Callback"));
SPI.begin(SCK, MISO, MOSI, SS);
LoRa.setPins(SS, RST, DI0);
if (!LoRa.begin(BAND)) {
Serial.println(F("Starting LoRa failed!"));
while (1);
}
//LoRa.onReceive(cbk);
LoRa.receive();
Serial.println(F("init ok"));
display.init();
display.flipScreenVertically(); // Anschlüsse unten
display.setFont(ArialMT_Plain_10);

display.drawString(0, 0, "init ok");
display.drawString(0, 11, "wait for signal");
display.display();
delay(1000);
}

void loop() {
int packetSize = LoRa.parsePacket();
if (packetSize) {
cbk(packetSize);
}
delay(10);
}

Erste LORA Reichweitentests

Nach dem flashen von Sender und Receiver Sketch können wir die ersten LORA Reichweitentests machen. Der Sender bleibt zu Hause und mit dem Receiver gehen wir auf Reisen. Mit den beiden Originalantennen erreiche ich Reichweiten von knapp 2 km auch ohne direkte Sichtverbindung. Die Original-Antennen eignen sich eigentlich nur für die Entwicklung am Schreibtisch und haben kaum etwas mit der gedachten Einsatz-Frequenz von 868MHz zu tun. Ein lieber Funkamateur hat mir dann besser passende Magnetfußantennen zur Verfügung gestellt. Mit den besseren Antennen erreiche ich Reichweiten von gesicherten 5 km, stellenweise erreiche ich auch 8km - und das sogar ohne direkter Sichtverbindung. Bemerkenswert, was alles mit nur 25mW möglich ist. Hier ist sicher noch mehr drinnen und das Thema "Antennen" werden wir später noch einmal näher behandeln.

Links

Die mit Sternchen (*) gekennzeichneten Verweise sind sogenannte Affiliate/Provision-Links. Wenn du auf so einen Verweis klickst und über diesen Link einkaufst, bekomme ich von deinem Einkauf eine (kleine) Provision. Für dich verändert sich der Preis dadurch nicht. Ich empfehle nur Produkte die ich selber besitze und wenn ich überzeugt bin, dass sie für andere interesssant sind.

Protokoll

erstellt: 2019-03-18 | Stand: 2023-04-10