Go Down

Topic: blink a led with push button (Read 11053 times) previous topic - next topic

Paul__B

#30
Jun 25, 2015, 02:22 pm Last Edit: Jun 25, 2015, 02:22 pm by Paul__B
OK, here we go:

How many buttons?  Duplicate "button1" to "button2", 3, etc.  Insert the correct pin numbers to service those buttons.

Also duplicate "bstate1" and "bcount1" in exactly the same fashion.

Do you want them to control flashing LEDs or constant LEDs?  For each one that needs to flash, it needs its own copy of "doflash" so "doflash2" etc - the numbers should mirror the button number you wish to have this functionality, not merely sequentially, so all numbers match up.  If button2 does not control a flash but button3 does, then you have "doflash3" but not "doflash2".

Each LED still has a matching "led1pin", also "count1", "count2" and so on and a "led1state", "led2state".  But these numbers match the LEDs, not the buttons.

Now duplicate this section of code:
Code: [Select]
// Toggle switch if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) if (toggle(&doflash) == LOW) {   
    // Turn off LEDs only as and when doflash is switched off
    led1State = LOW;
    led2State = LOW;
    led3State = LOW;
    digitalWrite(led1Pin, led1State);
    digitalWrite(led2Pin, led2State);
    digitalWrite(led3Pin, led3State);
  };

 for each button that needs to control flashing LEDs.

Note that it has two functions, to toggle the flashing mode, and if that toggle ends up LOW, to turn off the LEDs that correspond to that button.

If that button only turned a LED  ON or OFF, it would be:
Code: [Select]
// Toggle switch if button debounced
  if (butndown(digitalRead(button7), &bcount7, &bstate7, 10UL )) digitalWrite(led9Pin, toggle(&led9state))

or for more than one,
Code: [Select]
if (butndown(digitalRead(button7), &bcount7, &bstate7, 10UL )) {
  digitalWrite(led9Pin, toggle(&led9state)); 
  digitalWrite(led10Pin, toggle(&led10state));
}


Finally, you replicate this code section:
Code: [Select]
// flash if toggle is on
if (doflash2 == HIGH) {

  // Act if the latter time (ms) has now passed on this particular counter,
  if (timeout(&count1, 300UL )) {
    toggle(&led1State);
    digitalWrite(led1Pin, led1State);
  }

  if (timeout(&count2, 200UL )) {
    toggle(&led2State);
    digitalWrite(led2Pin, led2State);
  }

  if (timeout(&count3, 77UL )) {
    toggle(&led3State);
    digitalWrite(led3Pin, led3State);
  }
}

for each of the buttons that has a "doflashx" value, carefully matching the LED numbers for "countx", "ledxstate" and "ledxpin".

If you know how to turn one LED on and off with successive button presses then you could
(a) repeat the code 4 times
As I described

or
(b) use arrays of variables and pin numbers and a for loop to read the buttons and act on them.
One of my original permutations, but best suited to a small number of buttons a nd a large number of flashy LEDs. :smiley-lol:

jameskirk

#31
Jun 27, 2015, 07:06 pm Last Edit: Jun 27, 2015, 07:08 pm by jameskirk
OK here is what I have...
Tell me what I can do to fix it please...
Code: [Select]
// Blink without "delay()" - multi!

const int led1Pin =  13;    // LED pin number
const int led2Pin =  12;
const int led3Pin =  11;
const int led4Pin =  10;
const int button1 =  A1;
const int button2 =  A2;
const int button3 =  A3;
const int button4 =  A4;

char led1State = LOW;        // initialise the LED
char led2State = LOW;
char led3State = LOW;
char bstate1 = 0;
char bstate2 = 0;
char bstate3 = 0;
char doflash = LOW;

unsigned long count1 = 0;   // will store last time LED was updated
unsigned long count2 = 0;
unsigned long count3 = 0;
unsigned long bcount1 = 0;  // button debounce timer.  Replicate as necessary.
unsigned long bcount2 = 0;  // button debounce timer.  Replicate as necessary.
unsigned long bcount3 = 0;  // button debounce timer.  Replicate as necessary.
unsigned long bcount4 = 0;  // button debounce timer.  Replicate as necessary.

// ----------------------------- toggle ------------------------------------------
char toggle(char *flip) {   // Yes, it toggles the variable pointed to
  if (*flip == LOW) {
    *flip = HIGH;
  }
  else {
    *flip = LOW;
  }
  return *flip;
}

// ----------------------------- timeout -----------------------------------------
// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) {
    *marker += interval;    // move on ready for next interval
    return true;      
  }
  else return false;
}

// --------------------------- button read ---------------------------------------
// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
// Routines by Paul__B of Arduino Forum
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, 2 or > if debounce in progress
  case 0: // Button up so far,
    if (button == HIGH) return false; // Nothing happening!
    else {
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far,
    if (button == LOW) return false; // Nothing happening!
    else {
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else {
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else {
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}

// -------------------------------------------------------------------------------
void setup() {
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(button4, INPUT);
  digitalWrite(button1,HIGH);        // internal pullup all versions
  digitalWrite(button2,HIGH);        // internal pullup all versions
  digitalWrite(button3,HIGH);        // internal pullup all versions
  digitalWrite(button4,HIGH);        // internal pullup all versions
}

void loop() {
  // Toggle switch if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) if (toggle(&doflash) == HIGH) {
    digitalWrite(led4Pin, HIGH);
    // Toggle switch if button debounced
    if (butndown(digitalRead(button2), &bcount2, &bstate2, 10UL )) if (toggle(&doflash) == HIGH) {
    digitalWrite(led4Pin, HIGH);
    // Toggle switch if button debounced
    if (butndown(digitalRead(button3), &bcount3, &bstate3, 10UL )) if (toggle(&doflash) == HIGH) {
    digitalWrite(led4Pin, HIGH);
    // Toggle switch if button debounced
  if (butndown(digitalRead(button4), &bcount4, &bstate4, 10UL ))
  }
  else {    
    // Toggle switch if button debounced
      if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) if (toggle(&doflash) == LOW) {
    // Turn off LEDs only as and when doflash is switched off
    led1State = LOW;
    led2State = LOW;
    led3State = LOW;
    digitalWrite(led1Pin, led1State);
    digitalWrite(led2Pin, led2State);
    digitalWrite(led3Pin, led3State);
    digitalWrite(led4Pin, LOW);
  };

  // flash if toggle is on
  if (doflash == HIGH) {

    // Act if the latter time (ms) has now passed on this particular counter,
    if (timeout(&count1, 150UL )) {
      toggle(&led1State);
      digitalWrite(led1Pin, led1State);
    }

    if (timeout(&count2, 500UL )) {
      toggle(&led2State);
      digitalWrite(led2Pin, led2State);
    }

    if (timeout(&count3, 77UL )) {
      toggle(&led3State);
      digitalWrite(led3Pin, led3State);
      digitalWrite(led4Pin, toggle(&led4state))
    }
  }
}


Here is the errors...
Code: [Select]
Arduino: 1.6.5 (Windows 7), Board: "Arduino Nano, ATmega328"

Multi_Blink_Steady_Or_Sound_With_Button_.ino: In function 'void loop()':
Multi_Blink_Steady_Or_Sound_With_Button_:133: error: 'bstate4' was not declared in this scope
Multi_Blink_Steady_Or_Sound_With_Button_:134: error: expected primary-expression before '}' token
Multi_Blink_Steady_Or_Sound_With_Button_:134: error: expected ';' before '}' token
Multi_Blink_Steady_Or_Sound_With_Button_:165: error: 'led4state' was not declared in this scope
Multi_Blink_Steady_Or_Sound_With_Button_:166: error: expected ';' before '}' token
Multi_Blink_Steady_Or_Sound_With_Button_:168: error: expected '}' at end of input
Multi_Blink_Steady_Or_Sound_With_Button_:168: error: expected '}' at end of input
Multi_Blink_Steady_Or_Sound_With_Button_:168: error: expected '}' at end of input
'bstate4' was not declared in this scope

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.


Thanks
Mike

UKHeliBob

Maybe declare bstate4 somewhere as a start then

Code: [Select]
 if (butndown(digitalRead(button4), &bcount4, &bstate4, 10UL ))
  }

What should happen when the if statement returns true ?  Either a single statement of a block of statements enclosed in braces.  Not a closing brace that's for sure.

If you auto format your code the last 3 lines look like this
Code: [Select]
               }
              }
            }

Note the gaps before the braces.  It looks like you have missed out some braces or put them in the wrong place
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

jameskirk

Help I'm lost...
Everything I try keeps coming up with different error...  :o

Grumpy_Mike

Why are you using pointers all over the place?
The * is a pointer operation it is not needed and something that a beginner should not need at all.

Read what the error message tells you. It you don't understand it ask. Post the error message along with the code that gave it you.

Above all do not use pointers unless you know exactly why you are doing so.

UKHeliBob

Here is something to get you started
Code: [Select]

const byte ledPins[] = {10, 11, 12};
const byte buttonPins[] = {A1, A2, A3};
const byte NUMBER_OF_LEDS = sizeof(ledPins) / sizeof(ledPins[0]);
byte previousButtonStates[NUMBER_OF_LEDS];

void setup()
{
  Serial.begin(115200);
  for (int p = 0; p < NUMBER_OF_LEDS; p++)
  {
    pinMode(ledPins[p], OUTPUT);
    pinMode(buttonPins[p], INPUT_PULLUP);
  }
}

void loop()
{
  for (int button = 0; button < NUMBER_OF_LEDS; button++)
  {
    byte buttonState = digitalRead(buttonPins[button]);
    if (buttonState != previousButtonStates[button] && buttonState == LOW)
    {
      digitalWrite(ledPins[button], !digitalRead(ledPins[button]));
    }
    previousButtonStates[button] = buttonState;
  }
}
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

jameskirk

UKHeliBob
That Sketch works perfect to turn on the LED's...
Here is a pic of them working...

Now how to incorporate Blinking LED's into the sketch...
Thanks

Paul__B

#37
Jul 03, 2015, 06:54 am Last Edit: Jul 03, 2015, 06:55 am by Paul__B
Suggest you ignore "Grumpy".

The "pointers" - the "*" and "&" - are there for a perfectly good reason; they make the code simpler and easier to follow - which ends up as more reliable.

There is strictly speaking, no real need to understand them completely at this point; you just follow where and how they are used and cut-and-paste things so they match.

I was leaving it for a bit for jameskirk to figure it out and get some experience - if i have "half a chance" I can do some more work on that code.

Grumpy_Mike

Quote
The "pointers" - the "*" and "&" - are there for a perfectly good reason; they make the code simpler and easier to follow - which ends up as more reliable.
So you think it is a good idea to introduce pointers to someone who does not understand a "not declared in scope" error message.

run -> walk sequence error.

I rest my case.

Paul__B

So you think it is a good idea to introduce pointers to someone who does not understand a "not declared in scope" error message.
That message has many causes, of which misuse of pointers would be merely one.

If one cannot accurately copy, paste and adapt code snippets with the necessary precision, then pointers are the least of one's troubles.

I do not think of why I need to use "*" or "&" every time I adapt one of the sketches I post, I just copy them from the last time I used them and make them match up.  If you are honest, that would be exactly how you work on code as well.

I am not "introducing" pointers any more than every other element of "C" syntax.  You have to know where to put a semicolon, or where not to put one.  That is hardly intuitive for starters - must you know why it must be there in some cases and not others?  Or the perennial "==" and "=".  Of course there is a reason but it suffices to say that you put the right thing in the right place and it works and let's face it - that is how most of us program.

Grumpy_Mike

Why do you think that pointers are at the very back of virtually all books on C? It is because the concept is difficult for beginners.


jameskirk

OK sorry for the trouble in here...
But here is the new code...
Code: [Select]

const byte ledPins[] = {10, 11, 12, 13};
const byte buttonPins[] = {A1, A2, A3, A4};
const byte NUMBER_OF_LEDS = sizeof(ledPins) / sizeof(ledPins[0]);
boolean blinkStates[] = {false, false, false, false};
byte previousButtonStates[NUMBER_OF_LEDS];
unsigned long startTimes[4];
unsigned long periods[] = {300, 500, 700, 150};
byte ledStates[] = {HIGH, HIGH, HIGH, HIGH};

[code]const byte ledPins[] = {10, 11, 12, 13};
const byte buttonPins[] = {A1, A2, A3, A4};
const byte NUMBER_OF_LEDS = sizeof(ledPins) / sizeof(ledPins[0]);
boolean blinkStates[] = {false, false, false, false};
byte previousButtonStates[NUMBER_OF_LEDS];
unsigned long startTimes[4];
unsigned long periods[] = {300, 500, 700, 150};
byte ledStates[] = {HIGH, HIGH, HIGH, HIGH};

void setup()
{
  Serial.begin(115200);
  for (int p = 0; p < NUMBER_OF_LEDS; p++)
  {
    pinMode(ledPins[p], OUTPUT);
    pinMode(buttonPins[p], INPUT_PULLUP);
  }
}

void loop()
{
  for (int button = 0; button < NUMBER_OF_LEDS; button++)
  {
    byte buttonState = digitalRead(buttonPins[button]);
    if (buttonState != previousButtonStates[button] && buttonState == LOW)
    {
      blinkStates[button] = !blinkStates[button];
      if (blinkStates[button] == false)
      {
        digitalWrite(ledPins[button], LOW);
      }
    }
    previousButtonStates[button] = buttonState;
  }

  for (byte led = 0; led < NUMBER_OF_LEDS; led++)
  {
    if (blinkStates[led])
    {
      unsigned long currentTime = millis();
      if (currentTime - startTimes[led] >= periods[led])
      {
        ledStates[led] = !ledStates[led];
        digitalWrite(ledPins[led], ledStates[led]);
        startTimes[led] = currentTime;
      }
    }
  }
}

Here is a Video of it...
Next step is to add sound to the project...
What I was told before was to use the sound module I have as an LED...
So I have 4 buttons and 4 Blinking LED's so I would need 4 NON Blinking LED's added into the code...
With this sketch how do I add a NON Blinking LED with each button?
Thanks
Mike

UKHeliBob

When and how do you want to turn the non blinking LEDs on and off ?

Should they stay on whilst the button is pressed or should they turn on when the button is pressed the first time and off when the button is pressed again ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

jameskirk

That is a very good question...
The way my late friend had it in his my guess would be to
come on when the Blinking LED comes on and stays on until the button is pushed to off...
I don't know what will happen if the non blinking code will turn off the sound prematurely...
We could try it both ways to see which one works best...
Thanks
Mike

UKHeliBob

Quote
come on when the Blinking LED comes on and stays on until the button is pushed to off...
Just turn on the unblinking LED when blinkStates[button] becomes true and off again when it becomes false.  Job done.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Go Up