Sto cercando di creare una luce LED RGB con telecomando usando un ATtiny13A.
So che ATtiny85 è più adatto a questo scopo e so che alla fine potrei non essere in grado di adattare l'intero codice, ma per ora la mia preoccupazione principale è generare un PWM software usando gli interrupt in modalità CTC.
Non posso operare in qualsiasi altra modalità (ad eccezione di PWM veloce con OCR0Aquanto TOPche è fondamentalmente la stessa cosa) perché il codice ricevitore IR sto usando ha bisogno di una frequenza di 38 kHz, che genera con CTC e OCR0A=122.
Quindi sto cercando di (e ho visto persone menzionarlo su Internet) usare gli interrupt Output Compare Ae Output Compare Bper generare un software PWM.
OCR0A, che viene utilizzato anche dal codice IR, determina la frequenza, che non mi interessa. E OCR0Bdetermina il duty cycle del PWM che userò per cambiare i colori dei LED.
Mi aspetto di poter ottenere un PWM con duty cycle 0-100% modificando il OCR0Bvalore da 0a OCR0A. Questa è la mia comprensione di ciò che dovrebbe accadere:
Ma ciò che sta realmente accadendo è questo (questo è dalla simulazione ISIS di Proteus):
Come puoi vedere di seguito, sono in grado di ottenere circa il 25% -75% di duty cycle ma per ~ 0-25% e ~ 75-100% la forma d'onda è bloccata e non cambia.
Linea GIALLA: Hardware PWM
Linea ROSSA: software PWM con ciclo di lavoro fisso
Linea VERDE: software PWM con ciclo di lavoro variabile
Ed ecco il mio codice:
#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
}
OCR0Aviene utilizzato dal codice IR, quindi ho solo OCR0B. Sto cercando di usarlo per generare software PWM su 3 pin non PWM.

