Delay doesn't seem to work

Hello! I'm trying to make a very simple animation using an OLED display, but the delays don't seem to, well, delay. Are there any other ways I should do this? This is the code:


#include <U8glib.h>
bool blink = true;

U8GLIB_SH1106_128X64 screen(U8G_I2C_OPT_NONE);

void draw(void) {
    screen.setFont(u8g_font_baby);
    screen.drawStr(0, 5, "Arduno linux Terminal © 2024");
    screen.drawStr(0, 11, "pc C://users/Ash>");
    if (blink == true) {
      screen.drawStr(76, 11, "#");
      blink = false;
      delay(1000);
    }
    else {
      screen.drawStr(76, 11, " ");
      blink = true;
      delay(1000);
    }
    
}

void setup() {
      screen.setColorIndex(1);
}

void loop() {
    screen.firstPage();
    do {
      draw();
    } while(screen.nextPage());
}

Please explain what the code should do, and what it does instead. Also identify the Arduino.

delay() works as expected for me.

ok, so there is supposed to be a hashtag that blinks on and off every second, but for me, its just off. The Arduino I'm using is an Uno.

What do you think the .firstPage() and .nextPage() functions are doing?

No idea. This is my first time using the library.

When using a new library, it is a good idea to look over the documentation, and try out some of the examples in the library, before trying random bits of code.

Yeah good point i probably should have done that.

ok i read through the documentation and didn't find anything that i think would help

Does the screen show anything at all? I'm not psychic.

Yeah. the screen displays

Arduno linux Terminal © 2024
pc C://users/Ash>

but it doesnt display the flashing '#'

Is it possible that your chosen library doesn't draw background colour pixels when it writes to the screen, but only draw foreground colour pixels? That would account for the effect you seem to be seeing.

what do .firstPage() and .nextPage() do and yes, this is a straw. It should blink at least once, be '#' for a whole second.

Notice that you call draw() an unknown number of times. The call to firstPage() initialises a process for calling nextPage() as many times as it takes to paint the entire display.

draw() should be as fast as possible, and written to paint the entire display. Which it will accomplish by being called N times.


void loop() {
    screen.firstPage();
    do {
      draw();
    } while(screen.nextPage());
}

It is inappropriate and just won't work to expect delay() in the draw method to do anything like it does when you talking about blinking some LEDs.

Rewrite draw() so it paints a frame of animation, then the next time you launch the firstPage/nextPage dance, draw() should paint the new frame.

Space out your launches of the hole thing with delay() if you must. Draw the '#' the first time, don't draw it the second time and so forth.

It just means doing the work a bit differently. You can get displays that will immediately reflect the effects of calls to draw characters or whatever. It is also possible that another library would take that traditional approach - the first/next thing is done to reduce the RAM required, and is more important for limited RAM and/or large displays.

What qualifies as limited and large vary with the circumstances.

a7

So draw a frame with a first/next loop

Then delay

Repeat until finished.

I should probably post the code here so here it is.


#include <U8glib.h>
int blink = 0;

U8GLIB_SH1106_128X64 screen(U8G_I2C_OPT_NONE);

void draw(void) {
  screen.drawStr(0, 5, "Arduno linux Terminal © 2024");
  screen.drawStr(0, 11, "pc C://users/Ash>");

  if (blink == 1) {
    screen.drawStr(76, 11, "_");
    blink = 0;
  }
  else if (blink == 0) {
    screen.drawStr(76, 11, " ");
    blink = 1;
  }
  
}

void setup() {
  screen.setFont(u8g_font_baby);
  screen.setColorIndex(1);
}

void loop(void) {

  screen.firstPage();
  do {
    draw();
  } while(screen.nextPage());

  blink++; //change blink number
  if (blink>1) // if the animation is at a non-existent frame...
  blink = 0; //reset anim
  delay(750);
}

1 Like

a little tip with blink only ever being 0 or 1

if ( blink == 1 ) ...... else blink must be 0, there's no need to ( check ).

Memory in AVR's is tight and people work by habit. On Arduino, make an effort to store small numbers like pin numbers and t/f flags should be in unsigned 8 bits IMO.

If you want bit for bit logic, here's a good tutorial:
1 byte is 8 bool (expression)s at once if you want.

Please one thing about delay() use. Finding a way to get around this took time and effort and you still have periods where no inputs like bottons or sensors can be read and acted on. Help on the subject is like a forum specialty, learning to fly.

well, thank you! I did notice the code seemed to take up more storage space than it should. And about the delay() usage, thanks for telling me that.

A simple delay(1) wastes 16000 cpu cycles.

If I have a void loop() runnint > 50,000 times a second,
a single delay(1) would make that < 1,000 Hz.

People have made 256 led cubes and run them fast with Unos.
You can too.

Wow, didn't know it was that bad!

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.