Compare commits

...

9 Commits

Author SHA1 Message Date
FCS
1014df8ec7 Change Versions Date
Some checks failed
/ Build (push) Failing after 3m52s
/ Release (push) Has been skipped
2026-01-18 15:32:44 +01:00
FCS
9ee412126f send and Receive via NMEA, send time, non interrupt loop 2026-01-18 15:31:07 +01:00
24e5b5afe6 README.md aktualisiert 2025-12-10 08:56:16 +00:00
FCS
fa1c728187 Anpassung FlowChart 2025-12-08 13:08:41 +01:00
FCS
e22e6e8ab3 Flowchart Segelflugzeug 2025-12-08 10:25:59 +01:00
FCS
7c979dbd01 PCB Layout 2025-12-05 13:36:46 +01:00
FCS
1c1eddc872 comports 2025-12-02 20:00:10 +01:00
FCS
3232c7e5c4 formating 2025-12-02 19:59:58 +01:00
FCS
b4774d4b77 communicate via json, display rssi and from, dynamic min and max speed via json 2025-12-02 19:59:39 +01:00
8 changed files with 309 additions and 67 deletions

View File

@@ -1,5 +1,15 @@
CHANGELOG CHANGELOG
## 0.0.6 (18.01.2025)
+ Anpassung Programmablaufplan
### Segeflug Modul
+ Umsetzen der Sender-Logik
+ senden im NMEA Format
### Winden Modul
+ empfangen im NMEA Format
## 0.0.5 (30.11.2025) ## 0.0.5 (30.11.2025)
+ Formatierung Code + Formatierung Code
### Segeflug Modul ### Segeflug Modul

View File

@@ -1,4 +1,6 @@
[![build status](https://gitea.rabe11.de/FCS/Winden-Telemetry/actions/workflows/build_release.yaml/badge.svg?event=push)](https://gitea.rabe11.de/FCS/Winden-Telemetry/releases) [![build status](https://gitea.rabe11.de/FCS/Winden-Telemetry/actions/workflows/build_release.yaml/badge.svg?event=push)](https://gitea.rabe11.de/FCS/Winden-Telemetry/releases)
![Gitea Release](https://img.shields.io/gitea/v/release/FCS/Winden-Telemetry?gitea_url=https%3A%2F%2Fgitea.rabe11.de)
# Winden-Telemetry # Winden-Telemetry
@@ -22,17 +24,19 @@
- [ ] Kennzeichen einstellbar - [ ] Kennzeichen einstellbar
- [x] Analoge Anzeige in der Winde - [x] Analoge Anzeige in der Winde
- [x] Farbige LEDs für Limits - [x] Farbige LEDs für Limits
- [ ] Übertragungszeit Begrenzen - [x] Übertragungszeit Begrenzen
- [ ] Übertragungszeit einstellbar - [ ] Übertragungszeit einstellbar
- [ ] Übertragung Rundumleuchten Signal an Start - [ ] Übertragung Rundumleuchten Signal an Start
- [x] Luftdrucksensor für Höhe und Vario - [x] Luftdrucksensor für Höhe und Vario
### Aufbau ## Aufbau
Pin Layout Heltec WiFi LoRa (v3) Pin Layout Heltec WiFi LoRa (v3)
![Heltec WiFi LoRa (v3)](https://heltec.org/wp-content/uploads/2023/09/pin.png) ![Heltec WiFi LoRa (v3)](https://heltec.org/wp-content/uploads/2023/09/pin.png)
### Anschlusszuordnung
| Heltec WiFi LoRa (v3) Pin | MP1584 |SG90 Pin | BMP180 Pin | MS4525 Pin | LED Ring Pin | | Heltec WiFi LoRa (v3) Pin | MP1584 |SG90 Pin | BMP180 Pin | MS4525 Pin | LED Ring Pin |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |
| GND | OUT -| GND | GND | GND | GND | | GND | OUT -| GND | GND | GND | GND |
@@ -42,3 +46,59 @@ Pin Layout Heltec WiFi LoRa (v3)
| GPIO19| | | SDA| SDA | | GPIO19| | | SDA| SDA |
| GPIO20| | | SCL| SCL| | GPIO20| | | SCL| SCL|
| 5V | OUT + | VCC | | | | 5V | OUT + | VCC | | |
## PCB
Die Platine ist so gestaltet das sie individuell bestückt werden kann, je nach Verwendung
![Platine bestückt](img/Winden_Telemetry_PCB.png)
![Platinen Vorderseite](img/Winden_Telemetry_PCB_front.png)![Platinen Rückseite](img/Winden_Telemetry_PCB_back.png)
[Schaltplan](img/Winden_Telemetry_Schematic.pdf)
| Bauteil | Modul Segelflugzeug | Modul Winde | Modul SKP |
| --- |--- |--- |--- |
| J1 | x | x | x | optional|
| A1 | x | x | x | optional|
| I2C_1 | MS4525 | optional| optional|
| I2C_2 | BMP180 | optional| optional|
| I2C_3 | optional| optional| optional|
| I2C_4 | optional| optional| optional|
| GPIO3 | optional| optional| optional|
| GPIO4 | optional| optional| optional|
| GPIO5 | optional| Eingang Warnleuchte |optional|
| GPIO6 | optional| LED Ring | optional|
| GPIO7 | optional| Servo | für Relais|
## Programmablauf Segelflugzeug
```mermaid
flowchart TD
A(["Start"])
A --> B{"ist Senden an?"}
B --> | Ja | C{"Sende Timer <90 sec"}
I --> | Nein | E{"is airborn?"}
C --> | Nein | F["Sende Schleppen komplett"] -->G["is airborn=true"] -->L["Lowspeedtimer = 0"]
C --> | Ja | D["Sende Speed"]
D --> Z["Warte 1 Sekunde"]
L ----> H["Senden aus"] -->Z
Z --> B
B --> | nein | I{"Speed < 30 km/h"}
E --> | nein |J["Senden an"] -->P["Start Sendetimer"] --> D
I --> | ja| K["Lowspeedtimer + 1"]
K --> M{"lowspeedtimer >90"}
M --> | ja | N["is airborn=false"] --> Z
M --> | nein | Z
E --> | ja |O["Lowspeedtimer = 0"] --> Z
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

View File

@@ -28,34 +28,35 @@ build_flags =
lib_deps = lib_deps =
olikraus/U8g2@^2.36.15 olikraus/U8g2@^2.36.15
jgromes/RadioLib@^7.4.0 jgromes/RadioLib@^7.4.0
bblanchon/ArduinoJson@^7.4.2
monitor_speed = 115200 monitor_speed = 115200
extra_scripts = pre:extra_script.py extra_scripts = pre:extra_script.py
[env:heltec_wifi_lora_32_V3_sailplane] [env:heltec_wifi_lora_32_V3_sailplane]
extends = common extends = common
board = heltec_wifi_lora_32_V3 board = heltec_wifi_lora_32_V3
lib_deps = ${common.lib_deps} lib_deps =
${common.lib_deps}
bolderflight/Bolder Flight Systems MS4525@^1.1.3 bolderflight/Bolder Flight Systems MS4525@^1.1.3
bolderflight/Bolder Flight Systems Unit Conversions@^5.0.0 bolderflight/Bolder Flight Systems Unit Conversions@^5.0.0
bolderflight/Bolder Flight Systems Airdata Calculations@^4.0.0 bolderflight/Bolder Flight Systems Airdata Calculations@^4.0.0
adafruit/Adafruit BMP085 Library @ ^1.2.4 adafruit/Adafruit BMP085 Library @ ^1.2.4
lib_ignore = lib_ignore =
winde winde
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
-D DEVICE_SAILPLANE -D DEVICE_SAILPLANE
upload_port = COM8
monitor_port = COM8
[env:heltec_wifi_lora_32_V3_winde] [env:heltec_wifi_lora_32_V3_winde]
extends = common extends = common
board = heltec_wifi_lora_32_V3 board = heltec_wifi_lora_32_V3
lib_deps = ${common.lib_deps} lib_deps =
${common.lib_deps}
adafruit/Adafruit NeoPixel@^1.15.2 adafruit/Adafruit NeoPixel@^1.15.2
madhephaestus/ESP32Servo@^3.0.9 madhephaestus/ESP32Servo@^3.0.9
lib_ignore = lib_ignore =
sailplane sailplane
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
-D DEVICE_WINDE -D DEVICE_WINDE
upload_port = COM9
monitor_port = COM9

View File

@@ -2,24 +2,26 @@
#include <Arduino.h> #include <Arduino.h>
#include <U8g2lib.h> #include <U8g2lib.h>
#include <RadioLib.h> #include <RadioLib.h>
#include <ArduinoJson.h>
#ifdef DEVICE_WINDE #ifdef DEVICE_WINDE
#include <tacho.h> #include <tacho.h>
#endif #endif
#ifdef DEVICE_SAILPLANE #ifdef DEVICE_SAILPLANE
#include <airspeed.h> #include <airspeed.h>
unsigned long previousMillisSend = 0;
const long send_interval = 1000;
unsigned long previousMillissendtimer = 0;
const long sendtimer_max = 90000;
bool send_data = false;
bool is_airborn = false;
int lowspeedtimer = 0;
int lowspeedtimermax = 90000;
#endif #endif
SX1262 radio = new Module(LORA_NSS, LORA_DIO1, LORA_NRST, LORA_BUSY); SX1262 radio = new Module(LORA_NSS, LORA_DIO1, LORA_NRST, LORA_BUSY);
#ifdef DEVICE_WINDE #ifdef DEVICE_WINDE
volatile bool receivedFlag = false; volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32) #if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR ICACHE_RAM_ATTR
#endif #endif
@@ -34,6 +36,15 @@ void setFlag(void)
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, OLED_RST, OLED_CLK, OLED_DATA); U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, OLED_RST, OLED_CLK, OLED_DATA);
#endif #endif
#ifdef DEVICE_WINDE
String data_from;
int data_speed = 0;
int data_min = 0;
int data_max = 0;
#endif
void setup() void setup()
{ {
/* Serial to display data */ /* Serial to display data */
@@ -89,21 +100,56 @@ void setup()
u8g2.sendBuffer(); u8g2.sendBuffer();
} }
void loop() String nmea_checksum(String str)
{ {
#ifdef DEVICE_SAILPLANE byte cs = 0;
for (unsigned int n = 1; n < str.length(); n++)
{
if (str[n] != '$' || str[n] != '!' || str[n] != '*')
{
cs ^= str[n];
}
}
/* Read the sensor */ if (cs < 0x10)
get_pressure(); return "*0" + String(cs, HEX);
int vel_kmh = get_airspeed_kmh(); else
u8g2.clearBuffer(); return "*" + String(cs, HEX);
u8g2.setFont(u8g2_font_logisoso42_tr); }
u8g2.setCursor(0, 60); void draw_rssi(int Rssi){
u8g2.print(vel_kmh); u8g2.drawFrame(102,8,4,3);
u8g2.sendBuffer(); u8g2.drawFrame(107,6,4,5);
if (vel_kmh > 30) u8g2.drawFrame(112,4,4,7);
u8g2.drawFrame(117,2,4,9);
u8g2.drawFrame(122,0,4,11);
if ((Rssi > -120) && Rssi < 0 )
{
u8g2.drawBox(102,8,4,3);
}
if ((Rssi > -100) && Rssi < 0 )
{
u8g2.drawBox(107,6,4,5);
}
if ((Rssi > -85) && Rssi < 0 )
{
u8g2.drawBox(112,4,4,7);
}
if ((Rssi > -70) && Rssi < 0 )
{
u8g2.drawBox(117,2,4,9);
}
if ((Rssi > -55) && Rssi < 0 )
{
u8g2.drawBox(122,0,4,11);
}
}
void send_lora(String data)
{ {
String data = String(vel_kmh);
int state = radio.transmit(data); int state = radio.transmit(data);
if (state == RADIOLIB_ERR_NONE) if (state == RADIOLIB_ERR_NONE)
{ {
@@ -131,6 +177,130 @@ void loop()
Serial.print(F("failed, code ")); Serial.print(F("failed, code "));
Serial.println(state); Serial.println(state);
} }
}
void send_speed(int vel_kmh)
{
String data;
// serializeJson(sailplane_data, data);
// sprintf(data,"$PWTLS,%s,%u,%u,%u","D-1234",vel_kmh,70,140);
data = "$PWTLS,D1234," + String(vel_kmh) + ",70,140";
data += nmea_checksum(data);
Serial.println(data);
send_lora(data);
}
void send_airborn()
{
String data;
// serializeJson(sailplane_data, data);
data = "$PWTLA,D1234,1";
data += nmea_checksum(data);
Serial.println(data);
send_lora(data);
}
String getSplitValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++)
{
if (data.charAt(i) == separator || i == maxIndex)
{
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i + 1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
void decode_start(String data)
{
data_from = getSplitValue(data, ',', 1);
data_speed = (getSplitValue(data, ',', 2)).toInt();
data_min = (getSplitValue(data, ',', 3)).toInt();
data_max = (getSplitValue(data, ',', 4)).toInt();
}
void decode_airborn(String data)
{
data_from = getSplitValue(data, ',', 1);
data_speed = 0;
data_min = 0;
data_max = 0;
}
void decode_msg(String data)
{
String pos1 = getSplitValue(data, ',', 0);
if (pos1 == "$PWTLS")
{
decode_start(data);
}
else if (pos1 == "$PWTLA")
{
decode_airborn(data);
}
else
{
Serial.println("Nachricht nicht erkannt");
}
}
void loop()
{
#ifdef DEVICE_SAILPLANE
unsigned long currentMillis = millis();
if (currentMillis - previousMillisSend >= send_interval)
{
previousMillisSend = currentMillis;
/* Read the sensor */
get_pressure();
int vel_kmh = get_airspeed_kmh();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_logisoso42_tr);
u8g2.setCursor(0, 60);
u8g2.print(vel_kmh);
u8g2.sendBuffer();
if (send_data == false)
{
if (vel_kmh < 30)
{
lowspeedtimer++;
if (lowspeedtimer >= lowspeedtimermax)
{
is_airborn = false;
lowspeedtimer = lowspeedtimermax;
}
}
else
{
if (is_airborn)
{
lowspeedtimer = 0;
}
else
{
send_data = true;
send_speed(vel_kmh);
previousMillissendtimer = currentMillis;
}
}
}
else
{
if (currentMillis - previousMillissendtimer < sendtimer_max)
{
send_speed(vel_kmh);
}
else
{
send_airborn();
is_airborn = true;
lowspeedtimer = 0;
send_data = false;
}
}
#ifdef DEBUG #ifdef DEBUG
/* Display the data */ /* Display the data */
@@ -144,7 +314,6 @@ void loop()
Serial.print(pres.die_temp_c(), 6); Serial.print(pres.die_temp_c(), 6);
Serial.print("\n"); Serial.print("\n");
#endif #endif
delay(1000);
} }
#endif #endif
@@ -158,24 +327,26 @@ void loop()
String str; String str;
int state = radio.readData(str); int state = radio.readData(str);
// you can also read received data as byte array
/*
byte byteArr[8];
int numBytes = radio.getPacketLength();
int state = radio.readData(byteArr, numBytes);
*/
if (state == RADIOLIB_ERR_NONE) if (state == RADIOLIB_ERR_NONE)
{ {
decode_msg(str);
// packet was successfully received // packet was successfully received
u8g2.clearBuffer(); u8g2.clearBuffer();
u8g2.setFont(u8g2_font_logisoso42_tr); u8g2.setFont(u8g2_font_ncenB10_tr);
u8g2.setCursor(0, 60); u8g2.setCursor(0, 10);
u8g2.print(str); u8g2.print(data_from);
u8g2.setCursor(0, 64);
u8g2.print(data_min);
u8g2.setCursor(64, 64);
u8g2.print(data_max);
u8g2.setFont(u8g2_font_logisoso32_tr);
u8g2.setCursor(0, 50);
u8g2.print(data_speed);
draw_rssi(radio.getRSSI());
u8g2.sendBuffer(); u8g2.sendBuffer();
Serial.println(str); Serial.println(str);
int speed = str.toInt(); int speed = str.toInt();
set_tacho(speed, 70, 150); set_tacho(data_speed, data_min, data_max);
} }
} }
#endif #endif