some minor updates
This commit is contained in:
parent
e7360f2c1e
commit
da9d4367be
46
README.md
46
README.md
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
}
|
||||
|
||||
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) {
|
||||
for(int i=0; i<nNetworks; i++) {
|
||||
Serial.print("Comparing '");
|
||||
|
|
@ -206,10 +237,13 @@ void setup()
|
|||
// Handle button press
|
||||
attachInterrupt(0, buttonISR, CHANGE);
|
||||
|
||||
setupChannelList();
|
||||
#if 0
|
||||
sonde.clearSonde();
|
||||
sonde.addSonde(402.300, STYPE_RS41);
|
||||
sonde.addSonde(402.700, STYPE_RS41);
|
||||
sonde.addSonde(403.450, STYPE_DFM09);
|
||||
#endif
|
||||
/// not here, done by sonde.setup(): rs41.setup();
|
||||
sonde.setup();
|
||||
}
|
||||
|
|
@ -267,7 +301,7 @@ void loopScanner() {
|
|||
enterMode(ST_DECODER);
|
||||
return;
|
||||
}
|
||||
if(++tries>=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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Reference in New Issue