I'm working on a simple LED project using Atmega2560
microcontroller. I don't know how I can adjust the led brightness to the level I want.
I need to do all the processing with digital signals. In this case, PWM and Analog signals not allowed.
DEF consts:
LEDS
: Which LEDs will be work
LED_DATA
: I will use it to out DDRC
Theory
To get 50%
brightness:
- Turn on the LED (logic-1)
- Delay 5ms
- Turn off the LED (logic-0)
- Delay 5ms
Main Loop
.def LEDS = R16
.def LED_DATA = R21
.org 0
rjmp MAIN
MAIN:
ldi LEDS, 0xFF ; 0xFF = 1111 1111
out DDRC, LEDS ; make PORTC's all pins to output
sbi PORTB, 0
sbi PORTB, 1
sbi PORTB, 2
LOOP_MAIN:
out PORTC, LED_DATA
call DELAY
out PORTC, 0x00
call DELAY
rjmp LOOP_MAIN
My wait700ms command:
wait700ms:
push r17
ldi r16,0x40 ; run 0x400000 times
ldi r17,0x00 ; ~12 million cycle
ldi r18,0x00 ; for 16Mhz: ~0.7s delay
_w0:
dec r18
brne _w0
dec r17
brne _w0
dec r16
brne _w0
pop r17
ret
As you can see above, my delay command is insufficient even when i set the ldi r16,0x01
instead of ldi r16,0x40
. With 0x01
, It happens so fast, but it's not enough. I can see it with my eye and it flashes in full brightness. It's a situation we don't want. On average, it should blink between 90 Hz and 120 Hz to adjust brightness.
P.S: Creating duty-cycle with analog pulse not allowed.
Questions
How can I generate a 5ms delay?
Can we solve this problem by using (ISR) timer interrupts? *(If possible, how can i generate
5ms
delay with timer? (TCCR, OCR0 (for presaceler), ...))*