Hello boys and girls, I want to make a program where I can turn on and off a digital pin for a specified amount of time. I would have made it with "delay" but it will halt the complete program so my question how would you guys do it? My thought would be using the millis() function but then I hit a wall.
thx, but it only shows that it blinks for 50% of the time and I have two different times that can change.
Like this?
// constants won't change. Used here to set a pin number:
const int ledPin = LED_BUILTIN; // the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const long ON_interval = 500; // interval at which to blink ON (milliseconds)
const long OFF_interval = 1500; // interval at which to remain OFF (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop() {
// here is where you'd put code that needs to be running all the time.
unsigned long currentMillis = millis();
if (ledState == LOW) {
if (currentMillis - previousMillis >= OFF_interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
ledState = HIGH;
}
} else {
if (currentMillis - previousMillis >= ON_interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
ledState = LOW;
}
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
You need to use a variable to adjust the ‘delay’ period used by millis()
You can change that variable anytime the code is running, and next time the millis() value is checked, it will use the updated interval…
The trick is to test millis() frequently enough so your program is responsive.
thx, for that programm. With your help I was able to implement it into my bigger one.
The code is implemented but I have the problem that it stays on for some milliseconds and off for 2s when I set the t to 2000ms and the dc to 50%.
//-----Start/Stop-Dynamic-----
unsigned long currentMillis = millis();
if (dynamic_test == true && startstop == false) {
on = t * (dc / 100);
off = t * (1-(dc / 100));
if (FetState == LOW) {
if (currentMillis - previousMillis >= off) {
previousMillis = currentMillis;
FetState = HIGH;
}
} else {
if (currentMillis - previousMillis >= on) {
previousMillis = currentMillis;
FetState = LOW;
}
}
digitalWrite(Fet, FetState);
digitalWrite(Led_green, HIGH);
digitalWrite(Led_red, LOW);
submenu_stop.update();
delay(10);
} else if (dynamic_test == false && startstop == false) {
digitalWrite(Led_green, LOW);
digitalWrite(Led_red, HIGH);
}
the definition of the variables:
unsigned short t = 0;
byte dc = 1;
unsigned long on = 0;
unsigned long off = 0;
unsigned long previousMillis = 0;
Hello 7ower3efender
Consider this modified BlinkWithOutDelay example of the IDE.
An array is your friend.
// constants won't change. Used here to set a pin number:
const int ledPin = LED_BUILTIN;// the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const uint32_t interval[] = {1000,100}; // interval at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval[ledState]) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// 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);
}
}
Have a nice day and enjoy coding in C++.
It works already fine the problem that I have is my calculation of on and off times from the time and from the dutycycle that I put into my uC with an encoder. I already tested if I acquire the wrong values for t and dc but they are all good. But I get the wrong on and off times.
The problem is it cant calculate floating point. The solution is there: Calculation with different datatypes - #4 by oqibidipo
On another thread. That you had. On this topic. So I waste time.
Yes I am aware that there are already topics out there with the same name...
Self awareness. You might have just said it was you on the other thread.
Don't start new threads.
Do you have others scattered about?
Good luck and good day sir.
a7
I only had two others but only this one was the same as another.
look this over
the on/off values can be modified at run time.
an enable bit could be used to process that particular pin
struct Valve {
const byte Pin;
unsigned long MsecOn;
unsigned long MsecOff;
const char *desc;
unsigned long msecLst;
unsigned long msecPeriod;
};
Valve valves [] = {
{ 10, 500, 500, "V1" },
{ 11, 100, 300, "V2" },
{ 12, 250, 100, "V3" },
{ 13, 450, 200, "V4" },
};
#define Nvalve (sizeof(valves)/sizeof(Valve))
enum { Off = HIGH, On = LOW };
// -----------------------------------------------------------------------------
void
loop (void)
{
unsigned long msec = millis ();
Valve *v = valves;
for (unsigned n = 0; n < Nvalve; n++, v++) {
if (msec - v->msecLst > v->msecPeriod) {
v->msecLst = msec;
Serial.println (v->desc);
if (On == digitalRead (v->Pin)) {
v->msecPeriod = v->MsecOff;
digitalWrite(v->Pin, Off);
}
else {
v->msecPeriod = v->MsecOn;
digitalWrite(v->Pin, On);
}
}
}
}
void
setup (void)
{
Serial.begin (9600);
for (unsigned n = 0; n < Nvalve; n++) {
pinMode (valves [n].Pin, OUTPUT);
}
}
Yes I am aware that there are already topics out there with the same name but its a little bit different. I have a working code but the problem is the calculation of the on and off times is incorrect. On the serial monitor it shows that the t and dc values are correct but the on and off values are incorrect for example:
I type in for t 1000 and for dc 50 so normally it should calculate the following: for the on time it should then show 500 and for the off time also 500 but it shows 0 for the on time and 1000 for the off time.
A short note the dc stands for dutycycle and is a value between 1 and 99 and is percentage value. The variable t is time in ms.
//-----Start/Stop-Dynamic-----
unsigned long currentMillis = millis();
if (dynamic_test == true && startstop == false) {
on = t * (dc / 100);
off = t * (1-(dc / 100));
if (FetState == LOW) {
if (currentMillis - previousMillis >= off) {
previousMillis = currentMillis;
FetState = HIGH;
}
} else {
if (currentMillis - previousMillis >= on) {
previousMillis = currentMillis;
FetState = LOW;
}
}
digitalWrite(Fet, FetState);
digitalWrite(Led_green, HIGH);
digitalWrite(Led_red, LOW);
submenu_stop.softUpdate();
delay(10);
} else if (dynamic_test == false && startstop == false) {
FetState = LOW;
digitalWrite(Fet, FetState);
digitalWrite(Led_green, LOW);
digitalWrite(Led_red, HIGH);
}
The following code is used to assign the specific datatype:
unsigned short t = 0;
byte dc = 1;
unsigned long on = 0;
unsigned long off = 0;
unsigned long previousMillis = 0;
I already know that the problem is in that area:
on = t * (dc / 100);
off = t * (1-(dc / 100));
50 / 100 is zero in integer arithmetic.
1 - 0 is 1.
Oh, but how can I solve that problem?
on = t * (dc / 100.0);
off = t * (1-(dc / 100.0));
This forces the calculations to use floating point arithmetic.
big thx
When using integers: always multiply first, than divide...
on=(t*dc+50)/100;
50 is added to make rounding correct.
You might need uint32_t for larger t and/or dc.
... but be careful of using int arithmetic, if there's a risk of int overflow.
