Estoy tratando de hacer una luz LED RGB con 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 PWM de software usando interrupciones en modo CTC.
No puedo operar en ningún otro modo (excepto para PWM rápido, OCR0A
ya 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 yOCR0A=122
.
Así que estoy tratando (y he visto a gente mencionar esto en Internet) de usar Output Compare A
e Output Compare B
interrumpe para generar un software PWM.
OCR0A
, que también usa el código IR, determina la frecuencia, lo que no me importa. Y OCR0B
determina el ciclo de trabajo del PWM que usaré para cambiar los colores del LED.
Espero poder obtener un PWM con un ciclo de trabajo del 0-100% cambiando el OCR0B
valor de 0
a OCR0A
. Esta es mi comprensión de lo que debería suceder:
Pero lo que realmente está sucediendo es esto (esto es de la simulación Proteus ISIS):
Como puede ver a continuación, puedo obtener un ciclo de trabajo del 25% al 75%, pero para ~ 0-25% y ~ 75-100%, la forma de onda está atascada y no cambia.
Línea AMARILLA: Hardware PWM
Línea ROJA: Software PWM con ciclo de trabajo fijo
Línea VERDE: Software PWM con ciclo de trabajo variable
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
}
OCR0A
es usado por el código IR, así que solo tengo OCR0B
. Estoy tratando de usarlo para generar software PWM en 3 pines que no son PWM.