If you look to my program, I use a delay() outside the loop, but how can I avoid this? I don't want to pause the whole code (and I thought that's what a delay does...)
void setup() {
pinMode (6, INPUT); //1 button
pinMode (2, OUTPUT); //LED 1
pinMode (3, OUTPUT); //LED 2
pinMode (4, OUTPUT); //LED 3
pinMode (5, OUTPUT); //LED 4
}
unsigned long but1LastPress = 0;
const int buttonPressDelay = 600;
void loop() {
//Read the state of the button
int but1read = digitalRead(6);
//Button 1 is pressed
if ((but1read == HIGH) && ((millis() - but1LastPress) > buttonPressDelay)) {
but1LastPress = millis();
doButton1();
}else if ((but1read == LOW) && ((millis() - but1LastPress) > buttonPressDelay ))
but1LastPress = 0; // reset
}
void doButton1() {
Blink3Times();
}
void Blink3Times(){
for (int i=0; i < 3; i++){
for (int j=2; i <= 5; i++){
digitalWrite(j,LOW); //turn off the LEDS
}
delay(1000); //Wait 1 second
for (int j=2; i <= 5; i++){
digitalWrite(j,HIGH); //turn on the LEDS
}
delay(1000); //Wait 1 second
}
}
Thanks for the respond, it seems to work but can I add something so you can call the function updateLedState and choose how long they will blink?
const int Led1 = 2; // the pin numbers for the LEDs
const int Led2 = 3;
const int Led3 = 4;
const int Led4 = 5;
const int Led1Interval = 150; // number of millisecs between blinks
const int Led2Interval= 2500;
const int Led3Interval = 4500;
const int Led4Interval = 4500;
const int blinkDuration = 150; // number of millisecs that Led's are on - all three leds use this
byte Led1State = LOW; // used to record whether the LEDs are on or off
byte Led2State = LOW; // LOW = off
byte Led3State = LOW;
byte Led4State = LOW;
unsigned long currentMillis = 0; // stores the value of millis() in each iteration of loop()
unsigned long previousOnBoardLedMillis = 0; // will store last time the LED was updated
unsigned long previousLed_A_Millis = 0;
unsigned long previousLed_B_Millis = 0;
void setup() {
Serial.begin(9600);
Serial.println("Starting blink without delay test"); // so we know what sketch is running
// set the Led pins as output:
pinMode(Led1, OUTPUT);
pinMode(Led2, OUTPUT);
pinMode(Led3, OUTPUT);
pinMode(Led4, OUTPUT);
}
void loop() {
// Notice that none of the action happens in loop() apart from reading millis()
// it just calls the functions that have the action code
currentMillis = millis(); // capture the latest value of millis()
// this is equivalent to noting the time from a clock
// use the same time for all LED flashes to keep them synchronized
blinkLEDs();
}
//========
void updateLedState() {
if (Led1State == LOW) {
// if the Led is off, we must wait for the interval to expire before turning it on
if (currentMillis - previousOnBoardLedMillis >= Led1Interval) {
// time is up, so change the state to HIGH
Led1State = HIGH;
// and save the time when we made the change
previousOnBoardLedMillis += Led1Interval;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else { // i.e. if onBoardLedState is HIGH
// if the Led is on, we must wait for the duration to expire before turning it off
if (currentMillis - previousOnBoardLedMillis >= blinkDuration) {
// time is up, so change the state to LOW
Led1State = LOW;
// and save the time when we made the change
previousOnBoardLedMillis += blinkDuration;
}
}
}
void blinkLEDs() {
// this is the code that actually switches the LEDs on and off
updateLedState();
digitalWrite(Led1, Led1State);
//digitalWrite(led_A_Pin, led_A_State);
//digitalWrite(led_B_Pin, led_B_State);
//digitalWrite(buttonLed_Pin, buttonLed_State);
}
BramWerbrouck:
Thanks for the respond, it seems to work but can I add something so you can call the function updateLedState and choose how long they will blink?
Yes just change the value of ledInterval. Or pass a value as a parameter - but then you need to change the function so it uses the parameter rather than the global variable ledInterval.
BramWerbrouck:
If I change te value of ledInterval, it just keeps blinking... Faster or slower, but it is still the same
I thought that is what you were asking for.
If you want the blinking to operate for 10 seconds (say) then the simplest way is to create a boolean variable called blinkInProgress and modify the blink function so it will work when that variable is true - but not if it is false.
When you want the blinking to start change the value to true and start another (separate) millis() timer. When that expires it will change the value back to false.
I tried the code and when I past yours in a new sketch, everything works fine, but when I want to add it to my code, it just do nothing...
boolean blinkState = false;
unsigned long startTime;
void blinkLEDs(unsigned long duration, int FREQUENCY)
{
static int lastCount = ;
if (millis() - startTime <= duration)
{
int count = (millis() - startTime) / FREQUENCY;
if ( count != lastCount)
{
digitalWrite(2, !digitalRead(2));
Serial.println(count);
}
lastCount = count;
} else {
digitalWrite(2, LOW);
blinkState = false;
}
}
void longpress() {
unsigned long start_hold = millis(); // mark the time
Serial.println("Please keep on pressing for 5 seconds..");
while (sw_state == LOW) {
if (modus == 1) break; //NO long press in mode_Seconds
sw_state = digitalRead(hold_pin); // read input value
if ((millis() - start_hold) >= HOLD_DELAY){ // for longer than HOLD_DELAY
Serial.println("LONG PRESS ACCEPTED");
if (modus == 0){
iLang = iLang +1;
int iSize = sizeof(lang) / sizeof(lang[0]); //determine the length of the array (buttons)
if (iLang >= iSize) iLang = 0;
EEPROM.write(0, iLang); //Store the chosen language onboard
Serial.print("Language changed to ");
Serial.println(lang[iLang]);
startTime = millis();
blinkState = true;
if (blinkState){
blinkLEDs(3000,250);
}
ShowLang(iLang);
}
//Give the position of the Hold_pin number in the array
int len = sizeof(buttons) / sizeof(buttons[0]); //determine the length of the array (buttons)
int wantedval = hold_pin;
int wantedpos;
for (int i=0; i<len; i++) {
if (wantedval = buttons[i]) {
wantedpos = i; //wantedpos = the position of the HOLD button in the arrray of the buttons
break; //break the loop after initialized
}
}
justpressed[wantedpos] = 0; //Reset the SHORT PRESS for the hold_pin
break; //break the loop after initialized
}
}
}
void longpress() {
unsigned long start_hold = millis(); // mark the time
Serial.println("Please keep on pressing for 5 seconds..");
while (sw_state == LOW) {
if (modus == 1) break; //NO long press in mode_Seconds
sw_state = digitalRead(hold_pin); // read input value
if ((millis() - start_hold) >= HOLD_DELAY){ // for longer than HOLD_DELAY
Serial.println("LONG PRESS ACCEPTED");
if (modus == 0){
iLang = iLang +1;
int iSize = sizeof(lang) / sizeof(lang[0]); //determine the length of the array (buttons)
if (iLang >= iSize) iLang = 0;
EEPROM.write(0, iLang); //Store the chosen language onboard
Serial.print("Language changed to ");
Serial.println(lang[iLang]);
startTime = millis();
blinkState = true;
if (blinkState){
blinkLEDs(3000);
}
ShowLang(iLang);
}
//Give the position of the Hold_pin number in the array
int len = sizeof(buttons) / sizeof(buttons[0]); //determine the length of the array (buttons)
int wantedval = hold_pin;
int wantedpos;
for (int i=0; i<len; i++) {
if (wantedval = buttons[i]) {
wantedpos = i; //wantedpos = the position of the HOLD button in the arrray of the buttons
break; //break the loop after initialized
}
}
justpressed[wantedpos] = 0; //Reset the SHORT PRESS for the hold_pin
break; //break the loop after initialized
}
}
}
into
void longpress() {
unsigned long start_hold = millis(); // mark the time
Serial.println("Please keep on pressing for 5 seconds..");
while (sw_state == LOW) {
if (modus == 1) break; //NO long press in mode_Seconds
sw_state = digitalRead(hold_pin); // read input value
if ((millis() - start_hold) >= HOLD_DELAY){ // for longer than HOLD_DELAY
Serial.println("LONG PRESS ACCEPTED");
startTime = millis();
blinkState = true;
while(blinkState == true) blinkLEDs(3000);
if (modus == 0){
iLang = iLang +1;
int iSize = sizeof(lang) / sizeof(lang[0]); //determine the length of the array (buttons)
if (iLang >= iSize) iLang = 0;
EEPROM.write(0, iLang); //Store the chosen language onboard
Serial.print("Language changed to ");
Serial.println(lang[iLang]);
ShowLang(iLang);
}
//Give the position of the Hold_pin number in the array
int len = sizeof(buttons) / sizeof(buttons[0]); //determine the length of the array (buttons)
int wantedval = hold_pin;
int wantedpos;
for (int i=0; i<len; i++) {
if (wantedval = buttons[i]) {
wantedpos = i; //wantedpos = the position of the HOLD button in the arrray of the buttons
break; //break the loop after initialized
}
}
justpressed[wantedpos] = 0; //Reset the SHORT PRESS for the hold_pin
break; //break the loop after initialized
}
}
}
So I changed the IF into a WHILE statement
now it works, but I have another issue:
It is not 1 LED that has to blink but 4! so I added in the blinkState()-function this:
void blinkLEDs(unsigned long duration){
Clear_CornerLEDS();
static int lastCount;
if (millis() - startTime <= duration){
int count = (millis() - startTime) / FREQUENCY;
if (count != lastCount){
digitalWrite(2, !digitalRead(2));
digitalWrite(3, !digitalRead(3));
digitalWrite(4, !digitalRead(4));
digitalWrite(5, !digitalRead(5));
Serial.println(count);
}
lastCount = count;
} else {
digitalWrite(2, LOW);
blinkState = false;
}
}
What I see is this: they blink very "weak", not on "full power" if you understand what I mean, is there any solution?
//blink LEDs
boolean blinkState = false;
unsigned long startTime;
//Corner LEDs (minutes)
const byte LEDs[] = {2, 3, 4, 5};
const int NUMLEDS = sizeof(LEDs);
// Here is where we define the buttons that we'll use. button "6" is the first, button "9" is the 4th, etc
const byte buttons[] = {6, 7, 8, 9};
#define DEBOUNCE 10 // button debouncer, how many ms to debounce, 5+ ms is usually plenty
// This handy macro lets us determine how big the array up above is, by checking the size
const int NUMBUTTONS = sizeof(buttons);
//track if a button is just pressed, just released, or 'currently pressed'
byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
byte previous_keystate[NUMBUTTONS], current_keystate[NUMBUTTONS];
const int HOLD_DELAY = 5000; // Sets the hold delay for the LONG PRESS
int sw_state = HIGH;
const int hold_pin = 6; //pin number for the LONG PRESS
void setup() {
//SETUP PINS
for (byte i=0; i< NUMBUTTONS; i++) {
pinMode (buttons[i], INPUT_PULLUP);
}
for (byte i=0; i< NUMLEDS; i++) {
pinMode (LEDs[i], OUTPUT);
}
}
void loop() {
byte thisSwitch=thisSwitch_justPressed();
switch(thisSwitch){
case 0:
Serial.println("switch 1 just pressed");
doButton1();
break;
case 1:
Serial.println("switch 2 just pressed");
doButton2();
break;
case 2:
Serial.println("switch 3 just pressed");
doButton3();
break;
case 3:
Serial.println("switch 4 just pressed");
doButton4();
break;
}
}
void Clear_CornerLEDS(){
for (int i=0;i<=NUMLEDS;i++)
digitalWrite(LEDs[i],LOW);
}
void Light_CornerLEDS(){
for (int i=0;i<=NUMLEDS;i++)
digitalWrite(LEDs[i],HIGH);
}
void doButton1() {
//do something
}
void doButton2() {
//do something
}
void doButton3() {
//do something
}
void doButton4() {
//do something
}
void check_switches()
{
static byte previousstate[NUMBUTTONS];
static byte currentstate[NUMBUTTONS];
static long lasttime;
byte index;
if (millis() < lasttime) {
// we wrapped around, lets just try again
lasttime = millis();
}
if ((lasttime + DEBOUNCE) > millis()) {
// not enough time has passed to debounce
return;
}
// ok we have waited DEBOUNCE milliseconds, lets reset the timer
lasttime = millis();
for (index = 0; index < NUMBUTTONS; index++) {
justpressed[index] = 0; //when we start, we clear out the "just" indicators
justreleased[index] = 0;
currentstate[index] = digitalRead(buttons[index]); //read the button
if (currentstate[index] == previousstate[index]) {
if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
// just pressed
justpressed[index] = 1;
sw_state = digitalRead(hold_pin);
//Long press??
if (sw_state==LOW) longpress();
}
else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
justreleased[index] = 1; // just released
}
pressed[index] = !currentstate[index]; //remember, digital HIGH means NOT pressed
}
previousstate[index] = currentstate[index]; //keep a running tally of the buttons
}
}
byte thisSwitch_justPressed() {
byte thisSwitch = 255;
check_switches(); //check the switches & get the current state
for (byte i = 0; i < NUMBUTTONS; i++) {
current_keystate[i]=justpressed[i];
if (current_keystate[i] != previous_keystate[i]) {
if (current_keystate[i]) thisSwitch=i;
}
previous_keystate[i]=current_keystate[i];
}
return thisSwitch; //return the index number (of the array) of which button is pressed
}
void longpress() {
unsigned long start_hold = millis(); // mark the time
Serial.println("Please keep on pressing for 5 seconds..");
//if (modus == 0){
while (sw_state == LOW) {
sw_state = digitalRead(hold_pin); // read input value
if ((millis() - start_hold) >= HOLD_DELAY){ // for longer than HOLD_DELAY
//initialize_is_running = true; // keep loop running even though reset_settings_pin is low
Serial.println("LONG PRESS ACCEPTED");
startTime = millis();
blinkState = true;
while(blinkState == true) blinkLEDs(1500,100);
justpressed[6] = 0; //Reset the SHORT PRESS for the hold_pin
break; //break the loop after initialized
}
}
}
void blinkLEDs(unsigned long duration, int FREQUENCY){
Clear_CornerLEDS();
static int lastCount;
if (millis() - startTime <= duration){
int count = (millis() - startTime) / FREQUENCY;
if (count != lastCount){
Light_CornerLEDS();
delay(10);
}
lastCount = count;
} else {
blinkState = false;
}
}
try to simplify your base code with a Bounce2.h library:
#include <Bounce2.h>
#define NUMBER_OF_SWITCHES 4
Bounce debouncer[NUMBER_OF_SWITCHES];
int oldValue[NUMBER_OF_SWITCHES];
byte switchPin[NUMBER_OF_SWITCHES] = {2,3,4,5}; //<<<<<<<<<<< set your switch pins here
void setup()
{
for (int i = 0; i < NUMBER_OF_SWITCHES; i++)
{
pinMode(switchPin[i],INPUT_PULLUP);
debouncer[i] = Bounce();
debouncer[i].attach(switchPin[i]);
debouncer[i].interval(5);
}
}
//
void loop()
{
for (int i = 0; i < NUMBER_OF_SWITCHES; i++)
{
debouncer[i].update();
int value = debouncer[i].read();
if (value != oldValue[i])
{
doSomethingWith(i);
}
oldValue[i] = value;
}
}
void doSomethingWith(int pinNumber) // your pin was triggered, so do something with it here...
{
//
}
then blend in what we did earlier... (compiles but not tested)
#include <Bounce2.h>
#define NUMBER_OF_SWITCHES 4
#define BLINK_DURATION 20000
#define BLINK_FREQUENCY 100
Bounce debouncer[NUMBER_OF_SWITCHES];
int oldValue[NUMBER_OF_SWITCHES];
byte switchPin[NUMBER_OF_SWITCHES] = {2,3,4,5}; //<<<<<<<<<<< set your switch pins here
byte ledPin[NUMBER_OF_SWITCHES] = {6,7,8,9};
unsigned long startTime[NUMBER_OF_SWITCHES];
boolean blinkState[NUMBER_OF_SWITCHES];
void setup()
{
for (int i = 0; i < NUMBER_OF_SWITCHES; i++)
{
pinMode(ledPin[i], OUTPUT);
pinMode(switchPin[i],INPUT_PULLUP);
debouncer[i] = Bounce();
debouncer[i].attach(switchPin[i]);
debouncer[i].interval(5);
}
}
//
void loop()
{
for (int i = 0; i < NUMBER_OF_SWITCHES; i++)
{
debouncer[i].update();
int value = debouncer[i].read();
if (value != oldValue[i])
{
activateLed(i);
}
oldValue[i] = value;
}
//
for (int i = 0; i < NUMBER_OF_SWITCHES; i++)
{
if (blinkState[i])
{
blinkForTime(i, BLINK_DURATION, BLINK_FREQUENCY); //<<<< you could also store Durations and Frequencies in an array e.g.:
//blinkForTime(i, blinkDuration[i], blinkFrequency[i]);
}
}
}
//
void activateLed(int pin) // your pin was triggered, so do something with it here...
{
if (!blinkState[pin])
{
startTime[pin] = millis();
blinkState[pin] = true;
}
}
//
void blinkForTime(int led, unsigned long duration, int frequency)
{
static int lastCount[NUMBER_OF_SWITCHES];
if (millis() - startTime[led] <= duration)
{
int count = (millis() - startTime[led]) / frequency;
if ( count != lastCount[led])
{
digitalWrite(ledPin[led], !digitalRead(ledPin[led]));
Serial.println(count);
}
lastCount[led] = count;
}
else
{
digitalWrite(ledPin[led], LOW);
blinkState[led] = false;
}
}
There seems to be an awful lot of code in Reply #12 if all that is wanted is to read 4 switches and flash some LEDs.
Do you really need any debounce stuff?
The switch code in the Thread planning an implementing a program is much simpler and does not need any explicit debouncing. It has two switches and it does not use arrays although arrays would be a good idea with 4 buttons.
BulldogLowell:
It sounds like you are trying to have 4 buttons with different outputs for long and short button presses... no?
If that is what you want just record millis() when the button changes from high to low (assuming active low) and record it again when the button changes from low to high. Have separate values for each button. Use the difference between the press and release times to decide whether you have a long or a short press (or a press that is just a bounce). That way the same code serves all the purposes. Then you can have action code like
if (buttonApressMills < minMillis) {
// ignore a bounce
}
else if (buttonApressMillis < longMillis) {
// do the short stuff
}
else {
// do the long stuff
}
BulldogLowell:
It sounds like you are trying to have 4 buttons with different outputs for long and short button presses... no?
This is exactly what I need. I'm building a little game for my children. 4 buttons and 4 LEDs...
Every button should have a short press action and a long press action and I need combinations too.. (but 1 & but 2, but 1 & but 3, but 1 & but 4, but 2 & but 3, but 2 & but 4 and but 3 & but 4)
I saw that the buttons work better with debouncing.. That's the reason I used this code, I found it somewhere on the net.. But perhaps you guys have a nicer and better code for doing that?