Is it possible to replace delay with millis in this "for loop" ?
My goal is to draw one pixel every 100 ms, without delay.
TFT Screen..
for (int pixel = 80; pixel < 122; pixel++) {
myGLCD.drawPixel(pixel, 206);
delay(100);
}
Is it possible to replace delay with millis in this "for loop" ?
My goal is to draw one pixel every 100 ms, without delay.
TFT Screen..
for (int pixel = 80; pixel < 122; pixel++) {
myGLCD.drawPixel(pixel, 206);
delay(100);
}
AndyKe:
Is it possible to replace delay with millis in this "for loop" ?
My goal is to draw one pixel every 100 ms, without delay.
TFT Screen..for (int pixel = 80; pixel < 122; pixel++) {
myGLCD.drawPixel(pixel, 206);
delay(100);
}
Try this out
for (int pixel = 80; pixel < 122; ) {
myGLCD.drawPixel(pixel, 206);
static unsigned long _timer;
if((millis() - _timer) >= 100){
_timer = millis();
pixel++;
}
}
Z
Of course it's possible, but what's the point? The whole thing is still blocking, so you've gained absolutely nothing. You've just replaced one bad design with a different bad design.
Regards,
Ray L.
Don't use a for loop, let the loop() function do it for you.
Save the millis() value at the time that the start action happens. Then, each time through loop(), check whether the required wait period has elapsed by subtracting the start time from the millis() value now. If the period has elapsed then draw the pixel and save the start time for the next activity. Keep a count of how many times the period has elapsed in order to use the value of the counter as you do in your for loop.
RayLivingston:
Of course it's possible, but what's the point? The whole thing is still blocking, so you've gained absolutely nothing. You've just replaced one bad design with a different bad design.Regards,
Ray L.
Agreed but it still can be done in a non blocking way with for loop like this:
static unsigned long _timer;
for (static int pixel = 80; ((millis() - _timer) >= 100) && ( pixel < 122); pixel++) {
_timer = millis();
myGLCD.drawPixel(pixel, 206);
}
Z
I have no idea what the hell you're trying to do, zhomeslice. Whatever it is, it's horribly wrong.
The for loop needs to be changed to an if block. If it's time to draw the next pixel, draw the pixel, reset the timer and advance to the next index. If it's not yet time, move on to something else. That is the essence, the TL;DR version of a non-blocking timed sequence.
Jiggy-Ninja:
I have no idea what the hell you're trying to do, zhomeslice. Whatever it is, it's horribly wrong.The for loop needs to be changed to an if block. If it's time to draw the next pixel, draw the pixel, reset the timer and advance to the next index. If it's not yet time, move on to something else. That is the essence, the TL;DR version of a non-blocking timed sequence.
Lol , agreed it is crazy but possible! And yes I would recommend not doing this anywhere! But the question is not is it correct programming to do it with a for loop. The question is, is it possible. The answer is yes and it is possible to do it in a non blocking way.
Z
zhomeslice:
Agreed but it still can be done in a non blocking way with for loop like this:static unsigned long _timer;
for (static int pixel = 80; ((millis() - _timer) >= 100) && ( pixel < 122); pixel++) {
_timer = millis();
myGLCD.drawPixel(pixel, 206);
}
Z
Well, that will at least update pixel 80 every 100 mSec....
Regards,
Ray L.
RayLivingston:
Well, that will at least update pixel 80 every 100 mSec....Regards,
Ray L.
Static keyword allows it to count up. I did forget about the reset back to 80 once it gets to 122.
Z
zhomeslice:
Static keyword allows it to count up. I did forget about the reset back to 80 once it gets to 122.
Z
And what happens to this expression:
((millis() - _timer) >= 100)
after it runs the first pass of the loop with pixel=80?
Regards,
Ray L.
It maybe confusing, but it does sequence through pixel values. The reason is that local static variables are only initialized once, so the pixel variable is not reset to 80 when the for loop comes around each time.
It's still a terrible construction because there's no way to reset the pixel variable from the outside, since it's local to the for loop. It will run once through the sequence and never again.
Try it for yourself.
void setup()
{
Serial.begin(9600);
}
void loop()
{
static unsigned long _timer;
for (static int pixel = 80; ((millis() - _timer) >= 100) && ( pixel < 122); pixel++) {
_timer = millis();
Serial.println(pixel);
}
}
OK so it does work, but to me, that piece of code belongs in one of those obfuscated code competitions, and it is a really demented, and obtuse, way to implement the functionality, since it seems to depend on an idiosyncratic behavior of the compiler. This is an order of magnitude simpler, and more obvious:
static unsigned long _timer = millis();
static int pixel;
...
if ((millis() - _timer) >= 100)
{
_timer = millis();
myGLCD.drawPixel(pixel, 206);
if (++pixel > 121)
pixel = 80;
}
Regards,
Ray L.
void setup()
{
Serial.begin(9600);
}
void loop()
{
for (static unsigned long _timer,pixel; ((millis() - _timer) >= 100); _timer = millis()){
pixel = ++pixel%41;
Serial.println(pixel + 80);
}
Try this out.
Z
RayLivingston:
OK so it does work, but to me, that piece of code belongs in one of those obfuscated code competitions, and it is a really demented, and obtuse, way to implement the functionality, since it seems to depend on an idiosyncratic behavior of the compiler. This is an order of magnitude simpler, and more obvious:
It's not an idiosyncrasy, it is how static is defined to work in a local context.
I agree 110% with the rest of your statement though. "Demented and obtuse" indeed.
zhomeslice:
void setup()
{
Serial.begin(9600);
}
void loop()
{
for (static unsigned long _timer,pixel; ((millis() - _timer) >= 100); _timer = millis()){
pixel = ++pixel%41;
Serial.println(pixel + 80);
}
Try this out. Z
Now you're just being an ass. Stop confusing the poor newbie with horribly convoluted patterns. I had to look up one of those statements to make sure it didn't have undefined sequencing. I don't even think most people on this forum would even be able to spot that as a potential issue.
Jiggy-Ninja:
It's not an idiosyncrasy, it is how static is defined to work in a local context.I agree 110% with the rest of your statement though. "Demented and obtuse" indeed.Now you're just being an ass. Stop confusing the poor newbie with horribly convoluted patterns. I had to look up one of those statements to make sure it didn't have undefined sequencing. I don't even think most people on this forum would even be able to spot that as a potential issue.
Sorry, I will not torture them any more.
Z
Jiggy-Ninja:
It's not an idiosyncrasy, it is how static is defined to work in a local context.
It's not the static context that's confusing. It's using a static interator in a for loop. i first used c in about 1981, and spent many years writing code, and almost 20 years managing teams of programmers writing c and c++ code. In all that time I never once saw the iterator in a for loop declared as static like that. What's really bizarre about the behavior in this case is that the "static" initializer over-rides the for loop initialization, which makes the "int i=80;" initializer REALLY misleading, since it happens ONLY the very first time that loop is executed, and never again. I'd be amazed if that particular usage of the static modifier is actually documented to behave that way. I've looked, and can't find any reference that defines such a wacky usage of static, and have to wonder if the actual behavior would be, technically, undefined, making it compiler-dependent. Do you have any c or c++ language reference that would define the expected behavior?
Regards,
Ray L.
RayLivingston:
It's not the static context that's confusing. It's using a static interator in a for loop. i first used c in about 1981, and spent many years writing code, and almost 20 years managing teams of programmers writing c and c++ code. In all that time I never once saw the iterator in a for loop declared as static like that. What's really bizarre about the behavior in this case is that the "static" initializer over-rides the for loop initialization, which makes the "int i=80;" initializer REALLY misleading, since it happens ONLY the very first time that loop is executed, and never again. I'd be amazed if that particular usage of the static modifier is actually documented to behave that way. I've looked, and can't find any reference that defines such a wacky usage of static, and have to wonder if the actual behavior would be, technically, undefined, making it compiler-dependent. Do you have any c or c++ language reference that would define the expected behavior?Regards,
Ray L.
Thanks Ray,
Your insight is most valuable.
I'm self taught and find it intriguing to understand unique ways of programming. This unusual way of using the for loop has inspired me, and got me in trouble I'm posting both ways to clarify the correct way of programming the delay.
void setup()
{
Serial.begin(9600);
}
void loop()
{
for (static unsigned long _timer; ((millis() - _timer) >= 1000); _timer = millis()){
Serial.println("test");
}
}
And the correct way to do blink without delay:
void setup()
{
Serial.begin(9600);
}
void loop()
{
{// this is to isolate _timer in a similar way the for loop does
static unsigned long _timer;
if ( (millis() - _timer) >= 1000){
_timer = millis();
Serial.println("test");
}
}
}
These do the same exact thing. The second example is correct as I understand proper coding.
Z
@OP, if you haven't been chased away by the demented obscurity, go with UKHeliBob's reply#3; ignore zhomeslice's showing off.
nyphot:
@OP, if you haven't been chased away by the demented obscurity, go with UKHeliBob's reply#3; ignore zhomeslice's showing off.
You could say i got confused when i went back to this thread this early morning xD I see now, that a for loop is a bad design solving my problem.
And yes, You're all right about my lack of experience. Im an absolute newbie xD So the conclusion would be never to use a "for loop" for my specific task.
This would do the job then..?
static unsigned long _timer = millis();
static int pixel;
...
if ((millis() - _timer) >= 100)
{
_timer = millis();
myGLCD.drawPixel(pixel, 206);
if (++pixel > 121)
pixel = 80;
}
You will have to initialise the static int pixel with 80; by default it's initialised with 0. So the first time it will run from 0..121.