{"id":317,"date":"2007-05-29T10:52:00","date_gmt":"2007-05-29T18:52:00","guid":{"rendered":"http:\/\/diversifiedcuriosities.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/"},"modified":"2017-08-18T18:03:00","modified_gmt":"2017-08-18T18:03:00","slug":"drowsy-led-for-the-worlds-slowest-instant-messenger","status":"publish","type":"post","link":"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/","title":{"rendered":"Drowsy LED for The World's Slowest Instant Messenger"},"content":{"rendered":"

<\/p>\n

<\/p>\n

I dunno, I was staring at the Slow Messenger<\/a> and the power LED \u2014 your typical grasshopper green \u2014 was so bright and just staring at me and kind of giving me a headache. And I thought..that’s not about slow. And I thought about the drowsy white “sleep” pulse of my PowerBook and I was, like..I need something like that on this device. A slow, sleepy, drowsy pulse. And maybe the pulse will change at different times of the day or something.<\/p>\n

Lucky for me I had attached the LED to one of the timer\/comparator signals on the ATMega32 in the design.<\/p>\n

<\/p>\n

<\/p>\n

That signal \u2014 PB3? Over there on the left side of the Atmega32<\/a>? That has an “alternate” use as an output for the timer\/comparator circuit. That means that it will output a digital signal if you tell it to based on an internal counter equalling (comparing to) a value you specify, or when a timer is done counting up or down. So, by knowing things like how fast the chip is running (8 megahertz in my circuit) you can start to derive how often this signal will get turned on and off. Pretty soon you’re doing pulse-width modulation, something this MCU has built-in facilities for. With PWM you can make an LED think that the voltage being supplied to it is different values. If you change the PWM (and the apparent voltage to the LED) you can get it to dim to varying degrees. Or do a gooey, drozy pulse.<\/p>\n

Here’s the code that will do this on an Atmega32. I’m having trouble getting it to work on the Atmega324<\/a> (which appears to be a replacement for the Atmega32), but I’ll get that straightened out soon enough..
\n
\n#include <stdlib.h><\/font><\/strong><\/font>
\n#include <avr\/io.h><\/font><\/strong><\/font>
\n#include <avr\/interrupt.h><\/font><\/strong><\/font><\/p>\n

#include <avr\/pgmspace.h><\/font><\/strong><\/font>
\n#include <util\/delay.h><\/font><\/strong><\/font><\/p>\n

#include \"a2d.h\"<\/font><\/strong><\/font>
\n#include \"uart.h\"<\/font><\/strong><\/font>
\n#include \"avrlibdefs.h\"<\/font><\/strong><\/font>
\n#include \"avrlibtypes.h\"<\/font><\/strong><\/font><\/p>\n

\/* define CPU frequency in Mhz here if not defined in Makefile *\/<\/font>
\n#ifndef F_CPU<\/strong><\/font>
\n#define F_CPU 8000000UL<\/strong><\/font>
\n#endif<\/strong><\/font><\/p>\n

static<\/strong> char<\/strong> mPwrLedLevel<\/font> =<\/font> 0<\/font>;<\/font><\/p>\n

static<\/strong> void<\/strong> incr_pwr_led<\/font>(<\/font>void<\/strong>)<\/font>;<\/font><\/p>\n

ISR<\/font>(<\/font>SIG_OVERFLOW0<\/font>)<\/font> {<\/strong><\/font><\/p>\n

incr_pwr_led<\/font>(<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

ISR<\/font>(<\/font>TIMER0_COMP_vect<\/font>)<\/font> {<\/strong><\/font>
\nincr_pwr_led<\/font>(<\/font>)<\/font>;<\/font><\/p>\n

}<\/strong><\/font><\/p>\n

static<\/strong> char<\/strong> aDirection<\/font>;<\/font>
\nstatic<\/strong> void<\/strong>
\nincr_pwr_led<\/font>(<\/font>void<\/strong>)<\/font><\/p>\n

{<\/strong><\/font>
\n\/\/TIMSK<\/font> =<\/font> 0x03<\/font>;<\/font><\/p>\n

if<\/strong>(<\/font>mPwrLedLevel<\/font> =<\/font>=<\/font> 0x20<\/font>)<\/font> {<\/strong><\/font><\/p>\n

aDirection<\/font> =<\/font> 1<\/font>;<\/font>
\n}<\/strong><\/font>
\nif<\/strong>(<\/font>mPwrLedLevel<\/font> =<\/font>=<\/font> 0xE0<\/font>)<\/font> {<\/strong><\/font><\/p>\n

aDirection<\/font> =<\/font> 0<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

if<\/strong>(<\/font>aDirection<\/font> =<\/font>=<\/font> 1<\/font>)<\/font> mPwrLedLevel<\/font>+<\/font>+<\/font>;<\/font><\/p>\n

if<\/strong>(<\/font>aDirection<\/font> =<\/font>=<\/font> 0<\/font>)<\/font> mPwrLedLevel<\/font>-<\/font>-<\/font>;<\/font><\/p>\n

OCR0<\/font> =<\/font> mPwrLedLevel<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

int<\/strong> main<\/font>(<\/font>void<\/strong>)<\/font><\/p>\n

{<\/strong><\/font><\/p>\n

sbi<\/font>(<\/font>DDRB<\/font>, PB3<\/font>)<\/font>;<\/font>
\nPORTB<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>PORTB3<\/font>)<\/font>;<\/font><\/p>\n

for<\/strong>(<\/font>int<\/strong> j<\/font>=<\/font>0<\/font>;<\/font> j<\/font><<\/font>30<\/font>;<\/font> j<\/font>+<\/font>+<\/font>)<\/font><\/p>\n

_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font>
\ncbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font>
\nfor<\/strong>(<\/font>int<\/strong> j<\/font>=<\/font>0<\/font>;<\/font> j<\/font><<\/font>30<\/font>;<\/font> j<\/font>+<\/font>+<\/font>)<\/font><\/p>\n

_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font>
\nsbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font>
\nfor<\/strong>(<\/font>int<\/strong> j<\/font>=<\/font>0<\/font>;<\/font> j<\/font><<\/font>30<\/font>;<\/font> j<\/font>+<\/font>+<\/font>)<\/font><\/p>\n

_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font><\/p>\n

sbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font><\/p>\n

for<\/strong>(<\/font>int<\/strong> j<\/font>=<\/font>0<\/font>;<\/font> j<\/font><<\/font>50<\/font>;<\/font> j<\/font>+<\/font>+<\/font>)<\/font><\/p>\n

_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font><\/p>\n

TCCR0<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>WGM00<\/font>)<\/font> |<\/font> (<\/font>1<\/font><<\/font><<\/font>COM01<\/font>)<\/font> |<\/font> (<\/font>1<\/font><<\/font><<\/font>CS02<\/font>)<\/font>;<\/font><\/p>\n

\/\/ TCCR0A<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>CS02<\/font>)<\/font> |<\/font> (<\/font>0<\/font><<\/font><<\/font>CS01<\/font>)<\/font> |<\/font> (<\/font>0<\/font><<\/font><<\/font>CS00<\/font>)<\/font>;<\/font>
\n\/\/ TCCR0A<\/font> |<\/font>=<\/font> (<\/font>0<\/font><<\/font><<\/font>WGM02<\/font>)<\/font> |<\/font> (<\/font>1<\/font><<\/font><<\/font>WGM00<\/font>)<\/font>;<\/font><\/p>\n

\/\/ TCCR0A<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>COM0A1<\/font>)<\/font> |<\/font> (<\/font>0<\/font><<\/font><<\/font>COM0A0<\/font>)<\/font>;<\/font><\/p>\n

TCNT0<\/font> =<\/font> 0x00<\/font>;<\/font>
\nsbi<\/font>(<\/font>TIMSK<\/font>, TOIE0<\/font>)<\/font>;<\/font><\/p>\n

sei<\/font>(<\/font>)<\/font>;<\/font>
\nOCR0<\/font> =<\/font> 0x10<\/font>;<\/font>
\nint<\/strong> j<\/font>=<\/font>0x00<\/font>;<\/font><\/p>\n

while<\/strong>(<\/font>1<\/font>=<\/font>=<\/font>1<\/font>)<\/font> {<\/strong><\/font>
\n_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font>
\n}<\/strong><\/font>
\n<\/code><\/p>\n

For the Atmega324 a bunch of registers and bit names in registers changed. This is all documented here:<\/p>\n

http:\/\/www.atmel.com\/dyn\/resources\/prod_documents\/doc8001.pdf<\/a><\/p>\n

I misread a bunch of it and kind of got a bit fouled up, but finally got it straight. It’s actually pretty simple once you get the registers figured out (things got split up because extra timers appeared and such.)<\/p>\n

Basically you want to set up the PWM timer like this:<\/p>\n


\nTCCR0A |= (1<<wgm00) | (1<<com0A1); \/\/PWM Phase Correct, Clear OC0A on compare mach
\nTCCR0B |= (1<<cs02); \/\/ clk\/256<\/p>\n

TCNT0 = 0x00;
\nTIMSK0 |= (1<<toie0); \/\/ overflow interrupt enabled
\nOCR0A = 0x10; \/\/ start somewhere
\n<\/code><\/p>\n

Here’s a little CPP class that will run on the Atmega324p and slowly pulse an LED attached appropriately to PB3.<\/p>\n


\n#include <avrlibdefs.h><\/font><\/strong><\/font>
\n#include <avrlibtypes.h><\/font><\/strong><\/font>
\n#include <stdint.h><\/font><\/strong><\/font>
\n#include <stdio.h><\/font><\/strong><\/font><\/p>\n

#include <util\/delay.h><\/font><\/strong><\/font>
\n#include <avr\/io.h><\/font><\/strong><\/font>
\n#include <avr\/interrupt.h><\/font>\t\/\/ include interrupt support<\/font><\/strong><\/font><\/p>\n

#include "timer.h"<\/font><\/strong><\/font>
\n#ifdef __cplusplus<\/strong><\/font>
\nextern<\/strong> "C"<\/font>{<\/strong><\/font>
\n \/\/#include "a2d.h"<\/font>
\n#include "timer.h"<\/font><\/strong><\/font>
\n#include "uart.h"<\/font>\t\t\/\/ include uart function library<\/font><\/strong><\/font>
\n FILE<\/font> *<\/font> uart_str<\/font>;<\/font><\/p>\n

}<\/strong><\/font> \/\/extern "C"<\/font>
\n#endif<\/strong><\/font><\/p>\n

static<\/strong> uint8_t<\/font> mGoLow<\/font>;<\/font><\/p>\n

void<\/strong> setup<\/font>(<\/font>void<\/strong>)<\/font>;<\/font>
\nstatic<\/strong> void<\/strong> delay_1s<\/font>(<\/font>void<\/strong>)<\/font>;<\/font>
\nstatic<\/strong> void<\/strong> delay_600ms<\/font>(<\/font>void<\/strong>)<\/font>;<\/font>
\nstatic<\/strong> void<\/strong> delay_300ms<\/font>(<\/font>void<\/strong>)<\/font>;<\/font><\/p>\n

static<\/strong> void<\/strong> incr_pwr_led<\/font>(<\/font>void<\/strong>)<\/font>;<\/font>
\nstatic<\/strong> byte<\/font> mPwrLedLevel<\/font> =<\/font> 0x00<\/font>;<\/font><\/p>\n

ISR<\/font>(<\/font>SIG_OVERFLOW0<\/font>)<\/font> {<\/strong><\/font>
\n incr_pwr_led<\/font>(<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

ISR<\/font>(<\/font>TIMER0_COMPA_vect<\/font>)<\/font> {<\/strong><\/font>
\n incr_pwr_led<\/font>(<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

ISR<\/font>(<\/font>INT0_vect<\/font>)<\/font> {<\/strong><\/font>
\n cli<\/font>(<\/font>)<\/font>;<\/font>
\n sei<\/font>(<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

static<\/strong> void<\/strong>
\ndelay_600ms<\/font>(<\/font>void<\/strong>)<\/font>
\n{<\/strong><\/font>
\n uint8_t<\/font> i<\/font>;<\/font>
\n for<\/strong> (<\/font>i<\/font> =<\/font> 0<\/font>;<\/font> i<\/font> <<\/font> 60<\/font>;<\/font> i<\/font>+<\/font>+<\/font>)<\/font>
\n _delay_ms<\/font>(<\/font>10<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

static<\/strong> void<\/strong>
\ndelay_300ms<\/font>(<\/font>void<\/strong>)<\/font>
\n{<\/strong><\/font>
\n uint8_t<\/font> i<\/font>;<\/font>
\n for<\/strong> (<\/font>i<\/font> =<\/font> 0<\/font>;<\/font> i<\/font> <<\/font> 30<\/font>;<\/font> i<\/font>+<\/font>+<\/font>)<\/font>
\n _delay_ms<\/font>(<\/font>10<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

static<\/strong> void<\/strong>
\ndelay_1s<\/font>(<\/font>void<\/strong>)<\/font>
\n{<\/strong><\/font>
\n uint8_t<\/font> i<\/font>;<\/font>
\n for<\/strong> (<\/font>i<\/font> =<\/font> 0<\/font>;<\/font> i<\/font> <<\/font> 100<\/font>;<\/font> i<\/font>+<\/font>+<\/font>)<\/font>
\n _delay_ms<\/font>(<\/font>10<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

int<\/strong> main<\/font>(<\/font>)<\/font> {<\/strong><\/font>
\n setup<\/font>(<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

static<\/strong> char<\/strong> aDirection<\/font>;<\/font>
\nstatic<\/strong> void<\/strong>
\nincr_pwr_led<\/font>(<\/font>void<\/strong>)<\/font>
\n{<\/strong><\/font>
\n \/\/TIMSK = 0x03;<\/font><\/p>\n

if<\/strong>(<\/font>mPwrLedLevel<\/font> =<\/font>=<\/font> 0x10<\/font>)<\/font> {<\/strong><\/font>
\n aDirection<\/font> =<\/font> 1<\/font>;<\/font>
\n }<\/strong><\/font>
\n if<\/strong>(<\/font>mPwrLedLevel<\/font> =<\/font>=<\/font> 0xD0<\/font>)<\/font> {<\/strong><\/font>
\n aDirection<\/font> =<\/font> 0<\/font>;<\/font>
\n }<\/strong><\/font>
\n \/\/ printf("[[%d]]n", mPwrLedLevel);<\/font><\/p>\n

if<\/strong>(<\/font>aDirection<\/font> =<\/font>=<\/font> 1<\/font>)<\/font> mPwrLedLevel<\/font>+<\/font>+<\/font>;<\/font>
\n if<\/strong>(<\/font>aDirection<\/font> =<\/font>=<\/font> 0<\/font>)<\/font> mPwrLedLevel<\/font>-<\/font>-<\/font>;<\/font><\/p>\n

OCR0A<\/font> =<\/font> mPwrLedLevel<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

void<\/strong> setup<\/font>(<\/font>)<\/font>
\n{<\/strong><\/font>
\n uint16_t<\/font> *<\/font>base_addr<\/font>;<\/font>
\n uint16_t<\/font> k<\/font>;<\/font>
\n float<\/strong> x_sum<\/font>;<\/font>
\n mGoLow<\/font> =<\/font> 0x00<\/font>;<\/font>
\n \/\/uint16_t k;<\/font><\/p>\n

sei<\/font>(<\/font>)<\/font>;<\/font><\/p>\n

MCUCR<\/font> =<\/font> (<\/font>1<\/font><<\/font><<\/font>ISC01<\/font>)<\/font>;<\/font>
\n MCUCR<\/font> =<\/font> (<\/font>1<\/font><<\/font><<\/font>ISC00<\/font>)<\/font>;<\/font>
\n \/\/ GICR = (1<<INT0);<\/font><\/p>\n

sbi<\/font>(<\/font>DDRB<\/font>, 3<\/font>)<\/font>;<\/font> \/\/ use PB3 as an output<\/font><\/p>\n

PORTB<\/font>=<\/font>0x00<\/font>;<\/font><\/p>\n

sbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font> \/\/ PB3 high, on v04 is pwr led<\/font><\/p>\n

\/\/TCCR0 = 0x64; \/\/ prescaler and other stuff<\/font>
\n TCCR0A<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>WGM00<\/font>)<\/font> |<\/font> (<\/font>1<\/font><<\/font><<\/font>COM0A1<\/font>)<\/font>;<\/font>\/\/PWM Phase Correct, Clear OC0A on compare match<\/font>
\n TCCR0B<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>CS02<\/font>)<\/font>;<\/font> \/\/ clk\/256<\/font><\/p>\n

TCNT0<\/font> =<\/font> 0x00<\/font>;<\/font>
\n TIMSK0<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>TOIE0<\/font>)<\/font>;<\/font> \/\/ overflow interrupt enabled<\/font>
\n \/\/sbi(TIMSK0, TOIE0); \/\/ overflow interrupt enabled<\/font>
\n \/\/ TIMSK = 0x02; \/\/ overflow interrupt enabled<\/font><\/p>\n

OCR0A<\/font> =<\/font> 0x10<\/font>;<\/font><\/p>\n

delay_1s<\/font>(<\/font>)<\/font>;<\/font><\/p>\n

cbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font><\/p>\n

while<\/strong>(<\/font>true<\/strong>)<\/font> {<\/strong><\/font><\/p>\n

if<\/strong>(<\/font>mGoLow<\/font> =<\/font>=<\/font> 0x01<\/font>)<\/font> {<\/strong><\/font>
\n cbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font>
\n }<\/strong><\/font> else<\/strong> {<\/strong><\/font>
\n mGoLow<\/font> =<\/font> 0x00<\/font>;<\/font>
\n sbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font>
\n }<\/strong><\/font><\/p>\n

}<\/strong><\/font><\/p>\n

}<\/strong><\/font>
\n<\/code><\/p>\n

<\/p>\n

Technorati Tags: Near Future Laboratory<\/a>, slowest instant messenger<\/a><\/p>\n

<\/p>\n","protected":false},"excerpt":{"rendered":"

<\/p>\n

I dunno, I was staring at the Slow Messenger<\/a> and the power LED \u00e2\u20ac\u201d\u00c2 your typical grasshopper green \u00e2\u20ac\u201d was so bright and just staring at me and kind of giving me a headache. And I thought \u00e2\u20ac\u201d that’s not about slow. And I thought about the drowsy white “sleep” pulse of my PowerBook and I was, like..I need something like that on this device. A slow, sleepy, drowsy pulse. And maybe the pulse will change at different times of the day or something.<\/p>\n

Lucky for me I had attached the LED to one of the timer\/comparator signals on the ATMega32 in the design.<\/p>\n

<\/p>\n

That signal \u00e2\u20ac\u201d PB3? Over there on the left side of the Atmega32<\/a>? That has an “alternate” use as an output for the timer\/comparator circuit. That means that it will output a digital signal if you tell it to based on an internal counter equalling (comparing to) a value you specify, or when a timer is done counting up or down. So, by knowing things like how fast the chip is running (8 megahertz in my circuit) you can start to derive how often this signal will get turned on and off. Pretty soon you’re doing pulse-width modulation, something this MCU has built-in facilities for. With PWM you can make an LED think that the voltage being supplied to it is different values. If you change the PWM (and the apparent voltage to the LED) you can get it to dim to varying degrees. Or do a gooey, drozy pulse.<\/p>\n

Here’s the code that will do this on an Atmega32. I’m having trouble getting it to work on the Atmega324<\/a> (which appears to be a replacement for the Atmega32), but I’ll get that straightened out soon enough..<\/p>\n

#include <stdlib.h><\/font><\/strong><\/font>
\n#include <avr\/io.h><\/font><\/strong><\/font>
\n#include <avr\/interrupt.h><\/font><\/strong><\/font><\/p>\n

#include <avr\/pgmspace.h><\/font><\/strong><\/font>
\n#include <util\/delay.h><\/font><\/strong><\/font><\/p>\n

#include "a2d.h"<\/font><\/strong><\/font>
\n#include "uart.h"<\/font><\/strong><\/font>
\n#include "avrlibdefs.h"<\/font><\/strong><\/font>
\n#include "avrlibtypes.h"<\/font><\/strong><\/font><\/p>\n

\/* define CPU frequency in Mhz here if not defined in Makefile *\/<\/font>
\n#ifndef F_CPU<\/strong><\/font>
\n#define F_CPU 8000000UL<\/strong><\/font>
\n#endif<\/strong><\/font><\/p>\n

static<\/strong> char<\/strong> mPwrLedLevel<\/font> =<\/font> 0<\/font>;<\/font><\/p>\n

static<\/strong> void<\/strong> incr_pwr_led<\/font>(<\/font>void<\/strong>)<\/font>;<\/font><\/p>\n

ISR<\/font>(<\/font>SIG_OVERFLOW0<\/font>)<\/font> {<\/strong><\/font><\/p>\n

incr_pwr_led<\/font>(<\/font>)<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

ISR<\/font>(<\/font>TIMER0_COMP_vect<\/font>)<\/font> {<\/strong><\/font>
\n incr_pwr_led<\/font>(<\/font>)<\/font>;<\/font><\/p>\n

}<\/strong><\/font><\/p>\n

static<\/strong> char<\/strong> aDirection<\/font>;<\/font>
\nstatic<\/strong> void<\/strong>
\nincr_pwr_led<\/font>(<\/font>void<\/strong>)<\/font><\/p>\n

{<\/strong><\/font>
\n \/\/TIMSK<\/font> =<\/font> 0x03<\/font>;<\/font><\/p>\n

if<\/strong>(<\/font>mPwrLedLevel<\/font> =<\/font>=<\/font> 0x20<\/font>)<\/font> {<\/strong><\/font><\/p>\n

aDirection<\/font> =<\/font> 1<\/font>;<\/font>
\n }<\/strong><\/font>
\n if<\/strong>(<\/font>mPwrLedLevel<\/font> =<\/font>=<\/font> 0xE0<\/font>)<\/font> {<\/strong><\/font><\/p>\n

aDirection<\/font> =<\/font> 0<\/font>;<\/font>
\n }<\/strong><\/font><\/p>\n

if<\/strong>(<\/font>aDirection<\/font> =<\/font>=<\/font> 1<\/font>)<\/font> mPwrLedLevel<\/font>+<\/font>+<\/font>;<\/font><\/p>\n

if<\/strong>(<\/font>aDirection<\/font> =<\/font>=<\/font> 0<\/font>)<\/font> mPwrLedLevel<\/font>–<\/font>–<\/font>;<\/font><\/p>\n

OCR0<\/font> =<\/font> mPwrLedLevel<\/font>;<\/font>
\n}<\/strong><\/font><\/p>\n

int<\/strong> main<\/font>(<\/font>void<\/strong>)<\/font><\/p>\n

{<\/strong><\/font><\/p>\n

sbi<\/font>(<\/font>DDRB<\/font>, PB3<\/font>)<\/font>;<\/font>
\n PORTB<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>PORTB3<\/font>)<\/font>;<\/font><\/p>\n

for<\/strong>(<\/font>int<\/strong> j<\/font>=<\/font>0<\/font>;<\/font> j<\/font><<\/font>30<\/font>;<\/font> j<\/font>+<\/font>+<\/font>)<\/font><\/p>\n

_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font>
\n cbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font>
\n for<\/strong>(<\/font>int<\/strong> j<\/font>=<\/font>0<\/font>;<\/font> j<\/font><<\/font>30<\/font>;<\/font> j<\/font>+<\/font>+<\/font>)<\/font><\/p>\n

_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font>
\n sbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font>
\n for<\/strong>(<\/font>int<\/strong> j<\/font>=<\/font>0<\/font>;<\/font> j<\/font><<\/font>30<\/font>;<\/font> j<\/font>+<\/font>+<\/font>)<\/font><\/p>\n

_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font><\/p>\n

sbi<\/font>(<\/font>PORTB<\/font>, PB3<\/font>)<\/font>;<\/font><\/p>\n

for<\/strong>(<\/font>int<\/strong> j<\/font>=<\/font>0<\/font>;<\/font> j<\/font><<\/font>50<\/font>;<\/font> j<\/font>+<\/font>+<\/font>)<\/font><\/p>\n

_delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font><\/p>\n

TCCR0<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>WGM00<\/font>)<\/font> |<\/font> (<\/font>1<\/font><<\/font><<\/font>COM01<\/font>)<\/font> |<\/font> (<\/font>1<\/font><<\/font><<\/font>CS02<\/font>)<\/font>;<\/font><\/p>\n

\/\/ TCCR0A<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>CS02<\/font>)<\/font> |<\/font> (<\/font>0<\/font><<\/font><<\/font>CS01<\/font>)<\/font> |<\/font> (<\/font>0<\/font><<\/font><<\/font>CS00<\/font>)<\/font>;<\/font>
\n \/\/ TCCR0A<\/font> |<\/font>=<\/font> (<\/font>0<\/font><<\/font><<\/font>WGM02<\/font>)<\/font> |<\/font> (<\/font>1<\/font><<\/font><<\/font>WGM00<\/font>)<\/font>;<\/font><\/p>\n

\/\/ TCCR0A<\/font> |<\/font>=<\/font> (<\/font>1<\/font><<\/font><<\/font>COM0A1<\/font>)<\/font> |<\/font> (<\/font>0<\/font><<\/font><<\/font>COM0A0<\/font>)<\/font>;<\/font><\/p>\n

TCNT0<\/font> =<\/font> 0x00<\/font>;<\/font>
\n sbi<\/font>(<\/font>TIMSK<\/font>, TOIE0<\/font>)<\/font>;<\/font><\/p>\n

sei<\/font>(<\/font>)<\/font>;<\/font>
\n OCR0<\/font> =<\/font> 0x10<\/font>;<\/font>
\n int<\/strong> j<\/font>=<\/font>0x00<\/font>;<\/font><\/p>\n

while<\/strong>(<\/font>1<\/font>=<\/font>=<\/font>1<\/font>)<\/font> {<\/strong><\/font>
\n _delay_ms<\/font>(<\/font>32<\/font>)<\/font>;<\/font>
\n }<\/strong><\/font>
\n}<\/strong><\/font><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[22,48,78,84,138],"tags":[1067],"yoast_head":"\nDrowsy LED for The World's Slowest Instant Messenger - Near Future Laboratory<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Drowsy LED for The World's Slowest Instant Messenger - Near Future Laboratory\" \/>\n<meta property=\"og:description\" content=\"I dunno, I was staring at the Slow Messenger and the power LED \u00e2\u20ac\u201d\u00c2 your typical grasshopper green \u00e2\u20ac\u201d was so bright and just staring at me and kind of giving me a headache. And I thought \u00e2\u20ac\u201d that's not about slow. And I thought about the drowsy white "sleep" pulse of my PowerBook and I was, like..I need something like that on this device. A slow, sleepy, drowsy pulse. And maybe the pulse will change at different times of the day or something. Lucky for me I had attached the LED to one of the timer\/comparator signals on the ATMega32 in the design. That signal \u00e2\u20ac\u201d PB3? Over there on the left side of the Atmega32? That has an "alternate" use as an output for the timer\/comparator circuit. That means that it will output a digital signal if you tell it to based on an internal counter equalling (comparing to) a value you specify, or when a timer is done counting up or down. So, by knowing things like how fast the chip is running (8 megahertz in my circuit) you can start to derive how often this signal will get turned on and off. Pretty soon you're doing pulse-width modulation, something this MCU has built-in facilities for. With PWM you can make an LED think that the voltage being supplied to it is different values. If you change the PWM (and the apparent voltage to the LED) you can get it to dim to varying degrees. Or do a gooey, drozy pulse. Here's the code that will do this on an Atmega32. I'm having trouble getting it to work on the Atmega324 (which appears to be a replacement for the Atmega32), but I'll get that straightened out soon enough.. #include <stdlib.h> #include <avr\/io.h> #include <avr\/interrupt.h> #include <avr\/pgmspace.h> #include <util\/delay.h> #include "a2d.h" #include "uart.h" #include "avrlibdefs.h" #include "avrlibtypes.h" \/* define CPU frequency in Mhz here if not defined in Makefile *\/ #ifndef F_CPU #define F_CPU 8000000UL #endif static char mPwrLedLevel = 0; static void incr_pwr_led(void); ISR(SIG_OVERFLOW0) { incr_pwr_led(); } ISR(TIMER0_COMP_vect) { incr_pwr_led(); } static char aDirection; static void incr_pwr_led(void) { \/\/TIMSK = 0x03; if(mPwrLedLevel == 0x20) { aDirection = 1; } if(mPwrLedLevel == 0xE0) { aDirection = 0; } if(aDirection == 1) mPwrLedLevel++; if(aDirection == 0) mPwrLedLevel--; OCR0 = mPwrLedLevel; } int main(void) { sbi(DDRB, PB3); PORTB |= (1<<PORTB3); for(int j=0; j<30; j++) _delay_ms(32); cbi(PORTB, PB3); for(int j=0; j<30; j++) _delay_ms(32); sbi(PORTB, PB3); for(int j=0; j<30; j++) _delay_ms(32); sbi(PORTB, PB3); for(int j=0; j<50; j++) _delay_ms(32); TCCR0 |= (1<<WGM00) | (1<<COM01) | (1<<CS02); \/\/ TCCR0A |= (1<<CS02) | (0<<CS01) | (0<<CS00); \/\/ TCCR0A |= (0<<WGM02) | (1<<WGM00); \/\/ TCCR0A |= (1<<COM0A1) | (0<<COM0A0); TCNT0 = 0x00; sbi(TIMSK, TOIE0); sei(); OCR0 = 0x10; int j=0x00; while(1==1) { _delay_ms(32); } }\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/\" \/>\n<meta property=\"og:site_name\" content=\"Near Future Laboratory\" \/>\n<meta property=\"article:published_time\" content=\"2007-05-29T18:52:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-08-18T18:03:00+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/farm1.static.flickr.com\/217\/512533158_89260da9fa_d.jpg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nearfuturelab\" \/>\n<meta name=\"twitter:site\" content=\"@nearfuturelab\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#organization\",\"name\":\"Near Future Laboratory\",\"url\":\"https:\/\/blog.nearfuturelaboratory.com\/\",\"sameAs\":[\"https:\/\/www.instagram.com\/nearfuturelaboratory\/\",\"https:\/\/www.linkedin.com\/company\/near-future-laboratory\/\",\"https:\/\/twitter.com\/nearfuturelab\"],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#logo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/blog.nearfuturelaboratory.com\/wp-content\/uploads\/2019\/10\/NearFutureLaboratoryLogo-CS4.jpg\",\"width\":1049,\"height\":206,\"caption\":\"Near Future Laboratory\"},\"image\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#website\",\"url\":\"https:\/\/blog.nearfuturelaboratory.com\/\",\"name\":\"Near Future Laboratory\",\"description\":\"Clarify Today, Design Tomorrow\",\"publisher\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/blog.nearfuturelaboratory.com\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"http:\/\/farm1.static.flickr.com\/217\/512533158_89260da9fa_d.jpg\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/#webpage\",\"url\":\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/\",\"name\":\"Drowsy LED for The World's Slowest Instant Messenger - Near Future Laboratory\",\"isPartOf\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/#primaryimage\"},\"datePublished\":\"2007-05-29T18:52:00+00:00\",\"dateModified\":\"2017-08-18T18:03:00+00:00\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/#webpage\"},\"author\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#\/schema\/person\/4648c18232bc2e176a1197eda0225c08\"},\"headline\":\"Drowsy LED for The World's Slowest Instant Messenger\",\"datePublished\":\"2007-05-29T18:52:00+00:00\",\"dateModified\":\"2017-08-18T18:03:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/2007\/05\/29\/drowsy-led-for-the-worlds-slowest-instant-messenger\/#primaryimage\"},\"keywords\":\"Theory Object\",\"articleSection\":\"Atmel,Design Art Technology,Hardware,How To,Projects\",\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#\/schema\/person\/4648c18232bc2e176a1197eda0225c08\",\"name\":\"Julian\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/blog.nearfuturelaboratory.com\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"http:\/\/0.gravatar.com\/avatar\/f8c8f20a3bedb22c3adce22082147ae4?s=96&d=mm&r=g\",\"caption\":\"Julian\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/posts\/317"}],"collection":[{"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/comments?post=317"}],"version-history":[{"count":1,"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/posts\/317\/revisions"}],"predecessor-version":[{"id":10735,"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/posts\/317\/revisions\/10735"}],"wp:attachment":[{"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/media?parent=317"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/categories?post=317"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.nearfuturelaboratory.com\/wp-json\/wp\/v2\/tags?post=317"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}