В некоторых случаях, например, когда нет доступа к сотовой связи, необходимо передать короткие, но важные сообщения в точку, расположенную за несколько километров, а то и несколько десятков километров (если на открытом пространстве). В данном случае может помочь стандарт передачи данных по беспроводному каналу LoRa, который в последнее время заметно набирает популярность.

В рамках данного проекта мы сделаем своеобразный мессенджер на основе микроконтроллера ESP32 и LoRa-модуля RFM95W.
Помимо ESP32 и RFM95W в схеме также используются OLED-дисплей 128x32 для отображения сообщения, пьезозуммер для звукового оповещения о поступлении сообщения, кнопка для выбора и отправки сообщения, антенны и аккумулятора. Схема подключения компонентов представлена далее:

Код программы для Arduino представлен далее. Отдельно в файле messages.h имеются тексты сообщений. При желании проект можно модернизировать, добавив клавиатуру или организовав ввод сообщения через мобильный с передачей на ESP32 по WiFi или Bluetooth.
#include <SPI.h>
#include <LoRa.h>
#include <U8g2lib.h>
#include "OneButton.h"
#include "messages.h"
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, SCL, SDA, U8X8_PIN_NONE);
#define PIN_INPUT 15
#define PIN_BUZ 4
int buzState = LOW;
OneButton button(PIN_INPUT, true);
int exitFlag = 0;
int stringNumber = -1;
const int csPin = 5;
const int resetPin = 14;
const int irqPin = 2;
String outgoing;
byte msgCount = 0;
byte localAddress = 0xBA;
byte destination = 0xFF;
long lastSendTime = 0;
int interval = 2000;
void setup() {
Serial.begin(115200);
u8g2.begin();
pinMode(PIN_BUZ, OUTPUT);
digitalWrite(PIN_BUZ, buzState);
button.attachClick(Click);
button.attachLongPressStart(longPressStart);
LoRa.setPins(csPin, resetPin, irqPin);
if (!LoRa.begin(866E6)) {
Serial.println("LoRa init failed. Check your connections.");
while (true);
}
Serial.println("LoRa init succeeded.");
}
void loop() {
delay(10);
button.tick();
onReceive(LoRa.parsePacket());
}
void sendMessage(String outgoing) {
LoRa.beginPacket();
LoRa.write(destination);
LoRa.write(localAddress);
LoRa.write(msgCount);
LoRa.write(outgoing.length());
LoRa.print(outgoing);
LoRa.endPacket();
msgCount++;
}
void onReceive(int packetSize) {
if (packetSize == 0) return;
int recipient = LoRa.read();
byte sender = LoRa.read();
byte incomingMsgId = LoRa.read();
byte incomingLength = LoRa.read();
String incoming = "";
while (LoRa.available()) {
incoming += (char)LoRa.read();
}
if (incomingLength != incoming.length()) {
Serial.println("error: message length does not match length");
return;
}
if (recipient != localAddress && recipient != 0xFF) {
Serial.println("This message is not for me.");
return;
}
Serial.println("Received from: 0x" + String(sender, HEX));
Serial.println("Sent to: 0x" + String(recipient, HEX));
Serial.println("Message ID: " + String(incomingMsgId));
Serial.println("Message length: " + String(incomingLength));
Serial.println("Message: " + incoming);
Serial.println("RSSI: " + String(LoRa.packetRssi()));
Serial.println("Snr: " + String(LoRa.packetSnr()));
Serial.println();
digitalWrite(PIN_BUZ, !buzState);
Serial.println("Buzzer ON");
delay (100);
digitalWrite(PIN_BUZ, buzState);
Serial.println("Buzzer OFF");
sendDisplay(sender, incoming);
}
void sendDisplay(unsigned int nodeID, String messageLoRa) {
char messageLocal[MAX_STRING_SIZE];
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
sprintf (messageLocal, "Message From: %d", nodeID);
u8g2.drawStr(0,10, messageLocal);
messageLoRa.toCharArray(messageLocal, MAX_STRING_SIZE);
u8g2.drawStr(0,30, messageLocal);
u8g2.sendBuffer();
delay(1000);
}
void Click()
{
Serial.println("x1");
stringNumber++;
if (stringNumber > 3)
stringNumber = 0;
displayString (stringNumber+1, arr[stringNumber]);
exitFlag = 0;
}
void longPressStart()
{
Serial.println("Long");
displaySend (stringNumber+1, arr[stringNumber]);
//LoRaNow.clear();
sendMessage(arr[stringNumber]);
exitFlag = 1;
}
void displayString (unsigned int stringNo, char* stringToDisplay) {
char messageLocal[MAX_STRING_SIZE];
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
sprintf (messageLocal, "Destination: %d", destination);
u8g2.drawStr(0,10, messageLocal);
sprintf (messageLocal, "Text selection: %d of %d", stringNo, NUMBER_OF_STRING);
u8g2.drawStr(0,20, messageLocal);
u8g2.drawStr(0,30, stringToDisplay);
u8g2.sendBuffer();
delay(100);
}
void displaySend (unsigned int stringNo, char* stringToDisplay) {
char messageLocal[MAX_STRING_SIZE];
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
sprintf (messageLocal, "Destination: %d", destination);
u8g2.drawStr(0,10, messageLocal);
sprintf (messageLocal, "Sending Message: %d of %d", stringNo, NUMBER_OF_STRING);
u8g2.drawStr(0,20, messageLocal);
u8g2.drawStr(0,30, stringToDisplay);
u8g2.sendBuffer();
delay(100);
}
Содержимое файла messages.h:
#define NUMBER_OF_STRING 4
#define MAX_STRING_SIZE 40
char arr[NUMBER_OF_STRING][MAX_STRING_SIZE] =
{ "Get on the phone!",
"The music is too loud",
"I'm ready to move",
"See you at 10:00 AM"
};

© digitrode.ru