Estou tentando criar uma luz LED RGB de controle remoto usando um ATtiny13A.
Sei que o ATtiny85 é mais adequado para essa finalidade e sei que talvez não consiga ajustar todo o código, mas, por enquanto, minha principal preocupação é gerar um PWM de software usando interrupções no modo CTC.
Não posso operar em nenhum outro modo (exceto no PWM rápido com OCR0A
o TOP
qual é basicamente a mesma coisa) porque o código do receptor de IR que estou usando precisa de uma frequência de 38 kHz que gera usando CTC e OCR0A=122
.
Então, estou tentando (e vi pessoas mencionarem isso na Internet) usar o Output Compare A
e Output Compare B
interrompe para gerar um PWM de software.
OCR0A
, que também é usado pelo código IR, determina a frequência com a qual não me importo. E OCR0B
determina o ciclo de trabalho do PWM que utilizarei para alterar as cores dos LEDs.
Espero conseguir um PWM com ciclo de trabalho de 0 a 100%, alterando o OCR0B
valor de 0
para OCR0A
. Esta é a minha compreensão do que deve acontecer:
Mas o que realmente está acontecendo é isso (isto é, da simulação Proteus ISIS):
Como você pode ver abaixo, sou capaz de obter cerca de 25% a 75% do ciclo de trabalho, mas para ~ 0-25% e ~ 75-100% a forma de onda está presa e não muda.
Linha AMARELA: Hardware PWM
Linha RED: Software PWM com ciclo de serviço fixo
Linha VERDE: Software PWM com ciclo de trabalho variável
E aqui está o meu código:
#ifndef F_CPU
#define F_CPU (9600000UL) // 9.6 MHz
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int main(void)
{
cli();
TCCR0A = 0x00; // Init to zero
TCCR0B = 0x00;
TCCR0A |= (1<<WGM01); // CTC mode
TCCR0A |= (1<<COM0A0); // Toggle OC0A on compare match (50% PWM on PINB0)
// => YELLOW line on oscilloscope
TIMSK0 |= (1<<OCIE0A) | (1<<OCIE0B); // Compare match A and compare match B interrupt enabled
TCCR0B |= (1<<CS00); // Prescalar 1
sei();
DDRB = 0xFF; // All ports output
while (1)
{
OCR0A = 122; // This is the value I'll be using in my main program
for(int i=0; i<OCR0A; i++)
{
OCR0B = i; // Should change the duty cycle
_delay_ms(2);
}
}
}
ISR(TIM0_COMPA_vect){
PORTB ^= (1<<PINB3); // Toggle PINB3 on compare match (50% <SOFTWARE> PWM on PINB3)
// =>RED line on oscilloscope
PORTB &= ~(1<<PINB4); // PINB4 LOW
// =>GREEN line on oscilloscope
}
ISR(TIM0_COMPB_vect){
PORTB |= (1<<PINB4); // PINB4 HIGH
}
OCR0A
é usado pelo código IR, então eu só tenho OCR0B
. Estou tentando usá-lo para gerar software PWM em 3 pinos não-PWM.