diff --git a/README.md b/README.md index 274afb7..0b60bc9 100644 --- a/README.md +++ b/README.md @@ -1 +1,45 @@ -# rdz_ttgo_sonde \ No newline at end of file +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. + +## 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) + +## Wireless configuration + +On startup, as well as after a LONG button press, the WiFI configuration will +be started. The board will scan available WiFi networks, if the scan results +contains a WiFi network configured with ID and Password in networks.txt, it +will connect to that network in station mode. If no known network is found, or +the connection does not suceed after 5 seconds, it instead starts in access point +mode. In both cases, the ESP32's IP address will be shown in tiny letters in the +bottom line. Then the board will switch to scanning mode. + +## Scanning mode + +In the scanning mode, the board will iterate over all channels configured in +channels.txt, trying to decode a radio sonde on each channel for about 1 second +for RS41, a bit less for DMF06/09. If a valid signal is found, the board switches +to receiving mode on that channel. a SHORT buttong press will also switch to +receiving mode. + +## Receiving mode + +In receiving mode, a single frequency will be decoded, and sonde info (ID, GPS +coordinates, RSSI) will be displayed. The bar above the IP address indicates, +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 + +A medium press will active scan the whole band (400..406 MHz) and display a +spectrum diagram (each line == 50 kHz) diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 46b0674..ec03589 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -101,6 +101,37 @@ void setupWifiList() { for(int j=0; j=SCAN_MAXTRIES) { + if(++tries>=SCAN_MAXTRIES && !hasKeyPress()) { sonde.nextConfig(); tries = 0; } @@ -334,7 +368,7 @@ void loopWifiScan() { pw=fetchWifiPw(id); if(pw) break; } - if(!pw) { id="test"; pw="test"; } + if(1||!pw) { id="test"; pw="test"; } Serial.print("Connecting to: "); Serial.println(id); u8x8.drawString(0,6, "Conn:"); u8x8.drawString(6,6, id); @@ -344,6 +378,24 @@ void loopWifiScan() { Serial.print("."); u8x8.drawString(15,7,_scan[cnt&1]); cnt++; + if(cnt==4) { + WiFi.disconnect(); // retry, for my buggy FritzBox + WiFi.begin(id, pw); + } + if(cnt==10) { + WiFi.disconnect(); + delay(1000); + WiFi.softAP("sonde","sondesonde"); + IPAddress myIP = WiFi.softAPIP(); + Serial.print("AP IP address: "); + Serial.println(myIP); + sonde.setIP(myIP.toString().c_str()); + sonde.updateDisplayIP(); + SetupAsyncServer(); + delay(5000); + enterMode(ST_DECODER); + return; + } } Serial.println(""); @@ -354,7 +406,7 @@ void loopWifiScan() { sonde.updateDisplayIP(); SetupAsyncServer(); delay(5000); - mainState=ST_SPECTRUM; + enterMode(ST_DECODER); } diff --git a/RX_FSK/data/qrg.txt b/RX_FSK/data/qrg.txt new file mode 100644 index 0000000..6bb6ae2 --- /dev/null +++ b/RX_FSK/data/qrg.txt @@ -0,0 +1,8 @@ +# Frequency in Mhz (format nnn.nnn) +# Type (4=RS41, 6=DFM normal, DFM-06, 9=DFM inverted, DFM-09) +# +402.700 4 +402.300 4 +403.450 9 +405.100 4 +# end diff --git a/libraries/SondeLib/DFM.cpp b/libraries/SondeLib/DFM.cpp index 69113a7..1d8828f 100644 --- a/libraries/SondeLib/DFM.cpp +++ b/libraries/SondeLib/DFM.cpp @@ -2,6 +2,7 @@ /* DFM decoder functions */ #include "DFM.h" #include "SX1278FSK.h" +#include "Sonde.h" #define DFM_DEBUG 1 @@ -167,6 +168,8 @@ int DFM::decodeCFG(uint8_t *cfg) if((cfg[0]>>4)==0x06 && type==0) { // DFM-6 ID lowid = ((cfg[0]&0x0F)<<20) | (cfg[1]<<12) | (cfg[2]<<4) | (cfg[3]&0x0f); Serial.print("DFM-06 ID: "); Serial.print(lowid, HEX); + snprintf(sonde.si()->id, 10, "%x", lowid); + sonde.si()->validID = true; } if((cfg[0]>>4)==0x0A) { // DMF-9 ID type=9; @@ -180,6 +183,8 @@ int DFM::decodeCFG(uint8_t *cfg) if(idgood==3) { uint32_t dfmid = (highid<<16) | lowid; Serial.print("DFM-09 ID: "); Serial.print(dfmid); + snprintf(sonde.si()->id, 10, "%d", dfmid); + sonde.si()->validID = true; } } } @@ -204,6 +209,9 @@ int DFM::decodeDAT(uint8_t *dat) vh = (dat[4]<<8) + dat[5]; Serial.print("GPS-lat: "); Serial.print(lat*0.0000001); Serial.print(", hor-V: "); Serial.print(vh*0.01); + sonde.si()->lat = lat*0.0000001; + sonde.si()->hs = vh*0.01; + sonde.si()->validPos |= 0x11; } break; case 3: @@ -213,6 +221,9 @@ int DFM::decodeDAT(uint8_t *dat) dir = ((uint16_t)dat[4]<<8) + dat[5]; Serial.print("GPS-lon: "); Serial.print(lon*0.0000001); Serial.print(", dir: "); Serial.print(dir*0.01); + sonde.si()->lon = lon*0.0000001; + sonde.si()->dir = dir*0.01; + sonde.si()->validPos |= 0x42; } break; case 4: @@ -222,6 +233,9 @@ int DFM::decodeDAT(uint8_t *dat) vv = (int16_t)( (dat[4]<<8) | dat[5] ); Serial.print("GPS-height: "); Serial.print(hei*0.01); Serial.print(", vv: "); Serial.print(vv*0.01); + sonde.si()->hei = hei*0.01; + sonde.si()->vs = vv*0.01; + sonde.si()->validPos |= 0x0C; } break; case 8: @@ -258,7 +272,7 @@ int DFM::receiveFrame() { sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE); int e = sx1278.receivePacketTimeout(1000, data); - if(e) { return 1; } //if timeout... return 1 + if(e) { return RX_TIMEOUT; } //if timeout... return 1 deinterleave(data, 7, hamming_conf); deinterleave(data+7, 13, hamming_dat1); @@ -279,6 +293,7 @@ int DFM::receiveFrame() { decodeCFG(byte_conf); decodeDAT(byte_dat1); decodeDAT(byte_dat2); + return RX_OK; } DFM dfm = DFM(); diff --git a/libraries/SondeLib/Sonde.cpp b/libraries/SondeLib/Sonde.cpp index 22b5e52..86ff2a4 100644 --- a/libraries/SondeLib/Sonde.cpp +++ b/libraries/SondeLib/Sonde.cpp @@ -36,6 +36,10 @@ static const uint8_t font[10][5]={ 0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x06, 0x49, 0x39, 0x29, 0x1E }; // 9; .=0x40 +static uint8_t halfdb_tile[8]={0x80, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x00}; +static uint8_t empty_tile[8]={0x80, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00}; + + void Sonde::setIP(const char *ip) { int tp = 0; int len = strlen(ip); @@ -152,8 +156,11 @@ void Sonde::updateDisplayID() { void Sonde::updateDisplayRSSI() { char buf[16]; u8x8.setFont(u8x8_font_7x14_1x2_r); - snprintf(buf, 16, "%ddB ", sonde.si()->rssi); + snprintf(buf, 16, "-%d ", sonde.si()->rssi/2); + int len=strlen(buf)-3; + buf[5]=0; u8x8.drawString(0,6,buf); + u8x8.drawTile(len,6,1,(sonde.si()->rssi&1)?halfdb_tile:empty_tile); } void Sonde::updateStat() { diff --git a/libraries/SondeLib/Sonde.h b/libraries/SondeLib/Sonde.h index de3e80a..27936cd 100644 --- a/libraries/SondeLib/Sonde.h +++ b/libraries/SondeLib/Sonde.h @@ -23,7 +23,8 @@ typedef struct st_sondeinfo { float hei; float vs; float hs; - bool validPos; + float dir; // 0..360 + uint8_t validPos; // bit pattern for validity of above 6 fields // RSSI from receiver int rssi; uint8_t rxStat[20];