From d056ec8b762686d1738791b45891dd34f0d6a217 Mon Sep 17 00:00:00 2001 From: "Hans P. Reiser" Date: Tue, 23 Apr 2019 13:08:02 +0200 Subject: [PATCH] merging pull request #2 by DL2MF to devel branch --- README.md | 20 ++- RX_FSK/RX_FSK.ino | 264 +++++++++++++++++++++++---------- RX_FSK/data/config.txt | 45 +++++- RX_FSK/data/index.html | 27 +++- RX_FSK/data/networks.txt | 10 +- RX_FSK/data/qrg.txt | 23 ++- libraries/SondeLib/DFM.cpp | 8 +- libraries/SondeLib/RS41.cpp | 2 +- libraries/SondeLib/Scanner.cpp | 15 +- libraries/SondeLib/Sonde.cpp | 59 ++++++-- libraries/SondeLib/Sonde.h | 43 ++++-- libraries/SondeLib/aprs.cpp | 6 +- libraries/SondeLib/aprs.h | 2 +- 13 files changed, 373 insertions(+), 151 deletions(-) diff --git a/README.md b/README.md index 432f944..2666c61 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,20 @@ RDZ_TTGO_SONDE This a simple, experimental, not (well) tested, and incomplete decoder for radiosonde RS41 and DFM06/09 on a TTGO LoRa ESP32 with OLED display board. +There have been made some additions for TTGO LoRa ESP32 with only RST button. +Please check also your OLED port settings, both versions use different ports. +You can setup the depending ports in config.txt, OLED Setup is depending on hardware of LoRa board +- TTGO v1: SDA=4 SCL=15, RST=16 +- TTGO v2: SDA=21 SCL=22, RST=16 + ## Button commands You can use the button on the board (not the reset button, the second one) to issue some commands. The software distinguishes between several inputs: -SHORT Short button press (<1.5 seconds) -DOUBLE Short button press, followed by another button press within 0.5 seconds -MID Medium-length button press (2-4 seconds) -LONG Long button press (>5 seconds) +- SHORT Short button press (<1.5 seconds) +- DOUBLE Short button press, followed by another button press within 0.5 seconds +- MID Medium-length button press (2-4 seconds) +- LONG Long button press (>5 seconds) ## Wireless configuration @@ -39,10 +45,14 @@ for the last 18 frames, if reception was successfull (|) or failed (.) A DOUBLE press will switch to scanning mode. A SHORT press will switch to the next channel in channels.txt -# Spectrum mode +## Spectrum mode A medium press will active scan the whole band (400..406 MHz) and display a spectrum diagram (each line == 50 kHz) +For TTGO boards without configurable button there are some new parameter in config.txt: +- spectrum=10 // 0=off / 1-99 number of seconds to show spectrum after restart +- timer=1 // 0=off / 1= show spectrum countdown timer in spectrum display +- marker=1 // 0=off / 1= show channel edge freq in spectrum display ## Setup diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 9d5e473..557b8f6 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -12,11 +13,6 @@ #define LORA_LED 9 -// I2C OLED Display works with SSD1306 driver -//#define OLED_SDA 4 -//#define OLED_SCL 15 -//#define OLED_RST 16 - // UNCOMMENT one of the constructor lines below U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8=NULL; // initialize later after reading config file //U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ OLED_SCL, /* data=*/ OLED_SDA, /* reset=*/ OLED_RST); // Unbuffered, basic graphics, software I2C @@ -29,20 +25,14 @@ AsyncWebServer server(80); #define LOCALUDPPORT 9002 -// moved to sonde.config -//const char * udpAddress = "192.168.42.20"; -//const int udpPort = 9002; - boolean connected = false; WiFiUDP udp; - // Set LED GPIO -const int ledPin = 2; +int ledPin = 1; // Stores LED state String ledState; - // Replaces placeholder with LED state value String processor(const String& var){ Serial.println(var); @@ -91,6 +81,7 @@ void setupChannelList() { } int i=0; sonde.clearSonde(); + Serial.println("Reading channel config:"); while(file.available()) { String line = file.readStringUntil('\n'); if(!file.available()) break; @@ -105,8 +96,9 @@ void setupChannelList() { else if (space[1]=='6') { type=STYPE_DFM06; } else continue; int active = space[3]=='+'?1:0; - Serial.printf("Adding %f with type %d (active: %d)\n",freq,type,active); - sonde.addSonde(freq, type, active); + char *launchsite = strchr(line.c_str(), ' '); + Serial.printf("Add %f - type %d (on/off: %d)- Site: \n",freq,type,active,launchsite); + sonde.addSonde(freq, type, active, launchsite); i++; } } @@ -114,7 +106,7 @@ void setupChannelList() { const char *createQRGForm() { char *ptr = message; strcpy(ptr,"
"); - for(int i=0; i<10; i++) { + for(int i=0; i=sonde.nSonde?2:sonde.sondeList[i].type); sprintf(ptr+strlen(ptr), "" "" @@ -161,6 +153,9 @@ const char *handleQRGPost(AsyncWebServerRequest *request) { f.printf("%3.3f %c %c\n", atof(fstr), typech, active?'+':'-'); } f.close(); + Serial.println("Channel setup finished"); + Serial.println(); + setupChannelList(); } @@ -252,9 +247,9 @@ void addSondeStatus(char *ptr, int i) sprintf(ptr+strlen(ptr),"\n", s->freq, sondeTypeStr[s->type], s->validID?s->id:"", - s->lat, s->lon, s->hei); - sprintf(ptr+strlen(ptr), "", s->lat, s->lon); strcat(ptr, "
IDActiveFreqMode
%d
%3.3f MHz, Type: %s
ID: %s
QTH: %.6f,%.6f h=%.0fm
Geo-Ref -", s->lat, s->lon); - sprintf(ptr+strlen(ptr), "Google map - ", s->lat, s->lon); + s->lat, s->lon, s->alt); + sprintf(ptr+strlen(ptr), "
GEO-App - ", s->lat, s->lon); + sprintf(ptr+strlen(ptr), "WX.DL2MF.de - ", s->id); sprintf(ptr+strlen(ptr), "OSM

\n"); } @@ -291,8 +286,12 @@ struct st_configitems { int type; // 0: numeric; i>0 string of length i; -1: separator; -2: type selector void *data; }; -#define N_CONFIG 16 +#define N_CONFIG 20 struct st_configitems config_list[N_CONFIG] = { + {"ShowSpectrum (s)", 0, &sonde.config.spectrum}, + {"Startfreq (MHz)", 0, &sonde.config.startfreq}, + {"Bandwidth (kHz)", 0, &sonde.config.channelbw}, + {"---", -1, NULL}, {"Call", 8, sonde.config.call}, {"Passcode", 8, sonde.config.passcode}, {"---", -1, NULL}, @@ -415,11 +414,11 @@ void SetupAsyncServer() { const char *fetchWifiPw(const char *id) { for(int i=0; ibegin(); + delay(100); + u8x8->clear(); + + u8x8->setFont(u8x8_font_7x14_1x2_r); + u8x8->drawString(1, 1, "RDZ_TTGO_SONDE"); + u8x8->drawString(2, 3, " V0.1e"); + u8x8->drawString(1, 5, "Mods by DL2MF"); + delay(3000); + + sonde.clearDisplay(); + + setupWifiList(); + button1.pin = sonde.config.button_pin; + + // == show initial values from config.txt ========================= // + if (sonde.config.debug == 1) { + u8x8->setFont(u8x8_font_chroma48medium8_r); + u8x8->drawString(0, 0, "Config:"); + + delay(500); + itoa(sonde.config.oled_sda, buf, 10); + u8x8->drawString(0, 1, " SDA:"); + u8x8->drawString(6, 1, buf); + + delay(500); + itoa(sonde.config.oled_scl, buf, 10); + u8x8->drawString(0, 2, " SCL:"); + u8x8->drawString(6, 2, buf); + + delay(500); + itoa(sonde.config.oled_rst, buf, 10); + u8x8->drawString(0, 3, " RST:"); + u8x8->drawString(6, 3, buf); + + delay(1000); + itoa(sonde.config.led_pin, buf, 10); + u8x8->drawString(0, 4, " LED:"); + u8x8->drawString(6, 4, buf); + + delay(500); + itoa(sonde.config.spectrum, buf, 10); + u8x8->drawString(0, 5, " SPEC:"); + u8x8->drawString(6, 5, buf); + + delay(500); + itoa(sonde.config.maxsonde, buf, 10); + u8x8->drawString(0, 6, " MAX:"); + u8x8->drawString(6, 6, buf); + + delay(5000); + sonde.clearDisplay(); + } + // == show initial values from config.txt ========================= // + #if 0 + // == check the radio chip by setting default frequency =========== // if(rs41.setFrequency(402700000)==0) { Serial.println(F("Setting freq: SUCCESS ")); } else { @@ -501,6 +553,7 @@ void setup() float f = sx1278.getFrequency(); Serial.print("Frequency set to "); Serial.println(f); + // == check the radio chip by setting default frequency =========== // #endif //sx1278.setLNAGain(-48); @@ -511,11 +564,10 @@ void setup() Serial.println(gain); // Print a success message - Serial.println(F("sx1278 configured finished")); - Serial.println(); - + Serial.println(F("SX1278 configuration finished")); Serial.println("Setup finished"); + Serial.println(); // int returnValue = pthread_create(&wifithread, NULL, wifiloop, (void *)0); // if (returnValue) { @@ -526,20 +578,26 @@ void setup() // Handle button press attachInterrupt(button1.pin, buttonISR, CHANGE); + // == setup default channel list if qrg.txt read fails =========== // setupChannelList(); #if 0 sonde.clearSonde(); - sonde.addSonde(402.300, STYPE_RS41); sonde.addSonde(402.700, STYPE_RS41); + sonde.addSonde(405.700, STYPE_RS41); + sonde.addSonde(405.900, STYPE_RS41); sonde.addSonde(403.450, STYPE_DFM09); + Serial.println("No channel config file, using defaults!"); + Serial.println(); #endif /// not here, done by sonde.setup(): rs41.setup(); + // == setup default channel list if qrg.txt read fails =========== // + sonde.setup(); } enum MainState { ST_DECODER, ST_SCANNER, ST_SPECTRUM, ST_WIFISCAN }; -static MainState mainState = ST_DECODER; +static MainState mainState = ST_WIFISCAN; void enterMode(int mode) { mainState = (MainState)mode; @@ -571,7 +629,7 @@ void loopDecoder() { Serial.println("Sending position via UDP"); SondeInfo *s = sonde.si(); char raw[201]; - const char *str = aprs_senddata(s->lat, s->lon, s->hei, s->hs, s->dir, s->vs, sondeTypeStr[s->type], s->id, "TE0ST", + const char *str = aprs_senddata(s->lat, s->lon, s->alt, s->hs, s->dir, s->vs, sondeTypeStr[s->type], s->id, "TE0ST", sonde.config.udpfeed.symbol); int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN); Serial.print("Sending: "); Serial.println(raw); @@ -601,7 +659,7 @@ void loopScanner() { } // receiveFrame returns 0 on success, 1 on timeout int res = sonde.receiveFrame(); // Maybe instead of receiveFrame, just detect if right type is present? TODO - Serial.print("Scanner: receiveFrame returned"); + Serial.print("Scanner: receiveFrame returned: "); Serial.println(res); if(res==0) { enterMode(ST_DECODER); @@ -666,44 +724,55 @@ void WiFiEvent(WiFiEvent_t event){ } } - static char* _scan[2]={"/","\\"}; void loopWifiScan() { u8x8->setFont(u8x8_font_chroma48medium8_r); - u8x8->drawString(0,0,"WiFi Scan..."); + if (sonde.config.wifi != 0) { + u8x8->drawString(0,0,"WiFi Scan..."); + } + else if (sonde.config.wifiap != 0) { + u8x8->drawString(0,0,"WiFi AP-Mode:"); + } + int line=0; int cnt=0; + int marker=0; + char buf[5]; WiFi.disconnect(true); WiFi.mode(WIFI_STA); const char *id, *pw; char idstr[64]="test"; - int n = WiFi.scanNetworks(); - for (int i = 0; i < n; i++) { - Serial.print("Network name: "); - Serial.println(WiFi.SSID(i)); - u8x8->drawString(0,1+line,WiFi.SSID(i).c_str()); - line = (line+1)%5; - Serial.print("Signal strength: "); - Serial.println(WiFi.RSSI(i)); - Serial.print("MAC address: "); - Serial.println(WiFi.BSSIDstr(i)); - Serial.print("Encryption type: "); - String encryptionTypeDescription = translateEncryptionType(WiFi.encryptionType(i)); - Serial.println(encryptionTypeDescription); - Serial.println("-----------------------"); - id=WiFi.SSID(i).c_str(); - pw=fetchWifiPw(id); - if(pw) { strncpy(idstr, id, 63); } - } - if(!pw) { pw="test"; } - Serial.print("Connecting to: "); Serial.println(idstr); - u8x8->drawString(0,6, "Conn:"); - u8x8->drawString(6,6, idstr); - //register event handler - WiFi.onEvent(WiFiEvent); + + if (sonde.config.wifi != 0) { + int n = WiFi.scanNetworks(); + for (int i = 0; i < n; i++) { + Serial.print("Network name: "); + Serial.println(WiFi.SSID(i)); + u8x8->drawString(0,1+line,WiFi.SSID(i).c_str()); + line = (line+1)%5; + Serial.print("Signal strength: "); + Serial.println(WiFi.RSSI(i)); + Serial.print("MAC address: "); + Serial.println(WiFi.BSSIDstr(i)); + Serial.print("Encryption type: "); + String encryptionTypeDescription = translateEncryptionType(WiFi.encryptionType(i)); + Serial.println(encryptionTypeDescription); + Serial.println("-----------------------"); + id=WiFi.SSID(i).c_str(); + pw=fetchWifiPw(id); + if(pw) { strncpy(idstr, id, 63); } + } + if(!pw) { pw="test"; } + Serial.print("Connecting to: "); Serial.println(idstr); + u8x8->drawString(0,6, "Conn:"); + u8x8->drawString(6,6, idstr); + //register event handler + WiFi.onEvent(WiFiEvent); + + WiFi.begin(idstr, pw); + } - WiFi.begin(idstr, pw); while(WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); @@ -718,20 +787,58 @@ void loopWifiScan() { #endif if(cnt==15) { WiFi.disconnect(true); - delay(1000); - WiFi.softAP(networks[0].id.c_str(),networks[0].pw.c_str()); - IPAddress myIP = WiFi.softAPIP(); - Serial.print("AP IP address: "); - Serial.println(myIP); - u8x8->drawString(0,6, "AP: "); - u8x8->drawString(6,6, networks[0].id.c_str()); - sonde.setIP(myIP.toString().c_str(), true); - sonde.updateDisplayIP(); - SetupAsyncServer(); - delay(3000); - enterMode(ST_DECODER); + + if (sonde.config.wifiap != 0) { // enable WiFi AP mode in config.txt: wifi=1 + delay(1000); + WiFi.softAP(networks[0].id.c_str(),networks[0].pw.c_str()); + IPAddress myIP = WiFi.softAPIP(); + Serial.print("AP IP address: "); + Serial.println(myIP); + u8x8->drawString(0,6, "AP: "); + u8x8->drawString(6,6, networks[0].id.c_str()); + sonde.setIP(myIP.toString().c_str(), true); + sonde.updateDisplayIP(); + SetupAsyncServer(); + delay(3000); + } + + if (sonde.config.spectrum != 0) { // enable Spectrum in config.txt: spectrum=number_of_seconds + sonde.clearDisplay(); + u8x8->setFont(u8x8_font_chroma48medium8_r); + u8x8->drawString(0, 0, "Spectrum Scan..."); + delay(500); + + enterMode(ST_SPECTRUM); + + for (int i = 0; i < sonde.config.spectrum; i++) { + scanner.scan(); + scanner.plotResult(); + + if (sonde.config.marker != 0) { + itoa((sonde.config.startfreq), buf, 10); + u8x8->drawString(0, 1, buf); + u8x8->drawString(7, 1, "MHz"); + itoa((sonde.config.startfreq + 6), buf, 10); + u8x8->drawString(13, 1, buf); + } + + if (sonde.config.timer != 0) { + itoa((sonde.config.spectrum - i), buf, 10); + if (sonde.config.marker != 0) { + marker = 1; + } + u8x8->drawString(0, 1+marker, buf); + u8x8->drawString(2, 1+marker, "Sec."); + } + } + + delay(1000); + } + + enterMode(ST_SCANNER); return; } + } Serial.println(""); @@ -742,9 +849,10 @@ void loopWifiScan() { sonde.updateDisplayIP(); SetupAsyncServer(); delay(2000); - enterMode(ST_DECODER); -} + // enterMode(ST_DECODER); ### 2019-04-20 - changed DL2MF + enterMode(ST_SCANNER); +} void loop() { Serial.println("Running main loop"); diff --git a/RX_FSK/data/config.txt b/RX_FSK/data/config.txt index 6d252e1..2b70b11 100644 --- a/RX_FSK/data/config.txt +++ b/RX_FSK/data/config.txt @@ -1,14 +1,39 @@ -# Input button +#-------------------------------# +# Hardware depending settings +#-------------------------------# button_pin=0 -# oled: SDA, SCL, RST (4,15,16 für TTGO v1) -oled_sda=4 -oled_scl=15 +# LED port +led_pin=25 +# OLED Setup is depending on hardware of LoRa board +# TTGO v1: SDA=4 SCL=15, RST=16 +# TTGO v2: SDA=21 SCL=22, RST=16 +oled_sda=21 +oled_scl=22 oled_rst=16 - -noisefloor=-130 -call=NOCALL +#-------------------------------# +# General config settings +#-------------------------------# +maxsonde=20 +debug=0 +wifi=0 +wifiap=1 +#-------------------------------# +# Spectrum display settings +#-------------------------------# +startfreq=400 +channelbw=10 +spectrum=10 +timer=1 +noisefloor=-110 +marker=1 +#-------------------------------# +# APRS settings +#-------------------------------# +call=N0CALL passcode=12345 +#-------------------------------# # axudp for sending to aprsmap +#-------------------------------# # local use only, do not feed to public services # data not sanities / quality checked, outliers not filtered out axudp.active=1 @@ -17,7 +42,9 @@ axudp.port=9002 axudp.symbol=/O axudp.highrate=1 axudp.idformat=0 +#-------------------------------# # maybe some time in the future +#-------------------------------# # currently simply not implemented, no need to put anything here anyway tcp.active=0 tcp.host=radiosondy.info @@ -25,4 +52,6 @@ tcp.port=14590 tcp.symbol=/O tcp.highrate=20 tcp.idformat=0 - +#-------------------------------# +# EOF +#-------------------------------# diff --git a/RX_FSK/data/index.html b/RX_FSK/data/index.html index 35a3775..2a79aa0 100644 --- a/RX_FSK/data/index.html +++ b/RX_FSK/data/index.html @@ -1,13 +1,13 @@ - ESP32 Web Server + RDZSonde Server -

ESP32 Web Server

+

RDZSonde Server