From 9ee412126fd7e1dc362724403b6a8f4cfe2308ea Mon Sep 17 00:00:00 2001 From: FCS Date: Sun, 18 Jan 2026 15:31:07 +0100 Subject: [PATCH] send and Receive via NMEA, send time, non interrupt loop --- CHANGELOG.md | 10 +++ README.md | 21 +++-- src/main.cpp | 241 ++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 202 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80e6489..d97640a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ CHANGELOG +## 0.0.6 (04.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) + Formatierung Code ### Segeflug Modul diff --git a/README.md b/README.md index dd8766d..c2f28b8 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - [ ] Kennzeichen einstellbar - [x] Analoge Anzeige in der Winde - [x] Farbige LEDs für Limits -- [ ] Übertragungszeit Begrenzen +- [x] Übertragungszeit Begrenzen - [ ] Übertragungszeit einstellbar - [ ] Übertragung Rundumleuchten Signal an Start - [x] Luftdrucksensor für Höhe und Vario @@ -50,7 +50,7 @@ Pin Layout Heltec WiFi LoRa (v3) ## PCB -Die Platine ist so gestaltet das sie Induvidul bestückt werden kann, je nach Verwendung +Die Platine ist so gestaltet das sie individuell bestückt werden kann, je nach Verwendung ![Platine bestückt](img/Winden_Telemetry_PCB.png) @@ -81,21 +81,24 @@ flowchart TD A(["Start"]) A --> B{"ist Senden an?"} B --> | Ja | C{"Sende Timer <90 sec"} - B --> | Nein | E{"low speed timer <90 sec"} + I --> | Nein | E{"is airborn?"} - C --> | Nein | F["Sende Schleppen komplett"] -->G["Starte Low Speed Timer"] + C --> | Nein | F["Sende Schleppen komplett"] -->G["is airborn=true"] -->L["Lowspeedtimer = 0"] C --> | Ja | D["Sende Speed"] D --> Z["Warte 1 Sekunde"] - G ----> H["Senden aus"] -->Z + L ----> H["Senden aus"] -->Z Z --> B - E --> | nein | I{"Speed < 30 km/h"} - I --> | nein |J["Senden an"] --> D - I --> | ja|Z - E --> | ja|Z + 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 ``` \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e999933..30dab7d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,18 +9,19 @@ #ifdef DEVICE_SAILPLANE #include -JsonDocument sailplane_data; +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 SX1262 radio = new Module(LORA_NSS, LORA_DIO1, LORA_NRST, LORA_BUSY); - #ifdef DEVICE_WINDE 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) ICACHE_RAM_ATTR #endif @@ -35,6 +36,15 @@ void setFlag(void) U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, OLED_RST, OLED_CLK, OLED_DATA); #endif +#ifdef DEVICE_WINDE + +String data_from; +int data_speed = 0; +int data_min = 0; +int data_max = 0; + +#endif + void setup() { /* Serial to display data */ @@ -90,6 +100,22 @@ void setup() u8g2.sendBuffer(); } +String nmea_checksum(String str) +{ + byte cs = 0; + for (unsigned int n = 1; n < str.length(); n++) + { + if (str[n] != '$' || str[n] != '!' || str[n] != '*') + { + cs ^= str[n]; + } + } + + if (cs < 0x10) + return "*0" + String(cs, HEX); + else + return "*" + String(cs, HEX); +} void draw_rssi(int Rssi){ u8g2.drawFrame(102,8,4,3); u8g2.drawFrame(107,6,4,5); @@ -121,53 +147,159 @@ void draw_rssi(int Rssi){ } + +void send_lora(String data) +{ + int state = radio.transmit(data); + if (state == RADIOLIB_ERR_NONE) + { + // the packet was successfully transmitted + Serial.println(F("success!")); + + // print measured data rate + Serial.print(F("[SX1262] Datarate:\t")); + Serial.print(radio.getDataRate()); + Serial.println(F(" bps")); + } + else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) + { + // the supplied packet was longer than 256 bytes + Serial.println(F("too long!")); + } + else if (state == RADIOLIB_ERR_TX_TIMEOUT) + { + // timeout occured while transmitting packet + Serial.println(F("timeout!")); + } + else + { + // some other error occurred + Serial.print(F("failed, code ")); + 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(); - /* 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 (vel_kmh > 30) - { - sailplane_data["from"]= "D-1234"; - sailplane_data["telemetry"]["speed"]=vel_kmh; - sailplane_data["telemetry"]["min"]=70; - sailplane_data["telemetry"]["max"]=150; - String data; - serializeJson(sailplane_data,data); - //String data = String(vel_kmh); - int state = radio.transmit(data); - if (state == RADIOLIB_ERR_NONE) + if (send_data == false) { - // the packet was successfully transmitted - Serial.println(F("success!")); - - // print measured data rate - Serial.print(F("[SX1262] Datarate:\t")); - Serial.print(radio.getDataRate()); - Serial.println(F(" bps")); - } - else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) - { - // the supplied packet was longer than 256 bytes - Serial.println(F("too long!")); - } - else if (state == RADIOLIB_ERR_TX_TIMEOUT) - { - // timeout occured while transmitting packet - Serial.println(F("timeout!")); + 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 { - // some other error occurred - Serial.print(F("failed, code ")); - Serial.println(state); + if (currentMillis - previousMillissendtimer < sendtimer_max) + { + send_speed(vel_kmh); + } + else + { + send_airborn(); + is_airborn = true; + lowspeedtimer = 0; + send_data = false; + } } #ifdef DEBUG @@ -182,7 +314,6 @@ void loop() Serial.print(pres.die_temp_c(), 6); Serial.print("\n"); #endif - delay(1000); } #endif @@ -195,22 +326,10 @@ void loop() // you can read received data as an Arduino String String str; int state = radio.readData(str); - JsonDocument received; - deserializeJson(received,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) - { - String data_from=received["from"]; - int data_speed=received["telemetry"]["speed"]; - int data_min=received["telemetry"]["min"]; - int data_max=received["telemetry"]["max"]; + { + decode_msg(str); // packet was successfully received u8g2.clearBuffer(); u8g2.setFont(u8g2_font_ncenB10_tr);