mirror of
https://github.com/richonguzman/LoRa_APRS_iGate.git
synced 2026-10-31 02:51:58 +01:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa17b8ded1 | ||
|
|
228a3dde25 | ||
|
|
7f195e1725 | ||
|
|
48538a6162 | ||
|
|
a472c307d3 |
No files matched your search
@@ -68,7 +68,7 @@ ___________________________________________________________________*/
|
||||
#endif
|
||||
|
||||
|
||||
String versionDate = "2026-09-28";
|
||||
String versionDate = "2026-09-30";
|
||||
String versionNumber = "4.0.1";
|
||||
Configuration Config;
|
||||
WiFiClient aprsIsClient;
|
||||
|
||||
+84
-1
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <APRSPacketLib.h>
|
||||
#include <TinyGPS++.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <WiFi.h>
|
||||
#include "configuration.h"
|
||||
#include "board_pinout.h"
|
||||
@@ -31,6 +32,10 @@
|
||||
#define GPS_BAUD 9600
|
||||
#endif
|
||||
|
||||
#define GPS_BAUD_FILE "/gps_baud.dat"
|
||||
#define GPS_BAUD_PROBE_TIME_MS 1500
|
||||
const uint32_t gpsBaudRates[] = {9600, 115200, 38400, 4800, 57600}; // most common first
|
||||
|
||||
extern Configuration Config;
|
||||
extern HardwareSerial gpsSerial;
|
||||
extern TinyGPSPlus gps;
|
||||
@@ -40,6 +45,76 @@ String distance, iGateBeaconPacket, iGateLoRaBeaconPacket;
|
||||
|
||||
namespace GPS_Utils {
|
||||
|
||||
#ifdef HAS_GPS
|
||||
bool isKnownBaudRate(uint32_t baud) {
|
||||
if (baud == GPS_BAUD) return true;
|
||||
for (uint32_t knownBaud : gpsBaudRates) {
|
||||
if (knownBaud == baud) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t readSavedBaudRate() {
|
||||
File file = SPIFFS.open(GPS_BAUD_FILE, "r");
|
||||
if (!file) return 0;
|
||||
uint32_t baud = file.readString().toInt();
|
||||
file.close();
|
||||
return isKnownBaudRate(baud) ? baud : 0;
|
||||
}
|
||||
|
||||
void saveBaudRate(uint32_t baud) {
|
||||
File file = SPIFFS.open(GPS_BAUD_FILE, "w");
|
||||
if (!file) {
|
||||
Utils::println("GPS: could not save baud rate");
|
||||
return;
|
||||
}
|
||||
file.print(baud);
|
||||
file.close();
|
||||
}
|
||||
|
||||
bool probeBaudRate(uint32_t baud) {
|
||||
gpsSerial.end();
|
||||
delay(50);
|
||||
gpsSerial.begin(baud, SERIAL_8N1, GPS_TX, GPS_RX);
|
||||
uint32_t validSentences = gps.passedChecksum();
|
||||
uint32_t probeStart = millis();
|
||||
while (millis() - probeStart < GPS_BAUD_PROBE_TIME_MS) {
|
||||
while (gpsSerial.available() > 0) gps.encode(gpsSerial.read());
|
||||
if (gps.passedChecksum() > validSentences) return true; // NMEA with valid checksum
|
||||
delay(10);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t detectBaudRate() {
|
||||
uint32_t savedBaud = readSavedBaudRate();
|
||||
|
||||
uint32_t candidates[2 + sizeof(gpsBaudRates) / sizeof(gpsBaudRates[0])];
|
||||
size_t count = 0;
|
||||
auto addCandidate = [&](uint32_t baud) {
|
||||
if (baud == 0) return;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (candidates[i] == baud) return;
|
||||
}
|
||||
candidates[count++] = baud;
|
||||
};
|
||||
addCandidate(savedBaud); // saved first, then board default, then common ones
|
||||
addCandidate(GPS_BAUD);
|
||||
for (uint32_t baud : gpsBaudRates) addCandidate(baud);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (i == 1) displayShow("GPS", "Searching", "baud rate...", "", 0);
|
||||
bool found = probeBaudRate(candidates[i]);
|
||||
if (!found && i == 0) found = probeBaudRate(candidates[i]); // retry first one: GPS may be slow to start
|
||||
if (found) {
|
||||
if (candidates[i] != savedBaud) saveBaudRate(candidates[i]);
|
||||
return candidates[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
String getiGateLoRaBeaconPacket() {
|
||||
return iGateLoRaBeaconPacket;
|
||||
}
|
||||
@@ -104,7 +179,15 @@ namespace GPS_Utils {
|
||||
void setup() {
|
||||
#ifdef HAS_GPS
|
||||
if (Config.beacon.gpsActive && Config.digi.ecoMode != 1) {
|
||||
gpsSerial.begin(GPS_BAUD, SERIAL_8N1, GPS_TX, GPS_RX);
|
||||
uint32_t detectedBaud = detectBaudRate();
|
||||
if (detectedBaud != 0) {
|
||||
Utils::println("GPS: baud rate detected: " + String(detectedBaud));
|
||||
} else {
|
||||
Utils::println("GPS: no NMEA data found, using default baud rate: " + String(GPS_BAUD));
|
||||
gpsSerial.end();
|
||||
delay(50);
|
||||
gpsSerial.begin(GPS_BAUD, SERIAL_8N1, GPS_TX, GPS_RX);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
generateBeacons();
|
||||
|
||||
+27
-10
@@ -41,6 +41,8 @@ bool transmitFlag = true;
|
||||
|
||||
#define DIFS_SLOTS 2 // Number of secuential CAD slots to consider a free channel to Tx
|
||||
int backoffMax = 4; // Max Backoff value (number of CAD slots to wait before Tx)
|
||||
#define CAD_MAX_WAIT_MS 10000 // Max total time waiting for a free channel, then the packet is dropped
|
||||
unsigned long cadStartTime = 0;
|
||||
|
||||
#ifdef HAS_SX1262
|
||||
SX1262 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
|
||||
@@ -195,8 +197,13 @@ namespace LoRa_Utils {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cadTimedOut() {
|
||||
return millis() - cadStartTime > CAD_MAX_WAIT_MS;
|
||||
}
|
||||
|
||||
void waitForDIFS() {
|
||||
while (!doDIFS()) {
|
||||
if (cadTimedOut()) return;
|
||||
Serial.println("CAD/DIFS failed, retry...");
|
||||
}
|
||||
}
|
||||
@@ -204,6 +211,7 @@ namespace LoRa_Utils {
|
||||
void doBEB() {
|
||||
int backoffCounter = random(1, backoffMax + 1);
|
||||
while (backoffCounter > 0) {
|
||||
if (cadTimedOut()) return;
|
||||
if (doCAD()) {
|
||||
waitForDIFS(); // busy channel: freeze backoff and restart DIFS
|
||||
} else {
|
||||
@@ -225,22 +233,30 @@ namespace LoRa_Utils {
|
||||
if (Config.digi.ecoMode != 1) digitalWrite(INTERNAL_LED_PIN, HIGH); // disabled in Ultra Eco Mode
|
||||
#endif
|
||||
|
||||
bool cadDropped = false;
|
||||
if (Config.loramodule.cadActive) {
|
||||
cadStartTime = millis();
|
||||
waitForDIFS(); // DIFS (Distributed Inter-Frame Space)
|
||||
doBEB(); // BEB (Binary Exponential Backoff)
|
||||
if (cadTimedOut()) {
|
||||
Utils::println("CAD timeout, packet dropped: " + newPacket);
|
||||
cadDropped = true;
|
||||
}
|
||||
}
|
||||
|
||||
int state = radio.transmit("\x3c\xff\x01" + newPacket);
|
||||
transmitFlag = true;
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
if (Config.syslog.active && networkManager->isConnected()) {
|
||||
SYSLOG_Utils::logLoRaTx(newPacket);
|
||||
if (!cadDropped) {
|
||||
int state = radio.transmit("\x3c\xff\x01" + newPacket);
|
||||
transmitFlag = true;
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
if (Config.syslog.active && networkManager->isConnected()) {
|
||||
SYSLOG_Utils::logLoRaTx(newPacket);
|
||||
}
|
||||
Utils::print("---> LoRa Packet Tx : ");
|
||||
Utils::println(newPacket);
|
||||
} else {
|
||||
Utils::print(F("failed, code "));
|
||||
Utils::println(String(state));
|
||||
}
|
||||
Utils::print("---> LoRa Packet Tx : ");
|
||||
Utils::println(newPacket);
|
||||
} else {
|
||||
Utils::print(F("failed, code "));
|
||||
Utils::println(String(state));
|
||||
}
|
||||
#ifdef INTERNAL_LED_PIN
|
||||
if (Config.digi.ecoMode != 1) digitalWrite(INTERNAL_LED_PIN, LOW); // disabled in Ultra Eco Mode
|
||||
@@ -250,6 +266,7 @@ namespace LoRa_Utils {
|
||||
changeFreqRx();
|
||||
}
|
||||
}
|
||||
if (cadDropped) radio.startReceive(); // no Tx end IRQ will restart Rx
|
||||
}
|
||||
|
||||
String receivePacketFromSleep() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU
|
||||
/* Copyright (C) 2026 Ricardo Guzman - CA2RXU
|
||||
*
|
||||
* This file is part of LoRa APRS iGate.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU
|
||||
/* Copyright (C) 2026 Ricardo Guzman - CA2RXU
|
||||
*
|
||||
* This file is part of LoRa APRS iGate.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU
|
||||
/* Copyright (C) 2026 Ricardo Guzman - CA2RXU
|
||||
*
|
||||
* This file is part of LoRa APRS iGate.
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
// LoRa Radio
|
||||
#define HAS_SX1268
|
||||
#define HAS_TCXO
|
||||
#define RADIO_SCLK_PIN 5
|
||||
#define RADIO_MISO_PIN 19
|
||||
#define RADIO_MOSI_PIN 27
|
||||
|
||||
Reference in new issue
Block a user