I'm trying to switch some relays sequentially and things are going sideways.
Basically I have 13 outputs and 1 input
Outputs 1 - 9 need to switch on and off in sequence when the input button is pressed.
Then with each of those, outputs 10, 11 and 12 need to turn on and off. - output 10 triggering a few moments before 11 and 12. Then all 4 active outputs go off toeather before moving to the next one.
Essentially the switching order is as follows:
Output 13 is high indicating its at the start of the loop
Push momentary input 1
Output 13 goes low showing the loop has started
Output 1 high
200ms
Output 10 high
200ms
Output 11 & 12 high
200ms
All off
Then repeat with output 2 and so on.
What's the best way to program this in?
Can anyone give me an example to work from?
Here is a solution for what you mentioned with output 1:
const byte pins[] {2,3,10,11};
byte NoOfPins = sizeof pins / sizeof pins[0];
const byte buttonPin = 13;
const int delayTime = 2000;
enum Outputs {
OUT01,
OUT10,
OUT11,
OUT12
};
enum states {
IDLE,
ALL_OFF,
WAIT,
HIGH01,
HIGH10,
HIGH11_12,
};
byte state = IDLE;
byte nextState = IDLE;
unsigned long waitTime = 0;
unsigned long timeStamp;
void setup() {
Serial.begin(115200);
for (byte i=0;i < NoOfPins;i++){
pinMode(pins[i],OUTPUT);
digitalWrite(pins[i],LOW);
}
pinMode(buttonPin, INPUT_PULLUP);
Serial.println("Start");
}
void loop() {
if (state == IDLE && buttonWasPressed()) state = HIGH01;
stateMachine();
}
void stateMachine(){
switch (state){
case IDLE:
break;
case ALL_OFF:
for (byte i=0;i < NoOfPins;i++){
digitalWrite(pins[i],LOW);
}
state = IDLE; // No delay time required
break;
case WAIT:
if (TimeIsOver()) state = nextState;
break;
case HIGH01:
Serial.println("HIGH01");
digitalWrite(pins[OUT01], HIGH);
SetWaitTimeAndNextState(delayTime,HIGH10);
break;
case HIGH10:
Serial.println("HIGH10");
digitalWrite(pins[OUT10], HIGH);
SetWaitTimeAndNextState(delayTime,HIGH11_12);
break;
case HIGH11_12:
Serial.println("HIGH11_12");
digitalWrite(pins[OUT11], HIGH);
digitalWrite(pins[OUT12], HIGH);
SetWaitTimeAndNextState(delayTime,ALL_OFF);
break;
default:
break;
}
}
void SetWaitTimeAndNextState(unsigned long w, byte s){
timeStamp = millis();
waitTime = w;
nextState = s;
state = WAIT;
}
boolean TimeIsOver(){
if (millis()-timeStamp > waitTime) return true;
else return false;
}
boolean buttonWasPressed() {
static unsigned long lastPressTime = 0; // Stores the last time when the button state changed from HIGH to LOW
static boolean lastState = HIGH; // Stores the last detected state of the button for the "next round"
int buttonState = digitalRead(buttonPin); // Reads the actual button state
if (buttonState == LOW && lastState == HIGH) lastPressTime = millis(); // Store the time when the state hase changed to LOW
lastState = buttonState; // Now store the recent state for the "next round"
if (lastState == LOW && millis() - lastPressTime > 50) return true; // If lastState is still LOW for minimum 50 msec ... accept it
else return false; // else do not accept the LOW state (debouncing!)
}
You can test it on Wokwi and make your own copy there for further coding and testing ...
That's pretty neat. Too bad it doesn't have an "export Arduino code" option!
(Hmm. There is probably something more blinking-lights oriented. All those fancy Christmas displays don't spring out of nothing! Maybe https://manual.xlights.org/ or similar? )
You could make an Arduino get pretty close to that as far as processing input, but the program would be more complicated.
signal ready(WAVE, 13, "10...................................1.....");
signal focus(WAVE, 12, "0.1.0.1.0.1.0.1.0.1.0.1.0.1.0.1.0.1.0.......");
signal signame(type, pinNo, patternString);
// etc
Or you can make a simpler program that is more difficult to change the sequences...