Marco Zonca
Published © GPL3+

Flight ALARM Led Ring + LilyGO T-Echo

Enrich your SoftRF LilyGO T-Echo with a LED Ring + Sound to have in-flight alarms to avoid collisions between aircrafts.

IntermediateFull instructions provided246
Flight ALARM Led Ring + LilyGO T-Echo

Things used in this project

Hardware components

Arduino Nano ESP32
×1

Software apps and online services

Arduino Web Editor
Arduino Web Editor
PCBWay online Services for PCB and 3D Printing (optional)

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

3D printing Back cover

Sketchfab still processing.

3D printing top (LED)

Sketchfab still processing.

3D printing base

Sketchfab still processing.

Schematics

Gerber file for PCB

PCB top layer

PCB bottom layer

PCB top silk

PCB bottom silk

Fritzing schematic diagram

Code

Arduino code (sketch)

Arduino
/*
 * ard-blueTEcho by Marco Zonca 04/2025, make bluetooth connection with LilyGo T-Echo + SoftRF Moshe Braner version MB158
 *   
 * this sketch, with the LED Indicator circuit, connects T-Echo for receiving NMEA collision warnings sentences
 * via bluetooth-LE, evaluates the warning/s level and produces "bip" sounds with a buzzer (3 levels); additionally
 * il shows on 1 of 8 LED the relative direction and on 1 of 5 LEDs the relative altitude of the potential
 * collitioning aircraft; there is also a status LED to show NMEA activity;
 * 
 * Arduino Nano ESP32 MCU with onboard bluetooth-LE module, active buzzer, JST-HX connectors, SOIC-24 version of the
 * 74HC4067 3.3V 16 channel multiplexer, 8+5+1 = 14 x 3mm LEDs, self resettable fuse, 2 x mini switch to on/off,
 * a few other SMD components 1206 size; to program the MCU I used the free on-line Arduino Cloud;
 * 
 * About the LEDs let choose 3mm high efficiency ones producing very good light at low power consumption 
 * around 2-6mA max; I suggest blue color for the direction, red/orange/green for altitude, green for NMEA receiving;
 * I tested at 3.4V on VIN pin: the power consumption is around 150mA during BLE communication and one LED blinking;
 * this suggest to replace the factory (850mA/h) battery with a bigger one as per Li-Ion 3.7V 2100mA/h;
 * 
 * The whole circuit could be cutted into two PCBs because is possible to use only the main part with the MCU and the buzzer1
 * to have only audible warnings without LEDs; in this case you should close (solder) the JP1 jumper near the buzzer1;
 * using whole circuit you will install all components avoiding to install buzzer1 and leaving JP1 open (unsoldered);
 *
 * The switch-A on the top is to give power to the circuit, including T-Echo, the switch-B on the right is to on/off
 * the LED Indicator Circuit only;
 *
 * LED status (without active alarms): all off = circuit off, nmea on = T-Echo connected, nmea 1" blinking = nmea receiving ok,
 * red 5" blinking = searching T-Echo but not found yet (10 tries), red 0.5" blinking = T-Echo not found after 10 tries 
 * (to try searching again do a restart switching off/on);
 *
 * On T-Echo settings you have to activate bluetooth NMEA output, then use a computer or a phone to see his broacasting name
 * that should be something like "SoftRF8605a6-LE" so put his name in the code instead of mine: deviceName[] = "SoftRF8605a6-LE";
 *
 */

#include <ArduinoBLE.h>

const boolean isDebug=false;
unsigned long prevTest=0;
int testFase=0;

const char serUUID[] = "ffe0";
const char charUUID[] = "ffe1";
const char deviceName[] = "SoftRF8605a6-LE";

const byte pinNmea=A2;
const byte pinMux0=A3;
const byte pinMux1=A4;
const byte pinMux3=A5;
const byte pinMux2=A6;
const byte pinBuzzer=A7;

const byte pinIntLEDRed=LED_RED;
const byte pinIntLEDGreen=LED_GREEN;
const byte pinIntLEDBlue=LED_BLUE;

const int inactivityTimeout=10000;
const byte schemaLeds[16]={12,3,2,1,0,10,9,8,7,12,12,15,14,5,6,11};  // 0,9,10=off, 1-8 direction (in 45) clockwise,
                                                                     // 11-15 altitude lowest->low->same->high->highest
boolean isDeviceFound=false;
boolean isConnected=false;
boolean isNmeaComplete=false;
boolean ret = false;
boolean isLedToSwitch=false;
boolean isBeepToSwitch=false;

byte tryConnect=0;
byte exitStatus=0;
String inputString = "";
String inputStringNext = "";
unsigned long prevNmeaUpdate=0;
byte ALARM_beeps=0;
unsigned long ALARM_timeout=0;
unsigned long ALARM_ledtimeout=0;
unsigned long ALARM_beeptimeout=0;
int ALARM_period=0;
int ALARM_ledswitchperiod=0;
int ALARM_beepsperiod=0;
byte schemaAlt=0;
byte schemaDir=0;
int previous_alarm=0;

int nmi_gps=0;
int nmi_alarm=0;
int nmi_relBearing=0;
int nmi_alarmType=0;
int nmi_relVertical=0;
long nml_relHorizontal=0;

BLEDevice peripheral;
BLEService DataService;
BLECharacteristic DataCharacteristic;

void setup() {
  pinMode(pinNmea, OUTPUT);
  pinMode(pinBuzzer, OUTPUT);
  pinMode(pinMux0, OUTPUT);
  pinMode(pinMux1, OUTPUT);
  pinMode(pinMux2, OUTPUT);
  pinMode(pinMux3, OUTPUT);
  pinMode(pinIntLEDRed, OUTPUT);
  pinMode(pinIntLEDGreen, OUTPUT);
  pinMode(pinIntLEDBlue, OUTPUT);
  digitalWrite(pinNmea,LOW);
  digitalWrite(pinBuzzer,LOW);
  digitalWrite(pinMux3,HIGH);  //4 bit mux=12 as starting point (direction and altitude leds off)
  digitalWrite(pinMux2,HIGH);
  digitalWrite(pinMux1,LOW);
  digitalWrite(pinMux0,LOW);
  digitalWrite(pinIntLEDRed,HIGH);  //off
  digitalWrite(pinIntLEDGreen,HIGH);  //off
  digitalWrite(pinIntLEDBlue,HIGH);  //off
  if (isDebug==true) {Serial.begin(9600);}
  if (isDebug==true) {delay(5000);}
  if (!BLE.begin()) {
    dprint("Starting BLE failed! Sketch STOPPED!",true);
    while (1);
  }
  inputString.reserve(129);
  inputStringNext.reserve(129);
  dprint("BLE started",true);
  initialShow();
  dprint("Sketch initialized",true);
  delay(100);
}  //setup()

void loop() {
  if (isDeviceFound==false){  // ------------------------------search device/peripheral and check everything
    if (tryConnect<10) {
      tryConnect++;
      dprint("Searching for peripheral/Device, try nr. ",false);
      if (isDebug==true) {Serial.println(tryConnect);}
      setLed(schemaLeds[13]);  // one time red=on (error & retry)
      delay(200);
      setLed(schemaLeds[0]);  // all off
      deviceConnect();
     }else{
      dprint("Device not available/unknown after 10 tries! Sketch STOPPED!",true);
      while (1){
        setLed(schemaLeds[0]);  // all off
        delay(200);
        setLed(schemaLeds[13]);  // blinking red=on (error & halt)
        delay(200);
      }//while(1)
    }//if(tryConnect<10)
  }//if(isDeviceFound==false)
  
  if (isDeviceFound==true){  // ------------------------------device ok, reading data
    if (prevNmeaUpdate==0) {prevNmeaUpdate=millis();}
    if (DataCharacteristic.valueUpdated()) {
      unsigned char data[129] = {};
      if (inputStringNext.length()!=0) {inputString=inputStringNext; inputStringNext="";}  // retrieve previous remained data after '\n'
      DataCharacteristic.readValue(data, 128);
      for (int i = 0; i < 128; i++) {
        if (data[i] != 0) {
          //if (isDebug==true) {Serial.print(char(data[i]));}
          if (isNmeaComplete==false){
            inputString += char(data[i]);  // collect data until '\n'
            if (char(data[i]) == '\n') {isNmeaComplete=true;}
           }else{
            inputStringNext += char(data[i]);  // collect remaining data after '\n'
          }
         }else{
          break;
        }            
      }//for(int i...
      prevNmeaUpdate=millis();
    }//if(DataChar...)
    if (millis() > (prevNmeaUpdate+inactivityTimeout)){ //-------check inactivity
      dprint("Nmea inactivity timeout.",true);
      tryConnect=0;
      devDisconnect();
    }
  }//if(isDeviceFound==true)

  if (isNmeaComplete==true){  // ----------------------manage nmea sentence
    ret = nmeaExtractData();
    if ((ret==true) && (inputString.substring(0,6)=="$PFLAU")) { 
      dprint("Good   : ",false);
      if (isDebug==true) {Serial.print(inputString);}
      /*
      int nmi_gps=0;  // GPS 0=no GPS fix, 1=3D fix on ground, 2=GPS fix when airborn
      int nmi_alarm=0;  // ALARM level 0=none, 1=15-20" to impact, 2=10-15" to impact, 3=0-10" to impact
      int nmi_relBearing=0;  // RELATIVE BEARING of impact, 0=ahead, 180/-180=behind, -45=left, 45=right, etc.
      int nmi_alarmType=0;  // ALARM type 0=none, 2=aircraft, 3=obstacle/zone, 4=traffic advisory, 10-FF other ignored
      int nmi_relVertical=0;  // relative VERTICAL distance in meters, positive=OVER, negative=BELOW
      long nml_relHorizontal=0;  // relative HORIZONTAL distance in meters
      */

/*      // simulation of alarm
      switch (testFase) {
        case 0:
          nmi_alarm=0;
          nmi_relBearing=0;
          nmi_relVertical=0;
        break;
        case 1:
          nmi_alarm=1;
          nmi_relBearing=-65;
          nmi_relVertical=250;
        break;
        case 2:
          nmi_alarm=2;
          nmi_relBearing=-135;
          nmi_relVertical=120;
        break;
        case 3:
          nmi_alarm=1;
          nmi_relBearing=-65;
          nmi_relVertical=250;
        break;
        case 4:
          nmi_alarm=3;
          nmi_relBearing=0;
          nmi_relVertical=50;
        break;
        case 5:
          nmi_alarm=2;
          nmi_relBearing=50;
          nmi_relVertical=150;
        break;
        case 6:
          nmi_alarm=1;
          nmi_relBearing=150;
          nmi_relVertical=350;
        break;
        case 7:
          nmi_alarm=3;
          nmi_relBearing=150;
          nmi_relVertical=350;
        break;
      }
      if (millis()>prevTest) {
        prevTest=millis()+10000;
        testFase++;
        if (testFase==8) {testFase=0;}
      }      
*/      
      switch (nmi_alarm){  // ALARM level
        case 0:  // 0=none
          ALARM_beeps=0;  // how many beeps (series) for the alarm level
          ALARM_period=0;  // duration+pause between series of beeps
          ALARM_ledswitchperiod=0;  // duration of alternating dir/alt LEDs
          ALARM_beepsperiod=0;  // duration or pause of a beep
          break;
        case 1:  // 1=15-20" to impact
          ALARM_beeps=1;
          ALARM_period=4000;
          ALARM_ledswitchperiod=300;
          ALARM_beepsperiod=300;
          break;
        case 2:  // 2=10-15" to impact
          ALARM_beeps=2;
          ALARM_period=3000;
          ALARM_ledswitchperiod=200;
          ALARM_beepsperiod=200;
          break;
        case 3:  // 3=0-10" to impact
          ALARM_beeps=3;
          ALARM_period=2000;
          ALARM_ledswitchperiod=100;
          ALARM_beepsperiod=100;
          break;
        default:
          break;
      }
      digitalWrite(pinNmea,!digitalRead(pinNmea));  // blink nmea led
      if ((millis() < ALARM_timeout) && ( nmi_alarm <= previous_alarm)) {  // no more beeps if no timeout and same or less alarm
        ALARM_beeps=0;
      }
      if ((nmi_alarm <= previous_alarm) && (nmi_alarm!=0) && (millis() > ALARM_timeout)) {  // renew timeout
        ALARM_timeout=millis()+ALARM_period;
      }
      if ((nmi_alarm > previous_alarm) || (nmi_alarm==0)) {
        ALARM_timeout=millis()+ALARM_period;
        ALARM_ledtimeout=millis()+ALARM_ledswitchperiod;
        ALARM_beeptimeout=millis()+ALARM_beepsperiod;
        goLeds();
        goBeeps();
      }
      previous_alarm=nmi_alarm;
     }else{
      dprint("Discard: ",false);
      if (isDebug==true) {Serial.print(inputString);}
    }
    inputString="";
    isNmeaComplete=false;
  }
  // ----------------------------------ALARM MANAGER between NMEA sentences
  if ((nmi_alarm > 0) && (millis() > ALARM_ledtimeout)){  // if led timeout
    ALARM_ledtimeout=millis()+ALARM_ledswitchperiod;  // renew timeout
    goLeds();
  }
  if ((nmi_alarm > 0) && (millis() > ALARM_beeptimeout)){  // if beep timeout
    ALARM_beeptimeout=millis()+ALARM_beepsperiod;  // renew timeout
    goBeeps();
  }
  // ----------------------------------
}//loop()


void goLeds() {
  if (nmi_relVertical > 300){  // set altitude leds
    schemaAlt=15;
  }
  if ((nmi_relVertical >= 151) && (nmi_relVertical <= 300)){
    schemaAlt=14;
  }
  if ((nmi_relVertical >= -150) && (nmi_relVertical <= 150)){
    schemaAlt=13;
  }
  if ((nmi_relVertical <= -151) && (nmi_relVertical >= -300)){
    schemaAlt=12;
  }
  if (nmi_relVertical < -300){
    schemaAlt=11;
  }

  if ((nmi_relBearing >= 22.5) && (nmi_relBearing < 67.5)){  // set direction leds
    schemaDir=1;
  }
  if ((nmi_relBearing >= 67.5) && (nmi_relBearing < 112.5)){
    schemaDir=2;
  }
  if ((nmi_relBearing >= 112.5) && (nmi_relBearing < 157.5)){
    schemaDir=3;
  }
  if ((nmi_relBearing >= 157.5) || (nmi_relBearing <= -157.5)){
    schemaDir=4;
  }
  if ((nmi_relBearing > -157.5) && (nmi_relBearing <= -112.5)){
    schemaDir=5;
  }
  if ((nmi_relBearing > -112.5) && (nmi_relBearing <= -67.5)){
    schemaDir=6;
  }
  if ((nmi_relBearing > -67.5) && (nmi_relBearing <= -22.5)){
    schemaDir=7;
  }
  if ((nmi_relBearing > -22.5) && (nmi_relBearing < 22.5)){
    schemaDir=8;
  }

  if (nmi_alarm == 0){
    setLed(schemaLeds[0]);  //off
    isLedToSwitch=false;
  }
  if (nmi_alarm >= 1){
    if (isLedToSwitch == false){
      setLed(schemaLeds[schemaDir]);  //direction
     }else{
      setLed(schemaLeds[schemaAlt]);  //altitude
    }
  }
  isLedToSwitch = !isLedToSwitch;  // alternating
}//goLeds()


void goBeeps() {
  if (nmi_alarm == 0){
    isBeepToSwitch=false;
    digitalWrite(pinBuzzer,LOW);
  }
  if ((nmi_alarm > 0) && (ALARM_beeps > 0)){
    if (isBeepToSwitch == false){
      digitalWrite(pinBuzzer,HIGH);  //play
     }else{
      ALARM_beeps--;
      digitalWrite(pinBuzzer,LOW);  //silent
    }
    isBeepToSwitch = !isBeepToSwitch;  // alternating
  }
}//goBeeps()

void deviceConnect() {
  exitStatus=0;
  BLE.scanForName(deviceName);  // ------------scan device/peripheral
  delay(5000);
  peripheral = BLE.available();
  while (exitStatus==0){
    if (peripheral) {  // ----------------------------use device/peripheral
      isDeviceFound=true;
      dprint("Found",true);
      dprint("Device Address: ",false);
      if (isDebug==true) {Serial.println(peripheral.address());}
      dprint("Device RSSI: ",false);
      if (isDebug==true) {Serial.println(peripheral.rssi());}
      dprint("Connecting...",true);
      if (peripheral.connect()) {  // ----------------------------connect
        isConnected=true;
        digitalWrite(pinNmea,HIGH);
        dprint("Connected.",true);
        dprint("Discovering attributes...",true);
        if (peripheral.discoverAttributes()==0) {  // ------------check attributes
          dprint("Done",true);
          int serviceCount = peripheral.serviceCount();  // -------------count services
          dprint("Services discovered nr = ",false);
          if (isDebug==true) {Serial.println(serviceCount);}          
          dprint("Verifying service: ",false);
          if (isDebug==true) {Serial.println(serUUID);}
          if (peripheral.hasService(serUUID)) {  // ----------------check needed service
            DataService = peripheral.service(serUUID);            
            if (DataService) {  // ----------------------------------- use service, count characteristics
              dprint("Service is available",true);              
              int characteristicCount = DataService.characteristicCount();
              dprint("Characteristics discovered nr = ",false);
              if (isDebug==true) {Serial.println(characteristicCount);}
              dprint("Verifying Characteristic ",false);  // ---------------------check needed characteristic
              if (isDebug==true) {Serial.println(charUUID);}
              if (DataService.hasCharacteristic(charUUID)) {                
                DataCharacteristic = DataService.characteristic(charUUID);
                if (DataCharacteristic) {  // -------------------------use characteristic, check read & cansubscribe
                  dprint("Characteristic is available, properties mask is: ",false);
                  if (isDebug==true) {Serial.println(DataCharacteristic.properties(),BIN);}
                  dprint("(as bit masked: Broadcast|Read|WriteWithoutResponse|Write|Notify|Indicate)",true);
                  if (DataCharacteristic.canRead()) {dprint("Characteristic is readable",true);}
                  if (DataCharacteristic.canSubscribe()) {dprint("Characteristic can be subscribed",true);}  
                  if (DataCharacteristic.subscribe()==true) {  // ------------subscribe to data changing notification
                    dprint("Subscribed.",true);
                    dprint("Ready for data changing notifications...",true);
                    exitStatus=99;  // ok
                    break;
                   } else {
                    dprint("Subscribtion to data changing notifications FAILED!.",true);
                    exitStatus=8;
                    break;
                  }//if(DataCharacteristic.subscribe()      
                 } else {
                  dprint("Specified characteristic NOT AVAILABLE!",true);
                  exitStatus=7;
                  break;
                }//if(DataCharacteristic)                
               }else{
                dprint("Device/Peripheral DOES NOT HAVE needed characteristic!",true);
                exitStatus=6;
                break;
              }//if(Dataservice.has.characteristic...)    
             } else {
              dprint("Device/Peripheral service NOT AVAILABLE!",true);
              exitStatus=5;
              break;
            }//if(DataService)
           }else{
            dprint("Device/Peripheral DOES NOT HAVE the necessary service!",true);
            exitStatus=4;
            break;
          }//if(peripheral.has.service...    
         }else{
          dprint("Attributes discovering failed, try again.",true);
          exitStatus=3;
          break;
        }//if(peripheral.discoverAttributes()
       }else{
        dprint("Peripheral/Device does NOT WANT TO CONNECT, try again.",true);
        exitStatus=2;
        break;
      }//if(peripheral.connect()
     }else{
      dprint("Peripheral/Device NOT FOUND, try again.",true);
      exitStatus=1;
      break;
    }//if(peripheral)
  }//while(exitStatus==0)
  
  if (exitStatus!=99) {  //============ exit with error
    devDisconnect();
  }//if(exitStatus!=99)
  
  if (exitStatus==99) {  //============ exit ok
    isDeviceFound=true;
  }
}//deviceConnect()

void devDisconnect(){
  if (isConnected==true) {peripheral.disconnect();dprint("Disconnected",true);} 
  digitalWrite(pinNmea,LOW);
  setLed(schemaLeds[0]);
  isLedToSwitch=false;
  prevNmeaUpdate=0;
  isConnected=false;
  isDeviceFound=false;
  delay(2000);
}//devDisconnect()

void dprint(const char dtext[], boolean dnewline){
  if (isDebug==true && dnewline==true) {Serial.println(dtext);}
  if (isDebug==true && dnewline==false) {Serial.print(dtext);}
}//dprint()

void initialShow(){  // leds show
  digitalWrite(pinBuzzer,HIGH);
  for (int L=1;L<=8;L++){
    setLed(schemaLeds[L]);
    delay(200);
  }
  for (int L=11;L<=15;L++){
    setLed(schemaLeds[L]);
    delay(200);
  }
  setLed(schemaLeds[0]);
  digitalWrite(pinNmea,HIGH);  
  delay(250);
  digitalWrite(pinNmea,LOW);
  delay(250);
  digitalWrite(pinNmea,HIGH);  
  delay(250);
  digitalWrite(pinNmea,LOW);
  digitalWrite(pinBuzzer,LOW);
  delay(1000);
}//initialShow()

void setLed (byte led){
  byte L=led;
  if (L>=8) {L=L-8;digitalWrite(pinMux3,HIGH);}else{digitalWrite(pinMux3,LOW);}
  if (L>=4) {L=L-4;digitalWrite(pinMux2,HIGH);}else{digitalWrite(pinMux2,LOW);}
  if (L>=2) {L=L-2;digitalWrite(pinMux1,HIGH);}else{digitalWrite(pinMux1,LOW);}
  if (L>=1) {L=L-1;digitalWrite(pinMux0,HIGH);}else{digitalWrite(pinMux0,LOW);}
}//setLed()

String nmea0183_checksum(String nmea_data) {
    int crc = 0;
    String chSumString = "";
    int i;
    // ignore the first $ sign, checksum in sentence
    for (i = 1; i < (nmea_data.length()-5); i ++) { // remove the - 5 if no "*" + cksum + cr + lf are present
        crc ^= nmea_data[i];
    }
    chSumString = String(crc,HEX);
    if (chSumString.length()==1) {
      chSumString="0"+chSumString.substring(0,1);
    }
    chSumString.toUpperCase();
    return chSumString;
}  // nmea0183_checksum(String nmea_data)

bool nmeaExtractData() {
  int d=0;
  int s=0;
  int y=0;
  int z=0;
  float t=0;
  bool ret = false;  //true if nmea sentence = $PFLAU and valid CHKSUM

  //$PFLAU,<RX>,<TX>,<GPS>,<Power>,<AlarmLevel>,<RelativeBearing>,<AlarmType>,<RelativeVertical>,<RelativeDistance>,<ID>

  if ((inputString.substring(0,6)=="$PFLAU") && (inputString.substring(inputString.length()-4,inputString.length()-2)==nmea0183_checksum(inputString))) {
    y=0;
    for (s = 1; s < 11; s ++) { 
      y=inputString.indexOf(",",y);
      switch (s) {
      case 1: //-----------------------RX n.u.
        z=inputString.indexOf(",",y+1);
        y=z;
        break;
      case 2: //-----------------------TX n.u.
        z=inputString.indexOf(",",y+1);
        y=z;
        break;
      case 3: //-----------------------GPS 0=no GPS fix, 1=3D fix on ground, 2=GPS fix when airborn 
        z=inputString.indexOf(",",y+1);
        if (z>(y+1)) {
          nmi_gps=inputString.substring(y+1,z).toInt();
        }
        y=z;
        break;
      case 4: //-----------------------POWER n.u.
        z=inputString.indexOf(",",y+1);
        y=z;
        break;
      case 5: //-----------------------ALARM level 0=none, 1=15-20" to impact, 2=10-15" to impact, 3=0-10" to impact
        z=inputString.indexOf(",",y+1);
        if (z>(y+1)) {
          nmi_alarm=inputString.substring(y+1,z).toInt();
        }
        y=z;
        break;
      case 6: //-----------------------RELATIVE BEARING of impact, 0=ahead, 180/-180=behind, -45=left, 45=right, etc.
        z=inputString.indexOf(",",y+1);
        if (z>(y+1)) {
          nmi_relBearing=inputString.substring(y+1,z).toInt();
        }
        y=z;
        break;
      case 7:  //-----------------------ALARM type 0=none, 2=aircraft, 3=obstacle/zone, 4=traffic advisory, 10-FF other ignored
        z=inputString.indexOf(",",y+1);
        if (z>(y+1)) {
          nmi_alarmType=inputString.substring(y+1,z).toInt();
        }
        y=z;
        break;
      case 8: //-----------------------relative VERTICAL distance in meters, positive=OVER, negative=BELOW
        z=inputString.indexOf(",",y+1);
        if (z>(y+1)) {
          nmi_relVertical=inputString.substring(y+1,z).toInt();
        }
        y=z;
        break;
      case 9: //-----------------------relative HORIZONTAL distance in meters
        z=inputString.indexOf(",",y+1);
        if (z>(y+1)) {
          nml_relHorizontal=inputString.substring(y+1,z).toInt();
        }
        y=z;
        break;
      case 10: //-----------------------ID n.u.
        break;
      default:
        break;
      }
    }
    ret=true;
  }//if"$PFLAU"
  return ret;
}//bool nmeaExtractData()

Credits

Marco Zonca
19 projects • 52 followers
"From an early age I learned to not use pointers"

Comments