merging pull request #2 by DL2MF to devel branch

This commit is contained in:
Hans P. Reiser 2019-04-23 13:08:02 +02:00
parent 619631f80e
commit d056ec8b76
13 changed files with 373 additions and 151 deletions

View File

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

View File

@ -3,6 +3,7 @@
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#include <U8x8lib.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <SX1278FSK.h>
@ -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,"<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"qrg.html\" method=\"post\"><table><tr><th>ID</th><th>Active</th><th>Freq</th><th>Mode</th></tr>");
for(int i=0; i<10; i++) {
for(int i=0; i<sonde.config.maxsonde; i++) {
String s = sondeTypeSelect(i>=sonde.nSonde?2:sonde.sondeList[i].type);
sprintf(ptr+strlen(ptr), "<tr><td>%d</td><td><input name=\"A%d\" type=\"checkbox\" %s/></td>"
"<td><input name=\"F%d\" type=\"text\" value=\"%3.3f\"></td>"
@ -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),"<tr><td id=\"sfreq\">%3.3f MHz, Type: %s</td><tr><td>ID: %s</td></tr><tr><td>QTH: %.6f,%.6f h=%.0fm</td></tr>\n",
s->freq, sondeTypeStr[s->type],
s->validID?s->id:"<??>",
s->lat, s->lon, s->hei);
sprintf(ptr+strlen(ptr), "<tr><td><a target=\"_empty\" href=\"geo:%.6f,%.6f\">Geo-Ref</a> -", s->lat, s->lon);
sprintf(ptr+strlen(ptr), "<a target=\"_empty\" href=\"https://www.google.com/maps/search/?api=1&query=%.6f,%.6f\">Google map</a> - ", s->lat, s->lon);
s->lat, s->lon, s->alt);
sprintf(ptr+strlen(ptr), "<tr><td><a target=\"_empty\" href=\"geo:%.6f,%.6f\">GEO-App</a> - ", s->lat, s->lon);
sprintf(ptr+strlen(ptr), "<a target=\"_empty\" href=\"https://wx.dl2mf.de/?%s\">WX.DL2MF.de</a> - ", s->id);
sprintf(ptr+strlen(ptr), "<a target=\"_empty\" href=\"https://www.openstreetmap.org/?mlat=%.6f&mlon=%.6f&zoom=14\">OSM</a></td></tr>", s->lat, s->lon);
strcat(ptr, "</table><p/>\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; i<nNetworks; i++) {
Serial.print("Comparing '");
Serial.print(id);
Serial.print("' and '");
Serial.print(networks[i].id.c_str());
Serial.println("'");
//Serial.print("Comparing '");
//Serial.print(id);
//Serial.print("' and '");
//Serial.print(networks[i].id.c_str());
//Serial.println("'");
if(strcmp(id,networks[i].id.c_str())==0) return networks[i].pw.c_str();
}
return NULL;
@ -471,28 +470,81 @@ int hasKeyPress() {
void setup()
{
char buf[12];
// Open serial communications and wait for port to open:
Serial.begin(115200);
pinMode(LORA_LED, OUTPUT);
aprs_gencrctab();
pinMode(LORA_LED, OUTPUT);
// Initialize SPIFFS
// Initialize SPIFFS
if(!SPIFFS.begin(true)){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
setupWifiList();
setupConfigData();
button1.pin = sonde.config.button_pin;
setupConfigData(); // configuration must be read first due to OLED ports!!!
u8x8 = new U8X8_SSD1306_128X64_NONAME_SW_I2C(/* clock=*/ sonde.config.oled_scl, /* data=*/ sonde.config.oled_sda, /* reset=*/ sonde.config.oled_rst); // Unbuffered, basic graphics, software I2C
u8x8->begin();
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");

View File

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

View File

@ -1,13 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>ESP32 Web Server</title>
<title>RDZSonde Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>ESP32 Web Server</h1>
<h2>RDZSonde Server</h2>
<!--
<p>GPIO state: <strong> %STATE%</strong></p>
<p><a href="/on"><button class="button">ON</button></a></p>
@ -16,19 +16,20 @@
<div class="tab">
<button class="tablinks" onclick="selTab(event,'QRG')" id="defaultTab">QRG</button>
<button class="tablinks" onclick="selTab(event,'WIFI')">WLAN</button>
<button class="tablinks" onclick="selTab(event,'WLAN')">WLAN</button>
<button class="tablinks" onclick="selTab(event,'Data')">Data</button>
<button class="tablinks" onclick="selTab(event,'WebWX')">Webwx</button>
<button class="tablinks" onclick="selTab(event,'Config')">Config</button>
<button class="tablinks" onclick="selTab(event,'About')">About</button>
</div>
<div id="QRG" class="tabcontent">
<h3> QRG</h3>
<h3> QRG - Setup</h3>
<iframe src="qrg.html" style="border:none;" width="100%%" height="100%%"></iframe>
</div>
<div id="WIFI" class="tabcontent">
<h3> WIFI</h3>
<div id="WLAN" class="tabcontent">
<h3> WLAN - Settings</h3>
<iframe src="wifi.html" style="border:none;" width="100%%" height="100%%"></iframe>
</div>
@ -37,14 +38,24 @@
<iframe src="status.html" style="border:none;" width="100%%" height="100%%"></iframe>
</div>
<div id="Data" class="tabcontent">
<h3>wetterson.de</h3>
<iframe src="https://wetterson.de/karte/" style="border:none;" width="100%%" height="100%%"></iframe>
</div>
<div id="Config" class="tabcontent">
<h3>Config</h3>
<h3>Configuration</h3>
<iframe src="config.html" style="border:none;" width="100%%" height="100%%"></iframe>
</div>
<div id="About" class="tabcontent">
<h3>About</h3>
RDZSonde
RDZSonde - OpenSource<br>
Copyright &copy; 2019<br>
by Hans P. Reiser, DL9RDZ<br>
(devel-version 2019-04-23)<br>
-------------------------------<br>
with mods by Meinhard Guenther, DL2MF<br>
</div>
<script>

View File

@ -1,6 +1,4 @@
RDZsonde
RDZsonde
DinoGast
Schokolade
AndroidDD
dl9rdzhr
AUTORX
12345678
SONDERX
radiosonde

View File

@ -1,8 +1,23 @@
# 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 -
402.300 4 - Greifswald
402.500 4 - Schleswig
402.700 4 + HH-Sasel
403.000 4 - DeBilt
404.100 4 + Norderney
404.300 4 - Schleswig_2
404.500 4 - Meppen
404.700 4 - Greifswald_2
405.100 4 - Lindenberg
405.700 4 + Bergen
405.900 4 + Bergen_2
405.100 4 + Meppen_2
405.300 4 - Essen
403.330 9 - TrUebPl
403.450 9 - TrUebPl
403.470 9 - TrUebPl
403.850 9 - TrUebPl
403.870 9 - TrUebPl
403.890 9 - TrUebPl
# end

View File

@ -228,12 +228,12 @@ int DFM::decodeDAT(uint8_t *dat)
break;
case 4:
{
float hei, vv;
hei = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + dat[3];
float lat, vv;
lat = ((uint32_t)dat[0]<<24) + ((uint32_t)dat[1]<<16) + ((uint32_t)dat[2]<<8) + dat[3];
vv = (int16_t)( (dat[4]<<8) | dat[5] );
Serial.print("GPS-height: "); Serial.print(hei*0.01);
Serial.print("GPS-height: "); Serial.print(lat*0.01);
Serial.print(", vv: "); Serial.print(vv*0.01);
sonde.si()->hei = hei*0.01;
sonde.si()->lat = lat*0.01;
sonde.si()->vs = vv*0.01;
sonde.si()->validPos |= 0x0C;
}

View File

@ -351,7 +351,7 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
Serial.print("m/s ");
Serial.print(getcard16(b, b_len, p+18UL)&255UL);
Serial.print("Sats");
sonde.si()->hei = heig;
sonde.si()->alt = heig;
sonde.si()->validPos = true;
} /* end posrs41() */

View File

@ -2,19 +2,26 @@
#include <SX1278FSK.h>
#include <U8x8lib.h>
#include "Sonde.h"
extern U8X8_SSD1306_128X64_NONAME_SW_I2C *u8x8;
#define CHANBW 10
#define PIXSAMPL (50/CHANBW)
#define SMOOTH 3
#define STARTF 400000000
//#define STARTF 401000000
#define NCHAN ((int)(6000/CHANBW))
double STARTF = (sonde.config.startfreq * 1000000);
//int CHANBW = (sonde.config.channelbw);
//int NCHAN = ((int)(6000/CHANBW));
//int PIXSAMPL = (50/CHANBW);
int scanresult[NCHAN];
int scandisp[NCHAN/PIXSAMPL];
#define PLOT_N 120
#define TICK1 (120/6)
#define PLOT_N 128
#define TICK1 (128/6)
#define TICK2 (TICK1/4)
#define PLOT_MIN -250
#define PLOT_SCALE(x) (x<PLOT_MIN?0:(x-PLOT_MIN)/2)
@ -30,7 +37,7 @@ void Scanner::fillTiles(uint8_t *row, int value) {
}
/*
* There are 16*8 columns to plot, NPLOT must be lower than that
* currently, we use 120 * 50kHz channels
* currently, we use 128 * 50kHz channels
* There are 8*8 values to plot; MIN is bottom end,
*/
uint8_t tiles[16] = { 0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0, 1, 3, 7, 15, 31, 63, 127, 255};

View File

@ -52,10 +52,18 @@ Sonde::Sonde() {
config.oled_sda = 4;
config.oled_scl = 15;
config.oled_rst = 16;
config.noisefloor = -130;
strcpy(config.call,"NOCALL");
strcpy(config.passcode, "---");
config.maxsonde=15;
config.debug=0;
config.wifi=1;
config.wifiap=1;
config.startfreq=400;
config.channelbw=10;
config.spectrum=10;
config.timer=0;
config.marker=0;
config.udpfeed.active = 1;
config.udpfeed.type = 0;
strcpy(config.udpfeed.host, "192.168.42.20");
@ -80,7 +88,7 @@ void Sonde::setConfig(const char *cfg) {
char *val = s+1;
*s=0; s--;
while(s>cfg && (*s==' '||*s=='\t')) { *s=0; s--; }
Serial.printf("handling option '%s'='%s'\n", cfg, val);
Serial.printf("configuration option '%s'=%s \n", cfg, val);
if(strcmp(cfg,"noisefloor")==0) {
config.noisefloor = atoi(val);
if(config.noisefloor==0) config.noisefloor=-130;
@ -90,12 +98,32 @@ void Sonde::setConfig(const char *cfg) {
strncpy(config.passcode, val, 9);
} else if(strcmp(cfg,"button_pin")==0) {
config.button_pin = atoi(val);
} else if(strcmp(cfg,"led_pin")==0) {
config.led_pin = atoi(val);
} else if(strcmp(cfg,"oled_sda")==0) {
config.oled_sda = atoi(val);
} else if(strcmp(cfg,"oled_scl")==0) {
config.oled_scl = atoi(val);
} else if(strcmp(cfg,"oled_rst")==0) {
config.oled_rst = atoi(val);
} else if(strcmp(cfg,"maxsonde")==0) {
config.maxsonde = atoi(val);
} else if(strcmp(cfg,"debug")==0) {
config.debug = atoi(val);
} else if(strcmp(cfg,"wifi")==0) {
config.wifi = atoi(val);
} else if(strcmp(cfg,"wifiap")==0) {
config.wifiap = atoi(val);
} else if(strcmp(cfg,"startfreq")==0) {
config.startfreq = atoi(val);
} else if(strcmp(cfg,"channelbw")==0) {
config.channelbw = atoi(val);
} else if(strcmp(cfg,"spectrum")==0) {
config.spectrum = atoi(val);
} else if(strcmp(cfg,"timer")==0) {
config.timer = atoi(val);
} else if(strcmp(cfg,"marker")==0) {
config.marker = atoi(val);
} else if(strcmp(cfg,"axudp.active")==0) {
config.udpfeed.active = atoi(val)>0;
} else if(strcmp(cfg,"axudp.host")==0) {
@ -121,7 +149,7 @@ void Sonde::setConfig(const char *cfg) {
} else if(strcmp(cfg,"tcp.idformat")==0) {
config.tcpfeed.idformat = atoi(val);
} else {
Serial.printf("Invalid config option '%s'='%s'\n", cfg, val);
Serial.printf("Invalid config option '%s'=%s \n", cfg, val);
}
}
@ -146,21 +174,22 @@ void Sonde::setIP(const char *ip, bool AP) {
void Sonde::clearSonde() {
nSonde = 0;
}
void Sonde::addSonde(float frequency, SondeType type, int active) {
if(nSonde>=MAXSONDE) {
void Sonde::addSonde(float frequency, SondeType type, int active, char *launchsite) {
if(nSonde>=config.maxsonde) {
Serial.println("Cannot add another sonde, MAXSONDE reached");
return;
}
sondeList[nSonde].type = type;
sondeList[nSonde].freq = frequency;
sondeList[nSonde].active = active;
sondeList[nSonde].launchsite = launchsite;
memcpy(sondeList[nSonde].rxStat, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", 18); // unknown/undefined
nSonde++;
}
void Sonde::nextConfig() {
currentSonde++;
// Skip non-active entries (but don't loop forever if there are no active ones
for(int i=0; i<MAXSONDE; i++) {
for(int i=0; i<config.maxsonde; i++) {
if(!sondeList[currentSonde].active) {
currentSonde++;
if(currentSonde>=nSonde) currentSonde=0;
@ -230,7 +259,7 @@ void Sonde::updateDisplayPos2() {
u8x8->drawString(10,4," ");
return;
}
snprintf(buf, 16, si()->hei>999?" %5.0fm":" %3.1fm", si()->hei);
snprintf(buf, 16, si()->alt>999?" %5.0fm":" %3.1fm", si()->alt);
u8x8->drawString((10+6-strlen(buf)),2,buf);
snprintf(buf, 16, si()->hs>99?" %3.0f":" %2.1f", si()->hs);
u8x8->drawString((10+4-strlen(buf)),3,buf);
@ -276,7 +305,9 @@ void Sonde::updateDisplayRXConfig() {
u8x8->drawString(0,0, sondeTypeStr[si()->type]);
snprintf(buf, 16, "%3.3f MHz", si()->freq);
u8x8->drawString(5,0, buf);
//snprintf(buf, 8, "%s", si()->launchsite);
//u8x8->drawString(0,5, buf);
u8x8->drawTile(14,3,2,kmh_tiles);
}
void Sonde::updateDisplayIP() {
@ -287,11 +318,13 @@ void Sonde::updateDisplayIP() {
// 40x.xxx MHz
void Sonde::updateDisplayScanner() {
char buf[16];
u8x8->setFont(u8x8_font_7x14_1x2_r);
u8x8->drawString(0, 0, "Probing");
u8x8->setFont(u8x8_font_7x14_1x2_r);
u8x8->drawString(0, 0, "Scan:");
u8x8->drawString(8, 0, sondeTypeStr[si()->type]);
snprintf(buf, 16, "%3.3f MHz", si()->freq);
u8x8->drawString(0,3, buf);
snprintf(buf, 16, "%3.3f MHz", si()->freq);
u8x8->drawString(0,3, buf);
//snprintf(buf, 8, "%s", si()->launchsite);
//u8x8->drawString(0,5, buf);
updateDisplayIP();
}
@ -304,7 +337,7 @@ void Sonde::updateDisplay()
updateDisplayPos2();
updateDisplayRSSI();
updateStat();
updateDisplayIP();
updateDisplayIP();
}
void Sonde::clearDisplay() {

View File

@ -13,13 +13,23 @@ enum SondeType { STYPE_DFM06, STYPE_DFM09, STYPE_RS41 };
extern const char *sondeTypeStr[5];
typedef struct st_rdzconfig {
int button_pin;
int oled_sda;
int oled_scl;
int oled_rst;
int button_pin; // pin number of second button (for some boards)
int led_pin; // pin number of LED
int oled_sda; // OLED data pin
int oled_scl; // OLED clock pin
int oled_rst; // OLED reset pin
int debug; // show port and config options after reboot
int wifi; // connect to known WLAN 0=skip
int wifiap; // enable/disable WiFi AccessPoint mode 0=disable
int startfreq; // spectrum display start freq (400, 401, ...)
int channelbw; // spectrum channel bandwidth (valid: 5, 10, 20, 25, 50, 100 kHz)
int spectrum; // show freq spectrum for n seconds 0=disable
int timer; // show remaining time in spectrum 0=disable
int marker; // show freq marker in spectrum 0=disable
int maxsonde; // number of max sonde in scan (range=1-99)
int noisefloor; // for spectrum display
char call[9];
char passcode[9];
char call[9]; // APRS callsign
char passcode[9]; // APRS passcode
// for now, one feed for each type is enough, but might get extended to more?
struct st_feedinfo udpfeed; // target for AXUDP messages
struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections
@ -27,28 +37,29 @@ typedef struct st_rdzconfig {
typedef struct st_sondeinfo {
// receiver configuration
bool active;
bool active;
SondeType type;
float freq;
// decoded ID
char id[10];
bool validID;
char *launchsite;
// decoded position
float lat;
float lon;
float hei;
float vs;
float hs;
float dir; // 0..360
float lat; // latitude
float lon; // longitude
float alt; // altitude
float vs; // vertical speed
float hs; // horizontal speed
float dir; // 0..360
uint8_t validPos; // bit pattern for validity of above 6 fields
// RSSI from receiver
int rssi;
int rssi; // signal strength
uint8_t rxStat[20];
} SondeInfo;
// rxState: 0=undef[empty] 1=timeout[.] 2=errro[E] 3=ok[1]
#define MAXSONDE 10
#define MAXSONDE 99
class Sonde
{
@ -63,7 +74,7 @@ public:
void setConfig(const char *str);
void clearSonde();
void addSonde(float frequency, SondeType type, int active);
void addSonde(float frequency, SondeType type, int active, char *launchsite);
void nextConfig();
void setup();

View File

@ -251,7 +251,7 @@ static uint32_t dao91(double x)
char b[201];
char raw[201];
char * aprs_senddata(float lat, float lon, float hei, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym)
char * aprs_senddata(float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym)
{
*b=0;
aprsstr_append(b, usercall);
@ -281,9 +281,9 @@ char * aprs_senddata(float lat, float lon, float hei, float speed, float dir, fl
snprintf(b+i, APRS_MAXLEN-i, "%03d/%03d", realcard(dir+1.5), realcard(speed*1.0/KNOTS+0.5));
}
#endif
if(hei>0.5) {
if(alt>0.5) {
i=strlen(b);
snprintf(b+i, APRS_MAXLEN-i, "/A=%06d", realcard(hei*FEET+0.5));
snprintf(b+i, APRS_MAXLEN-i, "/A=%06d", realcard(alt*FEET+0.5));
}
#if 1
int dao=1;

View File

@ -20,7 +20,7 @@ typedef struct st_feedinfo {
#define APRS_MAXLEN 201
void aprs_gencrctab(void);
int aprsstr_mon2raw(const char *mon, char raw[], int raw_len);
char * aprs_senddata(float lat, float lon, float hei, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym);
char * aprs_senddata(float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym);
#endif