1
\$\begingroup\$

I made an IR blaster for controlling TV (on and off) based on ATmega644p. I am using Timer0 in CTC mode to generate 38kHz waveform. This is the code:

#include <mega644p.h>
#include <delay.h>

void start_waveform(void);
void stop_waveform(void);

// IR singal pattern
int ir_signal[] = { 
    1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, -1,
    1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, -1,
    1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, -1,
    1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 2  
};
int index;

void main(void) 
{
    // Pin input for button (PB0)
    DDRB &= ~(1 << 0);
    // Pin output for IR LED (OC0A) (PB3)  
    DDRB |= (1 << 3);  

    TCCR0A |= 
        // Toggle OC0A at compare match
        (1 << COM0A0) |
        // Mode 2 CTC
        (1 << WGM01);

    // Make 38kHz output frequency (F_CPU = 16MHz, Prescaler = 8)   
    OCR0A = 25;     

    while (1)
    {
        // If button is pressed
        if (!(PINB & (1 << 0))) 
        {
            // Transmitt IR signal   
            for (index = 0; index < 64; index++) 
            {
                if (ir_signal[index] == -1)
                {
                    start_waveform();
                    delay_us(280);   
                    stop_waveform();
                    delay_ms(45); 
                } 
                else if (ir_signal[index] == 0) 
                {
                    start_waveform();
                    delay_us(280);   
                    stop_waveform();   
                    delay_us(760);
                }
                else if (ir_signal[index] == 1) 
                {
                    start_waveform();
                    delay_us(280);   
                    stop_waveform();  
                    delay_us(1780);
                }
                else if (ir_signal[index] == 2) 
                {
                    start_waveform();
                    delay_us(280);   
                    stop_waveform();
                }
            }

            delay_ms(500);     
        }
    }
}

void start_waveform()
{
    // Start waveform at prescaler = 8    
    TCCR0B |= (1 << CS01);  
}

void stop_waveform()
{
    // Stop waveform  
    TCCR0B &= ~(1 << CS01);
}

This code works for turning on and off the TV, but the problem is; sometimes after the IR signal end, the IR LED is still on. I have tried adding code to make sure the PB3 is turn off using this code, but it is not working:

void stop_waveform()
{
    // Stop waveform
    TCCR0B &= ~(1 << CS01);
    // Make sure PB3 is turn off
    PORTB &= ~(1 << 3);
}

I am curious what's wrong with this code?

\$\endgroup\$
2
  • \$\begingroup\$ How do you have the LED connected? \$\endgroup\$
    – Golaž
    May 3, 2015 at 10:50
  • \$\begingroup\$ The anode of LED connected to PB3 and the cathode conected to GND through 27 ohm resistor. \$\endgroup\$ May 3, 2015 at 12:02

1 Answer 1

1
\$\begingroup\$

You might have burned something around the MCU output.

You should always read thru the datasheet. All of the electronic devices have a maximum operating range. For your MCU this is explained on page 316, a table named: Absolute maximum ratings. Here you will find a DC Current per I/O Pin which tells you the upper limit of how much one I/O pin can source/sink current. Generally you wouldn't want more than 20mA per pin.

You said you're driving the LED directly from the MCU pin thru 27Ohm resistor. Even if you're powering the MCU from 3.3V and the voltage across the LED is 1.3V, the current comes out to be around 70mA which is way above the upper limit (sure you're driving it with PWM but you should always assume the worst case scenario).

So what I would recommend is to first try driving the LED via transistor, there are bunch of tutorials out there how to. If that doesnt work, I would also try to replace the MCU.

\$\endgroup\$

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.