Estoy tratando de hacer una luz LED RGB de control remoto usando un ATtiny13A.
Sé que el ATtiny85 es más adecuado para este propósito, y sé que eventualmente no podré ajustar todo el código, pero por ahora mi principal preocupación es generar un software PWM utilizando interrupciones en modo CTC.
No puedo operar en ningún otro modo (excepto para PWM rápido con OCR0A
como TOP
, que es básicamente lo mismo) porque el código del receptor IR que estoy usando necesita una frecuencia de 38 kHz que genera usando CTC y OCR0A=122
.
Así que estoy intentando (y he visto a personas que mencionan esto en Internet) usar las interrupciones Output Compare A
y Output Compare B
para generar un software PWM.
OCR0A
, que también es usado por el código IR, determina la frecuencia, lo cual no me importa. Y OCR0B
, determina el ciclo de trabajo del PWM que usaré para cambiar los colores de los LED.
Estoy esperando poder obtener un PWM con un ciclo de trabajo de 0-100% cambiando el valor OCR0B
de 0
a OCR0A
. Este es mi entendimiento de lo que debería suceder:
Peroloquerealmenteestásucediendoesesto(estoesdelasimulacióndeProteusISIS):
Comopuedeveracontinuación,puedoobtenerunciclodetrabajodeaproximadamente25%-75%,peropara~0-25%y~75-100%,laformadeondaestábloqueadaynocambia.
líneaAMARILLA:HardwarePWM
LíneaROJA:SoftwarePWMconciclodeserviciofijo
LíneaVERDE:SoftwarePWMconciclodetrabajovariable
Y aquí está mi 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
}