Help ending while loop more effectively

Hi All, I've literally taught myself to program the Arduino so I'm still relatively new, so apologies if this is a stupid question.

I have this code set up so when my int "val = serial.Read() - '0'" receives a "1" it will go ahead and run my while loop which turns a relay on and off. In Addition to this, I have 3 buttons that will Serial.println 3 different messages when they pushed and also break the while loop. As it stands, this code works as it should except that it is only breaking a loop once it gets to the part of the loop that it reads the button, which means I need to hold the button 1 - 2 seconds until the code recognizes the change in button state. Basically I want to end the loop straight away but I can't seem to figure out a logical way how to do this.

Here is my code. I am using it in conjunction with some python code i stole from somewhere that reads the serial println and posts it to twitter for me whilst reading if I get any mentions, to which the arduino registers and triggers my relay to turn some pretty christmas lights on and off!

int relayPin = 3; int redPin = 8; int greenPin = 7; int switchPinHappy = 12; int switchPinOk = 11; int switchPinNotOk = 10;

void setup() { Serial.begin(9600);

pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT);

pinMode(relayPin, OUTPUT);

pinMode(switchPinOk, INPUT); pinMode(switchPinNotOk, INPUT); pinMode(switchPinHappy, INPUT); }

void loop() { //define val to read serial int val = Serial.read() - '0'; // if val is picked up, let's turn the relay on and off while (val == 1) { digitalWrite(relayPin, HIGH); delay (500); digitalWrite(relayPin, LOW); delay (500); //if the switch is pressed, println and break the while loop. if (digitalRead(switchPinOk) == LOW) { Serial.println("I have acknowledged your tweet and I am OK :|"); break; } //if the switch is pressed, println and break the while loop. if (digitalRead(switchPinNotOk) == LOW) { Serial.println("I have acknowledged your tweet and I not OK :("); break; } //if the switch is pressed, println and break the while loop. if (digitalRead(switchPinHappy) == LOW) { Serial.println("I have acknowledged your tweet and I am Super! :)"); break; } } //run when nothing is happening standByFlash(); }

void standByFlash() { digitalWrite(redPin, HIGH); delay (200); digitalWrite(redPin, LOW); delay (200); digitalWrite(greenPin, HIGH); delay (200); digitalWrite(greenPin, LOW); delay (200); }

Thanks heaps and now that I read the topic, maybe it should be titled "Help James code more effectively!" ^^

James

Correct me if I misunderstood your description but the problem you’re having is that the while(val==1) loop won’t exit unless you hold a button down?

aremotelocation: Correct me if I misunderstood your description but the problem you're having is that the while(val==1) loop won't exit unless you hold a button down?

Correct, that that's what I want it to do and it's doing, albeit not as effectively as I like. I want to be able to press it once and have it run the if statement inside the while statement straight away, without the delay. At the moment, I need to hold one of the three buttons down until it gets to that point in the code for the if statement to be executed.

how long is your delay between if statements? it should be something negligible.

from what you're describing you could try interrupts, however, arduino only provides two. once approach could be to leave one condition in the while loop and set the others as interrupts. yet another thing you could do to speed things up is read the pin values first and then simply compare in the if expression.

interrupts: http://arduino.cc/en/Reference/AttachInterrupt

aremotelocation: how long is your delay between if statements? it should be something negligible.

from what you're describing you could try interrupts, however, arduino only provides two. once approach could be to leave one condition in the while loop and set the others as interrupts. yet another thing you could do to speed things up is read the pin values first and then simply compare in the if expression.

interrupts: http://arduino.cc/en/Reference/AttachInterrupt

You totally broke my puny brain with interrupts! I am reading now the reference for it now.

I know I could speed up the delay so it reads my input pins more quickly but the problem with this is that it will speed up the delay between when my relay switches on and off. Even if I put my if statement up the top of the loop, it still needs to finish the loop before it gets to the point where it reads my input pins. I don't know if there is a way to read the input pins outside of the loop and have it inside the expression of my while loop.

Thanks for the tip on interrupts, i'll give it a read and see if I can make sense of it!

jampola: I don't know if there is a way to read the input pins outside of the loop and have it inside the expression of my while loop.

read here: http://arduino.cc/en/Reference/Scope

You don't need to resort to interrupts to fix the lag in your while loop. The problem is the two delays mean it could take up to a second before you check for button inputs. Take a look at the BlinkWithoutDelay example in the IDE - that approach will let you remove the delays and fix the problem.

dhunt: You don't need to resort to interrupts to fix the lag in your while loop. The problem is the two delays mean it could take up to a second before you check for button inputs. Take a look at the BlinkWithoutDelay example in the IDE - that approach will let you remove the delays and fix the problem.

Mate, I owe you a beer. Perfect and I even understand how it works. Thanks heaps buddy!

James

So this is the code I ended up with. Works perfectly. I might add a for loop to make sure the relay doesn't sit there clicking away for a solid couple of hours and pissing my co-workers off.

/*Tweet Flash

This is paired up with some python code to 
trigger a relay on the arduino to flash some
snazzy christmas lights or anything else you
may want to turn on and off. To change the on/off
delay, change the "long interval" to your desired 
delay in milliseconds.

jamesbos@gmail.com

*/

//this aint gonna change
const int relayPin = 3;

//set out relay state for the relay code
int relayState = HIGH;
long previousMillis = 0;

//relay delay ms
long interval = 500;

//set the ints for everything else
int redPin = 8;
int greenPin = 7;
int switchPinHappy = 12;
int switchPinOk = 11;
int switchPinNotOk = 10;


void setup()
{
  //begin serial
  Serial.begin(9600);
  
  //set out inputs/outputs
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(relayPin, OUTPUT);
  pinMode(switchPinOk, INPUT);
  pinMode(switchPinNotOk, INPUT);
  pinMode(switchPinHappy, INPUT);
  //read 1's and 0's yo!
  int val = Serial.read() - '0';
}

void loop()
{
 //define val to read serial
 int val = Serial.read() - '0';
  // if val is picked up, let's turn the relay on and off 
  while (val == 1)
  {
    relayLoop();
    if (digitalRead(switchPinOk) == LOW)
         { 
           Serial.println("I have acknowledged your tweet and I am OK :|");
           relayState = LOW;
           break; 
         }
       //if the switch is pressed, println and break the while loop.
       if (digitalRead(switchPinNotOk) == LOW)
         {
           Serial.println("I have acknowledged your tweet and I not OK :(");
           relayState = LOW;
           break;
         }
       //if the switch is pressed, println and break the while loop.
       if (digitalRead(switchPinHappy) == LOW)
         {
           Serial.println("I have acknowledged your tweet and I am Super! :)");
           relayState = LOW;
           break;
         }
  }
//run when nothing is happening
standByFlash();
}

void relayLoop() 
{  
 unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (relayState == HIGH)
      relayState = LOW;
    else
      relayState = HIGH;

    // set the LED with the ledState of the variable:
    digitalWrite(relayPin, relayState);
    
  }
}

void standByFlash()
{
  //resets our relayPin to LOW
  digitalWrite(relayPin, LOW);
  //begin flash loop
  digitalWrite(redPin, HIGH);
  delay (200);
  digitalWrite(redPin, LOW);
  delay (200);
  digitalWrite(greenPin, HIGH);
  delay (200);
  digitalWrite(greenPin, LOW);
  delay (200);  
}

I use some python code from pdxnat - http://www.instructables.com/member/pdxnat/ - and adapted it. The code is for her Twitter Mention Mood Light. As it turns out, you don't need to change anything in the python code apart from popping in your twitter OAuth details.

Thanks heaps dhunt, and if that's short for Duck Hunt, you rule my friend! And yes, my avatar is relevant!

Cheers, James

PLease use [ code] [ /code] tags (# button) iso quote button,

robtillaart: PLease use [ code] [ /code] tags (# button) iso quote button,

Changed. Sorry about that, when I "Copy for Forum" in the IDE, it pastes like that!

James

Sorry about that, when I "Copy for Forum" in the IDE, it pastes like that!

No need to apologize, thanks for fixing :)

"Copy to Forum" is a known "feature" of the IDE, I have reported it at - http://code.google.com/p/arduino/issues/detail?id=574