unsigned long PERIOD1 = 25; // interval at which to blink (microseconds) = 20 Hz
unsigned long PERIOD2 = 12.5; // interval at which to blink (microseconds) = 40 Hz
unsigned long PERIODact = 5000; // amount of time to keep blinking (milliseconds)
unsigned long PERIODbtn = 150; // (microseconds)
OK. I went thru it in a bit more detail. Try this:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define BTN_PRESSED HIGH //logic level of pin when button is pressed
// Pin assignement
const uint8_t ledPin = 7;
const uint8_t btnPin = 8;
LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
//LiquidCrystal_I2C lcd(0x3f, 16, 2);
enum fcnMode
{
OFF=0,
BLINK1,
BLINK2,
NBSTATE
}; // OFF = 0 and NBSTATE=7
uint8_t
ledState = LOW; // ledState used to set the led
uint8_t
btnLast;
uint8_t
funcState = OFF;
uint32_t
currentTime1,
currentTime2,
currentTimebtn,
currentTimeact1,
currentTimeact2; // will store current time
uint32_t
previousTime1,
previousTime2,
previousTimebtn,
previousTimeact1,
previousTimeact2; // will store last time led was updated
const uint32_t
PERIOD1 = 25000ul, // interval at which to blink (microseconds) = 20 Hz
PERIOD2 = 12500ul, // interval at which to blink (microseconds) = 40 Hz
PERIODact = 5000ul, // amount of time to keep blinking (milliseconds)
PERIODbtn = 50ul; // button read interval (milliseconds)
/******************************************************************\
SETUP
\******************************************************************/
void setup()
{
lcd.begin(16, 2); // LCD
pinMode(btnPin, INPUT_PULLUP);
btnLast = digitalRead( btnPin);
pinMode(ledPin, OUTPUT);
}
/******************************************************************\
Main Function of the code
\******************************************************************/
void loop()
{
buttonPressed();
setMode();
}
/******************************************************************
SUBFUNCTIONS
\******************************************************************/
void buttonPressed()
{
currentTimebtn = millis();
if (currentTimebtn - previousTimebtn >= PERIODbtn)
{
// push button delay to prevent fast toggling between funcstates when pressed
previousTimebtn = currentTimebtn;
uint8_t btnNow = digitalRead( btnPin );
if( btnNow != btnLast )
{
btnLast = btnNow;
if( btnNow == BTN_PRESSED )
{
funcState += 1;
if (funcState >= NBSTATE) //changed from '4'
funcState = 0;
lcd.clear();
switch( funcState )
{
case OFF:
digitalWrite(ledPin, LOW);
lcd.setCursor(4,0);
lcd.print("*Idle*"); // LCD main idle screen
break;
case BLINK1:
lcd.setCursor(2,0);
lcd.print("Mode: 20 Hz"); // LCD shows selected mode
currentTimeact1 = millis();
previousTime1 = micros();
break;
case BLINK2:
lcd.setCursor(2,0);
lcd.print("Mode: 40 Hz"); // LCD shows selected mode
currentTimeact2 = millis();
previousTime2 = micros();
break;
default:
break;
}//switch
}//if button is pressed
}//if now does not equal last
}//if time for a read
}//buttonPressed
void setMode()
{
// All Off
switch (funcState)
{
case OFF:
//do nothing
break;
case BLINK1:
blinkled1();
break;
case BLINK2:
blinkled2();
break;
}
}
void blinkled1()
{
currentTime1 = micros();
if( (currentTime1 - previousTime1) >= PERIOD1 )
{
// defines the blinking frequency
// save the last time you blinked the led
previousTime1 = currentTime1;
// if the led is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the led with the ledState of the variable:
digitalWrite(ledPin, ledState);
}//if
if( (millis() - previousTimeact1) >= PERIODact )
{
// checks if time after the start is equal or longer than 5 seconds to stop blinking
ReturnToIdleState();
}//if
}//blinkled1
void blinkled2()
{
currentTime2 = micros();
if( (currentTime2 - previousTime2) >= PERIOD2 )
{
// defines the blinking frequency
// save the last time you blinked the led
previousTime2 = currentTime2;
// if the led is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the led with the ledState of the variable:
digitalWrite(ledPin, ledState);
}//if
if( (millis() - previousTimeact2) >= PERIODact )
{
// checks if time after the start is equal or longer than 5 seconds to stop blinking
ReturnToIdleState();
}//if
}//blinkled2
void ReturnToIdleState( void )
{
lcd.clear();
funcState = OFF; //go back to iddle screen
digitalWrite(ledPin, LOW);
lcd.setCursor(4,0);
lcd.print("*Idle*"); // LCD main idle screen
}//ReturnToIdleState
This one if press button fast as soon as the program was loaded in arduino memory, or arduino is reseted, it works for 5 secs and stops, and then it does not matter how many times i hit the button again, it is still stuck in * Idle * and nothing happens.
It seem that the 5 secs counter starts as soon as arduino starts running the program and the operation below can not get the result equal or longer than 5 secs like it was suposed to do.
if( (millis() - previousTimeact1) >= PERIODact ) // checks if time after the start is equal or longer than 5 seconds to stop blinking
I guess the timer starts counting 1...2...3...4...5...6...7...8...9...10...infintely, so the program only gets 5 sec once, and then every math operation after, the result value is always higher than 5 sec, and it automatically stays in iddle forever.
I admittedly haven't tried it on an Arduino here; if time permits tomorrow I'll give it a try.
In the meantime, how is your switch wired? I noticed that you look for a HIGH to indicate the button is pressed but also use INPUT_PULLUP. I switched the code to look for a low-to-high transition but that still may not work right if the switch it wired weirdly.
May I ask you why? You won't be able to see a 40 Hz blinking when looking directly at it. You may be able to perceive some flicker with your peripheral vision (which is more sensitive to movement), but that's all. Perchance you are trying to emulate PWM? What is your prototype about?
No. It isn't. Setting currentTimeact1 is not the same as setting previousTimeact1 to the right value ("to millis()") in the right place ("when the button changes funcState").
OK, found the problem: I was updating currentTimeact1 instead of previousTimeact1 in the button-press section. Seems to work now:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define BTN_PRESSED HIGH //logic level of pin when button is pressed
// Pin assignement
const uint8_t ledPin = 7; //LED_BUILTIN; //built-in for debug
const uint8_t btnPin = 8;
//LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
LiquidCrystal_I2C lcd(0x3f, 16, 2);
enum fcnMode
{
OFF=0,
BLINK1,
BLINK2,
NBSTATE
}; // OFF = 0 and NBSTATE=7
uint8_t
ledState = LOW; // ledState used to set the led
uint8_t
btnLast;
uint8_t
funcState = OFF;
uint32_t
currentTime1,
currentTime2,
currentTimebtn,
currentTimeact1,
currentTimeact2; // will store current time
uint32_t
previousTime1,
previousTime2,
previousTimebtn,
previousTimeact1,
previousTimeact2; // will store last time led was updated
const uint32_t
PERIOD1 = 25000ul, // interval at which to blink (microseconds) = 20 Hz
PERIOD2 = 12500ul, // interval at which to blink (microseconds) = 40 Hz
PERIODact = 5000ul, // amount of time to keep blinking (milliseconds)
PERIODbtn = 50ul; // button read interval (milliseconds)
/******************************************************************\
SETUP
\******************************************************************/
void setup()
{
Serial.begin(9600); //debug
lcd.begin(16, 2); // LCD
pinMode(btnPin, INPUT);
btnLast = digitalRead( btnPin);
pinMode(ledPin, OUTPUT);
}
/******************************************************************\
Main Function of the code
\******************************************************************/
void loop()
{
buttonPressed();
setMode();
}
/******************************************************************
SUBFUNCTIONS
\******************************************************************/
void buttonPressed()
{
currentTimebtn = millis();
if (currentTimebtn - previousTimebtn >= PERIODbtn)
{
// push button delay to prevent fast toggling between funcstates when pressed
previousTimebtn = currentTimebtn;
uint8_t btnNow = digitalRead( btnPin );
if( btnNow != btnLast )
{
btnLast = btnNow;
if( btnNow == BTN_PRESSED )
{
funcState += 1;
if (funcState >= NBSTATE) //changed from '4'
funcState = 0;
//Serial.print( "Func state: " ); Serial.println( funcState );
lcd.clear();
switch( funcState )
{
case OFF:
digitalWrite(ledPin, LOW);
lcd.setCursor(4,0);
lcd.print("*Idle*"); // LCD main idle screen
break;
case BLINK1:
lcd.setCursor(2,0);
lcd.print("Mode: 20 Hz"); // LCD shows selected mode
previousTimeact1 = millis(); //activity timer
previousTime1 = micros(); //blink timer
break;
case BLINK2:
lcd.setCursor(2,0);
lcd.print("Mode: 40 Hz"); // LCD shows selected mode
previousTimeact2 = millis();
previousTime2 = micros();
break;
default:
break;
}//switch
}//if button is pressed
}//if now does not equal last
}//if time for a read
}//buttonPressed
void setMode()
{
// All Off
switch (funcState)
{
case OFF:
//do nothing
break;
case BLINK1:
blinkled1();
break;
case BLINK2:
blinkled2();
break;
}
}
void blinkled1()
{
currentTime1 = micros();
if( (currentTime1 - previousTime1) >= PERIOD1 )
{
// defines the blinking frequency
// save the last time you blinked the led
previousTime1 = currentTime1;
// if the led is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the led with the ledState of the variable:
digitalWrite(ledPin, ledState);
}//if
if( (millis() - previousTimeact1) >= PERIODact )
{
// checks if time after the start is equal or longer than 5 seconds to stop blinking
ReturnToIdleState();
}//if
}//blinkled1
void blinkled2()
{
currentTime2 = micros();
if( (currentTime2 - previousTime2) >= PERIOD2 )
{
// defines the blinking frequency
// save the last time you blinked the led
previousTime2 = currentTime2;
// if the led is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the led with the ledState of the variable:
digitalWrite(ledPin, ledState);
}//if
if( (millis() - previousTimeact2) >= PERIODact )
{
// checks if time after the start is equal or longer than 5 seconds to stop blinking
ReturnToIdleState();
}//if
}//blinkled2
void ReturnToIdleState( void )
{
lcd.clear();
funcState = OFF; //go back to iddle screen
digitalWrite(ledPin, LOW);
lcd.setCursor(4,0);
lcd.print("*Idle*"); // LCD main idle screen
}//ReturnToIdleState
@ johnwasser
@ Blackfin
First of all i would like to thank both of you guys, @ johnwasser your comment just made my first code work smoothly tha way i needed.
And also special thanks to @Blackfin for your effort to help me, your code also works the way it was supposed to do. Unfortunately, I can't mark both of your replies as a solution, but it is finally solved. It has been very important all the replies i got from the community, as a beginer i'm learning with you guys, i hope in the future i'll be able to help others as far as possible, as i get knowlodge. Thanks!