single push button to sequentially trigger 6 relays

Hello All!

I read the pinned post, and I hope I'm posting this according to the rules. I'm not posting code or anything like that, just asking for a push in the right direction.

I'm a super newbie. I know my way around motion control, and some things like that, that I've slowly learned when working with my 3D printers, CNC machines and such, but I only know how to either edit existing code, as I'm still going through the "learn arduino" tutorials.

I know how to do a simple push button relay circuit, but I have been struggling with wrapping my head around controlling multiples with a single button.

My intent is as follows:

Push button once, relay 1 triggers and stays on, push again, relay 2 triggers and stays on, push again, relay 3... up to relay 6. then the 7th press turns them all off.

I'm trying to learn to do this myself rather than pay someone on Fiverr or something like that.

I've found many tutorials and sample code for multiple buttons / relays, and I get that, but I cannot seem to dig up anything that explains the process for stacking multiple relays with the single pushbutton.

Can anyone recommend a sample code, or a tutorial that may go a bit deeper than just a single pushbutton on / off scenario?

I've been digging for days, and always end up back at the same couple of tutorials.

If there is a more specific name for this action, Please enlighten me. Half of my arduino troubles, are knowing what to call what I'm looking for.

Thanks so much!

IF you already know how to discover when a push button becomes pressed, you are almost there!. Begin by just counting the times the button becomes pressed. Let us know when you can do that.

Paul

I've been digging for days, and always end up back at the same couple of tutorials.

Did you ever end up back at the State Change Detection example in the ide? It detects a button press and increments a count.

File>Examples>02Digital>StateChangeDetection

Think in 2 parts. Buttons and relays. Just work on buttons. Look at button tutorials. If you can detect a button press then you just need to record it in a variable. Every time it is pressed variable ++
Then all you do is link this to the action you want. If variable = 1, relaypin1 is high. If 2 relaypin 2 is high etc if 0 all relaypins low.
That kind of thing

Think in 2 parts. Buttons and relays. Just work on buttons.

Always good advice! Work on the input & output separately.

Start with something that works (maybe the Digital Read Serial Example) and add one or two lines of code at a time, test-compiling and test-running as you go. If you try to write the whole program at once you'll get too many errors and the error messages are often not helpful and often the error messages don't point to the real error and they can be misleading. If you've added a couple of lines and an error pops-up, you know where the problem is.

Of course, professional programmers write more than one or two lines at a time, but nobody writes the whole program at once without testing the parts. (And, professional programmers are usually working on much larger programs.)

That's not quite as easy as it sounds because you need a "complete program" that "makes sense" to the compiler. You can't just start at the top and work down... You have to "develop" your code. For example, if you delete the bottom half of a program, it won't compile with just the 1st-half..

It's also helpful to send little messages to the serial monitor (like the Digital Read Serial Example, etc.). It's a way of "seeing" what your program is doing. You can send little messages like "Reading button", "button pushed" or "Relay 1 on", or whatever is helpful. I'm working on a project right now and its not behaving correctly (yet) so I'm sending debug messages to the serial monitor as well as trying some other debugging tricks.

The two most important concepts in programming are conditional execution ([u]If-statements[/u], etc.) and [u]loops[/u] and loops (doing something over-and-over, usually until some condition is reached).

In addition to the main loop() you can have for-loops, while-loops and do-while loops. (You may not need anything other than the main loop but I haven't completely thought it through.)

There is a LOT more to programming, but loops & conditional processing are what make programming useful!

For example, if the button is pushed and the 1st relay is on, turn the 2nd relay on, then loop-back and keep looping, reading the button every time through the loop.

You should be aware that switches & buttons "bounce". When you press (or release a button) it can switch on & off multiple times for a few microseconds. That's not a problem at human speed but if you are counting button-pressed with at microprocessor-speed you need to [u]debounce[/u] (i.e. ignore the bouncing).

Hmmm, noting your previous enquiry to a different forum (which I do not frequent) where you were trying to most inappropriately use an interrupt for a pushbutton, I hope you have now actually read the instructions for posting and comprehend how (point No. 7) to post your code.

The very first thing you need to know about buttons, is how to "de-bounce" the button input.

May I offer you some "ironclad" debounce code to start with. I suggest you wire it up to play with some buttons and LEDs with resistors. If you familiarise yourself with that, I am happy to explain and modify the code to your relay requirement (but you will need to tell me what relay module you will be using).

// Blink without "delay()" - multi!  With button de-bounce.
// Note that this code is immediately extensible to *many* buttons.

const int led1Pin =  13;    // LED pin number
const int led2Pin =  10;
const int led3Pin =  11;
const int button1 =  4;     // buttons & switches always connect from input to ground
const int button2 =  5;
const int button3 =  6;

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

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;
unsigned long bcount3 = 0;

// 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;
}

// 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.
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, >= 2 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);      
  digitalWrite(button1,HIGH);        // internal pullup all versions
  pinMode(button2, INPUT);      
  digitalWrite(button2,HIGH);        // internal pullup all versions
  pinMode(button3, INPUT);      
  digitalWrite(button3,HIGH);        // internal pullup all versions
}

void loop() {
  // Toggle LED if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    if (led1State == LOW) {
      led1State = HIGH;
    }
    else {
      led1State = LOW; 
    } 
    digitalWrite(led1Pin, led1State);
  } 

  if (butndown(digitalRead(button2), &bcount2, &bstate2, 10UL )) {
    if (led2State == LOW) {
      led2State = HIGH;
    }
    else {
      led2State = LOW; 
    } 
    digitalWrite(led2Pin, led2State);
  } 

  if (butndown(digitalRead(button3), &bcount3, &bstate3, 10UL )) {
    if (led3State == LOW) {
      led3State = HIGH;
    }
    else {
      led3State = LOW; 
    } 
    digitalWrite(led3Pin, led3State);
  } 

}