I am using a Arduino Mega.
I am trying to write a code that allows me to make a led blink with a certain on-off duration determined by a number entered on the serial monitor (for instance, 10 ms on- 10 ms off) that would automatically stop blinking after a given number of second (for instance after 3 seconds) until it receives a new number on the serial monitor, which would lead to a new blinking (possibly at a new frequency) for 3 seconds and so on..
I was able to write a short program code that allows me to use the serial monitor to determine the on-off duration of the led (see the code below). However, I could not figure out how to stop the loop after 3 seconds and, then, restart a new one when a new number if entered in the serial monitor. I wonder if someone could complete my code to achieve this?
Thanks in advance for your collaboration !
[code]
unsigned long blinkRate = 1000; //Default 1000 milliseconds between blinks
void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600);
Serial.println("Enter the blink delay length in milliseconds (try 100)");
}
void loop() {
if (Serial.available() > 0) {
blinkRate = Serial.parseInt();
Serial.println(blinkRate);
}
analogWrite(13, 255);
delay(blinkRate);
analogWrite(13, 0);
delay(blinkRate);
}
I could not figure out how to stop the loop after 3 seconds
One way :
Write a function that changes the state of the LED and call it from loop() at the required interval. Only call the function when a boolean is true. Start with the boolean false
Set the boolean to true and save the value of millis() when you want to start the blinking, then each time through loop() test whether the current value of millis() minus the start value is greater than the required period. If so, then set the boolean to false to stop the blinking
I am very grateful for your answer. I am sure this is a great idea, but unfortunately I am not advanced enough to understand what this all means/imply. Would you mind adapting/updating my code directly (I hope this does not violate the rules of the forum) ? I am a psychologist trying to set up an experiment to test people's flicker fusion threshold and I am getting lost with all this. Thanks in advance for your collaboration!
Thank you so much for your help ! Your code works almost perfectly and I am relieved to be "almost there".
There are still two minor issues:
(1) I need to led to be turned off at the end of the 3sec period. This is almost always the case with your code, but not always. By trial and error, it seems that when the duration of the delay (entered in the serial monitor) is a multiple of "8" (8, 16, 14, 32...), then, (1) the led stays on after the 3-sec period and (2) it stays on for all the next trials/durations until I close and open again the serial monitor.
(2) In my original code, the use of the "analogWrite" on the pin allowed me to set the intensity of the on and off phase on a scale from 0 to 255, which was very handy. It allowed to test participants' ability to detect flicker at different intensities. I tried to replace the digital to analog in your code but I can't make it work. Any help on this is welcome.
I hope you have an excellent St Patrick Day !
Gilles
In my original code, the use of the "analogWrite" on the pin allowed me to set the intensity of the on and off phase on a scale from 0 to 255,
You will need to change the LED blinking code in the for loop to something like you used so that each for loop step turns it on then off but, you will also need to divide the number of blinks by 2. Make the last digitalWrite() turn the LED off and you will solve the other problem at the same time
It seems that I managed to solve these two minor issues myself, thanks to your guidance and very clear example.
I can now control the on- and off- intensity of the led and make sure that the led turns off at the end of the blinking period. The only thing that I am not 100% sure about is that the blinking duration is exactly 3 sec. Do you confirm that this is the case? Once again thank you !
Gilles
[code]
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(10, OUTPUT);
analogWrite(10, 0);
}
void loop()
{
Serial.println("Enter the blink delay length in milliseconds (try 100)");
while (Serial.available() == 0);
int delayTime = Serial.parseInt();
int numberOfBlinks = 1500 / delayTime;
Serial.println("blinking");
for (int blink = 0; blink < numberOfBlinks; blink++)
{
analogWrite(10, 60);
delay(delayTime);
analogWrite(10, 30);
delay(delayTime);
}
analogWrite(10, 0);
}
If you just want it to work, this works. (using libraries)
Type in..
period 500 -- will give you period of 500 ms
pulse 20 -- will give you pulse width of 20 ms
blink -- restart the blinking without numbers changed
time 4000 -- Sets the blinking duration to 4 seconds.
You will need to install from the library manager, LC_baseTools and LC_lilParser to compile this.
#include <lilParser.h>
#include <blinker.h>
enum commands { noCommand, // ALWAYS start with noCommand. Or something simlar.
periodMS, // The rest is up to you. help would be a good one. Have it list
pulseMS, // What the other commands are, how they work and what they do.
blinkTime, // Set the time we'll blink for.
blink //
}; // Our list of commands.
lilParser ourParser; // The parser object.
blinker ourBlinker(13);
timeObj blinkTimer(3000);
void setup(void) {
Serial.begin(9600);
ourBlinker.setOnOff(false); // Make sure it's off.
ourParser.addCmd(periodMS,"period"); // Add periodMS
ourParser.addCmd(pulseMS,"pulse"); // Add pulseMS command
ourParser.addCmd(blinkTime,"time"); // Add blink duration time command
ourParser.addCmd(blink,"blink"); // Add blink command
}
void turnBlinkerOn(void) {
ourBlinker.setOnOff(true); // Turn it on.
blinkTimer.start(); // Start our blink timer.
}
// Your loop where it parses out all your typings.
void loop(void) {
char inChar;
int command;
idle(); // Runs background stuff.
if (Serial.available()) { // If serial has some data..
inChar = Serial.read(); // Read out a charactor.
Serial.print(inChar); // If using development machine, echo the charactor.
command = ourParser.addChar(inChar); // Try parsing what we have.
switch (command) { // Check the results.
case noCommand : break; // Nothing to report, move along.
case periodMS : setPeriod(); break; // Set the period (duration)
case pulseMS : setPulse(); break; // Set the pulse width.
case blinkTime : setTime(); break; // Set time duration for blinking.
case blink : turnBlinkerOn(); break; // Just turn on the blinker.
default : Serial.println("What?"); break; // No idea. Try again?
}
}
if (blinkTimer.ding()) { // If the blink timer has expired..
ourBlinker.setOnOff(false); // Turn it off.
blinkTimer.reset(); // Reset our blink timer.
}
}
/************************************************************************************
*************************************************************************************
Now the list of command handlers you call from
your main loop() when commands are parsed.
*************************************************************************************
*************************************************************************************/
// Grab a number and set period.
void setPeriod(void) {
char* param;
int numMs;
if (ourParser.numParams()) { // If they typed in somethng past the command.
param = ourParser.getParamBuff(); // We get the first parameter, assume its the new folder's name.
numMs = atoi(param); // Read this as an integer.
free(param); // Dump the parameter buffer ASAP.
ourBlinker.setPeriod(numMs); // Set the blinker.
turnBlinkerOn(); // Fire ujp the blinkings.
}
}
// Grab a number and set pulse..
void setPulse(void) {
char* param;
int numMs;
if (ourParser.numParams()) { // If they typed in somethng past the command.
param = ourParser.getParamBuff(); // We get the first parameter, assume its the new folder's name.
numMs = atoi(param); // Read this as an integer.
free(param); // Dump the parameter buffer ASAP.
ourBlinker.setPulse(numMs); // Set the blinker.
turnBlinkerOn(); // Fire ujp the blinkings.
}
}
// Grab a number and set pulse..
void setTime(void) {
char* param;
int numMs;
if (ourParser.numParams()) { // If they typed in somethng past the command.
param = ourParser.getParamBuff(); // We get the first parameter, assume its the new folder's name.
numMs = atoi(param); // Read this as an integer.
free(param); // Dump the parameter buffer ASAP.
blinkTimer.setTime(numMs); // Set the blinker.
turnBlinkerOn(); // Fire ujp the blinkings.
}
}