4
\$\begingroup\$

I have a working USBasp which is uploading sketches to an ATtiny13A and using a simple blink sketch. The LED ON part is working fine, staying on for 2 seconds, but after turning the LED off, the second _delay_ms has no effect. The LED is off for a fraction of a second, and then it comes on again for the correct _delay_ms.

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRB = 0xFF;

  while(1) {
    PORTB |= (1 << PB0);
    _delay_ms(2000);
    PORTB &= ~(1 << PB0);
    _delay_ms(20000);
  }
}

arduino-cli compile -e --fqbn MicroCore:avr:13 Blink
arduino-cli upload --fqbn MicroCore:avr:13 --programmer usbasp Blink

No matter what the second _delay_ms value is, the LED only briefly goes off before coming back on for the correct 2 seconds.

It is a standard red LED with a 200 ohm resistor connected to PB0 and GND, and 5 V in from the USBasp.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Have you tried e.g. 100ms on, 100ms off sequence? If the thing still resets every 2s then you should check if the watchdog is enabled and try again after disabling it. \$\endgroup\$
    – Justme
    Feb 23, 2022 at 10:26
  • \$\begingroup\$ thanks for the suggestion. It works fine on 100ms on/off (difficult to tell but the periods seem equal). If I push the off to 2000ms it goes off in about 500ms (it seems). Interestingly, if the on/off are both 1000ms it works but if the total off delay exceeds 2000ms the off period appears to be around 500ms. e.g. if PB0 is off >= 2000ms it "resets" after 500ms. How can I disable the watchdog if that's what's causing it? \$\endgroup\$
    – codebrane
    Feb 23, 2022 at 10:41
  • 1
    \$\begingroup\$ Make sure it actually resets. Are you sure you are even allowed to call the _delay_ms macro with such large a value, as it is intended for short delays. Do a while/for loop that delays 2000 times for 1 millisecond only to see what is the problem. \$\endgroup\$
    – Justme
    Feb 23, 2022 at 11:03
  • \$\begingroup\$ thank you very much, that works perfectly. 5000 x _delay_ms(1) works for both ON and OFF. I've found documentation on using timers and interrupts so I'll look into that, rather than _delay_ms, which as you say is only for short periods. Thanks very much for your insights. \$\endgroup\$
    – codebrane
    Feb 23, 2022 at 11:15

1 Answer 1

7
\$\begingroup\$

From the avr-libc _delay_ms documentation:

The maximal possible delay is 262.14 ms / F_CPU in MHz

When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency)

So you should implement your own function to get longer delays (calling _delay_ms in a loop for example), or use the Arduino delay function if you're using that environment.

Or better: use timers. There are plenty of examples and timer frequency calculators available for AVR chips. Randomly chosen example: ATtiny13 – blinky with timer OVF (Overflow)

\$\endgroup\$
1
  • \$\begingroup\$ thanks for the clarification and links \$\endgroup\$
    – codebrane
    Feb 23, 2022 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.