J'essaie de créer une lumière LED RGB à télécommande à l'aide d'un ATtiny13A.
Je sais que l'Attiny85 est mieux adapté à cette fin, et je sais que je ne pourrai peut-être pas éventuellement adapter tout le code, mais pour l'instant ma principale préoccupation est de générer un logiciel PWM utilisant des interruptions en mode CTC.
Je ne peux pas fonctionner dans un autre mode (sauf pour PWM rapide avec OCR0A
as TOP
qui est fondamentalement la même chose) parce que le code du récepteur IR que j'utilise a besoin d'une fréquence de 38 kHz qu'il génère en utilisant CTC et OCR0A=122
.
J'essaie donc (et j'ai vu des gens le mentionner sur Internet) d'utiliser les interruptions Output Compare A
et Output Compare B
pour générer un logiciel PWM.
OCR0A
, qui est également utilisé par le code IR, détermine la fréquence, ce qui m'est égal. Et OCR0B
, détermine le rapport cyclique du PWM que je vais utiliser pour changer les couleurs des LED.
Je m'attends à pouvoir obtenir un PWM avec un rapport cyclique de 0 à 100% en changeant la OCR0B
valeur de 0
à OCR0A
. Voici ma compréhension de ce qui devrait arriver:
Mais ce qui se passe réellement est le suivant (ceci provient de la simulation Proteus ISIS):
Comme vous pouvez le voir ci-dessous, je peux obtenir un rapport cyclique d'environ 25% à 75% mais pour ~ 0-25% et ~ 75-100% la forme d'onde est juste bloquée et ne change pas.
Ligne JAUNE: Matériel PWM
Ligne ROUGE: Logiciel PWM avec rapport cyclique fixe
Ligne VERTE: logiciel PWM avec cycle d'utilisation variable
Et voici mon code:
#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
est utilisé par le code IR donc je n'ai que OCR0B
. J'essaie de l'utiliser pour générer un logiciel PWM sur 3 broches non PWM.