Android Phone + ESP32-LoRa Module + Chat App = Text Transceiver!

This commit is contained in:
Eric
2023-06-05 23:10:21 -07:00
parent fe07730fb1
commit b4bbb148bb
3 changed files with 533 additions and 0 deletions

View File

@@ -0,0 +1,244 @@
/////////////////////////////////////////////////////////////////
/*
Android Phone + ESP32-LoRa Module + Chat App = Text Transceiver!
For More Information: https://youtu.be/4GVH3JicaPo
Created by Eric N. (ThatProject)
*/
/////////////////////////////////////////////////////////////////
#include <TinyGPS++.h>
#include <ArduinoJson.h>
#include <RadioLib.h>
#include "boards.h"
SX1262 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
int transmissionState = RADIOLIB_ERR_NONE;
bool transmitFlag = false;
volatile bool operationDone = false;
TinyGPSPlus gps;
StaticJsonDocument<1024> doc;
StaticJsonDocument<512> msg;
String userId, userName;
String gpsJson = "";
long previousMillis = 0;
long GPSupdateInterval = 10000; // 10sec
void setFlag(void) {
// we sent or received a packet, set the flag
operationDone = true;
}
void setup() {
initBoard();
delay(1500);
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
int state = radio.begin(LoRa_frequency);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true)
;
}
state = radio.setOutputPower(22);
Serial.print(F("LoRa_output Power Set"));
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true)
;
}
// set the function that will be called
// when new packet is received
radio.setDio1Action(setFlag);
Serial.print(F("[SX1262] Starting to listen ... "));
state = radio.startReceive();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true)
;
}
xTaskCreatePinnedToCore(Serial_Task, "Serial_Task", 4096, NULL, 10, NULL, 1);
}
void loop() {
// check if the previous operation finished
if (operationDone) {
// reset flag
operationDone = false;
if (transmitFlag) {
// listen for response
radio.startReceive();
transmitFlag = false;
} else {
// the previous operation was reception
// print data and send another packet
String str;
int state = radio.readData(str);
if (state == RADIOLIB_ERR_NONE) {
// packet was successfully received
if (!str.isEmpty()) {
Serial.println(str);
String chatId = parsingJson(str);
if (chatId != "null" && !chatId.isEmpty()) {
updateGPSInfo(chatId);
}
}
}
// wait a second before transmitting again
delay(500);
if (!gpsJson.isEmpty()) {
transmissionState = radio.startTransmit(gpsJson);
transmitFlag = true;
gpsJson = "";
}
}
} else {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > GPSupdateInterval) {
previousMillis = currentMillis;
smartDelay(0);
}
}
}
void Serial_Task(void *arg) {
String incomingString = "";
while (1) {
while (Serial.available()) {
incomingString = Serial.readStringUntil('\n');
}
if (incomingString.length() > 0 && !operationDone) {
parsingSerial(incomingString);
incomingString = "";
}
vTaskDelay(100 / portTICK_RATE_MS);
}
}
void parsingSerial(String strData) {
String opcode = strData.substring(0, 1);
String command = strData.substring(2);
switch (opcode.toInt()) {
case 0:
// Set User Id and Name
userId = command.substring(0, 8);
userName = command.substring(9);
Serial.println("userId : " + userId + " userName: " + userName);
break;
case 1:
// Send Chat Data
startTransmit(command);
break;
case 2:
// Update MY GPS
updateGPSInfo("0");
// Request Other GPS
requestGPS(command);
break;
default:
break;
}
}
void requestGPS(String chatId) {
msg.clear();
msg["id"] = chatId;
String temp;
serializeJson(msg, temp);
startTransmit(temp);
}
void startTransmit(String temp) {
transmissionState = radio.startTransmit(temp);
transmitFlag = true;
}
String parsingJson(String json) {
msg.clear();
DeserializationError error = deserializeJson(msg, json);
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return "";
}
String chatId = msg["id"];
return chatId;
}
void updateGPSInfo(String chatId) {
if (userId == NULL || userName == NULL) {
return;
}
doc.clear();
doc["appId"] = "LoRa_GPS";
doc["chatId"] = chatId.c_str();
doc["userId"] = userId.c_str();
doc["sys"]["RSSI"] = String(radio.getRSSI(), 0);
doc["sys"]["SNR"] = String(radio.getSNR(), 2);
doc["sys"]["BAT"]["CNT"] = PMU.isBatteryConnect();
doc["sys"]["BAT"]["VOL"] = String((PMU.getBattVoltage() / 1000), 2);
doc["loc"]["lat"] = String(gps.location.lat(), 6);
doc["loc"]["lng"] = String(gps.location.lng(), 6);
doc["sat"] = gps.satellites.value();
doc["alt"] = String((gps.altitude.feet() / 3.2808), 2);
char gpsDateTime[20];
sprintf(gpsDateTime, "%04d-%02d-%02d %02d:%02d:%02d",
gps.date.year(),
gps.date.month(),
gps.date.day(),
gps.time.hour(),
gps.time.minute(),
gps.time.second());
doc["time"] = gpsDateTime;
if (chatId == "0") {
String temp;
serializeJson(doc, temp);
Serial.println(temp);
} else {
serializeJson(doc, gpsJson);
Serial.println(gpsJson);
}
}
static void smartDelay(unsigned long ms) {
unsigned long start = millis();
do {
while (Serial1.available())
gps.encode(Serial1.read());
} while (millis() - start < ms);
}

View File

@@ -0,0 +1,138 @@
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include "utilities.h"
#ifdef HAS_SDCARD
#include <SD.h>
#include <FS.h>
#endif
#if defined(LILYGO_TBeam_V1_0) || defined(LILYGO_TBeam_V1_1)
#include <axp20x.h>
AXP20X_Class PMU;
bool initPMU()
{
if (PMU.begin(Wire, AXP192_SLAVE_ADDRESS) == AXP_FAIL) {
return false;
}
/*
* The charging indicator can be turned on or off
* * * */
// PMU.setChgLEDMode(LED_BLINK_4HZ);
/*
* The default ESP32 power supply has been turned on,
* no need to set, please do not set it, if it is turned off,
* it will not be able to program
*
* PMU.setDCDC3Voltage(3300);
* PMU.setPowerOutPut(AXP192_DCDC3, AXP202_ON);
*
* * * */
/*
* Turn off unused power sources to save power
* **/
PMU.setPowerOutPut(AXP192_DCDC1, AXP202_OFF);
PMU.setPowerOutPut(AXP192_DCDC2, AXP202_OFF);
PMU.setPowerOutPut(AXP192_LDO2, AXP202_OFF);
PMU.setPowerOutPut(AXP192_LDO3, AXP202_OFF);
PMU.setPowerOutPut(AXP192_EXTEN, AXP202_OFF);
/*
* Set the power of LoRa and GPS module to 3.3V
**/
PMU.setLDO2Voltage(3300); //LoRa VDD
PMU.setLDO3Voltage(3300); //GPS VDD
PMU.setDCDC1Voltage(3300); //3.3V Pin next to 21 and 22 is controlled by DCDC1
PMU.setPowerOutPut(AXP192_DCDC1, AXP202_ON);
PMU.setPowerOutPut(AXP192_LDO2, AXP202_ON);
PMU.setPowerOutPut(AXP192_LDO3, AXP202_ON);
pinMode(PMU_IRQ, INPUT_PULLUP);
attachInterrupt(PMU_IRQ, [] {
// pmu_irq = true;
}, FALLING);
PMU.adc1Enable(AXP202_VBUS_VOL_ADC1 |
AXP202_VBUS_CUR_ADC1 |
AXP202_BATT_CUR_ADC1 |
AXP202_BATT_VOL_ADC1,
AXP202_ON);
PMU.enableIRQ(AXP202_VBUS_REMOVED_IRQ |
AXP202_VBUS_CONNECT_IRQ |
AXP202_BATT_REMOVED_IRQ |
AXP202_BATT_CONNECT_IRQ,
AXP202_ON);
PMU.clearIRQ();
return true;
}
void disablePeripherals()
{
PMU.setPowerOutPut(AXP192_DCDC1, AXP202_OFF);
PMU.setPowerOutPut(AXP192_LDO2, AXP202_OFF);
PMU.setPowerOutPut(AXP192_LDO3, AXP202_OFF);
}
#else
#define initPMU()
#define disablePeripherals()
#endif
SPIClass SDSPI(HSPI);
void initBoard()
{
Serial.begin(115200);
Serial.println("initBoard");
SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN);
Wire.begin(I2C_SDA, I2C_SCL);
#ifdef HAS_GPS
Serial1.begin(GPS_BAUD_RATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
Serial.println("init GPS");
#endif
#if OLED_RST
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, HIGH); delay(20);
digitalWrite(OLED_RST, LOW); delay(20);
digitalWrite(OLED_RST, HIGH); delay(20);
#endif
initPMU();
#ifdef HAS_SDCARD
SDSPI.begin(SDCARD_SCLK, SDCARD_MISO, SDCARD_MOSI, SDCARD_CS);
if (!SD.begin(SDCARD_CS, SDSPI)) {
Serial.println("setupSDCard FAIL");
} else {
uint32_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.print("setupSDCard PASS . SIZE = ");
Serial.print(cardSize);
Serial.println(" MB");
}
#endif
#ifdef BOARD_LED
/*
* T-BeamV1.0, V1.1 LED defaults to low level as trun on,
* so it needs to be forced to pull up
* * * * */
#if LED_ON == LOW
gpio_hold_dis(GPIO_NUM_4);
#endif
pinMode(BOARD_LED, OUTPUT);
digitalWrite(BOARD_LED, LED_ON);
#endif
}

View File

@@ -0,0 +1,151 @@
#pragma once
// #define LILYGO_TBeam_V0_7
// #define LILYGO_TBeam_V1_0
#define LILYGO_TBeam_V1_1
// #define LILYGO_T3_V1_0
// #define LILYGO_T3_V1_6
// #define LILYGO_T3_V2_0
/*
* The default program uses 868MHz,
* if you need to change it,
* please open this note and change to the frequency you need to test
* */
#define LoRa_frequency 915.0
#define UNUSE_PIN (0)
#if defined(LILYGO_TBeam_V0_7)
#define GPS_RX_PIN 12
#define GPS_TX_PIN 15
#define BUTTON_PIN 39
#define BUTTON_PIN_MASK GPIO_SEL_39
#define I2C_SDA 21
#define I2C_SCL 22
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_DI0_PIN 26
#define RADIO_RST_PIN 23
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 32
#define BOARD_LED 14
#define LED_ON HIGH
#define LED_OFF LOW
#define GPS_BAUD_RATE 9600
#define HAS_GPS
#define HAS_DISPLAY //Optional, bring your own board, no OLED !!
#elif defined(LILYGO_TBeam_V1_0) || defined(LILYGO_TBeam_V1_1)
#define GPS_RX_PIN 34
#define GPS_TX_PIN 12
#define BUTTON_PIN 38
#define BUTTON_PIN_MASK GPIO_SEL_38
#define I2C_SDA 21
#define I2C_SCL 22
#define PMU_IRQ 35
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_DI0_PIN 26
#define RADIO_RST_PIN 23
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 32
#define BOARD_LED 4
#define LED_ON LOW
#define LED_OFF HIGH
#define GPS_BAUD_RATE 9600
#define HAS_GPS
#elif defined(LILYGO_T3_V1_0)
#define I2C_SDA 4
#define I2C_SCL 15
#define OLED_RST 16
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_DI0_PIN 26
#define RADIO_RST_PIN 14
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 32
#define HAS_DISPLAY
#elif defined(LILYGO_T3_V1_6)
#define I2C_SDA 21
#define I2C_SCL 22
#define OLED_RST UNUSE_PIN
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_DI0_PIN 26
#define RADIO_RST_PIN 23
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 32
#define SDCARD_MOSI 15
#define SDCARD_MISO 2
#define SDCARD_SCLK 14
#define SDCARD_CS 13
#define BOARD_LED 25
#define LED_ON HIGH
#define ADC_PIN 35
#define HAS_SDCARD
#define HAS_DISPLAY
#elif defined(LILYGO_T3_V2_0)
#define I2C_SDA 21
#define I2C_SCL 22
#define OLED_RST UNUSE_PIN
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_DI0_PIN 26
#define RADIO_RST_PIN 14
#define RADIO_DIO1_PIN UNUSE_PIN
#define RADIO_BUSY_PIN UNUSE_PIN
#define SDCARD_MOSI 15
#define SDCARD_MISO 2
#define SDCARD_SCLK 14
#define SDCARD_CS 13
#define BOARD_LED 0
#define LED_ON LOW
#define HAS_SDCARD
#else
#error "Please select the version you purchased in utilities.h"
#endif