From da9d4367be473c0ca1b1a27d5f664314a50d9994 Mon Sep 17 00:00:00 2001
From: "Hans P. Reiser"
Date: Fri, 5 Apr 2019 23:32:26 +0200
Subject: [PATCH] some minor updates
---
README.md | 46 +++++++++++++++++++++++++++-
RX_FSK/RX_FSK.ino | 58 ++++++++++++++++++++++++++++++++++--
RX_FSK/data/qrg.txt | 8 +++++
libraries/SondeLib/DFM.cpp | 17 ++++++++++-
libraries/SondeLib/Sonde.cpp | 9 +++++-
libraries/SondeLib/Sonde.h | 3 +-
6 files changed, 134 insertions(+), 7 deletions(-)
create mode 100644 RX_FSK/data/qrg.txt
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];