From b4bbb148bb75cb149a23ce5282ff8fc6a3c460cf Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 5 Jun 2023 23:10:21 -0700 Subject: [PATCH] Android Phone + ESP32-LoRa Module + Chat App = Text Transceiver! --- .../Chat_APP_SX1262/Chat_APP_SX1262.ino | 244 ++++++++++++++++++ ESP32-LoRa/Chat_APP_SX1262/boards.h | 138 ++++++++++ ESP32-LoRa/Chat_APP_SX1262/utilities.h | 151 +++++++++++ 3 files changed, 533 insertions(+) create mode 100644 ESP32-LoRa/Chat_APP_SX1262/Chat_APP_SX1262.ino create mode 100755 ESP32-LoRa/Chat_APP_SX1262/boards.h create mode 100755 ESP32-LoRa/Chat_APP_SX1262/utilities.h diff --git a/ESP32-LoRa/Chat_APP_SX1262/Chat_APP_SX1262.ino b/ESP32-LoRa/Chat_APP_SX1262/Chat_APP_SX1262.ino new file mode 100644 index 0000000..39e79f0 --- /dev/null +++ b/ESP32-LoRa/Chat_APP_SX1262/Chat_APP_SX1262.ino @@ -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 +#include +#include +#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); +} diff --git a/ESP32-LoRa/Chat_APP_SX1262/boards.h b/ESP32-LoRa/Chat_APP_SX1262/boards.h new file mode 100755 index 0000000..b4d1435 --- /dev/null +++ b/ESP32-LoRa/Chat_APP_SX1262/boards.h @@ -0,0 +1,138 @@ +#include +#include +#include +#include "utilities.h" + +#ifdef HAS_SDCARD +#include +#include +#endif + +#if defined(LILYGO_TBeam_V1_0) || defined(LILYGO_TBeam_V1_1) +#include +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 + +} + + diff --git a/ESP32-LoRa/Chat_APP_SX1262/utilities.h b/ESP32-LoRa/Chat_APP_SX1262/utilities.h new file mode 100755 index 0000000..449e734 --- /dev/null +++ b/ESP32-LoRa/Chat_APP_SX1262/utilities.h @@ -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 + + + + + + + + +