Simple coding question for painfully new user

Okay, so I've only been doing this stuff (I mean coding and electronics at all) for like 4 days or so, so I'm not too familiar with any of it. I've been wading through the reference and trying different solutions, but I can't get seem to find it.

My goal is to have three momentaries controlling an LED. One turns it on, the other turns it off and the last makes the LED blink. The first two work fine and I can turn it on and off over and over again, but as I have it coded now, when I make the LED blink, nothing can stop it (not pressing either of the other two buttons, nor the same one again). I'd like to make the while loop check the value, but I'm not sure how to do this.

Any help would be great!

int ledPin = 13;

int btnPin1 = 2; int btnPin2 = 3; int btnPin3 = 4;

int val1; int val2; int val3; void setup() { pinMode(btnPin1, INPUT); pinMode(btnPin2, INPUT); pinMode(btnPin3, INPUT); pinMode(ledPin, OUTPUT); }

void loop() { val1 = digitalRead(btnPin1); val2 = digitalRead(btnPin2); val3 = digitalRead(btnPin3); if (val1 == LOW) { digitalWrite(ledPin, HIGH); } if (val2 == LOW) { digitalWrite(ledPin, LOW); } while (val3 == LOW) { digitalWrite(ledPin, HIGH); delay(250); digitalWrite(ledPin, LOW); delay(250); } }

You're not updating the value of val3 inside your while loop so once it gets in that loop it stays there as val3 can never change again. So the simplest solution is to put "[b]val3 = digitalRead(btnPin3);[/b]" inside your while loop. You'll probably notice once you get that working that it's only checking whether button 3 is down once every half a second, so your next challenge will be to rewrite your while loop without using delay().

Andrew

So would checking val3 change the LED when val1 or val2 changed? I'd like it to be able to switch the LED between all three states as often as I'd like.

This should behave as you would like.

int ledPin = 13;

int btnPin1 = 2; int btnPin2 = 3; int btnPin3 = 4;

void setup() { pinMode(btnPin1, INPUT); pinMode(btnPin2, INPUT); pinMode(btnPin3, INPUT); pinMode(ledPin, OUTPUT); }

void loop() { if (digitalRead(btnPin1) == LOW) { digitalWrite(ledPin, HIGH); } if (digitalRead(btnPin2) == LOW) { digitalWrite(ledPin, LOW); } while (digitalRead(btnPin3) == LOW) { digitalWrite(ledPin, HIGH); delay(250); digitalWrite(ledPin, LOW); delay(250); } }

The main difference is that while loop continously checks the condition, and reads the current state. :)

I had it like that initially, but what it now does is flash once when the button is pressed and continuously blink while I hold down the button. I"m trying to make it blink continuously with one press of button 3 until it receives input from one of the other buttons. (Essentially I'm trying to get myself to create a bike light. I wanted to do it with three different buttons first and then figure out how to do it with one button.)

You need a variable that holds what "mode" the light is in, say 0 for off, 1 for on and 2 for blinking. Then button presses change the contents of your mode variable, and each time round the loop you check what the mode is and do stuff to the LED accordingly. You'll definitely want to read up on blinking an LED without using delay (hint - "BlinkWithoutDelay").

Andrew

I'm looking it up right now, thanks!

I looked up BlinkWithoutDelay and got a little help from my father and here's what came up with (it works);

int ledPin = 13;

int btnPin1 = 2; int btnPin2 = 3; int btnPin3 = 4;

int val1; int val2; int val3;

int value = LOW; long previousMillis = 0; long interval = 250;

void setup() { pinMode(btnPin1, INPUT); pinMode(btnPin2, INPUT); pinMode(btnPin3, INPUT); pinMode(ledPin, OUTPUT); }

void loop() { val1 = digitalRead(btnPin1); val2 = digitalRead(btnPin2); val3 = digitalRead(btnPin3); if (val1 == LOW) { digitalWrite(ledPin, LOW); } if (val2 == LOW) { digitalWrite(ledPin, HIGH); } while (val3 == LOW) { int val1 = digitalRead(btnPin1); int val2 = digitalRead(btnPin2); if (val1 == LOW || val2 == LOW) { break; } if (millis() - previousMillis > interval) { previousMillis = millis(); if (value == LOW) value = HIGH; else value = LOW; digitalWrite(ledPin, value); } } }

My next goal is to get the led to cycle through all three states with just one button.

Well, that's not quite what I was thinking of but well done for getting it working. I had in mind something like this (this isn't necessarily actual working code, just a rough outline):

int MODE_OFF=0;
int MODE_ON=1;
int MODE_BLINKING=2;
int value = LOW;
long previousMillis = 0;
long interval = 250;
int mode;

setup() {
  mode=MODE_OFF;
}

loop() {
 val1 = digitalRead(btnPin1);
 val2 = digitalRead(btnPin2);
 val3 = digitalRead(btnPin3);
 if (val1 == LOW) {
   mode = MODE_OFF;
 }
 else if (val2 == LOW) {
   mode = MODE_ON;
 }
 else if (val3 == LOW) {
   mode = MODE_BLINKING;
 }

 switch (mode) {
   case MODE_OFF:
     digitalWrite(ledPin, LOW);
     break;

   case MODE_ON:
     digitalWrite(ledPin, HIGH);
     break;

   case MODE_BLINKING:
     if (millis() - previousMillis > interval) {
       previousMillis = millis();
       if (value == LOW)
         value = HIGH;
       else
         value = LOW;
       digitalWrite(ledPin, value);
     }
 }

}

then you can convert it to use just one button easily. Each time the button is pushed, set "mode" to the next value, wrapping around from blinking to off. You'll probably then need to use debouncing on your switch or it could advance several modes on each push; see http://arduino.cc/en/Tutorial/Debounce for an introduction and here http://www.arduino.cc/playground/Main/InterfacingWithHardware#Switches for some more advanced stuff to help you debounce switches.

Finally the code as above is a bit inelegant - each time around the loop it does a digitalWrite to the pin even if the mode hasn't changed e.g. it's still OFF or still ON. You could modify it to only do the digitalWrite if the mode has changed from off to on or vice versa, but elegance and efficiency come after getting something working.

Andrew

My next goal is to get the led to cycle through all three states with just one button.

Here is a solution for you:

//TimedAction.zip
#include <TimedAction.h>
//Button.zip
#include <Button.h>
//FSM_beta.zip
#include <FiniteStateMachine.h>
//LED.zip
#include <LED.h>

//initialize buttons
Button button1 = Button(12,PULLUP);

//initialize the LED
LED led = LED(13);

//initialize a protothread that blinks the led
TimedAction blinker = TimedAction(250,toggleLed);

//initialize states
State onState = State(on);
State offState = State(off);
State blinkState = State(blink);

//initialize state machine
FSM ledStateMachine = FSM(onState);

//a current state counter
byte currentState = 0;
byte previousState = 0;

void setup(){ /nothing to setup/ }

void loop(){
if ( button1.isPressed() ){
previousState = currentState;
currentState = currentState+1%3;
}

if (currentState!=previousState){
//set state
switch (currentState){
case 0: ledStateMachine.transitionTo(onState); break;
case 1: ledStateMachine.transitionTo(offState); break;
case 2: ledStateMachine.transitionTo(blinkState); break;
}
previousState = currentState;
}

ledStateMachine.update();
}

//utility functions
void on(){ led.on(); }
void off(){ led.off(); }
void blink(){ blinker.check(); }
void toggleLed(){ led.toggle(); }