Go Down

Topic: Blink With Out Delay (Read 681 times) previous topic - next topic

Arrch

Code: [Select]
if (val != buttonState)
{
  if (val == LOW)
  {
    if (mode == 0)
    {
      mode = 1;
      interval = 100;
    }   
  }
  else
  {
    interval = 3000;
  } 
}


After fixing your cod indenting, it should become evident that your else is incorrect. What you are saying here is "when the switch goes from HIGH to LOW set mode to 1 and interval to 100. When the switch goes from LOW to HIGH, set the interval to 3000. Your else should probably be nested within the signal edge detection if statement.

westfw

In the interest of introducing some "best (well, better) practices", try breaking your problem down into smaller parts that are more easily understood:
Code: [Select]
void loop() {
   read_button_and_adjust_time();
   maybe_flash_led();
}

OK so far, right?  That was pretty trivial.  But we've already made things easier; the led timing and the button timing will no longer be "mixed up."
The maybe_flash_led() comes pretty straight from blink_without_delay(), except it has code for "off"
Code: [Select]
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated
long interval = 1000;           // interval at which to blink (milliseconds)
void maybe_flash_led() {
  unsigned long currentMillis = millis();
  if (interval == 0) {  // turn off?
    if (ledState == HIGH) {
       ledState = LOW;
       digitalWrite(ledPin, ledState);
    }
    return;  // don't do the rest
  }
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;   
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    digitalWrite(ledPin, ledState);
  }
}

(most of that was copy&paste from the blinkwithoutDelay sketch.  No delay() calls at all)  Now you have to write the button code.  Debouncing without delays might be a bit tricky, so ... let's just defer that for now.
Code: [Select]

void read_button_and_adjust_time() {
  if (read_button_w_debounce()) {
     // The button had been pressed.  Adjust our time interval.  1000ms, 100ms, off.
     if (interval == 1000) {
       interval = 100;
     } else if (interval == 100) {
       interval = 0;   // off
     } else if (interval == 0) {
       interval = 1000;
     } else {
       // just to be safe, make any unknown interval go to 1000ms
     }
  }
}

That was straightforward as well, right?  The trick is to make each little piece of the program be easy to understand.  Reasonably easy, anyway.  Now we have reading the button itself.  the way the code has been arranged so far, we only want the function to return TRUE when the button changes state, not continually when it is IN a particular state.  Now, WHICH state transition you want to sense is up to you.  You have UP, debouncing on the way down, DOWN,  and debouncing on the way up again.  You can act at either the start or the end of the debounce time, as long as you only act once!
Code: [Select]
#define BUT_UP 0
#define BUT_DBOUNCE 1
#define BUT_DOWN 2
#define BUT_UBOUNCE 3
char button_state = BUT_UP;
boolean read_button_w_debounce() {
  static unsigned long changetime;  // when the last state change occurred.
  boolean pin_state = digitalRead(buttonpin);  // (pin state of 0 means pressed)
  if (button_state == BUT_UP) {
     // Button was not pressed.  See if it's pressed now
     if (pin_state == LOW) {  // Pressed?
       button_state = BUT_DBOUNCE;  // now we're debouncing the press
       changetime = millis();
     }
  } else if (button_state == BUT_DBOUNCE) {
    // Button is being pressed but might be bouncing.
    if (pin_state == LOW  && (millis() > (changetime + 10))) {
      pin_state = BUT_DOWN;
      return true;  //  this is what counts as a button press!
    } else if (pin_state == HIGH) { // it looks like the pin is bouncing
      changetime = millis(); // so extend our debounce time.
    }
  } else if (button_state == BUT_DOWN) {
    // Button is held down, and has been.  Check for release.
    if (pin_state == HIGH) { // Released?
      button_state = BUT_UBOUNCE;
      changetime = millis();
    }
  } else if (button_state == BUT_UBOUNCE) {
     // exercise for the reader :-)
  }
  return false;  //any state or transition that hasn't returned true, returns false
}

This is an example of what's known as "top down" program design; you start with your big problem, and break it apart into smaller pieces until each piece is "easy."  The other common technique is "bottom up" design, where you start with pieces that are easy enough to write, and combine them to make bigger programs.

kculm

With Help, This is what I ended up with.

Thanks for all the help.

Code: [Select]
const int ledPin =  1;      // the number of the LED pin
int switchPin = 3;          // number of switch Pin

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


long interval = 0;         
int val;
int val2;
int buttonState;
int mode = 0;


void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
  pinMode(switchPin, INPUT);
  digitalWrite(switchPin, HIGH);
  //Serial.begin(9600);

  buttonState = digitalRead(switchPin);
}

void loop(){
  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds
  val2 = digitalRead(switchPin);

  if (val == val2){
    if (val != buttonState){
      if (val == LOW){

        if (mode == 0){
          interval = 1000;
          mode = 1;
        }
        else if (mode == 1){
          interval = 500;
          mode = 2;
        }
        else if (mode == 2){
          mode = 0;
        }
      }
      buttonState = val;
    }
  }

  // Serial.println(interval);
  unsigned long currentMillis = millis();
  if (mode == 1 || mode == 2){
    if(currentMillis - previousMillis > interval) {
      // save the last time you blinked the LED
     // Serial.println(mode);
      previousMillis = currentMillis; 

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

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


Go Up