Nav LED loop

Hey my fellow Arduino gurus,

New guy here! :slight_smile:

So it has been forever and a day since I have messed with any programming. Honestly I have forgotten most of it 'cause I haven't used it in so long. Any who.. Below is my code that I am currently working on. This code is for my Arduino Plane that I am slowly putting together. The Idea behind this project is to fly a plane that is controlled via my pc. Like a UAV of sorts. Anyways Its in the early Alpha stages of the build and I am only working on the Nav lights and how they react that this point. So What I am trying to do is loop the Nav light code until another command is received. I am sure there is a much better way to do what I am trying to do and I am open to suggestions. But for now this is what I have.

/*
Airplane Navigation Lights Testing
*/

int incomingByte;

void setup() {
pinMode(13, OUTPUT); // Nav Red and Green
pinMode(12, OUTPUT); // Nav Strobe
pinMode(8, OUTPUT); // Top Beacon
pinMode(7, OUTPUT); // Bottom Beacon
Serial.begin(9600);
}

void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
if (incomingByte == 'l') { // Needs to loop until another serial command is received
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
delay(100);
digitalWrite(8, LOW);
delay(100);
digitalWrite(12, LOW);
delay(100);
digitalWrite(12, HIGH);
delay(100);
digitalWrite(12, LOW);
delay(1000);
digitalWrite(8, HIGH);
delay(150);
digitalWrite(8, LOW);
delay(150) ;
digitalWrite(7, HIGH);
delay(150);
digitalWrite(7, LOW) ;
delay(150);
} // End of landing Nav
else if (incomingByte == 't') { //Turns Lights On for Testing
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
}
else if (incomingByte == 'g') { //Turns Lights Off
digitalWrite(13, LOW);
digitalWrite(12, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);

}}}

Thanks in advance!!!!

Hi there, and welcome to the forum, well first of all, sometimes the simpler the better, if it works it works, and often it may be a bit more robust and easier to debug, but just a couple of notes, using a delay() will stop your entire program for the specified time, so if you are relaying on something else to work, I would avoid it, but its fine.

What I would suggest to you is to check out the millis() function, this will log the time since start up. so for example if your arduino has been powered to 2 seconds it will return 2000 to you.

Using this, you can log the time of each command and then base your switching on the elapsed time, sorry if its a little confusing, check out blink without delay as well.

if you are secuencing lights then you could use a for loop or something, reduces the amount of code a bit!

Sounds like a cool project, keep us posted of your progress.

Thanks for the reply. Whenever I send the l command it does the command once and wont loop that one command until the next is received. In the mean time I will take a look at the blink without delay and for loops.

I have some ‘general’ suggestions. For readability create constants to represent your lights like so:

const int LightNavRG = 13;
const int LightNavstrobe = 12;
const int LightTopBeacon = 8;
const int LightBottomBeacon = 7;

int incomingByte;

void setup() {                
  pinMode(LightNavRG        , OUTPUT);  // Nav Red and Green 
  pinMode(LightNavstrobe    , OUTPUT);  // Nav Strobe
  pinMode(LightTopBeacon    , OUTPUT);   // Top Beacon
  pinMode(LightBottomBeacon , OUTPUT);   // Bottom Beacon
  Serial.begin(9600);
}
....

I would also put your blinking code into various functions.

For now the code is fine but technobabologist is correct that the delay function does stop everything.

Also in the two cases where you want to turn your lights all on or all off… there is an advanced feature that allows you write to the port registers directly which makes that particular part of the code much faster. I would only use it if you really needed to tighten up your code. You can find information about it here: http://www.arduino.cc/en/Reference/PortManipulation

For an example how to blink without using the main loop at all have a look at my POV experiment: Persistence of Vision | Blinkenlight. It leaves the main loop completely empty thus you can do whatever you want while still blinking. You only have to take care that the interrupt function returns in less than one millisecond, otherwise it will surely lock up the processor.

Awesome! Thanks so much for the replies. I am in the process of creating functions as we speak. I just have to remember how to call them. A quick look in my C++ book should help. I'll keep everyone posted on my project. Thanks for the help thus far.

So did I write something wrong here? if I hit "t" it should run that function yes? Am I calling the function correctly? A few of the notes are irrelevant at this point just because I cant the the taxi function to work..

/* Airplane Nav Lights
* 
* This is the Lighting Process for an Arduino + PC controlled 
* Airplane. 

*/
void taxi ();
int WingLeds = 13; // Wing  LEDs
int NavLeds = 12; //Nav LEDs
int TBL = 8; // Top Beacon LED
int BBL = 7; // Bottom Beacon LED
int incomingByte; //Serial command for LEDs

void setup() {
  Serial.begin(9600);
  pinMode(WingLeds, OUTPUT);
  pinMode(NavLeds, OUTPUT);
  pinMode(TBL, OUTPUT);
  pinMode(BBL, OUTPUT);
  
}


  
/* Wing LEDs on, Nav LEDs two quick blinks long off
Top Beacon Blink then Bottom Beacon Blink during long off */

void taxi()
{  
 while(1)
  digitalWrite(WingLeds, HIGH); // just testing to see if the function works
   
}

void loop(){
    Serial.available();
    incomingByte = Serial.read();
    if (incomingByte == 't') {
       void taxi ();
}
}
    if (incomingByte == 't') {
       void taxi ();

Remove the 'void' from here. The compiler will think you are creating a local function prototype, rather that calling the function.

    Serial.available();

Serial.available() returns a value. The reason for calling the function is because you want to know that number. If you don't use that number, you've wasted time and effort asking for that number.

    incomingByte = Serial.read();

You are STILL reading a value that may not be available to read.

       void taxi ();

As was already pointed out, this is not how to call the function.

 while(1)
  digitalWrite(WingLeds, HIGH); // just testing to see if the function works

Once turned on, a pin stays on. There is no reason to turn it on over and over in a loop.

Why there is an infinite loop here is a mystery. This function will never end, and the Arduino will never do another thing (until it is reset).

Apparently, once you turn the taxi lights on, the flight is over. Good thing real airplanes don't work that way.

ok now I need each condition to loop until the next one is received is there an easy way to do this? It was suggested before that I should use functions and no delay. So that's what I am working on now.

Thanks again for any help that is given.

/* Airplane Nav Lights
* 
* This is the Lighting Process for an Arduino + PC controlled 
* Airplane. 

*/
// constants that wont change
const int WingLeds = 13; // Wing  LEDs
const int NavLeds = 12; //Nav LEDs
const int TBL = 8; // Top Beacon LED
const int BBL = 7; // Bottom Beacon LED

int incomingByte; //Serial command for LEDs

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated
long interval = 500; 

void setup() {
  pinMode(WingLeds, OUTPUT);
  pinMode(NavLeds, OUTPUT);
  pinMode(TBL, OUTPUT);
  pinMode(BBL, OUTPUT);
  Serial.begin(9600);
}


  
/* Wing LEDs on, Nav LEDs two quick blinks long off
Top Beacon Blink then Bottom Beacon Blink during long blink*/

void taxi(){
  unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > interval) {
     previousMillis = currentMillis;
     if (ledState == LOW)
      ledState = HIGH;
    else if(ledState = HIGH)
      ledState = LOW;
    digitalWrite(NavLeds, ledState);
    digitalWrite(WingLeds, HIGH);
  }
}

void flying () {
  //Flying Lights will be here
  Serial.println ("Flying lights are running"); //just to see if we are in the function 
}

void landing () {
  //Landing Lights will be here
  Serial.println ("Landing lights are running"); //just to see if we are in the function 
}

void emergency () {
  //If batteries are low this state will come on
  //or if "e" is pressed
  Serial.println ("Emergency lights are running"); //just to see if we are in the function 
}
void loop(){
  if(Serial.available() > 0) {
    incomingByte = Serial.read();
    if(incomingByte == 't') {
       taxi ();
    if(incomingByte == 'f') {
       flying ();
    if(incomingByte == 'l') {
       landing ();
    if(incomingByte == 'e') {
       emergency();
    }}}}
  }
}

ok now I need each condition to loop

I recognize each of these words. The order that they are presented in, however, conveys no meaning at all. Please try again.

I can't see that you need any looping at all. Turning landing lights on should turn any other lights off. The landing lights should stay on until told to turn off. That is the normal way that pins work, so you need do nothing to alter business as usual.

Sorry bad wording on my part. I need each function to loop when called and continue to loop until another command is received. The very first code I posted (the one with all the delays) is what I am currently trying to replicate using blink without delay so the lights need to blink while in that function and continue to do so. On any airplane you have the left and right wing lights (red and green) Navigation Strobes (white) and Red Beacon lights Top and Bottom on the main fuselage and landing gear lights. Those lights are what I am trying to replicate. If you watch the first few mins of this video it gives you an idea of my goal. Jets landing at Kennedy Airport (KJFK) runway 13L - YouTube

Thanks!

You need to separate the processing of serial input from your function calls. Have the switch statement that checks the serial char set a state variable to indicate what lights you currently want. Have another switch statement in loop that uses the state variable to decide which function to call. Then, on every iteration of loop, the appropriate aircraft lights will be operated on.

Thank for your reply. I'm not sure what you mean. would you mind giving me an example? I'm going to do some research on what you said...

Thanks for everyone that has helped me so far.

@wildbill

are you thinking something like this?

int a = 10;
int b = 10;
int c = 20;

switch ( a ) {
case b:
  // Code
  break;
case c:
  // Code
  break;
default:
  // Code
  break;
}

That will not work with variables like b and c.
Case must be constant.

AWOL:
That will not work with variables like b and c.
Case must be constant.

Which I understand I am just trying to get a gist of what he is talking about. :smiley:

Yes.

void loop()
{
if(Serial.available() > 0) 
  {
  incomingByte = Serial.read();
  }
  
switch(incomingByte)
  {
  case 't':
    taxi ();
    break;
  case 'f':  
    flying ();
    break;
  case 'l':  
    landing ();
    break;
  case 'e':  
    emergency();
    break;
  default:
    Serial.println ("Unknown state");
    delay(1000); // Don't spam the serial port
    break;
  }
}

You might want to set incomingByte to 't' in setup, so it doesn't spit unknown state messages at you. Also, I'm assuming that you want to call the selected routine repeatedly to let the responsible routine implement the flashing.

@wildbill

Thanks that is was I was looking for. Now to get all the led codes wrote. I'm sure that I will have more questions.

Thanks again for all the help thus far!!

James

Here is another problem. So What I am trying to implement now is in void taxi I need to run the first for statement 4 times, this flashes my lights on off on off quick, then I need to do a pause for say 1 second. I need to do this without delays. In my code my leds stay on and don’t run thru the for loops. Also since my leds are stuck on I am unable to send a command to the arduino.

Thanks

/* Airplane Nav Lights

This is the lighting process for an Arduino + PC controlled Airplane

*/

// Constants that wont change :
const int WingLeds = 13; //Wing LEDs
const int NavLeds = 12;  //Navigation LEDs
const int TBL = 8;       //Top Beacon LED
const int BBL = 7;       //Bottom Beacon LED
// Variables will change :
int ledState = LOW;
long OldMillis = 0;
long intA = 2000;
long intB = 1000;
long intC = 100;
long intZ = 5000;
//int varA = 0;
//Serial Commands:
int incomingByte;

//Setup
void setup () {
  pinMode (WingLeds, OUTPUT);
  pinMode (NavLeds, OUTPUT);
  pinMode (TBL, OUTPUT);
  pinMode (BBL, OUTPUT);
  Serial.begin(9600);
}

//Taxi Lights

void taxi() {
  unsigned long NowMillis = millis();
  
for(int varA = 0; varA <= 4; varA++) { //do this four times
    if(NowMillis -OldMillis > intC) { 
      OldMillis = NowMillis;          
      if (ledState == LOW)
        ledState = HIGH;
     else if (ledState == HIGH)
      ledState = LOW;
  digitalWrite(NavLeds, ledState);
  digitalWrite(WingLeds, HIGH);
  varA++;
  }}
 for (int varA = 5; varA >= 5; varA++) {// @ 5 do this once
    if(NowMillis - OldMillis > intA){
      OldMillis = NowMillis;
      if (ledState == LOW)
        ledState = LOW;
      else(ledState == HIGH);
        ledState = LOW;
    digitalWrite(NavLeds, ledState);
    digitalWrite(WingLeds, HIGH);
    int varA = 0; 
  }
//Serial.println("Looping Taxi"); debugging
  }}
  
void flying () {
  //Flying lights will be here
  Serial.println ("Looping Flying");
}

void landing () {
  //Landing Lights will be here
  Serial.println ("Looping Landing");
}

void emergency () {
  //If batteries are low this state will come on
  //or if "e" is pressed 
  Serial.println ("Looping Emergency");
}
void test () {
  digitalWrite(WingLeds, HIGH);
  digitalWrite(NavLeds, HIGH);
}

void quit () {
  digitalWrite(WingLeds, LOW);
  digitalWrite(NavLeds, LOW);
  digitalWrite(TBL, LOW);
  digitalWrite(BBL, LOW);
}
void loop () {
  if(Serial.available() > 0)
  {
   incomingByte = Serial.read();
  }
  
  switch(incomingByte)
  {
    case 't':
      taxi ();
      break;
    case 'f':
      flying ();
      break;
    case 'l':
      landing ();
      break;
    case 'e':
      emergency ();
      break;
    case '`':
       test ();
       break;
     case 'q':
       quit ();
       break;
    default:
      Serial.println ("Airplane ready");
      Serial.println ("Waiting for input");
      delay(intB);
      break;
  }
}