help speeding up code or display

hey guys,

I’m looking for some help with a small project I’m working on.

first, I’m using version 1.85 of the arduino IDE, with a heltec ESP32 wifi_kit_32 (

quick overview of what I’m after, them what I’ve accomplished. This is my first Arduino experience so please be gentle. I have been doing research but its such a specific issue I cant seem to find much info.

What I’m trying to do is use an IR break-beam type sensor (IR Break Beam Sensor - 5mm LEDs : ID 2168 : $6.50 : Adafruit Industries, Unique & fun DIY electronics and kits) in a hoop of sorts to record every time something crosses the threshold. I want to display the current count (of times the beam was tripped) on the integrated i2c ssd1306 .96" OLED, just the number, no text. In addition I want to flash a LED string every time the beam breaks, but I’m not there yet and I think I can handle that on my own.

I have the code working to count and output to the screen using the u8g2 library. The problem I’m having is that I cant get the screen/code to react fast enough for my purposes, it counts but i need a relatively quick count, I cannot tell if its the sensor not registering a break, or the processing time of the code/screen. When outputting to the serial monitor it reacts fine, so I’m curious where the problem lies, it has to be in the sensor, code, or the screen library. I am no code guru, I’m sure you don’t like hearing that but I’ve chopped this up and applied some of what I have learned into this. I had already created this in python using raspberry pi zeros but need to move to an Arduino based board with a screen. I should note the python code was also a little slow but I figured that was because I was running an OS on top of it.

You guys are the pro’s, I usually would prefer to find my own answers so I can learn along the way but I’m needing to navigate this in a timely manner. I am of course open to anyone who would be willing to help, either by pointing me in the right direction, or by helping me with my code. I had thought maybe using an interrupt may be more responsive but thought I should get input first.

Thanks in advance!

#include <U8g2lib.h>

int ir_pin = 36;
int counter = 0;
int hitObject = false;

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 15, 4, 16);

void setup(void) {
  pinMode(ir_pin, INPUT);

void loop(void) {
  u8g2.setCursor(0, 63);
  int val = digitalRead(ir_pin);
  if( (val == 0) && (hitObject == false) ){
        hitObject = true;
  }else if( (val ==1) && (hitObject == true) ) {
        hitObject = false;
  do {
  } while ( u8g2.nextPage() );

Are your numbers changing as fast as this video or faster?

Are you in control of how fast it changes, that is can you slow it down and see if it keeps up with this slower rate.

What speed do your numbers change at?

i need a relatively quick count,

I tried to find a scientific definition for this term, but it escapes me.
maybe it is the relative bit. can you offer a bit more of a scientific description ?

How fast is it, and how fast do you need it to be?

Is it that you're missing tripping events? What objects are passing through your hoop, and how fast are they passing (i.e. how long is the beam broken during a passage)? Maybe interrupts are needed if it's really short.

It will also help to only print to your display after the counter has changed. You can do this through a counter change check, or update the screen in the if block where you increase the counter.

Your Arduino is spending all is time updating the display. As already pointed out, your code it’s continually updating the display even when the count has not changed, so that’s the first thing to fix.

But that may not fix the problem completely. U8g2 produces great looking results, but it will be slow, partly because you are using a fancy font which requires a lot of processing power to render, partly because the Arduino does not have enough ram to hold a copy of the screen, so has to do it in sections, repeating the entire processing for each section, and partly because the i2c interface is slow. So there will always be a “dead time” while the display is being updated, where the sensor is not being read.

Things to try:

Increase the i2c speed to 400KHz

Switch to using the SPI interface. Some of those oled screens will do either i2c or SPI, if you change position of some tiny 0R resistors on the back of the display. Or just buy the SPI version.

Use U8x8 instead of U8g2. Results may not look as good, and you may not be able to print the digits large enough.

Use a separate counter IC to count the sensor pulses. Read the chip from the Arduino between screen updates.

Use a separate counter IC to count the sensor pulses. Read the chip from the Arduino between screen updates.

Won't Arduino's pin change or external interrupts on the counter pin work to count while the screen is being updated?

Won't Arduino's pin change or external interrupts on the counter pin work to count while the screen is being updated?

Maybe, I'm not sure. The interrupts might interfere with i2c timing. But that's done in hardware, so it might be ok.

Another possibility is, rather than use an external counter chip, get one of the atmega's internal counters to do it. I think it's possible to use those to count pulses on an external pin.

I tried to find a scientific definition for this term, but it escapes me.
maybe it is the relative bit. can you offer a bit more of a scientific description ?

Sorry I should have been more specific. I'm counting a basketball dribbling inside a hoop, the sensor is on either side of the hoop counting. So as far as "fairly quick" I guess it can depend on how fast someone can dribble, I'm thinking 5 or 6 trips per second maximum but usually much slower.

I have it set up and can trip it with my hand just fine but if I move too quickly it either doesn't have the time to reset the code or I'm outrunning the sensor, which seems like it would be the same issue since the sensor is just reporting to the board. Would using interrupts be better? I don't mind constantly polling the sensor state,unless that's what's slowing it down, because it won't be doing anything other than counting.

The large font is necessary to have it at your feet and be able to easily read it. I don't particulaly care about the font style but large size in needed, larger than what I have in the code now actually, I just hadn't adjusted that yet.

The screen on these boards are fixed so, although I haven't looked yet, I don't think I can get behind it to look for jumpers to switch to SPI.

I am at work now but will try and measure out its speed when I get a chance tonight. It's not really important to me the frequency the screen updates as long as it's as quick as I can get it, I just don't want to miss any counts in between refreshes and I don't want to miss any LED flashes, so if I can get the sensor and LED strip to be in sync, have the LEDS flash with the actual sensor break, and have the screen update every 200-400 milliseconds independent of the actual count I would be happy. I'm very new to this stuff so I really appreciate your patience and guidence.

Apologies, I did not bother to follow the link in the OP (my excuse is that it was not posted properly).

Now that I have, many of my suggestions do not apply. I was imagining an atmega328 was being used. An esp32 has way more ram and speed. Which makes me wonder why its response to the sensor is so poor.

you guys (and gals) were absolutely correct, moving the print code to the If statement for the counter made it significantly more responsive. thanks for the help on that. im not really sure what I was thinking updating it every cycle. thanks.

Try speeding up the i2c bus:


Do this in setup().

Even higher speeds may be possible with esp32 and ssd1306, I'm not sure.

May be worth PM-ing olikrous, give him a link to this thread and ask if he has any suggestions. He developed the U8g2 library.