some minor updates

This commit is contained in:
Hans P. Reiser 2019-04-05 23:32:26 +02:00
parent e7360f2c1e
commit da9d4367be
6 changed files with 134 additions and 7 deletions

View File

@ -1 +1,45 @@
# rdz_ttgo_sonde 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)

View File

@ -101,6 +101,37 @@ void setupWifiList() {
for(int j=0; j<i; j++) { Serial.print(networks[j].id); Serial.print(": "); Serial.println(networks[j].pw); } for(int j=0; j<i; j++) { Serial.print(networks[j].id); Serial.print(": "); Serial.println(networks[j].pw); }
} }
void setupChannelList() {
File file = SPIFFS.open("/qrg.txt", "r");
if(!file) {
Serial.println("There was an error opening the file '/qrg.txt' for reading");
return;
}
int i=0;
sonde.clearSonde();
while(file.available()) {
String line = file.readStringUntil('\n');
if(!file.available()) break;
if(line[0] == '#') continue;
char *space = strchr(line.c_str(), ' ');
if(!space) continue;
*space = 0;
float freq = atof(line.c_str());
SondeType type;
if(space[1]=='4') { type=STYPE_RS41; }
else if (space[1]=='9') { type=STYPE_DFM09; }
else if (space[1]=='6') { type=STYPE_DFM06; }
else continue;
Serial.printf("Adding %f with type %d\b",freq,type);
sonde.addSonde(freq, type);
i++;
}
nNetworks = i;
Serial.print(i); Serial.println(" networks in networks.txt\n");
for(int j=0; j<i; j++) { Serial.print(networks[j].id); Serial.print(": "); Serial.println(networks[j].pw); }
}
const char *fetchWifiPw(const char *id) { const char *fetchWifiPw(const char *id) {
for(int i=0; i<nNetworks; i++) { for(int i=0; i<nNetworks; i++) {
Serial.print("Comparing '"); Serial.print("Comparing '");
@ -206,10 +237,13 @@ void setup()
// Handle button press // Handle button press
attachInterrupt(0, buttonISR, CHANGE); attachInterrupt(0, buttonISR, CHANGE);
setupChannelList();
#if 0
sonde.clearSonde(); sonde.clearSonde();
sonde.addSonde(402.300, STYPE_RS41); sonde.addSonde(402.300, STYPE_RS41);
sonde.addSonde(402.700, STYPE_RS41); sonde.addSonde(402.700, STYPE_RS41);
sonde.addSonde(403.450, STYPE_DFM09); sonde.addSonde(403.450, STYPE_DFM09);
#endif
/// not here, done by sonde.setup(): rs41.setup(); /// not here, done by sonde.setup(): rs41.setup();
sonde.setup(); sonde.setup();
} }
@ -267,7 +301,7 @@ void loopScanner() {
enterMode(ST_DECODER); enterMode(ST_DECODER);
return; return;
} }
if(++tries>=SCAN_MAXTRIES) { if(++tries>=SCAN_MAXTRIES && !hasKeyPress()) {
sonde.nextConfig(); sonde.nextConfig();
tries = 0; tries = 0;
} }
@ -334,7 +368,7 @@ void loopWifiScan() {
pw=fetchWifiPw(id); pw=fetchWifiPw(id);
if(pw) break; if(pw) break;
} }
if(!pw) { id="test"; pw="test"; } if(1||!pw) { id="test"; pw="test"; }
Serial.print("Connecting to: "); Serial.println(id); Serial.print("Connecting to: "); Serial.println(id);
u8x8.drawString(0,6, "Conn:"); u8x8.drawString(0,6, "Conn:");
u8x8.drawString(6,6, id); u8x8.drawString(6,6, id);
@ -344,6 +378,24 @@ void loopWifiScan() {
Serial.print("."); Serial.print(".");
u8x8.drawString(15,7,_scan[cnt&1]); u8x8.drawString(15,7,_scan[cnt&1]);
cnt++; 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(""); Serial.println("");
@ -354,7 +406,7 @@ void loopWifiScan() {
sonde.updateDisplayIP(); sonde.updateDisplayIP();
SetupAsyncServer(); SetupAsyncServer();
delay(5000); delay(5000);
mainState=ST_SPECTRUM; enterMode(ST_DECODER);
} }

8
RX_FSK/data/qrg.txt Normal file
View File

@ -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

View File

@ -2,6 +2,7 @@
/* DFM decoder functions */ /* DFM decoder functions */
#include "DFM.h" #include "DFM.h"
#include "SX1278FSK.h" #include "SX1278FSK.h"
#include "Sonde.h"
#define DFM_DEBUG 1 #define DFM_DEBUG 1
@ -167,6 +168,8 @@ int DFM::decodeCFG(uint8_t *cfg)
if((cfg[0]>>4)==0x06 && type==0) { // DFM-6 ID if((cfg[0]>>4)==0x06 && type==0) { // DFM-6 ID
lowid = ((cfg[0]&0x0F)<<20) | (cfg[1]<<12) | (cfg[2]<<4) | (cfg[3]&0x0f); lowid = ((cfg[0]&0x0F)<<20) | (cfg[1]<<12) | (cfg[2]<<4) | (cfg[3]&0x0f);
Serial.print("DFM-06 ID: "); Serial.print(lowid, HEX); 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 if((cfg[0]>>4)==0x0A) { // DMF-9 ID
type=9; type=9;
@ -180,6 +183,8 @@ int DFM::decodeCFG(uint8_t *cfg)
if(idgood==3) { if(idgood==3) {
uint32_t dfmid = (highid<<16) | lowid; uint32_t dfmid = (highid<<16) | lowid;
Serial.print("DFM-09 ID: "); Serial.print(dfmid); 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]; vh = (dat[4]<<8) + dat[5];
Serial.print("GPS-lat: "); Serial.print(lat*0.0000001); Serial.print("GPS-lat: "); Serial.print(lat*0.0000001);
Serial.print(", hor-V: "); Serial.print(vh*0.01); 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; break;
case 3: case 3:
@ -213,6 +221,9 @@ int DFM::decodeDAT(uint8_t *dat)
dir = ((uint16_t)dat[4]<<8) + dat[5]; dir = ((uint16_t)dat[4]<<8) + dat[5];
Serial.print("GPS-lon: "); Serial.print(lon*0.0000001); Serial.print("GPS-lon: "); Serial.print(lon*0.0000001);
Serial.print(", dir: "); Serial.print(dir*0.01); 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; break;
case 4: case 4:
@ -222,6 +233,9 @@ int DFM::decodeDAT(uint8_t *dat)
vv = (int16_t)( (dat[4]<<8) | dat[5] ); vv = (int16_t)( (dat[4]<<8) | dat[5] );
Serial.print("GPS-height: "); Serial.print(hei*0.01); Serial.print("GPS-height: "); Serial.print(hei*0.01);
Serial.print(", vv: "); Serial.print(vv*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; break;
case 8: case 8:
@ -258,7 +272,7 @@ int DFM::receiveFrame() {
sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE); sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE);
int e = sx1278.receivePacketTimeout(1000, data); 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, hamming_conf);
deinterleave(data+7, 13, hamming_dat1); deinterleave(data+7, 13, hamming_dat1);
@ -279,6 +293,7 @@ int DFM::receiveFrame() {
decodeCFG(byte_conf); decodeCFG(byte_conf);
decodeDAT(byte_dat1); decodeDAT(byte_dat1);
decodeDAT(byte_dat2); decodeDAT(byte_dat2);
return RX_OK;
} }
DFM dfm = DFM(); DFM dfm = DFM();

View File

@ -36,6 +36,10 @@ static const uint8_t font[10][5]={
0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x36, 0x49, 0x49, 0x49, 0x36, // 8
0x06, 0x49, 0x39, 0x29, 0x1E }; // 9; .=0x40 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) { void Sonde::setIP(const char *ip) {
int tp = 0; int tp = 0;
int len = strlen(ip); int len = strlen(ip);
@ -152,8 +156,11 @@ void Sonde::updateDisplayID() {
void Sonde::updateDisplayRSSI() { void Sonde::updateDisplayRSSI() {
char buf[16]; char buf[16];
u8x8.setFont(u8x8_font_7x14_1x2_r); 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.drawString(0,6,buf);
u8x8.drawTile(len,6,1,(sonde.si()->rssi&1)?halfdb_tile:empty_tile);
} }
void Sonde::updateStat() { void Sonde::updateStat() {

View File

@ -23,7 +23,8 @@ typedef struct st_sondeinfo {
float hei; float hei;
float vs; float vs;
float hs; float hs;
bool validPos; float dir; // 0..360
uint8_t validPos; // bit pattern for validity of above 6 fields
// RSSI from receiver // RSSI from receiver
int rssi; int rssi;
uint8_t rxStat[20]; uint8_t rxStat[20];