Why does this counter not work

Hello,

IM practising with not using the 'delay`.
So I try to make a counter which now counts to 3 but later will be bigger so it counts to 255 with 8 leds.

But right now the code seems to do nothing at all
Project so far: Wokwi - Online ESP32, STM32, Arduino Simulator

Can anyone help me figure out where I made the thinking errors ?

  • Display your code and schematics here on the forum.

I’m not familiar with that simulator, but you should be able to debug the code using something similar to the Serial Monitor.

Maybe if you print out your variables, you might find the cause. My guess is it is working it’s just working too fast to see it.

This line of code looks familiar. Can you explain what you are going for with it, and TBH with the entire sketch?

    if (counter & (1 << (cnt - 1)))

a7

Also, thanks for sharing your wokwi simulation.

You can, I hope you know, wire things without the breadboard. It can make things easier to discern.

a7

Working code: (with some things to correct but it's up to you)

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

uint8_t counter = 0;
const uint8_t numbits = 2;

// struct for LED
struct LED {
  uint8_t pin;
  uint32_t nextTick;
  const uint32_t interval;
};

LED leds[] = {
  {6, 0, 1000},
  {4, 0, 1000},
};

void setup() {
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(leds); cnt++) {
    pinMode(leds[cnt].pin, OUTPUT);
    leds[cnt].nextTick = millis() + leds[cnt].interval;
  }
}

void loop() {
  for (uint8_t cnt = 0; cnt < numbits; cnt++) {
    if (counter & (1 << cnt)) {
      if (millis() > leds[cnt].nextTick) {
        leds[cnt].nextTick += leds[cnt].interval;
        digitalWrite(leds[cnt].pin, HIGH);
      }
    } else {
      digitalWrite(leds[cnt].pin, LOW);
    }
  }

  counter++;
  if (counter == (1 << numbits)) {
    counter = 0;
  }

  delay(100); // Optional: slow things down a bit if needed
}

You had more than one error
First of, at the entry of the for loop, you set cnt to numbits which is equal to
This means that accessing leds[cnt].nextTick is out of range this the array goes from 0 to
The counter++ instruction was in the if (counter & (1 << (cnt - 1))) which is false at the beggining, so you never increment the counter

Another error (that I only partialy corrected, I'll leave you try to solve it) it that you were turning the LED off as soon as you set it to HIGH.
Without my delay(100); you wouldn't be able (no time) to see the leds turn on

Besides the mystery conditional pointed out by @alto777:

  • You never initialize the value of counter.
  • Your code does not seem to include any logic for deciding how long each LED should stay lit after being set HIGH.

Lets say counter is 1
and cnt is also 1
Then we get 1 & ( 1 << 0)
one has no zero . so we get

1 & 0

Which will be false

So I can check if a digit on a particular place is a 0 or a 1 digital

The led should be on for 1 second

Do a forced test on your hardware. Add something like this to the end of setup()

void setup() {
.
.
  digitalWrite(4, HIGH);
  digitalWrite(6, HIGH);
  while(1);
}

Thanks

Pity that I have to use a delay.
I just try to make things work without using it

Yeah well the code works now
So you can have fun trying to add the necessary instructions to blink without delay
You ask why the counter doesn't work, I explained and gave a solution
But if I also give you the solution to the delay thing then you won't practise anything but your copy paste skill

Where in your code are the statements that determine whether 1 second has passed since the LED state was set to HIGH?

Here I set the interval

struct LED {
  uint8_t pin;
  uint32_t nextTick;
  const uint32_t interval; <== time the led must be on or off
};

Then here I calculate when there schould something happen :

 leds[cnt].nextTick = millis() + leds[cnt].interval;

and here I check if the nextTick when something is happening is due

(millis() > leds[cnt].nextTick)

How many errors can you see in one line of code?

Everytime you reach the said time saved in leds[cnt].nextTick you set the led to HIGH
You should just change the state of the LED then. If HIGH => LOW and vice versa

That's one way (complicated) now look at the State Machine tutorials here on the forum.

This is only for deciding when to turn the LED on, not for deciding when to turn it off.

I do not agree. When the if is not true then the else is working
And there I set the led off

Suppose nextTick = 1000 and millis() is just about to approach this value:

millis() nextTick LED State
999 1000 LOW
1000 1000 LOW
1001 2000 HIGH
1002 2000 LOW
1003 2000 LOW
... 2000 LOW
2000 2000 LOW
2001 3000 HIGH
2002 3000 LOW
2003 3000 LOW

etc.

So the only thing that determines how long the LED stays lit is how fast the MCU can complete each loop(). When the LED has been turned on (and the value of nextTick incremented), the LED will be turned off in very the next execution of loop().