So I'm very new to coding, and this is my first real project. I am kinda understanding it but I had to piece this together bit by bit from pieces of code I found elsewhere and have just been trying to modify to get it to do what I want.
Right now the program is running 10 neopixels: the lower 7 are turned red and don't change at all. However the upper 3 lights is what I'm working on. I have it so when I push the button and hold it for 10 or more seconds it changes those 3 neopixels from yellow to red, but when I release it it changes right back to yellow. My issue is I'd like it to stay red for a few seconds after releasing the button but I'm not sure what the best way to go about that would be. Would I need to make another 'IF' statement?
And I also had a second question about the button. I would like to be able to run two buttons and have them do the same thing. I tried just copying and pasting everything and defining a new button running off of pin 5 (#define PIN_BUTTON2 5), but only one of the buttons would work when testing it. I've since taken that out and the code I'm posting is the one that works.
So what do I need to do to get two buttons to have the same result?
The code you posted works great, thanks again for that! But I had a few questions about mods I'd like to add. I would love to make the 3 neopixels that turn red to pulse on and off. I've been trying to get something to work but a lot of the examples I'm finding online are for standard leds or they use delays. What would the best way to go about making these pulse red instead of being static? Starting with a 'for' loop but how would I populate that line?
I'm still such a noob, this is about as good as I could get it. But the thing I'd like it do is keep blinking when the button is released. What would I need to modify or add to keep it blinking until the 10 seconds are up and the yellow light comes back on?
Thanks
#include <Adafruit_NeoPixel.h>
#define PIN_LED 2
#define PIN_BUTTON 4
#define NUM_LEDS 10
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN_LED, NEO_GRB + NEO_KHZ800);
int buttonState = 0;
int lastButtonState = 0;
long buttonPressTime = 0;
long buttonReleaseTime = 0;
void setup() {
strip.begin();
pinMode(PIN_BUTTON, INPUT_PULLUP);
//Red dome light
for(int i=0;i<7;i++)strip.setPixelColor(i, strip.Color(200, 0, 0));
for(int i=7;i<10;i++)strip.setPixelColor(i, strip.Color(255, 115, 0));
strip.show();
}
void loop() {
//Holding down firing button, radiation light goes from yellow to red after firing for 10 seconds
buttonState = digitalRead(PIN_BUTTON);
if (buttonState == LOW) {
if (lastButtonState == HIGH)buttonPressTime = millis();
if (millis() - buttonPressTime > 10000) {
for(int i=7; i<NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(255,0,0));
}
strip.show();
delay(400);
for(int i=7; i<NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(5,0,0));
}
strip.show();
delay(400);
}
}
else {
if (lastButtonState == LOW)buttonReleaseTime = millis();
if (millis() - buttonReleaseTime > 10000) {
strip.setPixelColor(7, strip.Color(255, 115, 0));
strip.setPixelColor(8, strip.Color(255, 115, 0));
strip.setPixelColor(9, strip.Color(255, 115, 0));
strip.show();
}
}
lastButtonState = buttonState;
}
Please explain exactly what you need to happen using Step working:
Step 1
At power up, pixels 0-6 are to be Red and 7-9 are to be Amber.
Step 2
When the switch on pin 4 is pressed, . . .
Step 3
When the switch on pin 4 is released . . .
Step 4
. . .
Step 5
. . .
Etc.
Edit
Try this:
Ask questions.
//================================================^================================================
//
// https://forum.arduino.cc/t/need-pointers-on-a-led-project/1199855
//
//
//
// Version YY/MM/DD Comments
// ======= ======== ========================================================================
// 1.00 23/12/14 Running code
// 1.10 23/12/15 Fixed a bug
//
//
#include <Adafruit_NeoPixel.h>
//================================================
#define LEDon HIGH //PIN---[220R]---A[LED]K---GND
#define LEDoff LOW
#define PRESSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define RELEASED HIGH
#define ENABLED true
#define DISABLED false
#define BRIGHTred true
#define DIMred false
// G P I O s
//================================================^================================================
const byte PIN_LED = 2;
const byte PIN_BUTTON = 4;
const byte heartbeatLED = 13;
//Variables
bool tenMoreSecondsFlag = DISABLED;
bool colourFlag = DIMred;
const byte NUM_LEDS = 10;
byte lastPIN_BUTTON;
//timing stuff
unsigned long heartbeatTime;
unsigned long checkSwitchTime;
unsigned long machineTime;
unsigned long commonTime;
unsigned long tenSecondTime;
unsigned long commonInterval;
// S t a t e M a c h i n e
//================================================^================================================
//the states in our machine
enum STATES : byte
{
STARTUP, WAITING, HOLDtime, PULSING, TENseconds, FINISHED
};
STATES mState = STARTUP;
//NeoPixels
//================================================
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN_LED, NEO_GRB + NEO_KHZ800);
// s e t u p ( )
//================================================^================================================
void setup()
{
Serial.begin(115200);
strip.begin();
pinMode(heartbeatLED, OUTPUT);
pinMode(PIN_BUTTON, INPUT_PULLUP); //+5V---[Internal 50k]---PIN---[Switch]---GND
//========================
//Red dome light
for (int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(200, 0, 0));
}
//========================
for (int i = 7; i < 10; i++)
{
strip.setPixelColor(i, strip.Color(255, 115, 0));
}
strip.show();
} //END of setup()
// l o o p ( )
//================================================^================================================
void loop()
{
//======================================================================== T I M E R heartbeatLED
//every 500ms, is it time to toggle the heartbeat LED ?
if (millis() - heartbeatTime >= 500ul)
{
//restart this TIMER
heartbeatTime = millis();
//toggle the heartbeat LED
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== T I M E R check switches
//every 50ms, is it time to scan our switches ?
if (millis() - checkSwitchTime >= 50ul)
{
//restart this TIMER
checkSwitchTime = millis();
checkSwitches();
}
//======================================================================== T I M E R machine
//every 10ms, is it time to scan our switches ?
if (millis() - machineTime >= 10ul)
{
//restart this TIMER
machineTime = millis();
checkMachine();
}
//================================================
//other non blocking code goes here
//================================================
} //END of loop()
// c h e c k M a c h i n e ( )
//================================================^================================================
void checkMachine()
{
//================================================
//service the current "state"
switch (mState)
{
//========================
case STARTUP:
{
//do startup stuff
//next state in the machine
mState = WAITING;
}
break;
//========================
case WAITING:
{
//do nothing
}
break;
//========================
case HOLDtime:
{
//has the TIMER expired ?
if (millis() - commonTime >= commonInterval)
{
colourFlag = BRIGHTred; //3 pixels will be bright Red
for (int i = 7; i < NUM_LEDS; i++)
{
strip.setPixelColor(i, strip.Color(255, 0, 0));
}
strip.show();
//restart the TIMER
commonTime = millis();
//every 500ms, set the TIMER interval
commonInterval = 500ul;
//next state in the machine
mState = PULSING;
}
}
break;
//========================
case PULSING:
{
//has the TIMER expired ?
if (millis() - commonTime >= commonInterval)
{
//restart the TIMER
commonTime = millis();
unsigned long colour;
//toggling the last 3 pixel colours
// Dim Red Bright Red
colour = colourFlag == BRIGHTred ? 0x050000 : 0xFF0000;
//get ready for the next sequence
colourFlag = colourFlag == BRIGHTred ? DIMred : BRIGHTred;
//set the 3 pixel colour
for (int i = 7; i < NUM_LEDS; i++)
{
strip.setPixelColor(i, colour);
}
strip.show();
}
//next state in the machine
mState = TENseconds;
}
break;
//========================
case TENseconds:
{
//should we extend pulsing for 10 more seconds ?
if (tenMoreSecondsFlag == ENABLED && millis() - tenSecondTime >= 10000ul)
{
//we are done with this TIMER
tenMoreSecondsFlag = DISABLED;
//we are done with colour changing
colourFlag = DIMred;
//back to amber
strip.setPixelColor(7, strip.Color(255, 115, 0));
strip.setPixelColor(8, strip.Color(255, 115, 0));
strip.setPixelColor(9, strip.Color(255, 115, 0));
strip.show();
//we are now finished, back to normal
//next state in the machine
mState = WAITING;
}
else
{
//next state in the machine
mState = PULSING;
}
}
break;
//========================
case FINISHED:
{
}
break;
} //END of switch/case
} //END of checkMachine()
// c h e c k S w i t c h e s ( )
//================================================^================================================
void checkSwitches()
{
byte state;
//======================================================================== PIN_BUTTON
state = digitalRead(PIN_BUTTON);
//has this switch changed state ?
if (lastPIN_BUTTON != state)
{
//update to the new state
lastPIN_BUTTON = state;
//========================
//when machine is in waiting, has the switch been pressed (closed) ?
if (mState == WAITING && state == PRESSED)
{
//restart the TIMER
commonTime = millis();
//set the TIMER interval
commonInterval = 10000ul;
//next state in the machine
mState = HOLDtime;
}
//========================
//has the switch been released (opened) ?
else if ((mState == PULSING || mState == TENseconds) && tenMoreSecondsFlag == DISABLED && state == RELEASED)
` {
//allow 10 more seconds of pulsing
tenMoreSecondsFlag = ENABLED;
//restart the TIMER
tenSecondTime = millis();
}
else if (mState == HOLDtime)
{
//back to amber
strip.setPixelColor(7, strip.Color(255, 115, 0));
strip.setPixelColor(8, strip.Color(255, 115, 0));
strip.setPixelColor(9, strip.Color(255, 115, 0));
strip.show();
mState = WAITING;
}
} //END of this switch
//======================================================================== nextSwitch
} //END of checkSwitches()
//================================================^================================================
i suggest a sub-function, either a block of code within loop() or a separate function that uses millis() to implement a timer that toggles the LED every blink period and stops after the # of iterations amounting to 10 secs.
the code to recognize a button press is a separate sub-function. it should enable the blinking by setting a flag variable to true which is checked in the timer sub-function.
I'm a prop maker and right now I'm working on a Ghostbuster costume. This code is going to be be used for a piece of gear I'm making.
Step 1: like you said, when the power is switched on I want the lights to turn on.
Step 2: When button is pushed for 10 or more seconds, top 3 pixels in the chain to go from amber to flashing/pulsing red.
Step 3: When button is released the flashing should continue 10 seconds more before fading back to amber.
Step 4: Wait to do steps 2-3 again.
I checked the code and it works exactly how I was wanting it to! Thank you!
I did have a few questions. First off I guess the first thing I noticed was that code you posted was a lot more complicated than I was expecting. Is there any way I can simplify it without losing its function? Like removing that timer that’s making the Nanos onboard led blink?
And with everything else that going on, would I be able to add to that in the future? I would some time like to add to the code to address those first 7 pixels separate from those last 3.
Thanks again!
What one expects should not be important, something that works is important.
This sketch was written to expose you to: millis( ) based TIMERS, State Machine techniques, readability, non-blocking code, and ensure ease of adding future modifications (for example, it is a simple matter to add a 2nd, 3rd more switches for more functionality).
The sketch has a heartbeat LED which can be removed but provides indication of code blocking; the LED should toggle every 500ms.
Fair enough. I still have a lot to learn, and even being exposed to more functions and stuff, I’m not finding it any easier to grasp.
But to conclude, I appreciate you taking the time out of your days to make that code and for your responses. Thank you.
You have an opportunity to learn from the sketch offered here.
Go thru the sketch, if there is something you need explained, ask questions.
The following example has the heartbeat LED changed from pin 13 to pin 11 (PWM pin).
The heartbeat LED now fades in and out at a 1 second rate.
Try this version with a LED and series resistor connected to Arduino pin 11.
//================================================^================================================
//
// https://forum.arduino.cc/t/need-pointers-on-a-led-project/1199855
//
//
//
// Version YY/MM/DD Comments
// ======= ======== ========================================================================
// 1.00 23/12/14 Running code
//
//
//
#include <Adafruit_NeoPixel.h>
//================================================
#define LEDon HIGH //PIN---[220R]---A[LED]K---GND
#define LEDoff LOW
#define PRESSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define RELEASED HIGH
#define ENABLED true
#define DISABLED false
#define BRIGHTred true
#define DIMred false
// G P I O s
//================================================^================================================
const byte PIN_LED = 2;
const byte PIN_BUTTON = 4;
const byte heartbeatLED = 11;
//Variables
bool tenMoreSecondsFlag = DISABLED;
bool colourFlag = DIMred;
const byte NUM_LEDS = 10;
byte lastPIN_BUTTON;
int heartbeatCounter;
int incdec = 1;
unsigned long colour;
//timing stuff
unsigned long heartbeatTime;
unsigned long checkSwitchTime;
unsigned long machineTime;
unsigned long commonTime;
unsigned long tenSecondTime;
unsigned long commonInterval;
// S t a t e M a c h i n e
//================================================^================================================
//the states in our machine
enum STATES : byte
{
STARTUP, WAITING, HOLDING, PULSING, TENseconds, FINISHED
};
STATES mState = STARTUP;
//NeoPixels
//================================================
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN_LED, NEO_GRB + NEO_KHZ800);
// s e t u p ( )
//================================================^================================================
void setup()
{
Serial.begin(115200);
strip.begin();
pinMode(heartbeatLED, OUTPUT);
pinMode(PIN_BUTTON, INPUT_PULLUP); //+5V---[Internal 50k]---PIN---[Switch]---GND
//========================
//Red dome light
for (int i = 0; i < 7; i++)
{
strip.setPixelColor(i, strip.Color(255, 0, 0));
}
//========================
for (int i = 7; i < 10; i++)
{
strip.setPixelColor(i, strip.Color(255, 115, 0));
}
strip.show();
} //END of setup()
// l o o p ( )
//================================================^================================================
void loop()
{
//======================================================================== T I M E R heartbeatLED
//every 1 second, go thru the fading values of the heartbeat LED ?
if (micros() - heartbeatTime >= 1953ul)
{
//restart this TIMER
heartbeatTime = micros();
//next intensity level
analogWrite(heartbeatLED, heartbeatCounter);
//next level in our heartbeat LED fading
heartbeatCounter = heartbeatCounter + incdec;
//have we reached a limit in our fading
if (heartbeatCounter > 255 || heartbeatCounter < 0)
{
//go the other way in our fading
incdec = 0 - incdec;
heartbeatCounter = heartbeatCounter + incdec;
}
}
//======================================================================== T I M E R check switches
//every 50ms, is it time to scan our switches ?
if (millis() - checkSwitchTime >= 50ul)
{
//restart this TIMER
checkSwitchTime = millis();
checkSwitches();
}
//======================================================================== T I M E R machine
//every 10ms, is it time to scan our switches ?
if (millis() - machineTime >= 10ul)
{
//restart this TIMER
machineTime = millis();
checkMachine();
}
//================================================
//other non blocking code goes here
//================================================
} //END of loop()
// c h e c k M a c h i n e ( )
//================================================^================================================
void checkMachine()
{
//================================================
//service the current "state"
switch (mState)
{
//========================
case STARTUP:
{
//do startup stuff
//next state in the machine
mState = WAITING;
}
break;
//========================
case WAITING:
{
//do nothing
}
break;
//========================
case HOLDING:
{
//has the TIMER expired ?
if (millis() - commonTime >= commonInterval)
{
colourFlag = BRIGHTred; //3 pixels will be bright Red
for (int i = 7; i < NUM_LEDS; i++)
{
strip.setPixelColor(i, strip.Color(255, 0, 0));
}
strip.show();
//restart the TIMER
commonTime = millis();
//every 500ms, set the TIMER interval
commonInterval = 500ul;
//next state in the machine
mState = PULSING;
}
}
break;
//========================
case PULSING:
{
//has the TIMER expired ?
if (millis() - commonTime >= commonInterval)
{
//restart the TIMER
commonTime = millis();
//toggling the last 3 pixel colours
// Dim Red Bright Red
colour = colourFlag == BRIGHTred ? 0x050000 : 0xFF0000;
//get ready for the next sequence
colourFlag = colourFlag == BRIGHTred ? DIMred : BRIGHTred;
//set the 3 pixel colour
for (int i = 7; i < NUM_LEDS; i++)
{
strip.setPixelColor(i, colour);
}
strip.show();
}
//next state in the machine
mState = TENseconds;
}
break;
//========================
case TENseconds:
{
//should we extend pulsing for 10 more seconds ?
if (tenMoreSecondsFlag == ENABLED && millis() - tenSecondTime >= 10000ul)
{
//we are done with this TIMER
tenMoreSecondsFlag = DISABLED;
//we are done with colour changing
colourFlag = DIMred;
//back to Amber
strip.setPixelColor(7, 0xFF7300);
strip.setPixelColor(8, 0xFF7300);
strip.setPixelColor(9, 0xFF7300);
strip.show();
//we are now finished, back to normal
//next state in the machine
mState = WAITING;
}
else
{
//next state in the machine
mState = PULSING;
}
}
break;
//========================
case FINISHED:
{
}
break;
} //END of switch/case
} //END of checkMachine()
// c h e c k S w i t c h e s ( )
//================================================^================================================
void checkSwitches()
{
byte state;
//======================================================================== PIN_BUTTON
state = digitalRead(PIN_BUTTON);
//has this switch changed state ?
if (lastPIN_BUTTON != state)
{
//update to the new state
lastPIN_BUTTON = state;
//========================
//when machine is in the waiting state, was the switch pressed ?
if (mState == WAITING && state == PRESSED)
{
//restart the TIMER
commonTime = millis();
//set the TIMER interval
commonInterval = 10000ul;
//next state in the machine
mState = HOLDING;
}
//========================
//during the PULSING OR TENseconds state, when we are not adding ten seconds,
//was the switch released ?
else if ((mState == PULSING || mState == TENseconds) && tenMoreSecondsFlag == DISABLED && state == RELEASED)
{
//allow 10 more seconds of pulsing
tenMoreSecondsFlag = ENABLED;
//restart the TIMER
tenSecondTime = millis();
}
//were we in the HOLDING state when the switch was released ?
else if (mState == HOLDING)
{
//back to Amber
strip.setPixelColor(7, 0xFF7300);
strip.setPixelColor(8, 0xFF7300);
strip.setPixelColor(9, 0xFF7300);
strip.show();
//back to normal conditions
mState = WAITING;
}
} //END of this switch
//======================================================================== nextSwitch
} //END of checkSwitches()
//================================================^================================================
You learn coding by writing code. ;)
BTW
You can use this tool to help select colour values for your sketch.
Yeah, I know. I guess where I get hung up is with how arbitrary coding is. It's hard for me to wrap my head around all the infinite possibilities there is. I get lost very easily, so even if I can read someone else's code and kinda understand why they did the things they did, I often don't even know where to begin on my own coding. Or if I land on a function to use I don't know how I'm supposed to populate it.
Hats off to those out there who understand it and can write out stuff like that, I know I certainly couldn't do it.
Oh and testing that first code more it wasn't working like I wanted. Holding the button down 10+ seconds would cause the leds to blink but when the button was released they would continue to blink until I powered them off.
So I'm going to attempt to come up with something myself.
Thanks for your help and the example codes you sent. It was interesting reading through them.
I sometimes offer new people this skeleton sketch.
I add/modify/delete sections of the code as needed.
The skeleton provides a starting point for new sketches.
//================================================^================================================
//
// URL
//
// LarryD
//
// Version YY/MM/DD Comments
// ======= ======== ========================================================================
// 1.00 YY/MM/DD Running code
//
//
//
//#include <Wire.h>
//================================================
#define PULSE62_13 cli(); PINB = bit(PINB5); PINB = bit(PINB5); sei() //for ATMEGA 328 (UNO)
#define LEDon HIGH //PIN---[220R]---A[LED]K---GND
#define LEDoff LOW
#define PRESSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define RELEASED HIGH
#define CLOSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define OPENED HIGH
//================================================
//Optional way of defining inputs and outputs
//#define LEDon LOW //+5V---[220R]---A[LED]K---PIN
//#define LEDoff HIGH
//#define PRESSED HIGH //+5V---[Switch]---PIN---[10k]---GND
//#define RELEASED LOW
//================================================^================================================
// millis() / micros() B a s e d T I M E R S
//================================================^================================================
//To keep the sketch tidy, you can put this structure in a different tab in the IDE
//
//These TIMER objects are non-blocking
struct makeTIMER
{
#define MILLIS 1
#define MICROS 1000 //we can use this value to divide into a variable to get milliseconds
#define ENABLED true
#define DISABLED false
#define YES true
#define NO false
#define STILLtiming 0
#define EXPIRED 1
#define TIMERdisabled 2
//these are the bare minimum "members" needed when defining a TIMER
int TimerType; //what kind of TIMER is this? MILLIS/MICROS
unsigned long Time; //when the TIMER started
unsigned long Interval; //delay time which we are looking for
bool TimerFlag; //is the TIMER enabled ? ENABLED/DISABLED
bool Restart; //do we restart this TIMER ? YES/NO
//================================================
//condition returned: STILLtiming (0), EXPIRED (1) or TIMERdisabled (2)
//function to check the state of our TIMER ex: if(myTimer.checkTIMER() == EXPIRED);
byte checkTIMER()
{
//========================
//is this TIMER enabled ?
if (TimerFlag == ENABLED)
{
//========================
//has this TIMER expired ?
if (getTime() - Time >= Interval)
{
//========================
//should this TIMER restart again?
if (Restart == YES)
{
//restart this TIMER
Time = getTime();
}
//this TIMER has expired
return EXPIRED;
}
//========================
else
{
//this TIMER has not expired
return STILLtiming;
}
} //END of if (TimerFlag == ENABLED)
//========================
else
{
//this TIMER is disabled
return TIMERdisabled;
}
} //END of checkTime()
//================================================
//function to enable and restart this TIMER ex: myTimer.enableRestartTIMER();
void enableRestartTIMER()
{
TimerFlag = ENABLED;
//restart this TIMER
Time = getTime();
} //END of enableRestartTIMER()
//================================================
//function to disable this TIMER ex: myTimer.disableTIMER();
void disableTIMER()
{
TimerFlag = DISABLED;
} //END of disableTIMER()
//================================================
//function to restart this TIMER ex: myTimer.restartTIMER();
void restartTIMER()
{
Time = getTime();
} //END of restartTIMER()
//================================================
//function to force this TIMER to expire ex: myTimer.expireTimer();
void expireTimer()
{
//force this TIMER to expire
Time = getTime() - Interval;
} //END of expireTimer()
//================================================
//function to set the Interval for this TIMER ex: myTimer.setInterval(100);
void setInterval(unsigned long value)
{
//set the Interval
Interval = value;
} //END of setInterval()
//================================================
//function to return the current time
unsigned long getTime()
{
//return the time i.e. millis() or micros()
//========================
if (TimerType == MILLIS)
{
return millis();
}
//========================
else
{
return micros();
}
} //END of getTime()
}; //END of struct makeTIMER
// D e f i n e a l l a r e T I M E R S
//================================================^================================================
/*example
//========================
makeTIMER toggleLED =
{
MILLIS/MICROS, 0, 500ul, ENABLED/DISABLED, YES/NO //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
Function examples:
toggleLED.checkTIMER();
toggleLED.enableRestartTIMER();
toggleLED.disableTIMER();
toggleLED.expireTimer();
toggleLED.setInterval(100ul);
*/
//========================
makeTIMER heartbeatTIMER =
{
MILLIS, 0, 500ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER switchesTIMER =
{
MILLIS, 0, 5ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER machineTIMER =
{
MICROS, 0, 1000ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER commonTIMER =
{
MILLIS, 0, 1000ul, DISABLED, NO //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
// S t a t e M a c h i n e
//================================================^================================================
//the states in our machine
enum STATES : byte
{
STARTUP, STATE1, STATE2, STATE3, STATE4, FINISHED
};
STATES mState = STARTUP;
// G P I O s
//================================================^================================================
//
//structure to define input objects
struct makeInput
{
const byte pin;
byte lastState;
byte counter;
}; //END of struct makeInput
//INPUTS
//===================================
makeInput mySwitch =
{
2, OPENED, 0 //pin, lastState, counter
};
byte filter = 10;
//"TIMER check switches" runs every 5ms.
//5ms * 10 = 50ms is needed to validate a switch change in state.
//A switch change in state is valid "only after" 10 identical changes is detected.
//used to filter out EMI noise in the system
//OUTPUTS
//===================================
const byte testLED = 12;
const byte heartbeatLED = 13;
//VARIABLES
//===================================
// s e t u p ( )
//================================================^================================================
void setup()
{
Serial.begin(115200);
//Serial.begin(9600);
pinMode(mySwitch.pin, INPUT_PULLUP);
pinMode(heartbeatLED, OUTPUT);
digitalWrite(testLED, LEDoff);
pinMode(testLED, OUTPUT);
} //END of setup()
// l o o p ( )
//================================================^================================================
void loop()
{
//================================================
//Print loop() speed
// PULSE62_13;
// static unsigned long speedTime;
// Serial.println(micros() - speedTime);
// speedTime = micros();
// PULSE62_13;
//======================================================================== T I M E R heartbeatLED
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
//is it time to toggle the heartbeat LED ?
if (heartbeatTIMER.checkTIMER() == EXPIRED)
{
//toggle the heartbeat LED
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== T I M E R switches
//is it time to check our switches ?
if (switchesTIMER.checkTIMER() == EXPIRED)
{
checkSwitches();
}
//======================================================================== T I M E R machine
//is it time to service our State Machine ?
if (machineTIMER.checkTIMER() == EXPIRED)
{
checkMachine();
}
//================================================
//other non blocking code goes here
//================================================
} //END of loop()
// c h e c k M a c h i n e ( )
//================================================^================================================
void checkMachine()
{
//================================================
//service the current "state"
switch (mState)
{
//========================
case STARTUP:
{
//do startup stuff
}
break;
//========================
case STATE1:
{
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
if (commonTIMER.checkTIMER() == EXPIRED)
{
digitalWrite(testLED, LEDoff);
//we are finished with this TIMER
commonTIMER.disableTIMER();
//next state
mState = STATE2;
}
}
break;
//========================
case STATE2:
{
//Do something
}
break;
//========================
case STATE3:
{
//Do something
}
break;
//========================
case STATE4:
{
//Do something
}
break;
//========================
case FINISHED:
{
//Do something
}
break;
} //END of switch/case
} //END of checkMachine()
// c h e c k S w i t c h e s ( )
//================================================^================================================
void checkSwitches()
{
byte pinState;
//======================================================================== mySwitch.pin
pinState = digitalRead(mySwitch.pin);
//===================================
//has this switch changed state ?
if (mySwitch.lastState != pinState)
{
mySwitch.counter++;
//is this change in state stable ?
if (mySwitch.counter >= filter)
{
//get ready for the next sequence
mySwitch.counter = 0;
//update to this new state
mySwitch.lastState = pinState;
//========================
//did this switch go closed ?
if (pinState == CLOSED)
{
digitalWrite(testLED, LEDon);
//2 seconds
commonTIMER.setInterval(2000ul);
commonTIMER.enableRestartTIMER();
//next state
mState = STATE1;
}
//========================
//did this switch go opened ?
else if (pinState == OPENED)
{
}
}
}
//===================================
//a valid switch change has not been confirmed
else
{
mySwitch.counter = 0;
}
//END of mySwitch.pin
//======================================================================== Next Switch
} //END of checkSwitches()
//================================================^================================================
i think you really need to see well written code to understand how to code. you both need to see how the language is used to do things as well as to see the structures and concepts for doing things.
for example knowing a particular language doesn't imply that you understand operating system concepts.
i learned a lot from unix, xinu and minix, but also from books on compilers. Kernighan's books on software tools and the unix programming environment also show a lot of small application code
and ironically the above don't address the concepts needed for embedded applications that interface to hardware