release of Version 1.2

pull/2/head
Christian OE3CJB Bauer 3 years ago
parent 694c76b562
commit 68ca7e4940
  1. 23
      README.md
  2. 703
      src/TTGO_T-Beam_LoRa_APRS.ino
  3. 10
      src/TTGO_T-Beam_LoRa_APRS_config.h

@ -3,32 +3,41 @@ He is the author of BG_RF95!<br>
<br>
If you want to discuss with other LoRa APRS interested persons join the growing community at the LoRa-APRS Telegram group<br>
<br>
<b>USER GUIDE of TTGO T-Beam LoRa APRS V1.1:</b><br>
<b>USER GUIDE of TTGO T-Beam LoRa APRS V1.2:</b><br>
<b>Attention: a new HW Version is available - if you use the old version uncomment "// #define T_BEAM_V0_7" and comment out "#define T_BEAM_V1_0".</b>You can recognize the new Rev1.0-Boards at their three push buttons instead of two at the older boards - both versions are now supported.<br>
As the new board only has two LEDs for the GPS and battery charger I've moved the TX Led to PIN 33 - please use a LED with reasonable resistor of 470R.<br>
<br>
You can now do an immediate TX beacon if you press the key for 2secs - use this for testing purposes.<br>
<br>
<b>Callsign setting:</b><br>
Now two possibilities are implemented:<br>
1st) enter your callsign in the file TTGO_T-Beam_LoRa_APRS_<b>config</b>.h and replace the OE1XYZ-0 with your data with 6 characters plus SSID-<br>
in case of shorter callsign use "SPACES" and extend up to total length of 6 characters<br>
2nd) if you leave the config-file unchanged, you will run into a simple setup routine at the very first boot and you will be asked to enter your callsign and SSID(s).<br>
Once the callsign is programmed you can reenter the programming mode by pressing the BUTTON for 3secs while switching on the tracker.<br>
Once the callsign is programmed you can reenter the programming mode by pressing the BUTTON for 5secs while switching on the tracker.<br>
<br>
The MODE of the tracker can now be changed by pressing the button 10secs!<br>
This can be done now without connected display but with a mounted TX LED.<br>
<b>The modes are</b><br>
TRACKER ... normal APRS tracker<br>
WX&TRACKER ... alternate transmission of normal position packet and WX packet (if DHT22 is mounted)<br>
WX-MOVE ... only WX packets are sent but with position from GPSLED<br>
WX-FIXED ... only WX packets are transmitted but with fixed position given in Header-File<br>
TRACKER ... LED blinks 1x - normal APRS tracker<br>
WX&TRACKER ... LED blinks 2x - alternate transmission of normal position packet and WX packet (if DHT22 is mounted)<br>
WX-MOVE ... LED blinks 3x - only WX packets are sent but with position from GPS<br>
WX-FIXED ... LED blinks 4x - only WX packets are transmitted but with fixed position given in Header-File<br>
<br>
The <b>fixed position</b> is used for a fixed weather station, e.g. without GPS signal.<br>
<br>
Possible symbols are<br>
Weather Station, Car, Runner, Bicyle, Motorcycle<br>
Weather Station (1x blink), Car (2x blink), Runner (3x blink), Bicyle (4x blink), Motorcycle (5x blink)<br>
The symbol can now be changed without attached display - during normal operation press the key for 3secs and you will enter the setup routine. The first value to set is now the symbol and the currently selected symbol is represented by blinks of the TX LED. Once the one needed blinks, just press the key for short moment. After that you will be asked if you want to continue the setup routine (which only makes sense with a connected display) or if you want to stop and so the new symbol will be stored in the NVS memory.<br>
<b>2x TX LED blinks represent "yes" to leave the setup</b> - press here the key to leave the setup - please do so if you don't have a display attached.<br>
1x TX LED blinks represent "no" to continue with the setup - press here the key to continue the setup - please do so if you have a display attached.<br>
<br>
for DHT22 I used the library from https://github.com/beegee-tokyo/DHTesp, as the standard library gives to many wrong readings<br>
<br>
new features:<br>
- immediate TX with short key press
- course changes of >30° will cause a TX beacon
- code optimized and cleaned
- preset of callsign and SSID in file TTGO_T-Beam_LoRa_APRS_<b>config</b>.h --- this is the <b>only</b> you should change - if you are not familiar with programming ;-)<br>
- corrected format of speed, course and height to be shown correctly in aprs.fi and aprsdirect.com
- Smart Beaconing - the maximum period can be set in the config-file - the minimum period is limited to 60sec, the calculation is based on speeds between 0 and 50 km/h, the default is smart beaconing is off with a minimium period setting of 60secs<br>

@ -11,10 +11,16 @@
//
// licensed under CC BY-NC-SA
//
// version: V1.1beta
// last update: 22.11.2019
// version: V1.2
// last update: 02.01.2020
//
// change history
// added course change to smart Beaconing
// code cleaned
// change of mode with KEY (without display but with LED only)
// change of symbol with KEY (without display but with LED only)
//
// version V1.1
// added HW Version V1.0 support
// added presetting in the header TTGO...config.h to prevent long initial setup at first boot up
// added "SPACE" to allowed letters for callsign for shorter callsigns - has to be added at the end
@ -47,7 +53,21 @@
#include <gfxfont.h>
#include <axp20x.h>
//Hardware definitions
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//PINs used for HW extensions
// Pin for battery voltage -> bei T-Beam ADC1_CHANNEL_7
// #define ANALOG_PIN_0 35 // connected to battery
// I2C LINES
#define I2C_SDA 21
#define I2C_SCL 22
// DISPLAY address
#define SSD1306_ADDRESS 0x3C
// AXP192 address
#define AXP192_SLAVE_ADDRESS 0x34
/* for feather32u4
#define RFM95_CS 8
@ -55,7 +75,8 @@
#define RFM95_INT 7
*/
//Variables for DHT22 temperature and humidity sensor
// Variables for DHT22 temperature and humidity sensor
int chk;
boolean hum_temp = false;
float hum=0; //Stores humidity value
@ -66,6 +87,9 @@ float tempf=99.99; //Stores temperature value
String Textzeile1, Textzeile2;
int button=0;
int button_ctr=0;
// int version=0; // 0 = V0.7, 1 = V1.0
// bool ssd1306_found = false;
// bool axp192_found = false;
enum Tx_Mode {TRACKER, WX_TRACKER, WX_MOVE, WX_FIXED};
// Position from GPS for TRACKER and WX_TRACKER
@ -73,14 +97,8 @@ enum Tx_Mode {TRACKER, WX_TRACKER, WX_MOVE, WX_FIXED};
Tx_Mode tracker_mode;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//PINs used for HW extensions
// Pin for battery voltage -> bei T-Beam ADC1_CHANNEL_7
// #define ANALOG_PIN_0 35 // connected to battery
// Pins for GPS
#ifdef T_BEAM_V1_0
static const int RXPin = 12, TXPin = 34; // changed BG A3 A2
#else
@ -101,9 +119,10 @@ const byte RX_en = 0; //TX/RX enable 1W modul
// Button of TTGO T-Beam
#ifdef T_BEAM_V1_0
const byte BUTTON = 38; //pin number for Button on TTGO T-Beam
// const byte BUTTON = 38; //pin number for Button on TTGO T-Beam
#define BUTTON 38 //pin number for Button on TTGO T-Beam
#else
const byte BUTTON = 39; //pin number for Button on TTGO T-Beam
#define BUTTON 39 //pin number for Button on TTGO T-Beam
#endif
// const byte GPSLED = 6; // pin gps & Heartbeat
@ -172,7 +191,8 @@ unsigned long lastTX = 0L;
float BattVolts;
// variables for smart beaconing
float average_speed[5] = {0,0,0,0,0}, average_speed_final=0, max_speed=50, min_speed=0;
float average_speed[5] = {0,0,0,0,0}, average_speed_final=0, max_speed=30, min_speed=0;
float old_course = 0, new_course = 0;
int point_avg_speed = 0;
ulong min_time_to_nextTX=60000L; // minimum time period between TX = 60000ms = 60secs = 1min
ulong nextTX=60000L; // preset time period between TX = 60000ms = 60secs = 1min
@ -210,6 +230,10 @@ BG_RF95 rf95(18, 26); // TTGO T-Beam has NSS @ Pin 18 and Interrupt IO @
#define OLED_RESET 4 // not used
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);
// +---------------------------------------------------------------------+//
// + SETUP --------------------------------------------------------------+//
// +---------------------------------------------------------------------+//
void setup()
{
prefs.begin("nvs", false);
@ -231,12 +255,13 @@ void setup()
digitalWrite(TXLED, LOW); // turn blue LED off
Serial.begin(115200);
Wire.begin(I2C_SDA, I2C_SCL);
#ifdef T_BEAM_V1_0 // initialize power controller - new on HW V1.0
Wire.begin(21, 22);
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
Serial.println("AXP192 Begin PASS");
Serial.println("LoRa-APRS / Init / AXP192 Begin PASS");
} else {
Serial.println("AXP192 Begin FAIL");
Serial.println("LoRa-APRS / Init / AXP192 Begin FAIL");
}
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON);
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON);
@ -246,14 +271,13 @@ void setup()
axp.setDCDC1Voltage(3300);
#endif
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
if(!display.begin(SSD1306_SWITCHCAPVCC, SSD1306_ADDRESS)) {
for(;;); // Don't proceed, loop forever
}
digitalWrite(TXLED, HIGH);
writedisplaytext("LoRa-APRS","","Init:","Display OK!","","Press 3sec for Config",250);
digitalWrite(TXLED, LOW);
Serial.println("Init: Display OK!");
writedisplaytext("LoRa-APRS","","Init:","Display OK!","","PRESS 3sec for config",1000);
Serial.println("LoRa-APRS / Init / Display OK! / PRESS 3sec for config");
#ifndef DONT_USE_FLASH_MEMORY
//////////////////////////// Setup CALLSIGN
prefs.begin("nvs", false);
Tcall = prefs.getString("Tcall", CALLSIGN);
@ -262,218 +286,304 @@ void setup()
LatFixed = prefs.getString("LatFixed", LATIDUDE_PRESET);
TxSymbol = prefs.getString("TxSymbol", APRS_SYMBOL);
prefs.end();
#else
Tcall = CALLSIGN;
wxTcall = WX_CALLSIGN;
LongFixed = LONGITUDE_PRESET;
LatFixed = LATIDUDE_PRESET;
TxSymbol = APRS_SYMBOL;
#endif
Serial.println("LoRa-APRS / Call="+Tcall+" / WX-Call="+wxTcall+" / TxSymbol="+TxSymbol);
int start_button_pressed = millis();
#ifndef DONT_USE_FLASH_MEMORY
while ((digitalRead(BUTTON) == LOW) && (millis()<start_button_pressed+3000)) {
}
//if (((start_button_pressed+3000<millis())&&(digitalRead(BUTTON) == LOW)) || (Tcall == "OE1000-0")) {
if ((digitalRead(BUTTON) == LOW) || (Tcall == "OE1XYZ-0")) { // into setup when no real data entered in TTGO...config.h
writedisplaytext("LoRa-APRS","","","Entering Setup!","","",2000);
setup_data();
}
#endif
switch(tracker_mode) {
case TRACKER:
writedisplaytext("LoRa-APRS","","Init:","Mode","TRACKER","",1000);
Serial.println("Init: Mode TRACKER");
Serial.println("LoRa-APRS / Init / Mode / TRACKER");
blinker(1);
break;
case WX_TRACKER:
writedisplaytext("LoRa-APRS","","Init:","Mode","WX&TRACKER","",1000);
Serial.println("LoRa-APRS / Init / Mode / WX & TRACKER");
blinker(2);
break;
case WX_MOVE:
writedisplaytext("LoRa-APRS","","Init:","Mode","WX_MOVE","",1000);
Serial.println("Init: Mode WX only - moving");
Serial.println("LoRa-APRS / Init / Mode / WX only - moving");
blinker(3);
break;
case WX_FIXED:
writedisplaytext("LoRa-APRS","","Init:","Mode","WX_FIXED","(no GPS used)",1000);
Serial.println("Init: Mode WX only - fixed Pos");
break;
case WX_TRACKER:
writedisplaytext("LoRa-APRS","","Init:","Mode","WX&TRACKER","",1000);
Serial.println("Init: Mode WX & TRACKER");
Serial.println("LoRa-APRS / Init / Mode / WX only - fixed Pos (no GPS used)");
blinker(4);
break;
default:
writedisplaytext("LoRa-APRS","","Init:","Mode","UNKNOWN","STOPPED",1000);
Serial.println("Init: Mode UNKNOWN STOPPED!!!!");
while (true) {}
Serial.println("LoRa-APRS / Init / Mode / UNKNOWN STOPPED!!!!");
while (true) {
blinker(1);
}
break;
}
if (!rf95.init()) {
writedisplaytext("LoRa-APRS","","Init:","RF95 FAILED!",":-(","",250);
Serial.println("Init: RF95 FAILED!");
Serial.println("LoRa-APRS / Init / RF95 FAILED!");
for(;;); // Don't proceed, loop forever
}
if (max_time_to_nextTX < nextTX) {max_time_to_nextTX=nextTX;}
digitalWrite(TXLED, HIGH);
// digitalWrite(TXLED, HIGH);
writedisplaytext("LoRa-APRS","","Init:","RF95 OK!","","",250);
digitalWrite(TXLED, LOW);
Serial.println("Init: RF95 OK!");
// digitalWrite(TXLED, LOW);
Serial.println("LoRa-APRS / Init / RF95 OK!");
if (tracker_mode != WX_FIXED) {
ss.begin(GPSBaud, SERIAL_8N1, TXPin, RXPin); //Startup HW serial for GPS
writedisplaytext("LoRa-APRS","","Init:","GPS Serial OK!","","",250);
Serial.println("LoRa-APRS / Init / GPS Serial OK!");
writedisplaytext(" "+Tcall,"","Init:","Waiting for GPS","","",250);
Serial.println("LoRa-APRS / Init / Waiting for GPS");
while (millis() < 5000 && gps.charsProcessed() < 10) {}
if (millis() > 5000 && gps.charsProcessed() < 10) {
writedisplaytext(" "+Tcall,"","Init:","ERROR!","No GPS data!","Please restart TTGO",0);
Serial.println("LoRa-APRS / Init / GPS ERROR - no GPS data - please RESTART TTGO");
while (true) {blinker(1);}
}
writedisplaytext(" "+Tcall,"","Init:","Data from GPS OK!","","",250);
Serial.println("LoRa-APRS / Init / Data from GPS OK!");
}
digitalWrite(TXLED, HIGH);
writedisplaytext("LoRa-APRS","","Init:","GPS Serial OK!","","",250);
digitalWrite(TXLED, LOW);
Serial.println("Init: GPS Serial OK!");
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_6);
writedisplaytext("LoRa-APRS","","Init:","ADC OK!","BAT: "+String(analogRead(35)*7.221/4096,1),"",250);
Serial.println("Init: ADC OK!");
#ifdef T_BEAM_V1_0
writedisplaytext("LoRa-APRS","","Init:","ADC OK!","BAT: "+String(axp.getBattVoltage()/1000,1),"",250);
Serial.print("LoRa-APRS / Init / ADC OK! / BAT: ");
Serial.println(String(axp.getBattVoltage()/1000,1));
#else
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_7,ADC_ATTEN_DB_6);
writedisplaytext("LoRa-APRS","","Init:","ADC OK!","BAT: "+String(analogRead(35)*7.221/4096,1),"",250);
Serial.print("LoRa-APRS / Init / ADC OK! / BAT: ");
Serial.println(String(analogRead(35)*7.221/4096,1));
#endif
rf95.setFrequency(433.775);
rf95.setModemConfig(BG_RF95::Bw125Cr45Sf4096); // hard coded because of double definition
// rf95.setModemConfig(ModemConfig); // das ist irgendwo doppelt definiert ???
rf95.setTxPower(5);
//rf95.printRegisters();
//rf95.setPromiscuousbg();
dht.setup(DHTPIN,dht.AUTO_DETECT); // initialize DHT22
delay(250);
temp = dht.getTemperature();
hum = dht.getHumidity();
writedisplaytext("LoRa-APRS","","Init:","DHT OK!","TEMP: "+String(temp,1),"HUM: "+String(hum,1),250);
Serial.print("Init: DHT OK! Temp=");
Serial.print("LoRa-APRS / Init / DHT OK! Temp=");
Serial.print(String(temp));
Serial.print(" Hum=");
Serial.println(String(hum));
digitalWrite(TXLED, HIGH);
writedisplaytext("LoRa-APRS","","Init:","All DONE OK!",":-D","",500);
digitalWrite(TXLED, LOW);
Serial.println("Init: ALL DONE OK! :-D");
writedisplaytext("LoRa-APRS","","Init:","FINISHED OK!"," =:-) ","",250);
Serial.println("LoRa-APRS / Init / FINISHED OK! / =:-)");
writedisplaytext("","","","","","",0);
}
// +---------------------------------------------------------------------+//
// + MAINLOOP -----------------------------------------------------------+//
// +---------------------------------------------------------------------+//
void loop() {
if (digitalRead(BUTTON)==LOW) {
++button_ctr;
if (button_ctr>=5){
switch(tracker_mode) {
case TRACKER:
tracker_mode = WX_TRACKER;
writedisplaytext("LoRa-APRS","","New Mode","WX-TRACKER","","",500);
Serial.println("LoRa-APRS / New Mode / WX-TRACKER");
blinker(2);
break;
case WX_TRACKER:
tracker_mode = WX_MOVE;
writedisplaytext("LoRa-APRS","","New Mode","WX-MOVING","","",500);
Serial.println("LoRa-APRS / New Mode / WX-MOVING");
blinker(3);
break;
case WX_MOVE:
tracker_mode = WX_FIXED;
writedisplaytext("LoRa-APRS","","New Mode","WX-FIXED","","",500);
Serial.println("LoRa-APRS / New Mode / WX-FIXED");
blinker(4);
break;
case WX_FIXED:
default:
tracker_mode = TRACKER;
writedisplaytext("LoRa-APRS","","New Mode","TRACKER","","",500);
Serial.println("LoRa-APRS / New Mode / TRACKER");
blinker(1);
break;
}
prefs.begin("nvs", false);
prefs.putChar("tracker_mode", (char)tracker_mode);
prefs.end();
button_ctr=0;
}
} else {
button_ctr = 0;
}
if (hum_temp) {
hum_temp=false;
temp = dht.getTemperature();
} else {
hum_temp=true;
hum = dht.getHumidity();
}
// MAINLOOP
while (ss.available() > 0) {
gps.encode(ss.read());
}
void loop()
{
if (digitalRead(BUTTON)==LOW) {
++button_ctr;
if (button_ctr>=3){
switch(tracker_mode) {
case TRACKER:
tracker_mode = WX_TRACKER;
writedisplaytext("LoRa-APRS","","New Mode","WX-TRACKER","","",500);
break;
case WX_TRACKER:
tracker_mode = WX_MOVE;
writedisplaytext("LoRa-APRS","","New Mode","WX-MOVING","","",500);
break;
case WX_MOVE:
tracker_mode = WX_FIXED;
writedisplaytext("LoRa-APRS","","New Mode","WX-FIXED","","",500);
break;
case WX_FIXED:
default:
tracker_mode = TRACKER;
writedisplaytext("LoRa-APRS","","New Mode","TRACKER","","",500);
break;
if (rf95.waitAvailableTimeout(100)) {
if (rf95.recvAPRS(buf, &len)) {
}
prefs.begin("nvs", false);
prefs.putChar("tracker_mode", (char)tracker_mode);
prefs.end();
button_ctr=0;
}
}
if (hum_temp){
hum_temp=false;
temp = dht.getTemperature();
} else {
hum_temp=true;
hum = dht.getHumidity();
}
#if DEBUG
writedisplaytext("LoRa-APRS","","DEBUG",millis(),String(millis()),"",0);
#endif
if (tracker_mode != WX_FIXED) {
LatShown = String(gps.location.lat(),5);
LongShown = String(gps.location.lng(),5);
while (ss.available() > 0) {
gps.encode(ss.read());
}
average_speed[point_avg_speed] = gps.speed.kmph(); // calculate smart beaconing
++point_avg_speed;
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 = (max_time_to_nextTX-min_time_to_nextTX)/(max_speed-min_speed)*(max_speed-average_speed_final)+min_time_to_nextTX;
if (rf95.waitAvailableTimeout(100)) {
if (rf95.recvAPRS(buf, &len)) {
if (nextTX < min_time_to_nextTX) {nextTX=min_time_to_nextTX;}
if (nextTX > max_time_to_nextTX) {nextTX=max_time_to_nextTX;}
} else {
LatShown = LatFixed;
LongShown = LongFixed;
}
}
if (tracker_mode != WX_FIXED) {
LatShown = String(gps.location.lat(),5);
LongShown = String(gps.location.lng(),5);
} else {
LatShown = LatFixed;
LongShown = LongFixed;
}
average_speed[point_avg_speed] = gps.speed.kmph(); // calculate smart beaconing
++point_avg_speed;
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;
batt_read();
nextTX = (max_time_to_nextTX-min_time_to_nextTX)/(max_speed-min_speed)*(max_speed-average_speed_final)+min_time_to_nextTX;
if (button_ctr==2) {
nextTX = 0;
}
if (nextTX < min_time_to_nextTX) {nextTX=min_time_to_nextTX;}
if (nextTX > max_time_to_nextTX) {nextTX=max_time_to_nextTX;}
new_course = gps.course.deg();
if (abs(new_course-old_course)>=30) {
nextTX = 0;
}
old_course = new_course;
if (hum_temp)
{
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000),"LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
} else {
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000),"LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"GPS: "+String(gps.satellites.value())+" TEMP: "+String(temp,1),0);
}
smartDelay(1000);
batt_read();
if ((millis()<max_time_to_nextTX)&&(lastTX == 0)) {
nextTX = 0;
}
if ( (lastTX+nextTX) <= millis() ) {
if (tracker_mode != WX_FIXED) {
if (gps.location.isValid()) {
digitalWrite(TXLED, HIGH);
if (hum_temp) {
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
if ( (lastTX+nextTX) <= millis() ) {
if (tracker_mode != WX_FIXED) {
// if (gps.location.isValid()) {
if (gps.location.age() < 2000) {
digitalWrite(TXLED, HIGH);
if (hum_temp) {
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
} else {
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"SAT: "+String(gps.satellites.value())+" TEMP: "+String(temp,1),0);
}
sendpacket();
Serial.print("((TX)) / LAT: ");
Serial.print(LatShown);
Serial.print(" / LON: ");
Serial.print(LongShown);
Serial.print(" / SPD: ");
Serial.print(String(gps.speed.kmph(),1));
Serial.print(" / CRS: ");
Serial.print(String(gps.course.deg(),1));
Serial.print(" / SAT: ");
Serial.print(String(gps.satellites.value()));
Serial.print(" / BAT: ");
Serial.print(String(BattVolts,1));
Serial.print(" / TEMP: ");
Serial.print(String(temp,1));
Serial.print(" / HUM: ");
Serial.println(String(hum,1));
digitalWrite(TXLED, LOW);
} else {
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"GPS: "+String(gps.satellites.value())+" TEMP: "+String(temp,1),0);
if (hum_temp) {
writedisplaytext(" "+Tcall,"(TX) at valid GPS","LAT: not valid","LON: not valid","SPD: --- CRS: ---","BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
} else {
writedisplaytext(" "+Tcall,"(TX) at valid GPS","LAT: not valid","LON: not valid","SPD: --- CRS: ---","SAT: "+String(gps.satellites.value())+" TEMP: "+String(temp,1),0);
}
Serial.print("(TX) at valid GPS / LAT: not valid / Lon: not valid / SPD: --- / CRS: ---");
Serial.print(" / SAT: ");
Serial.print(String(gps.satellites.value()));
Serial.print(" / BAT: ");
Serial.print(String(BattVolts,1));
Serial.print(" / TEMP: ");
Serial.print(String(temp,1));
Serial.print(" / HUM: ");
Serial.println(String(hum,1));
}
sendpacket();
Serial.println("State: Packet sent!");
digitalWrite(TXLED, LOW);
} else {
if ( (lastTX+nextTX*2) <= millis() ) {
} else { // ab hier Code für WX_FIXED
digitalWrite(TXLED, HIGH);
if (hum_temp) {
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"No GPS used","BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
} else {
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"GPS: "+String(gps.satellites.value())+" TEMP: "+String(temp,1),0);
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"No GPS used","SAT: --- TEMP: "+String(temp,1),0);
}
Serial.print("((TX)) / LAT: ");
Serial.print(LatShown);
Serial.print(" / LON: ");
Serial.print(LongShown);
Serial.print(" / No GPS used / SAT: --- / BAT: ");
Serial.print(String(BattVolts,1));
Serial.print(" / TEMP: ");
Serial.print(String(temp,1));
Serial.print(" / HUM: ");
Serial.println(String(hum,1));
sendpacket();
Serial.println("State: Packet sent!");
digitalWrite(TXLED, LOW);
}
}
} else {
digitalWrite(TXLED, HIGH);
if (hum_temp) {
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"No GPS used","BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
} else {
writedisplaytext(" ((TX))","","LAT: "+LatShown,"LON: "+LongShown,"No GPS used","GPS: "+String(gps.satellites.value())+" TEMP: "+String(temp,1),0);
}
sendpacket();
Serial.println("State: Packet sent!");
digitalWrite(TXLED, LOW);
}
}
smartDelay(1000);
if (tracker_mode != WX_FIXED) {
if (millis() > 200000 && gps.charsProcessed() < 10) {
writedisplaytext(" "+Tcall,"","Warning","No GPS Signal!","","",1000);
Serial.println("Warning: No GPS Signal!");
if (tracker_mode != WX_FIXED) {
if (gps.location.age() < 2000) {
if (hum_temp) {
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000)+"sec","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
} else {
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000)+"sec","LAT: "+LatShown,"LON: "+LongShown,"SPD: "+String(gps.speed.kmph(),1)+" CRS: "+String(gps.course.deg(),1),"SAT: "+String(gps.satellites.value())+" TEMP: "+String(temp,1),0);
}
} else {
if (hum_temp) {
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000)+"sec","LAT: not valid","LON: not valid","SPD: --- CRS: ---","BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
} else {
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000)+"sec","LAT: not valid","LON: not valid","SPD: --- CRS: ---","SAT: "+String(gps.satellites.value())+" TEMP: "+String(temp,1),0);
}
}
} else { // ab hier WX_FIXED code
if (hum_temp) {
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000)+"sec","LAT: "+LatShown,"LON: "+LongShown,"SPD: --- CRS: ---","BAT: "+String(BattVolts,1)+" HUM: "+String(hum,1),0);
} else {
writedisplaytext(" "+Tcall,"Time to TX: "+String(((lastTX+nextTX)-millis())/1000)+"sec","LAT: "+LatShown,"LON: "+LongShown,"SPD: --- CRS: ---","SAT: --- TEMP: "+String(temp,1),0);
}
}
}
smartDelay(900);
}
/////////////////////////////////////////////////////////////////////////////////////////
@ -812,12 +922,13 @@ void setup_data(void) {
char werte_call[37] = {' ','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9','0'};
String werte_SSID[16] = {"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"};
char werte_latlon[14] = {'0','1','2','3','4','5','6','7','8','9','N','S','E','W'};
String werte_TxSymbol_text[5] = {"WX Station","Auto","Fussgaenger","Fahrrad","Motorrad"};
String werte_TxSymbol_text[5] = {"WX Station"," Car"," Person"," Bicycle","Motorcycle"};
String werte_TxSymbol_symbol[5] = {"_",">","[","b","<"};
String werte_weiter_symbol[5] = {"yes","no"};
int8_t pos_in_string;
int8_t pos_ssid;
bool key_pressed = false;
int waiter;
int waiter, symbol_only;
int initial_waiter = 2000;
char aktueller_letter;
int8_t pos_letter;
@ -825,49 +936,12 @@ void setup_data(void) {
int8_t initial_ssid;
// set callsign - one for both reports
pos_in_string = 0;
while (pos_in_string < 6) {
key_pressed = false;
aktueller_letter = (char) Tcall.charAt(pos_in_string);// ist Buchstabe holen
for (pos_letter=0;pos_letter<37;pos_letter++) {
if (aktueller_letter == werte_call[pos_letter]) {
break;
}
}
while (true) {
Tcall.setCharAt(pos_in_string, aktueller_letter);
writedisplaytext(" SETUP", " Call"," "+Tcall," "+pfeile, "PRESS KEY to select", "", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
key_pressed = true;
}
}
initial_waiter = 0;
if (key_pressed==true) {
key_pressed = false;
break;
}
// nächster Buchstabe
++pos_letter;
if (pos_letter>=37) {pos_letter=0;}
aktueller_letter=werte_call[pos_letter];
}
initial_waiter = 2000;
pfeile = " "+pfeile;
++pos_in_string;
}
// set normal SSID
initial_ssid = (int8_t) (Tcall.substring(7,9)).toInt();
pos_ssid = initial_ssid;
pfeile = " ^";
key_pressed = false;
initial_waiter = 2000;
// set Tx Symbol - gleich zu Beginn, falls man nur das Symbol ändern möchte
pos_ssid = 0;
while (true) {
writedisplaytext(" SETUP", " normal SSID"," "+Tcall, pfeile, "PRESS KEY to select", "", 0);
TxSymbol = werte_TxSymbol_symbol[pos_ssid];
blinker(pos_ssid+1);
writedisplaytext(" SETUP", " Symbol",werte_TxSymbol_text[pos_ssid], "", "PRESS KEY to select", "", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
@ -877,21 +951,23 @@ void setup_data(void) {
initial_waiter = 0;
if (key_pressed==true) {
key_pressed = false;
writedisplaytext(" SETUP", " Symbol",werte_TxSymbol_text[pos_ssid], "", "programmed", "", 2000);
break;
}
++pos_ssid;
if (pos_ssid>=16) {pos_ssid=0;}
Tcall = Tcall.substring(0,6)+"-"+werte_SSID[pos_ssid];
if (pos_ssid>=5) {pos_ssid=0;}
}
// set WX SSID
initial_ssid = (int8_t) (wxTcall.substring(7,9)).toInt();
// smartDelay(500);
pos_ssid = initial_ssid;
// fragen, ob es weiter gehen soll
pos_ssid = 0;
key_pressed = false;
initial_waiter = 2000;
while (true) {
writedisplaytext(" SETUP", " WX SSID"," "+wxTcall, pfeile, "PRESS KEY to select", "", 0);
// TxSymbol = werte_TxSymbol_symbol[pos_ssid];
blinker(2-pos_ssid);
writedisplaytext(" SETUP", " stop it?"," "+werte_weiter_symbol[pos_ssid], "", "PRESS KEY to select", "", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
@ -901,29 +977,60 @@ void setup_data(void) {
initial_waiter = 0;
if (key_pressed==true) {
key_pressed = false;
writedisplaytext(" SETUP", " stop it?"," "+werte_weiter_symbol[pos_ssid], "", "selected", "", 2000);
break;
}
++pos_ssid;
if (pos_ssid>=16) {pos_ssid=0;}
wxTcall = wxTcall.substring(0,6)+"-"+werte_SSID[pos_ssid];
if (pos_ssid>=2) {pos_ssid=0;}
}
// set LONGITUDE
pfeile = "^";
pos_in_string = 0;
key_pressed = false;
initial_waiter = 2000;
while (pos_in_string < 9) {
if (pos_ssid != 0) {
// set callsign - one for both reports
pos_in_string = 0;
key_pressed = false;
aktueller_letter = (char) LongFixed.charAt(pos_in_string);// ist Buchstabe holen
for (pos_letter=0;pos_letter<14;pos_letter++) {
if (aktueller_letter == werte_latlon[pos_letter]) {
break;
initial_waiter = 2000;
while (pos_in_string < 6) {
key_pressed = false;
aktueller_letter = (char) Tcall.charAt(pos_in_string);// ist Buchstabe holen
for (pos_letter=0;pos_letter<37;pos_letter++) {
if (aktueller_letter == werte_call[pos_letter]) {
break;
}
}
while (true) {
Tcall.setCharAt(pos_in_string, aktueller_letter);
writedisplaytext(" SETUP", " Call"," "+Tcall," "+pfeile, "PRESS KEY to select", "", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
key_pressed = true;
}
}
initial_waiter = 0;
if (key_pressed==true) {
key_pressed = false;
break;
}
// nächster Buchstabe
++pos_letter;
if (pos_letter>=37) {pos_letter=0;}
aktueller_letter=werte_call[pos_letter];
}
initial_waiter = 2000;
pfeile = " "+pfeile;
++pos_in_string;
}
// set normal SSID
initial_ssid = (int8_t) (Tcall.substring(7,9)).toInt();
pos_ssid = initial_ssid;
pfeile = " ^";
key_pressed = false;
initial_waiter = 2000;
while (true) {
LongFixed.setCharAt(pos_in_string, aktueller_letter);
writedisplaytext(" SETUP", " Longitude"," "+LongFixed," "+pfeile, "for fixed POS", "PRESS KEY to select", 0);
writedisplaytext(" SETUP", " normal SSID"," "+Tcall, pfeile, "PRESS KEY to select", "", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
@ -935,36 +1042,21 @@ void setup_data(void) {
key_pressed = false;
break;
}
// nächster Buchstabe
++pos_letter;
if (pos_letter>=14) {pos_letter=0;}
aktueller_letter=werte_latlon[pos_letter];
}
initial_waiter = 2000;
pfeile = " "+pfeile;
++pos_in_string;
if (pos_in_string == 5) {
++pos_in_string;
pfeile = " "+pfeile;
++pos_ssid;
if (pos_ssid>=16) {pos_ssid=0;}
Tcall = Tcall.substring(0,6)+"-"+werte_SSID[pos_ssid];
}
}
// set LATITUDE
pfeile = "^";
pos_in_string = 0;
key_pressed = false;
initial_waiter = 2000;
while (pos_in_string < 8) {
writedisplaytext(" SETUP", " Call"," "+Tcall," ", "programmed", "", 2000);
// set WX SSID
initial_ssid = (int8_t) (wxTcall.substring(7,9)).toInt();
pos_ssid = initial_ssid;
key_pressed = false;
aktueller_letter = (char) LatFixed.charAt(pos_in_string);// ist Buchstabe holen
for (pos_letter=0;pos_letter<14;pos_letter++) {
if (aktueller_letter == werte_latlon[pos_letter]) {
break;
}
}
initial_waiter = 2000;
while (true) {
LatFixed.setCharAt(pos_in_string, aktueller_letter);
writedisplaytext(" SETUP", " Latitude"," "+LatFixed," "+pfeile, "for fixed POS", "PRESS KEY to select", 0);
writedisplaytext(" SETUP", " WX SSID"," "+wxTcall, pfeile, "PRESS KEY to select", "", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
@ -976,42 +1068,99 @@ void setup_data(void) {
key_pressed = false;
break;
}
// nächster Buchstabe
++pos_letter;
if (pos_letter>=14) {pos_letter=0;}
aktueller_letter=werte_latlon[pos_letter];
++pos_ssid;
if (pos_ssid>=16) {pos_ssid=0;}
wxTcall = wxTcall.substring(0,6)+"-"+werte_SSID[pos_ssid];
}
writedisplaytext(" SETUP", " WX-Call"," "+wxTcall," ", "programmed", "", 2000);
// set LONGITUDE
pfeile = "^";
pos_in_string = 0;
key_pressed = false;
initial_waiter = 2000;
pfeile = " "+pfeile;
++pos_in_string;
if (pos_in_string == 4) {
++pos_in_string;
while (pos_in_string < 9) {
key_pressed = false;
aktueller_letter = (char) LongFixed.charAt(pos_in_string);// ist Buchstabe holen
for (pos_letter=0;pos_letter<14;pos_letter++) {
if (aktueller_letter == werte_latlon[pos_letter]) {
break;
}
}
while (true) {
LongFixed.setCharAt(pos_in_string, aktueller_letter);
writedisplaytext(" SETUP", " Longitude"," "+LongFixed," "+pfeile, "for fixed POS", "PRESS KEY to select", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
key_pressed = true;
}
}
initial_waiter = 0;
if (key_pressed==true) {
key_pressed = false;
break;
}
// nächster Buchstabe
++pos_letter;
if (pos_letter>=14) {pos_letter=0;}
aktueller_letter=werte_latlon[pos_letter];
}
initial_waiter = 2000;
pfeile = " "+pfeile;
}
}
// set Tx Symbol
pos_ssid = 0;
key_pressed = false;
initial_waiter = 2000;
while (true) {
TxSymbol = werte_TxSymbol_symbol[pos_ssid];
writedisplaytext(" SETUP", " Symbol"," "+werte_TxSymbol_text[pos_ssid], "", "PRESS KEY to select", "", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
key_pressed = true;
++pos_in_string;
if (pos_in_string == 5) {
++pos_in_string;
pfeile = " "+pfeile;
}
}
initial_waiter = 0;
if (key_pressed==true) {
writedisplaytext(" SETUP", " Longitude"," "+LongFixed,"", "for fixed POS", "programmed", 2000);
// set LATITUDE
pfeile = "^";
pos_in_string = 0;
key_pressed = false;
initial_waiter = 2000;
while (pos_in_string < 8) {
key_pressed = false;
break;
}
++pos_ssid;
if (pos_ssid>=5) {pos_ssid=0;}
aktueller_letter = (char) LatFixed.charAt(pos_in_string);// ist Buchstabe holen
for (pos_letter=0;pos_letter<14;pos_letter++) {
if (aktueller_letter == werte_latlon[pos_letter]) {
break;
}
}
while (true) {
LatFixed.setCharAt(pos_in_string, aktueller_letter);
writedisplaytext(" SETUP", " Latitude"," "+LatFixed," "+pfeile, "for fixed POS", "PRESS KEY to select", 0);
waiter = millis();
while (millis()<(waiter+1000+initial_waiter)) {
if (digitalRead(BUTTON)==LOW) {
key_pressed = true;
}
}
initial_waiter = 0;
if (key_pressed==true) {
key_pressed = false;
break;
}
// nächster Buchstabe
++pos_letter;
if (pos_letter>=14) {pos_letter=0;}
aktueller_letter=werte_latlon[pos_letter];
}
initial_waiter = 2000;
pfeile = " "+pfeile;
++pos_in_string;
if (pos_in_string == 4) {
++pos_in_string;
pfeile = " "+pfeile;
}
}
writedisplaytext(" SETUP", " Latitude"," "+LatFixed,"", "for fixed POS", "programmed", 2000);
}
// write all values to NVRAM
prefs.begin("nvs", false);
prefs.putString("Tcall", Tcall);
@ -1020,5 +1169,17 @@ void setup_data(void) {
prefs.putString("LongFixed", LongFixed);
prefs.putString("TxSymbol", TxSymbol);
prefs.end();
writedisplaytext(" SETUP", "DONE","", "stored in NVS", "", "", 2500);
writedisplaytext(" SETUP", "ALL DONE","", "stored in NVS", "", "", 2000);
}
void blinker(int counter) {
for (int i = 0; i < (counter-1); i++) {
digitalWrite(TXLED, HIGH); // turn blue LED ON
smartDelay(150);
digitalWrite(TXLED, LOW); // turn blue LED OFF
smartDelay(100);
}
digitalWrite(TXLED, HIGH); // turn blue LED ON
smartDelay(150);
digitalWrite(TXLED, LOW); // turn blue LED OFF
}

@ -20,16 +20,18 @@
// added "SPACE" to allowed letters for callsign for shorter callsigns - has to be added at the end
// added smart beaconing
//
// version V1.0b
// version V1.2
// first released version
// SET HW version
// #define T_BEAM_V1_0 // use this for older Boards AKA Rev1 (second board release)
#define T_BEAM_V0_7 // use this for older Boards AKA Rev0 (first board release)
#define T_BEAM_V1_0 // use this for older Boards AKA Rev1 (second board release)
// #define T_BEAM_V0_7 // use this for older Boards AKA Rev0 (first board release)
// USER DATA - USE THESE LINES TO MODIFY YOUR PREFERENCES
// IF NOT CHANGED you have to go through the configuration routine at first boot up of the TTGO T-Beam
// #define DONT_USE_FLASH_MEMORY // uncomment if you don't want to use Flashmemory - instead data below must be corrected
#define CALLSIGN "OE1XYZ-0" // enter your callsign here - less then 6 letter callsigns please add "spaces" so total length is 6 (without SSID)
#define WX_CALLSIGN "OE1XYZ-0" // use same callsign but you can use different SSID
#define LONGITUDE_PRESET "01539.85E" // please in APRS notation DDMM.mmN or DDMM.mmS
@ -42,5 +44,5 @@
// "<" => MOTORCYCLE
// TRANSMIT INTERVAL
unsigned long max_time_to_nextTX = 60000L; // set here MAXIMUM time in ms(!) for smart beaconing - minimum time is always 1 min = 60 secs = 60000L !!!
unsigned long max_time_to_nextTX = 300000L; // set here MAXIMUM time in ms(!) for smart beaconing - minimum time is always 1 min = 60 secs = 60000L !!!
// when entering 60000L intervall is fixed to 1 min

Loading…
Cancel
Save