TTGO-T-Beam-LoRa-APRS/src/TTGO_T-Beam_LoRa_APRS.ino

1234 lines
38 KiB
Arduino
Raw Normal View History

2018-11-25 22:11:22 +02:00
// Tracker for LoRA APRS
// from OE1ACM and OE3CJB redesigned by SQ9MDD
2021-02-14 02:09:11 +02:00
// KISS ans Bluetooth by SQ5RWU
// TTGO T-Beam v1.0 only
//
// licensed under CC BY-NC-SA
// Includes
//#include <TTGO_T-Beam_LoRa_APRS_config.h> // to config user parameters
#include <Arduino.h>
#include <SPI.h>
2018-12-01 22:31:34 +02:00
#include <BG_RF95.h> // library from OE1ACM
#include <math.h>
#include <driver/adc.h>
#include <Wire.h>
2020-12-13 11:35:40 +02:00
#include <Adafruit_I2CDevice.h>
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <axp20x.h>
2021-02-13 18:42:51 +02:00
#include "taskGPS.h"
2021-03-21 20:30:04 +02:00
#include "version.h"
#include "preference_storage.h"
#include "syslog_log.h"
2021-03-24 16:35:42 +02:00
2021-02-15 22:53:37 +02:00
#ifdef KISS_PROTOCOL
2021-02-17 00:38:28 +02:00
#include "taskTNC.h"
2021-02-12 17:25:14 +02:00
#endif
2021-02-18 18:59:18 +02:00
#ifdef ENABLE_WIFI
#include "taskWebServer.h"
#endif
2021-02-15 22:53:37 +02:00
2021-09-06 20:15:00 +03:00
#ifdef USE_BME280
#include <Adafruit_BMP280.h> // BME280 Library
#endif
2021-03-24 16:35:42 +02:00
// oled address
2021-03-22 17:30:22 +02:00
#define SSD1306_ADDRESS 0x3C
2021-04-03 10:24:10 +03:00
// SPI config
2021-07-01 10:00:17 +03:00
#ifdef ESP32_DEV_V1
#define SPI_sck 18
#define SPI_miso 19
#define SPI_mosi 23
#define SPI_ss 5
#else
#define SPI_sck 5
#define SPI_miso 19
#define SPI_mosi 27
#define SPI_ss 18
#endif
2021-03-21 19:38:48 +02:00
// IO config
2021-07-01 10:00:17 +03:00
#ifdef T_BEAM_V1_0
#define I2C_SDA 21
2021-03-22 17:30:22 +02:00
#define I2C_SCL 22
2021-03-21 19:50:50 +02:00
#define BUTTON 38 //pin number for Button on TTGO T-Beam
#define BUZZER 15 // enter your buzzer pin gpio
2021-03-21 20:30:04 +02:00
const byte TXLED = 4; //pin number for LED on TX Tracker
2021-03-24 16:35:42 +02:00
#elif T_BEAM_V0_7
#define I2C_SDA 21
#define I2C_SCL 22
2021-03-21 19:50:50 +02:00
#define BUTTON 39 //pin number for Button on TTGO T-Beam
#define BUZZER 15 // enter your buzzer pin gpio
2021-03-21 20:30:04 +02:00
const byte TXLED = 4; //pin number for LED on TX Tracker
2021-03-22 17:30:22 +02:00
#elif LORA32_21
2021-07-25 23:16:54 +03:00
#define I2C_SDA 21
#define I2C_SCL 22
2021-03-21 19:50:50 +02:00
#define BUTTON 2 //pin number for BUTTO
#define BUZZER 13 // enter your buzzer pin gpio
2021-07-25 23:16:54 +03:00
const byte TXLED = 25; //pin number for LED on TX Tracker
2021-03-22 17:30:22 +02:00
#elif LORA32_2
#define I2C_SDA 21
#define I2C_SCL 22
2021-03-21 19:50:50 +02:00
#define BUTTON 2 //pin number for BUTTO
#define BUZZER 13 // enter your buzzer pin gpio
2021-03-21 20:30:04 +02:00
const byte TXLED = 4; //pin number for LED on TX Tracker
2021-03-22 17:30:22 +02:00
#elif LORA32_1
#define I2C_SDA 21
#define I2C_SCL 22
2021-03-21 19:50:50 +02:00
#define BUTTON 2 //pin number for BUTTO
#define BUZZER 13 // enter your buzzer pin gpio
2021-03-21 20:30:04 +02:00
const byte TXLED = 4; //pin number for LED on TX Tracker
2021-03-22 17:30:22 +02:00
#elif HELTEC_V1
#define I2C_SDA 4
#define I2C_SCL 15
2021-03-21 20:30:04 +02:00
#define BUTTON 2 //pin number for BUTTO
2021-03-21 19:50:50 +02:00
#define BUZZER 13 // enter your buzzer pin gpio
2021-06-29 22:27:04 +03:00
const byte TXLED = 2; //pin number for LED on TX Tracker
2021-03-22 17:30:22 +02:00
#elif HELTEC_V2
#define I2C_SDA 4
2021-03-21 19:38:48 +02:00
#define I2C_SCL 15
#define BUTTON 0 //pin number for BUTTO
2021-03-21 19:50:50 +02:00
#define BUZZER 13 // enter your buzzer pin gpio
const byte TXLED = 25; //pin number for LED on TX Tracker
2021-06-28 00:52:45 +03:00
#elif ESP32_DEV_V1
#define I2C_SDA 21
#define I2C_SCL 22
#define BUTTON 0 //pin number for BUTTO
#define BUZZER 13
const byte TXLED = 2; // enter your buzzer pin gpio
#endif
#ifdef TX_RX_LNA
const byte TXPIN = 17; //pin number for TX on 1W Modules
const byte RXPIN = 16; //pin number for RX on 1W Modules
#endif
2019-11-22 15:22:31 +02:00
// Variables for APRS packaging
2021-03-21 20:30:04 +02:00
String Tcall; //your Call Sign for normal position reports
String aprsSymbolTable = APRS_SYMBOL_TABLE;
String aprsSymbol = APRS_SYMBOL;
2021-02-12 09:08:36 +02:00
String relay_path;
String aprsComment = MY_COMMENT;
String aprsLatPreset = LATIDUDE_PRESET;
String aprsLonPreset = LONGITUDE_PRESET;
2021-07-23 13:33:07 +03:00
2021-09-06 20:15:00 +03:00
//Set params
double aprsFreq = TXFREQ;
#ifdef SPEED_1200
ulong aprsMode = 1200;
#else
ulong aprsMode = 300;
#endif
2021-07-14 23:19:31 +03:00
boolean gps_state = true;
boolean key_up = true;
2021-02-16 11:11:22 +02:00
boolean t_lock = false;
boolean fixed_beacon_enabled = false;
2021-03-09 00:59:33 +02:00
boolean show_cmt = true;
2021-03-13 14:50:04 +02:00
2021-02-18 18:59:18 +02:00
#ifdef SHOW_ALT
2021-02-27 23:50:17 +02:00
boolean showAltitude = true;
2021-02-18 18:59:18 +02:00
#else
2021-02-27 23:50:17 +02:00
boolean showAltitude = false;
2021-02-18 18:59:18 +02:00
#endif
#ifdef SHOW_BATT
2021-02-27 23:50:17 +02:00
boolean showBattery = true;
2021-02-18 18:59:18 +02:00
#else
2021-02-27 23:50:17 +02:00
boolean showBattery = false;
2021-02-18 18:59:18 +02:00
#endif
2021-03-08 23:47:00 +02:00
#ifdef ENABLE_BLUETOOTH
boolean enable_bluetooth = true;
#else
boolean enable_bluetooth = false;
#endif
2021-03-09 00:59:33 +02:00
#ifdef ENABLE_OLED
boolean enabled_oled = true;
#else
boolean enabled_oled = false;
#endif
2021-09-06 20:15:00 +03:00
#ifdef USE_BME280
boolean enable_bme280 = true;
#else
boolean enable_bme280 = false;
#endif
// Variables and Constants
2021-03-24 16:35:42 +02:00
String loraReceivedFrameString = ""; //data on buff is copied to this string
String Outputstring = "";
2021-03-24 16:35:42 +02:00
String outString=""; //The new Output String with GPS Conversion RAW
2018-12-09 23:23:20 +02:00
String LongShown="";
String LatShown="";
2018-12-24 16:29:36 +02:00
String LongFixed="";
String LatFixed="";
#if defined(ENABLE_TNC_SELF_TELEMETRY) && defined(KISS_PROTOCOL)
time_t nextTelemetryFrame;
#endif
//byte arrays
byte lora_TXBUFF[BG_RF95_MAX_MESSAGE_LEN]; //buffer for packet to send
byte lora_RXBUFF[BG_RF95_MAX_MESSAGE_LEN]; //buffer for packet to send
//byte Variables
byte lora_TXStart; //start of packet data in TXbuff
byte lora_TXEnd; //end of packet data in TXbuff
byte lora_FTXOK; //flag, set to 1 if TX OK
byte lora_TXPacketType; //type number of packet to send
byte lora_TXDestination; //destination address of packet to send
byte lora_TXSource; //source address of packet received
byte lora_FDeviceError; //flag, set to 1 if RFM98 device error
byte lora_TXPacketL; //length of packet to send, includes source, destination and packet type.
unsigned long lastTX = 0L;
float BattVolts;
2021-03-13 14:50:04 +02:00
float InpVolts;
2019-11-22 15:22:31 +02:00
// variables for smart beaconing
ulong sb_min_interval = 60000L;
ulong sb_max_interval = 360000L;
float sb_min_speed = 0;
float sb_max_speed = 30;
float average_speed[5] = {0,0,0,0,0}, average_speed_final=0;
2020-01-02 21:13:30 +02:00
float old_course = 0, new_course = 0;
2020-01-05 19:12:52 +02:00
int point_avg_speed = 0, point_avg_course = 0;
2021-07-12 14:27:39 +03:00
ulong min_time_to_nextTX=sb_min_interval; // minimum time period between TX = 60000ms = 60secs = 1min
ulong max_time_to_nextTX= sb_max_interval;
ulong nextTX=60000L; // preset time period between TX = 60000ms = 60secs = 1min
2021-02-13 21:58:41 +02:00
ulong time_to_refresh = 0;
2021-02-15 14:01:52 +02:00
ulong next_fixed_beacon = 0;
2021-02-15 14:27:59 +02:00
ulong fix_beacon_interval = FIX_BEACON_INTERVAL;
ulong showRXTime = SHOW_RX_TIME;
2021-02-16 11:11:22 +02:00
ulong time_delay = 0;
2021-03-13 14:50:04 +02:00
ulong shutdown_delay = 0;
ulong shutdown_delay_time = 10000;
ulong shutdown_countdown_timer = 0;
2021-09-06 20:15:00 +03:00
boolean shutdown_active =false;
2021-03-13 14:50:04 +02:00
boolean shutdown_countdown_timer_enable = false;
boolean shutdown_usb_status_bef = false;
#define ANGLE 60 // angle to send packet at smart beaconing
#define ANGLE_AVGS 3 // angle averaging - x times
2020-04-19 18:52:27 +03:00
float average_course[ANGLE_AVGS];
float avg_c_y, avg_c_x;
2021-03-24 16:35:42 +02:00
2021-09-06 20:15:00 +03:00
//Variables for BME Sensors
boolean hum_temp = false;
uint8_t hum_temp_ctr, hum_temp_ctr_max = 3;
boolean tempsensoravailable=true;
float hum=0; //Stores humidity value
float temp=99.99; //Stores temperature value
float tempf=99.99; //Stores temperature value
float pressure=0; //Stores pressure value in hPa
int pressure_offset=0; //Stores offset for pressure correction
uint8_t txPower = TXdbmW;
2020-04-19 18:52:27 +03:00
2021-02-18 18:59:18 +02:00
#ifdef ENABLE_WIFI
2021-02-27 23:50:17 +02:00
tWebServerCfg webServerCfg;
2021-02-18 18:59:18 +02:00
#endif
static const adc_atten_t atten = ADC_ATTEN_DB_6;
static const adc_unit_t unit = ADC_UNIT_1;
#ifdef T_BEAM_V1_0
2021-02-17 00:38:28 +02:00
AXP20X_Class axp;
#endif
// checkRX
uint8_t loraReceivedLength = sizeof(lora_RXBUFF);
// Singleton instance of the radio driver
2021-07-01 10:00:17 +03:00
#ifdef ESP32_DEV_V1
BG_RF95 rf95(5, 26); // For custom ESP32 and LoRa module
#else
BG_RF95 rf95(18, 26); // TTGO T-Beam has NSS @ Pin 18 and Interrupt IO @ Pin26
2021-07-01 10:00:17 +03:00
#endif
2021-03-14 23:21:30 +02:00
// initialize OLED display
#ifdef TX_RX_LNA
#define OLED_RESET 15 // not used
#else
#define OLED_RESET 16
#endif
2021-09-06 20:15:00 +03:00
//Temp sensor
#ifdef USE_BME280
Adafruit_BMP280 bme; // if BME is used
#endif
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);
// + FUNCTIONS-----------------------------------------------------------+//
2020-01-02 21:13:30 +02:00
char *ax25_base91enc(char *s, uint8_t n, uint32_t v){
2020-08-27 22:41:54 +03:00
/* Creates a Base-91 representation of the value in v in the string */
/* pointed to by s, n-characters long. String length should be n+1. */
for(s += n, *s = '\0'; n; n--)
{
*(--s) = v % 91 + 33;
v /= 91;
}
return(s);
}
2021-02-15 22:53:37 +02:00
void prepareAPRSFrame(){
2021-03-24 16:35:42 +02:00
String helper;
String Altx;
String Speedx, Coursex;
2020-08-27 22:41:54 +03:00
char helper_base91[] = {"0000\0"};
2021-02-15 17:58:22 +02:00
double Tlat=52.0000, Tlon=20.0000;
double Tspeed=0, Tcourse=0;
2021-03-24 16:35:42 +02:00
uint32_t aprs_lat, aprs_lon;
2021-02-15 17:58:22 +02:00
int i;
2021-02-18 18:59:18 +02:00
int Talt;
Tlat=gps.location.lat();
Tlon=gps.location.lng();
Tcourse=gps.course.deg();
Tspeed=gps.speed.knots();
2021-03-24 16:35:42 +02:00
aprs_lat = 900000000 - Tlat * 10000000;
aprs_lat = aprs_lat / 26 - aprs_lat / 2710 + aprs_lat / 15384615;
aprs_lon = 900000000 + Tlon * 10000000 / 2;
aprs_lon = aprs_lon / 26 - aprs_lon / 2710 + aprs_lon / 15384615;
2021-02-12 01:03:15 +02:00
outString = "";
outString += Tcall;
2021-03-24 16:35:42 +02:00
if (relay_path){
2021-03-18 08:27:48 +02:00
outString += ">APLS01," + relay_path + ":!";
2021-03-24 16:35:42 +02:00
}else{
2021-03-18 08:27:48 +02:00
outString += ">APLS01:!";
}
2021-02-13 19:15:02 +02:00
2021-03-24 16:35:42 +02:00
if(gps_state && gps.location.isValid()){
outString += aprsSymbolTable;
ax25_base91enc(helper_base91, 4, aprs_lat);
2021-02-18 18:59:18 +02:00
for (i = 0; i < 4; i++) {
outString += helper_base91[i];
}
ax25_base91enc(helper_base91, 4, aprs_lon);
2021-02-18 18:59:18 +02:00
for (i = 0; i < 4; i++) {
outString += helper_base91[i];
}
outString += aprsSymbol;
2021-02-18 18:59:18 +02:00
ax25_base91enc(helper_base91, 1, (uint32_t) Tcourse / 4);
outString += helper_base91[0];
2021-02-18 18:59:18 +02:00
ax25_base91enc(helper_base91, 1, (uint32_t) (log1p(Tspeed) / 0.07696));
outString += helper_base91[0];
2021-02-15 17:58:22 +02:00
outString += "H";
2021-03-24 16:35:42 +02:00
if (showAltitude){
2021-02-18 18:59:18 +02:00
Talt = gps.altitude.meters() * 3.28d;
2021-02-15 17:58:22 +02:00
Altx = Talt;
2021-02-15 14:15:38 +02:00
outString += "/A=";
2021-03-24 16:35:42 +02:00
for (i = 0; i < (6 - Altx.length()); ++i){
2021-02-15 17:58:22 +02:00
outString += "0";
}
outString += Talt;
2021-02-18 18:59:18 +02:00
}
2021-09-06 20:15:00 +03:00
}
else
{
//fixed position not compresed
outString += aprsLatPreset;
2021-02-17 08:52:42 +02:00
outString += aprsSymbolTable;
outString += aprsLonPreset;
outString += aprsSymbol;
2021-09-06 20:15:00 +03:00
#ifdef USE_BME280
if(enable_bme280)
{
// bme.takeForcedMeasurement();
tempf = bme.readTemperature()*9/5+29;
// hum = bme.readHumidity();
pressure = bme.readPressure()/100 + pressure_offset;
outString += ".../...g...t";
if (tempf < 0) { // negative Werte erstellen
outString += "-";
if(tempf>-10) {outString += "0"; }
tempf = abs(tempf);
}
else
{ // positive Werte erstellen
if(tempf<100) {outString += "0"; }
if(tempf<10) {outString += "0"; }
}
helper = String(tempf-3,0);
helper.trim();
outString += helper;
outString += "r...p...P...h";
if(hum<10) {outString += "0"; }
helper = String(hum,0);
helper.trim();
outString += helper;
outString += "b";
if(pressure<1000) {outString += "0"; }
helper = String(pressure*10,0);
helper.trim();
outString += helper;
}
#endif
}
2021-03-24 16:35:42 +02:00
2021-03-09 00:59:33 +02:00
if(show_cmt){
outString += aprsComment;
}
2021-03-24 16:35:42 +02:00
if(showBattery){
2021-02-12 01:03:15 +02:00
outString += " Batt=";
2021-02-13 19:15:02 +02:00
outString += String(BattVolts, 2);
2021-02-12 01:03:15 +02:00
outString += ("V");
2021-02-18 18:59:18 +02:00
}
2021-02-13 19:15:02 +02:00
2021-02-13 00:00:36 +02:00
#ifdef KISS_PROTOCOL
2021-02-15 22:53:37 +02:00
sendToTNC(outString);
#endif
}
2021-03-18 00:24:37 +02:00
#ifdef BUZZER
/**
* Buzzer sound playback
* @param melody - must be an array. Consisting of an even number of values. frequency and duration
* @param array_size - number of elements in the array
*/
void buzzer(int* melody, int array_size){
for(int i=0; i<array_size; i+=2){
ledcWriteTone(0, *melody);
melody++;
delay(*melody);
melody++;
}
ledcWriteTone(0,0); // turn off buzzer
}
#endif
void sendpacket(){
2021-03-18 00:24:37 +02:00
#ifdef BUZZER
int melody[] = {1000, 50, 800, 100};
buzzer(melody, sizeof(melody)/sizeof(int));
#endif
batt_read();
2021-02-15 22:53:37 +02:00
prepareAPRSFrame();
2021-07-23 07:31:16 +03:00
loraSend(txPower, aprsFreq, outString); //send the packet, data is in TXbuff from lora_TXStart to lora_TXEnd
}
2021-02-15 22:53:37 +02:00
/**
* Send message as APRS LoRa packet
2021-07-23 21:52:52 +03:00
* @param txPower
2021-07-23 07:31:16 +03:00
* @param aprsFreq
2021-02-15 22:53:37 +02:00
* @param message
*/
2021-09-06 20:15:00 +03:00
void loraSend(byte txPower, float aprsFreq, const String &message) {
#ifdef TX_RX_LNA
digitalWrite(TXPIN, HIGH);
digitalWrite(RXPIN, LOW);
#endif
#ifdef ENABLE_LED_SIGNALING
digitalWrite(TXLED, HIGH);
#endif
2018-12-06 08:47:42 +02:00
lastTX = millis();
2021-02-15 22:53:37 +02:00
int messageSize = min(message.length(), sizeof(lora_TXBUFF) - 1);
message.toCharArray((char*)lora_TXBUFF, messageSize + 1, 0);
2021-09-06 20:15:00 +03:00
if (aprsMode == 1200)
{
rf95.setModemConfig(BG_RF95::Bw125Cr47Sf512);
2021-09-06 20:15:00 +03:00
}
else
{
rf95.setModemConfig(BG_RF95::Bw125Cr45Sf4096);
2021-09-06 20:15:00 +03:00
}
rf95.setFrequency(aprsFreq);
2021-07-23 21:52:52 +03:00
rf95.setTxPower(txPower);
2021-02-15 22:53:37 +02:00
rf95.sendAPRS(lora_TXBUFF, messageSize);
rf95.waitPacketSent();
#ifdef TX_RX_LNA
digitalWrite(TXPIN, LOW);
digitalWrite(RXPIN, HIGH);
#endif
#ifdef ENABLE_LED_SIGNALING
digitalWrite(TXLED, LOW);
#endif
}
void batt_read(){
2021-02-13 19:05:18 +02:00
#ifdef T_BEAM_V1_0
BattVolts = axp.getBattVoltage()/1000;
2021-03-13 14:50:04 +02:00
InpVolts = axp.getVbusVoltage()/1000;
2021-02-13 19:05:18 +02:00
#else
BattVolts = analogRead(35)*7.221/4096;
#endif
}
2021-02-28 00:22:07 +02:00
void writedisplaytext(String HeaderTxt, String Line1, String Line2, String Line3, String Line4, String Line5) {
2021-02-13 22:41:56 +02:00
batt_read();
2021-02-27 20:52:08 +02:00
if (BattVolts < 3.5 && BattVolts > 3.2){
2021-02-15 14:35:51 +02:00
#ifdef T_BEAM_V1_0
# ifdef ENABLE_LED_SIGNALING
2021-02-15 14:35:51 +02:00
axp.setChgLEDMode(AXP20X_LED_BLINK_4HZ);
#endif
2021-02-15 14:35:51 +02:00
#endif
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(0,0);
2018-12-06 08:47:42 +02:00
display.println(HeaderTxt);
display.setTextSize(1);
display.setCursor(0,16);
display.println(Line1);
display.setCursor(0,26);
display.println(Line2);
display.setCursor(0,36);
display.println(Line3);
display.setCursor(0,46);
display.println(Line4);
display.setCursor(0,56);
display.println(Line5);
2021-03-09 09:04:17 +02:00
if (enabled_oled){
//axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // enable oled
2021-03-15 00:31:17 +02:00
display.dim(true);
2021-03-09 09:04:17 +02:00
}else{
//axp.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); // disable oled
2021-03-15 00:31:17 +02:00
display.dim(false);
2021-03-09 09:04:17 +02:00
}
display.display();
time_to_refresh = millis() + showRXTime;
}
2021-02-14 02:09:11 +02:00
String getSatAndBatInfo() {
String line5;
if(gps_state == true){
2021-03-13 14:50:04 +02:00
if(InpVolts > 4){
line5 = "SAT: " + String(gps.satellites.value()) + " BAT: " + String(BattVolts, 1) + "V *";
}else{
line5 = "SAT: " + String(gps.satellites.value()) + " BAT: " + String(BattVolts, 1) + "V";
}
2021-02-14 02:09:11 +02:00
}else{
2021-03-13 14:50:04 +02:00
if(InpVolts > 4){
line5 = "SAT: X BAT: " + String(BattVolts, 1) + "V *";
}else{
line5 = "SAT: X BAT: " + String(BattVolts, 1) + "V";
}
}
2021-02-15 22:53:37 +02:00
#if defined(ENABLE_BLUETOOTH) && defined(KISS_PROTOCOL)
2021-02-15 19:05:45 +02:00
if (SerialBT.hasClient()){
2021-02-14 02:09:11 +02:00
line5 += "BT";
}
#endif
return line5;
}
void displayInvalidGPS() {
2021-06-28 00:38:59 +03:00
char *nextTxInfo;
if (!gps_state){
nextTxInfo = (char*)"(TX) GPS DISABLED";
} else {
nextTxInfo = (char*)"(TX) at valid GPS";
}
writedisplaytext(" " + Tcall, nextTxInfo, "LAT: not valid", "LON: not valid", "SPD: --- CRS: ---", getSatAndBatInfo());
2021-02-14 02:09:11 +02:00
}
2021-02-15 22:53:37 +02:00
#if defined(KISS_PROTOCOL)
/**
*
* @param TNC2FormatedFrame
*/
void sendToTNC(const String& TNC2FormatedFrame) {
if (tncToSendQueue){
auto *buffer = new String();
buffer->concat(TNC2FormatedFrame);
if (xQueueSend(tncReceivedQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS){
// remove buffer on error
2021-02-15 22:53:37 +02:00
delete buffer;
}
}
}
#endif
#if defined(ENABLE_WIFI)
/**
*
* @param TNC2FormatedFrame
*/
void sendToWebList(const String& TNC2FormatedFrame, const int RSSI, const int SNR) {
if (webListReceivedQueue){
auto *receivedPacketData = new tReceivedPacketData();
receivedPacketData->packet = new String();
receivedPacketData->packet->concat(TNC2FormatedFrame);
receivedPacketData->RSSI = RSSI;
receivedPacketData->SNR = SNR;
2021-04-26 15:45:29 +03:00
getLocalTime(&receivedPacketData->rxTime);
if (xQueueSend(webListReceivedQueue, &receivedPacketData, (1000 / portTICK_PERIOD_MS)) != pdPASS){
// remove buffer on error
delete receivedPacketData->packet;
delete receivedPacketData;
}
}
}
#endif
2021-02-15 22:53:37 +02:00
String prepareCallsign(const String& callsign){
String tmpString = "";
for (int i=0; i<callsign.length();++i){ // remove unneeded "spaces" from callsign field
if (callsign.charAt(i) != ' ') {
tmpString += callsign.charAt(i);
}
}
return tmpString;
}
#if defined(ENABLE_TNC_SELF_TELEMETRY) && defined(KISS_PROTOCOL)
void sendTelemetryFrame() {
#ifdef T_BEAM_V1_0
uint8_t b_volt = (axp.getBattVoltage() - 3000) / 5.1;
uint8_t b_in_c = (axp.getBattChargeCurrent()) / 10;
uint8_t b_out_c = (axp.getBattDischargeCurrent()) / 10;
uint8_t ac_volt = (axp.getVbusVoltage() - 3000) / 28;
uint8_t ac_c = (axp.getVbusCurrent()) / 10;
String telemetryParamsNames = String(":") + Tcall + ":PARM.B Volt,B In,B Out,AC V,AC C";
String telemetryUnitNames = String(":") + Tcall + ":UNIT.mV,mA,mA,mV,mA";
String telemetryEquations = String(":") + Tcall + ":EQNS.0,5.1,3000,0,10,0,0,10,0,0,28,3000,0,10,0";
String telemetryData = String("T#MIC") + String(b_volt) + ","+ String(b_in_c) + ","+ String(b_out_c) + ","+ String(ac_volt) + ","+ String(ac_c) + ",00000000";
String telemetryBase = "";
2021-03-18 08:27:48 +02:00
telemetryBase += Tcall + ">APLS01" + ":";
sendToTNC(telemetryBase + telemetryParamsNames);
sendToTNC(telemetryBase + telemetryUnitNames);
sendToTNC(telemetryBase + telemetryEquations);
sendToTNC(telemetryBase + telemetryData);
#endif
}
#endif
2021-02-15 22:53:37 +02:00
// + SETUP --------------------------------------------------------------+//
void setup(){
2021-04-03 10:24:10 +03:00
SPI.begin(SPI_sck,SPI_miso,SPI_mosi,SPI_ss); //DO2JMG Heltec Patch
2021-09-06 20:15:00 +03:00
bool bme_status;
2021-03-18 00:24:37 +02:00
#ifdef BUZZER
ledcSetup(0,1E5,12);
ledcAttachPin(BUZZER,0);
ledcWriteTone(0,0); // turn off buzzer on start
#endif
2021-02-18 18:59:18 +02:00
#ifdef DIGI_PATH
2021-02-27 23:50:17 +02:00
relay_path = DIGI_PATH;
2021-02-18 18:59:18 +02:00
#else
2021-02-27 23:50:17 +02:00
relay_path = "";
2021-02-18 18:59:18 +02:00
#endif
2021-02-27 23:50:17 +02:00
#ifdef FIXED_BEACON_EN
2021-02-27 23:50:17 +02:00
fixed_beacon_enabled = true;
2021-02-18 18:59:18 +02:00
#endif
#ifdef ENABLE_PREFERENCES
2021-02-22 22:30:27 +02:00
int clear_preferences = 0;
if(digitalRead(BUTTON)==LOW){
clear_preferences = 1;
}
2021-02-18 18:59:18 +02:00
preferences.begin("cfg", false);
aprsSymbolTable = preferences.getString(PREF_APRS_SYMBOL_TABLE);
if (aprsSymbolTable.isEmpty()){
preferences.putString(PREF_APRS_SYMBOL_TABLE, APRS_SYMBOL_TABLE);
aprsSymbolTable = preferences.getString(PREF_APRS_SYMBOL_TABLE);
}
aprsSymbol = preferences.getString(PREF_APRS_SYMBOL);
if (aprsSymbol.isEmpty()){
preferences.putString(PREF_APRS_SYMBOL, APRS_SYMBOL);
aprsSymbol = preferences.getString(PREF_APRS_SYMBOL, APRS_SYMBOL);
}
2021-07-14 23:19:31 +03:00
if (!preferences.getBool(PREF_APRS_COMMENT_INIT)){
2021-02-18 18:59:18 +02:00
preferences.putBool(PREF_APRS_COMMENT_INIT, true);
preferences.putString(PREF_APRS_COMMENT, MY_COMMENT);
}
aprsComment = preferences.getString(PREF_APRS_COMMENT);
if (!preferences.getBool(PREF_APRS_RELAY_PATH_INIT)){
preferences.putBool(PREF_APRS_RELAY_PATH_INIT, true);
preferences.putString(PREF_APRS_RELAY_PATH, DIGI_PATH);
}
relay_path = preferences.getString(PREF_APRS_RELAY_PATH);
if (!preferences.getBool(PREF_APRS_SHOW_ALTITUDE_INIT)){
preferences.putBool(PREF_APRS_SHOW_ALTITUDE_INIT, true);
preferences.putBool(PREF_APRS_SHOW_ALTITUDE, showAltitude);
}
showAltitude = preferences.getBool(PREF_APRS_SHOW_ALTITUDE);
2021-03-08 19:55:52 +02:00
if (!preferences.getBool(PREF_APRS_GPS_EN_INIT)){
preferences.putBool(PREF_APRS_GPS_EN_INIT, true);
preferences.putBool(PREF_APRS_GPS_EN, gps_state);
}
gps_state = preferences.getBool(PREF_APRS_GPS_EN);
2021-02-18 18:59:18 +02:00
if (!preferences.getBool(PREF_APRS_SHOW_BATTERY_INIT)){
preferences.putBool(PREF_APRS_SHOW_BATTERY_INIT, true);
preferences.putBool(PREF_APRS_SHOW_BATTERY, showBattery);
}
showBattery = preferences.getBool(PREF_APRS_SHOW_BATTERY);
if (!preferences.getBool(PREF_APRS_LATITUDE_PRESET_INIT)){
preferences.putBool(PREF_APRS_LATITUDE_PRESET_INIT, true);
preferences.putString(PREF_APRS_LATITUDE_PRESET, LATIDUDE_PRESET);
}
aprsLatPreset = preferences.getString(PREF_APRS_LATITUDE_PRESET);
2021-02-18 18:59:18 +02:00
if (!preferences.getBool(PREF_APRS_LONGITUDE_PRESET_INIT)){
preferences.putBool(PREF_APRS_LONGITUDE_PRESET_INIT, true);
preferences.putString(PREF_APRS_LONGITUDE_PRESET, LONGITUDE_PRESET);
}
aprsLonPreset = preferences.getString(PREF_APRS_LONGITUDE_PRESET);
if (!preferences.getBool(PREF_APRS_FIXED_BEACON_PRESET_INIT)){
preferences.putBool(PREF_APRS_FIXED_BEACON_PRESET_INIT, true);
preferences.putBool(PREF_APRS_FIXED_BEACON_PRESET, fixed_beacon_enabled);
}
fixed_beacon_enabled = preferences.getBool(PREF_APRS_FIXED_BEACON_PRESET);
2021-03-09 11:45:15 +02:00
2021-02-18 18:59:18 +02:00
if (!preferences.getBool(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET_INIT)){
preferences.putBool(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET_INIT, true);
preferences.putInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET, fix_beacon_interval/1000);
}
2021-02-23 17:49:22 +02:00
fix_beacon_interval = preferences.getInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET) * 1000;
// + SMART BEACONING
2021-03-09 11:45:15 +02:00
if (!preferences.getBool(PREF_APRS_SB_MIN_INTERVAL_PRESET_INIT)){
preferences.putBool(PREF_APRS_SB_MIN_INTERVAL_PRESET_INIT, true);
preferences.putInt(PREF_APRS_SB_MIN_INTERVAL_PRESET, sb_min_interval/1000);
}
sb_min_interval = preferences.getInt(PREF_APRS_SB_MIN_INTERVAL_PRESET) * 1000;
if (!preferences.getBool(PREF_APRS_SB_MAX_INTERVAL_PRESET_INIT)){
preferences.putBool(PREF_APRS_SB_MAX_INTERVAL_PRESET_INIT, true);
preferences.putInt(PREF_APRS_SB_MAX_INTERVAL_PRESET, sb_max_interval/1000);
}
sb_max_interval = preferences.getInt(PREF_APRS_SB_MAX_INTERVAL_PRESET) * 1000;
if (!preferences.getBool(PREF_APRS_SB_MIN_SPEED_PRESET_INIT)){
preferences.putBool(PREF_APRS_SB_MIN_SPEED_PRESET_INIT, true);
preferences.putInt(PREF_APRS_SB_MIN_SPEED_PRESET, sb_min_speed);
}
sb_min_speed = preferences.getInt(PREF_APRS_SB_MIN_SPEED_PRESET);
if (!preferences.getBool(PREF_APRS_SB_MAX_SPEED_PRESET_INIT)){
preferences.putBool(PREF_APRS_SB_MAX_SPEED_PRESET_INIT, true);
preferences.putInt(PREF_APRS_SB_MAX_SPEED_PRESET, sb_max_speed);
}
sb_max_speed = preferences.getInt(PREF_APRS_SB_MAX_SPEED_PRESET);
2021-07-14 23:19:31 +03:00
//Set parameters (freq,mode,txpower)
if (!preferences.getBool(PREF_APRS_FREQ_INIT)){
preferences.putBool(PREF_APRS_FREQ_INIT, true);
2021-09-06 20:15:00 +03:00
preferences.putDouble(PREF_APRS_FREQ, aprsFreq);
2021-07-14 23:19:31 +03:00
}
2021-09-06 20:15:00 +03:00
aprsFreq = preferences.getDouble(PREF_APRS_FREQ);
2021-07-14 23:19:31 +03:00
if (!preferences.getBool(PREF_APRS_MODE_INIT)){
preferences.putBool(PREF_APRS_MODE_INIT, true);
2021-09-06 20:15:00 +03:00
preferences.putInt(PREF_APRS_MODE, aprsMode);
2021-07-14 23:19:31 +03:00
}
2021-09-06 20:15:00 +03:00
aprsMode = preferences.getInt(PREF_APRS_MODE);
if (!preferences.getBool(PREF_APRS_TXPOWER_INIT)){
preferences.putBool(PREF_APRS_TXPOWER_INIT, true);
2021-07-23 07:31:16 +03:00
preferences.putInt(PREF_APRS_TXPOWER, txPower);
}
2021-07-23 07:31:16 +03:00
txPower = preferences.getInt(PREF_APRS_TXPOWER);
2021-07-14 23:19:31 +03:00
//End set parameters
2021-03-09 11:45:15 +02:00
if (!preferences.getBool(PREF_DEV_SHOW_RX_TIME_INIT)){
preferences.putBool(PREF_DEV_SHOW_RX_TIME_INIT, true);
preferences.putInt(PREF_DEV_SHOW_RX_TIME, showRXTime/1000);
}
showRXTime = preferences.getInt(PREF_DEV_SHOW_RX_TIME) * 1000;
2021-03-13 14:50:04 +02:00
if (!preferences.getBool(PREF_DEV_AUTO_SHUT_PRESET_INIT)){
preferences.putBool(PREF_DEV_AUTO_SHUT_PRESET_INIT, true);
preferences.putInt(PREF_DEV_AUTO_SHUT_PRESET, shutdown_delay_time/1000);
}
shutdown_delay_time = preferences.getInt(PREF_DEV_AUTO_SHUT_PRESET) * 1000;
if (!preferences.getBool(PREF_DEV_AUTO_SHUT_INIT)){
preferences.putBool(PREF_DEV_AUTO_SHUT_INIT, true);
preferences.putBool(PREF_DEV_AUTO_SHUT, shutdown_active);
}
shutdown_active = preferences.getBool(PREF_DEV_AUTO_SHUT);
2021-03-09 11:45:15 +02:00
2021-02-22 22:30:27 +02:00
if (clear_preferences){
delay(1000);
if(digitalRead(BUTTON)==LOW){
clear_preferences = 2;
}
}
2021-03-08 23:47:00 +02:00
2021-03-09 00:59:33 +02:00
if (!preferences.getBool(PREF_APRS_SHOW_CMT_INIT)){
preferences.putBool(PREF_APRS_SHOW_CMT_INIT, true);
preferences.putBool(PREF_APRS_SHOW_CMT, show_cmt);
}
show_cmt = preferences.getBool(PREF_APRS_SHOW_CMT);
2021-03-08 23:47:00 +02:00
if (!preferences.getBool(PREF_DEV_BT_EN_INIT)){
preferences.putBool(PREF_DEV_BT_EN_INIT, true);
preferences.putBool(PREF_DEV_BT_EN, enable_bluetooth);
}
2021-03-25 01:54:53 +02:00
enable_bluetooth = preferences.getBool(PREF_DEV_BT_EN);
2021-03-09 00:59:33 +02:00
if (!preferences.getBool(PREF_DEV_OL_EN_INIT)){
preferences.putBool(PREF_DEV_OL_EN_INIT, true);
preferences.putBool(PREF_DEV_OL_EN,enabled_oled);
}
enabled_oled = preferences.getBool(PREF_DEV_OL_EN);
#endif
for (int i=0;i<ANGLE_AVGS;i++) { // set average_course to "0"
average_course[i]=0;
2018-12-24 16:29:36 +02:00
}
#ifdef TX_RX_LNA
pinMode(TXPIN, OUTPUT);
pinMode(RXPIN, OUTPUT);
#endif
pinMode(TXLED, OUTPUT);
2021-07-26 22:01:54 +03:00
2021-03-14 23:21:30 +02:00
#ifdef T_BEAM_V1_0
pinMode(BUTTON, INPUT);
#elif T_BEAM_V0_7
pinMode(BUTTON, INPUT);
#else
pinMode(BUTTON, INPUT_PULLUP);
#endif
#ifdef TX_RX_LNA
digitalWrite(TXPIN, LOW); // turn blue LED off
digitalWrite(RXPIN, HIGH); // turn blue LED off
#endif
digitalWrite(TXLED, LOW); // turn blue LED off
Serial.begin(115200);
Wire.begin(I2C_SDA, I2C_SCL);
2018-12-09 23:23:20 +02:00
2021-02-13 19:15:02 +02:00
#ifdef T_BEAM_V1_0
2021-02-27 23:53:46 +02:00
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
}
axp.setLowTemp(0xFF); //SP6VWX Set low charging temperature
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // LoRa
2021-06-28 00:38:59 +03:00
if (gps_state){
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // switch on GPS
} else {
axp.setPowerOutPut(AXP192_LDO3, AXP202_OFF); // switch off GPS
}
2021-02-13 19:15:02 +02:00
axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON);
axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON);
axp.setDCDC1Voltage(3300);
2021-02-15 14:27:59 +02:00
// Enable ADC to measure battery current, USB voltage etc.
2021-02-13 19:15:02 +02:00
axp.adc1Enable(0xfe, true);
axp.adc2Enable(0x80, true);
2021-03-09 09:04:17 +02:00
axp.setChgLEDMode(AXP20X_LED_OFF);
axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // oled do not turn off
#endif
2021-02-13 19:15:02 +02:00
if(!display.begin(SSD1306_SWITCHCAPVCC, SSD1306_ADDRESS)) {
2021-02-27 23:50:17 +02:00
for(;;); // Don't proceed, loop forever
}
2021-03-21 19:38:48 +02:00
2021-02-22 22:30:27 +02:00
#ifdef ENABLE_PREFERENCES
if (clear_preferences == 2){
2021-02-28 00:22:07 +02:00
writedisplaytext("LoRa-APRS","","","Factory reset","","");
2021-02-22 22:32:06 +02:00
delay(1000);
2021-03-14 23:21:30 +02:00
//#ifdef T_BEAM_V1_0
2021-03-14 18:05:10 +02:00
if(digitalRead(BUTTON)==LOW){
clear_preferences = 3;
preferences.clear();
preferences.end();
writedisplaytext("LoRa-APRS","","Factory reset","Done!","","");
delay(2000);
ESP.restart();
} else {
writedisplaytext("LoRa-APRS","","Factory reset","Cancel","","");
delay(2000);
}
2021-03-14 23:21:30 +02:00
//#endif
2021-02-22 22:30:27 +02:00
}
#endif
2021-02-28 00:22:07 +02:00
writedisplaytext("LoRa-APRS","","Init:","Display OK!","","");
2021-02-18 18:59:18 +02:00
Tcall = prepareCallsign(String(CALLSIGN));
2021-02-18 18:59:18 +02:00
#ifdef ENABLE_PREFERENCES
Tcall = preferences.getString(PREF_APRS_CALLSIGN);
if (Tcall.isEmpty()){
preferences.putString(PREF_APRS_CALLSIGN, String(CALLSIGN));
Tcall = preferences.getString(PREF_APRS_CALLSIGN);
}
#endif
2021-02-13 19:15:02 +02:00
if (!rf95.init()) {
//writedisplaytext("LoRa-APRS","","Init:","RF95 FAILED!",":-(","");
Serial.println("init failed");
for(;;); // Don't proceed, loop forever
}
if (sb_max_interval < nextTX){
sb_max_interval=nextTX;
2021-02-12 01:03:15 +02:00
}
2021-02-28 00:22:07 +02:00
writedisplaytext("LoRa-APRS","","Init:","RF95 OK!","","");
writedisplaytext(" "+Tcall,"","Init:","Waiting for GPS","","");
2021-02-19 02:27:14 +02:00
xTaskCreate(taskGPS, "taskGPS", 5000, nullptr, 1, nullptr);
2021-02-28 00:22:07 +02:00
writedisplaytext(" "+Tcall,"","Init:","GPS Task Created!","","");
2021-02-13 19:05:18 +02:00
#ifndef T_BEAM_V1_0
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_6);
#endif
batt_read();
2021-02-28 00:22:07 +02:00
writedisplaytext("LoRa-APRS","","Init:","ADC OK!","BAT: "+String(BattVolts,1),"");
2021-09-06 20:15:00 +03:00
if (aprsMode == 1200)
{
rf95.setModemConfig(BG_RF95::Bw125Cr47Sf512);
2021-09-06 20:15:00 +03:00
}
else
{
rf95.setModemConfig(BG_RF95::Bw125Cr45Sf4096);
2021-09-06 20:15:00 +03:00
}
rf95.setFrequency(aprsFreq);
rf95.setTxPower(txPower);
delay(250);
2021-02-15 22:53:37 +02:00
#ifdef KISS_PROTOCOL
xTaskCreatePinnedToCore(taskTNC, "taskTNC", 10000, nullptr, 1, nullptr, xPortGetCoreID());
#endif
2021-03-08 23:47:00 +02:00
#if defined(KISS_PROTOCOL)
if (enable_bluetooth){
#ifdef BLUETOOTH_PIN
SerialBT.setPin(BLUETOOTH_PIN);
#endif
2021-03-15 00:31:17 +02:00
#ifdef ENABLE_BLUETOOTH
2021-07-05 23:36:12 +03:00
SerialBT.begin(String("LORA APRS ") + Tcall);
2021-03-15 00:31:17 +02:00
writedisplaytext("LoRa-APRS","","Init:","BT OK!","","");
#endif
2021-03-08 23:47:00 +02:00
}
2021-02-12 20:01:50 +02:00
#endif
2021-03-08 23:47:00 +02:00
2021-02-18 18:59:18 +02:00
#ifdef ENABLE_WIFI
webServerCfg = {.callsign = Tcall};
2021-06-11 03:15:42 +03:00
xTaskCreate(taskWebServer, "taskWebServer", 12000, (void*)(&webServerCfg), 1, nullptr);
2021-02-28 00:22:07 +02:00
writedisplaytext("LoRa-APRS","","Init:","WiFi task started"," =:-) ","");
2021-02-18 18:59:18 +02:00
#endif
2021-02-28 00:22:07 +02:00
writedisplaytext("LoRa-APRS","","Init:","FINISHED OK!"," =:-) ","");
writedisplaytext("","","","","","");
time_to_refresh = millis() + showRXTime;
2021-02-13 23:16:45 +02:00
displayInvalidGPS();
2021-09-06 20:15:00 +03:00
#ifdef USE_BME280
bme_status = bme.begin(0x76);
if (!bme_status)
{
Serial.println("Could not find a valid BME280 sensor, check wiring!");
//writedisplaytext("LoRa-APRS","","Init:","BME280 ERROR!","","",3000);
tempsensoravailable = false;
}
pressure_offset = calc_pressure_offset(HEIGTH_PRESET);
// bme.takeForcedMeasurement();
temp = bme.readTemperature() - 3; // bme Temperatur auslesen
// hum = bme.readHumidity();
pressure = bme.readPressure()/100 + pressure_offset;
#endif
#ifdef TX_RX_LNA
digitalWrite(TXPIN, LOW);
digitalWrite(RXPIN, HIGH);
#endif
digitalWrite(TXLED, LOW);
2021-09-06 20:15:00 +03:00
hum_temp_ctr = 0;
}
2020-01-02 21:13:30 +02:00
// +---------------------------------------------------------------------+//
// + MAINLOOP -----------------------------------------------------------+//
// +---------------------------------------------------------------------+//
void loop() {
if(digitalRead(BUTTON)==LOW && key_up == true){
key_up = false;
2021-02-16 11:11:22 +02:00
delay(50);
if(digitalRead(BUTTON)==LOW){
delay(300);
2021-02-16 11:11:22 +02:00
time_delay = millis() + 1500;
if(digitalRead(BUTTON)==HIGH){
if(gps_state == true && gps.location.isValid()){
2021-02-28 00:22:07 +02:00
writedisplaytext("((MAN TX))","","","","","");
sendpacket();
}else{
2021-02-28 00:22:07 +02:00
writedisplaytext("((FIX TX))","","","","","");
sendpacket();
}
2021-02-16 11:11:22 +02:00
key_up = true;
}
}
2021-02-16 11:11:22 +02:00
}
2021-02-17 00:38:28 +02:00
if(digitalRead(BUTTON)==LOW && key_up == false && millis() >= time_delay && t_lock == false){
t_lock = true;
if(gps_state){
2021-02-17 00:38:28 +02:00
gps_state = false;
#ifdef T_BEAM_V1_0
2021-04-13 16:52:07 +03:00
axp.setPowerOutPut(AXP192_LDO3, AXP202_OFF); // GPS OFF
2021-02-17 00:38:28 +02:00
#endif
2021-02-28 00:22:07 +02:00
writedisplaytext("((GPSOFF))","","","","","");
2021-02-17 00:38:28 +02:00
next_fixed_beacon = millis() + fix_beacon_interval;
#ifdef ENABLE_PREFERENCES
preferences.putBool(PREF_APRS_GPS_EN, false);
#endif
2021-02-17 00:38:28 +02:00
}else{
gps_state = true;
#ifdef T_BEAM_V1_0
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON);
#endif
2021-02-28 00:22:07 +02:00
writedisplaytext("((GPS ON))","","","","",""); // GPS ON
#ifdef ENABLE_PREFERENCES
preferences.putBool(PREF_APRS_GPS_EN, true);
#endif
2021-02-17 00:38:28 +02:00
}
}
2021-02-16 11:11:22 +02:00
if(digitalRead(BUTTON)==HIGH && !key_up){
key_up = true;
2021-02-16 11:11:22 +02:00
t_lock = false;
}
if (fixed_beacon_enabled) {
if (millis() >= next_fixed_beacon && !gps_state) {
2021-02-15 14:01:52 +02:00
next_fixed_beacon = millis() + fix_beacon_interval;
2021-02-28 00:22:07 +02:00
writedisplaytext("((AUT TX))", "", "", "", "", "");
2021-02-15 14:01:52 +02:00
sendpacket();
}
}
2021-03-13 14:50:04 +02:00
#ifdef T_BEAM_V1_0
if(shutdown_active){
if(InpVolts> 4){
shutdown_usb_status_bef = true;
shutdown_countdown_timer_enable = false;
}
if(InpVolts < 4 && shutdown_usb_status_bef == true){
shutdown_usb_status_bef = false;
shutdown_countdown_timer_enable = true;
shutdown_countdown_timer = millis() + shutdown_delay_time;
}
if(shutdown_countdown_timer_enable){
if(millis() >= shutdown_countdown_timer){
axp.shutdown();
}
}
}
#endif
2021-02-13 00:00:36 +02:00
#ifdef KISS_PROTOCOL
2021-02-15 22:53:37 +02:00
String *TNC2DataFrame = nullptr;
if (tncToSendQueue) {
if (xQueueReceive(tncToSendQueue, &TNC2DataFrame, (1 / portTICK_PERIOD_MS)) == pdPASS) {
2021-02-28 00:22:07 +02:00
writedisplaytext("((KISSTX))","","","","","");
time_to_refresh = millis() + showRXTime;
2021-07-23 07:31:16 +03:00
loraSend(txPower, aprsFreq, *TNC2DataFrame);
2021-02-15 22:53:37 +02:00
delete TNC2DataFrame;
2021-02-12 17:25:14 +02:00
}
2021-02-15 22:53:37 +02:00
}
2021-02-12 01:03:15 +02:00
#endif
2021-09-06 20:15:00 +03:00
if (hum_temp)
{
++hum_temp_ctr;
if (hum_temp_ctr>hum_temp_ctr_max)
{
hum_temp_ctr = 0;
hum_temp=false;
}
#ifdef USE_BME280
//bme.takeForcedMeasurement();
temp = bme.readTemperature() - 3; // bme Temperatur auslesen
#endif
}
else
{
++hum_temp_ctr;
if (hum_temp_ctr>hum_temp_ctr_max)
{
hum_temp_ctr = 0;
hum_temp=true;
}
#ifdef USE_BME280
//bme.takeForcedMeasurement();
//hum = bme.readHumidity();
pressure = bme.readPressure()/100 + pressure_offset;
#endif
}
if (rf95.waitAvailableTimeout(100)) {
2021-02-15 14:35:51 +02:00
#ifdef T_BEAM_V1_0
#ifdef ENABLE_LED_SIGNALING
axp.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
#endif
2021-02-15 14:35:51 +02:00
#endif
2021-03-18 00:24:37 +02:00
#ifdef BUZZER
int melody[] = {300, 50, 500, 100};
buzzer(melody, sizeof(melody)/sizeof(int));
#endif
#ifdef SHOW_RX_PACKET // only show RX packets when activitated in config
2021-02-13 22:41:56 +02:00
loraReceivedLength = sizeof(lora_RXBUFF); // reset max length before receiving!
if (rf95.recvAPRS(lora_RXBUFF, &loraReceivedLength)) {
loraReceivedFrameString = "";
2021-02-17 21:26:10 +02:00
//int rssi = rf95.lastSNR();
//Serial.println(rssi);
for (int i=0 ; i < loraReceivedLength ; i++) {
loraReceivedFrameString += (char) lora_RXBUFF[i];
}
2021-02-28 00:22:07 +02:00
writedisplaytext(" ((RX))", "", loraReceivedFrameString, "", "", "");
2021-02-13 00:00:36 +02:00
#ifdef KISS_PROTOCOL
2021-07-01 14:03:38 +03:00
#ifdef RSSI_SNR_REPORT
2021-07-01 16:02:17 +03:00
sendToTNC(loraReceivedFrameString + ", RSSI:"+ rf95.lastRssi() + ", SNR:" + rf95.lastSNR() / 10); //show RSSI & SNR in packet
2021-07-01 14:03:38 +03:00
#else
sendToTNC(loraReceivedFrameString);
#endif
2021-01-22 13:40:48 +02:00
#endif
#ifdef ENABLE_WIFI
sendToWebList(loraReceivedFrameString, rf95.lastRssi(), rf95.lastSNR());
#endif
syslog_log(LOG_INFO, String("Received LoRa: '") + loraReceivedFrameString + "', RSSI:" + rf95.lastRssi() + ", SNR: " + rf95.lastSNR());
2018-12-24 16:29:36 +02:00
}
#endif
2021-02-15 14:35:51 +02:00
#ifdef T_BEAM_V1_0
#ifdef ENABLE_LED_SIGNALING
axp.setChgLEDMode(AXP20X_LED_OFF);
#endif
2021-02-15 14:35:51 +02:00
#endif
}
LatShown = String(gps.location.lat(),5);
LongShown = String(gps.location.lng(),5);
average_speed[point_avg_speed] = gps.speed.kmph(); // calculate smart beaconing
++point_avg_speed;
2021-02-12 01:03:15 +02:00
if (point_avg_speed>4) {
point_avg_speed=0;
}
average_speed_final = (average_speed[0]+average_speed[1]+average_speed[2]+average_speed[3]+average_speed[4])/5;
nextTX = (sb_max_interval-sb_min_interval)/(sb_max_speed-sb_min_speed)*(sb_max_speed-average_speed_final)+sb_min_interval;
if (nextTX < sb_min_interval) {nextTX=sb_min_interval;}
if (nextTX > sb_max_interval) {nextTX=sb_max_interval;}
average_course[point_avg_course] = gps.course.deg(); // calculate smart beaconing course
++point_avg_course;
if (point_avg_course>(ANGLE_AVGS-1)) {
point_avg_course=0;
avg_c_y = 0;
avg_c_x = 0;
for (int i=0;i<ANGLE_AVGS;i++) {
avg_c_y += sin(average_course[i]/180*3.1415);
avg_c_x += cos(average_course[i]/180*3.1415);
2018-12-24 16:29:36 +02:00
}
new_course = atan2f(avg_c_y,avg_c_x)*180/3.1415;
if (new_course < 0) {
new_course=360+new_course;
}
if ((old_course < ANGLE) && (new_course > (360-ANGLE))) {
if (abs(new_course-old_course-360)>=ANGLE) {
nextTX = 0;
// lastTX = sb_min_interval
2020-01-02 21:13:30 +02:00
}
} else {
if ((old_course > (360-ANGLE)) && (new_course < ANGLE)) {
if (abs(new_course-old_course+360)>=ANGLE) {
nextTX = 0;
2020-01-02 21:13:30 +02:00
}
} else {
if (abs(new_course-old_course)>=ANGLE) {
nextTX = 0;
2020-01-02 21:13:30 +02:00
}
}
2018-12-24 16:29:36 +02:00
}
old_course = new_course;
}
if ((millis()<sb_max_interval)&&(lastTX == 0)) {
nextTX = 0;
}
if ( (lastTX+nextTX) <= millis() ) {
if (gps.location.age() < 2000) {
2021-02-28 00:22:07 +02:00
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),getSatAndBatInfo());
sendpacket();
2021-02-13 23:16:45 +02:00
} else {
if (millis() > time_to_refresh){
displayInvalidGPS();
}
}
}else{
2021-02-15 00:08:00 +02:00
if (millis() > time_to_refresh){
if (gps.location.age() < 2000) {
2021-02-28 00:22:07 +02:00
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000)+"sec","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph())+" CRS: "+String(gps.course.deg(),1),getSatAndBatInfo());
2021-02-12 16:43:10 +02:00
} else {
displayInvalidGPS();
}
2021-02-15 00:08:00 +02:00
}
}
#if defined(ENABLE_TNC_SELF_TELEMETRY) && defined(KISS_PROTOCOL)
if (nextTelemetryFrame < millis()){
nextTelemetryFrame = millis() + TNC_SELF_TELEMETRY_INTERVAL;
sendTelemetryFrame();
}
#endif
2021-02-13 00:00:36 +02:00
#ifdef KISS_PROTOCOL
2021-02-13 19:15:02 +02:00
#ifdef KISS_DEBUG
static auto last_debug_send_time = millis();
if (millis() - last_debug_send_time > 1000*5) {
last_debug_send_time = millis();
String debug_message = "";
2021-02-15 14:35:51 +02:00
#ifdef T_BEAM_V1_0
debug_message += "Bat V: " + String(axp.getBattVoltage());
debug_message += ", ";
debug_message += "Bat IN A: " + String(axp.getBattChargeCurrent());
debug_message += ", ";
debug_message += "Bat OUT A: " + String(axp.getBattDischargeCurrent());
debug_message += ", ";
debug_message += "USB Plugged: " + String(axp.isVBUSPlug());
debug_message += ", ";
debug_message += "USB V: " + String(axp.getVbusVoltage());
debug_message += ", ";
debug_message += "USB A: " + String(axp.getVbusCurrent());
debug_message += ", ";
debug_message += "Temp C: " + String(axp.getTemp());
#else
debug_message += "Bat V: " + String(BattVolts);
#endif
2021-02-13 19:15:02 +02:00
Serial.print(encapsulateKISS(debug_message, CMD_HARDWARE));
#ifdef ENABLE_BLUETOOTH
SerialBT.print(encapsulateKISS(debug_message, CMD_HARDWARE));
#endif
}
2021-02-12 23:56:59 +02:00
#endif
2021-02-12 22:44:06 +02:00
#endif
2021-02-13 18:42:51 +02:00
vTaskDelay(1);
2021-09-06 20:15:00 +03:00
}
int calc_pressure_offset(int height) {
//
// A very simple method to calculate the offset for correcting the measured air pressure
// to the pressure at mean sea level (MSL). It is simplificated to "For each 8m change in height
// the pressure is changing by 1hPa."
// The exact method is described at
// https://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Internationale_H%C3%B6henformel
//
int offset = round(height / 8);
return(offset);
2021-02-17 00:38:28 +02:00
}