PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] RGB LED Software PWM Fragen, zwischenzeitlicher Jitter / Flicker



chrisavr1981
09.10.2015, 22:32
Hallo zusammen,

eigentlich würde ich so etwas ja nicht fragen, weil es schon ein wenig unangenehm ist, da das Thema so ausführlich erklärt wird, aber ich komme einfach nicht auf einen Nenner.
Ich habe schon seit langer Zeit eine Software PWM LED Steuerung vor, doch ich habe ich in meinem Aufbau, bei der Ausführung in der Steuerung LED-PWM, Jitter / Flicker Effekte.
Im Code sieht man, dass ich schon mit dem CPU Takt herumgespielt habe, teilweise habe ich mir andere Codeschnipsel angesehen und überlegt, ob dort eine Lösung zu finden sei, aber es hilft alles nix.

Vielleicht hat einer noch ein wenig Bock, sich den Code anzusehen?

Auf einem Entwicklungsboard sehe ich auch das Flickern / Jittern der LEDs, das einzige was ein wenig geholfen hat, ist den Timer Overflow Wert in der ISR Routine neuzusetzen, aber 100%tig bekomme ich den Fehler damit nicht heraus.
Zusätzlich habe ich "alles andere" entfernt um Fehler auszuschließen.

MCU : ATMEGA 168PA, 8Mhz Quarz



#include <avr/io.h>
#include <avr/interrupt.h> // Interrupts
//#include <avr/pgmspace.h>
//#include <avr/eeprom.h> // EEPROM Zugriffe
// setup the debugging
#define DEBUG 1
//#define XTAL 7372800UL // 8MHz
//#define F_CPU 7372800UL
//#define F_CPU 8000000UL
#define F_CPU 16000000UL
#include <util/delay.h> // definiert _delay_ms und _delay_loop_2
#include <stdlib.h>
#include <string.h>

#define FALSE 0
#define TRUE 1

// LED light for bed
// LED color red
#define U_LED_RED 0
#define U_LED_PIN_RED PC0
#define U_LED_PIN_RED_OUTPUT (DDRC |= (1<<U_LED_PIN_RED))
#define U_LED_PIN_RED_INPUT (DDRC &=~ (1<<U_LED_PIN_RED))
#define U_LED_PIN_RED_HI (PORTC |= (1<<U_LED_PIN_RED))
#define U_LED_PIN_RED_LOW (PORTC &=~ (1<<U_LED_PIN_RED))
#define U_LED_PIN_RED_TOG (PORTC ^= (1<<U_LED_PIN_RED))

// LED color green
#define U_LED_GREEN 1
#define U_LED_PIN_GREEN PC1
#define U_LED_PIN_GREEN_OUTPUT (DDRC |= (1<<U_LED_PIN_GREEN))
#define U_LED_PIN_GREEN_INPUT (DDRC &=~ (1<<U_LED_PIN_GREEN))
#define U_LED_PIN_GREEN_HI (PORTC |= (1<<U_LED_PIN_GREEN))
#define U_LED_PIN_GREEN_LOW (PORTC &=~ (1<<U_LED_PIN_GREEN))
#define U_LED_PIN_GREEN_TOG (PORTC ^= (1<<U_LED_PIN_GREEN))

// LED color blue
#define U_LED_BLUE 2
#define U_LED_PIN_BLUE PC2
#define U_LED_PIN_BLUE_OUTPUT (DDRC |= (1<<U_LED_PIN_BLUE))
#define U_LED_PIN_BLUE_INPUT (DDRC &=~ (1<<U_LED_PIN_BLUE))
#define U_LED_PIN_BLUE_HI (PORTC |= (1<<U_LED_PIN_BLUE))
#define U_LED_PIN_BLUE_LOW (PORTC &=~ (1<<U_LED_PIN_BLUE))
#define U_LED_PIN_BLUE_TOG (PORTC ^= (1<<U_LED_PIN_BLUE))

// !!!!!! FIXME !!!!
// we must change it to EEPROM
volatile uint8_t led_on;
volatile uint8_t led_time_on;
volatile uint16_t time_counter = 0;

volatile uint16_t U_PWM0_ENC = 255;
volatile uint16_t U_PWM1_ENC = 255;
volatile uint16_t U_PWM2_ENC = 255;

//
volatile uint8_t H_PWM0;
volatile uint8_t H_PWM1;
volatile uint8_t H_PWM2;

//
volatile uint16_t U_PWM0;
volatile uint16_t U_PWM1;
volatile uint16_t U_PWM2;


void initialisize(void)
{
// define register for timer
// TOIE0 for Timer0 and TOIE2 for Timer2
TIMSK |= (1<<TOIE0) | (1<<TOIE2) | (1<<TOIE1);
// Prescaler for Timer2 = 1024

TCCR2 |= (1<<CS20) | (1<<CS21) | (1<<CS22);

//TCCR2 |= (1<<WGM12) | (1<<CS21);

TCCR1B |= (1<<CS10) ;

// Prescaler CTC for TIMER1
//TCCR1B |= (1<<WGM12) | (1<<CS11) | (1<<CS10); // CTC, XTAL / 64

TCCR0 |= (1<<CS00);
// start value for overflow timer0
TCNT2 = 220;
// start value for overflow timer2
//TCNT2 = 128;
}

ISR (TIMER1_OVF_vect)
{
if (led_on == TRUE)
{
time_counter--;
}

if (time_counter <=1)
{
led_on = 0;
time_counter = 0;
}

if (U_PWM0 >= time_counter && led_on == TRUE && U_PWM0 > 1)
{
U_PWM0--;
}

if (U_PWM1 >= time_counter && led_on == TRUE && U_PWM1 > 1)
{
U_PWM1--;
}

if (U_PWM2 >= time_counter && led_on == TRUE && U_PWM2 > 1)
{
U_PWM2--;
}
}

ISR(TIMER0_OVF_vect)
{
counter++;

if (led_on != 0 && counter >= 1024 )
{
counter = 0;
if (U_PWM0 > 0 )
{
U_LED_PIN_RED_HI;
}
else
{
U_LED_PIN_RED_LOW;
}

if (U_PWM1 > 0 )
{
U_LED_PIN_GREEN_HI;
}
else
{
U_LED_PIN_GREEN_LOW;
}

if (U_PWM2 > 0 )
{
U_LED_PIN_BLUE_HI;
}
else
{
U_LED_PIN_BLUE_LOW;
}
}
else
{
if (counter == U_PWM0 )
{
U_LED_PIN_RED_LOW;
}

if (counter == U_PWM1 )
{
U_LED_PIN_GREEN_LOW;
}

if (counter == U_PWM2 )
{
U_LED_PIN_BLUE_LOW;
}
}

TCNT2 = 220;
}

int main(void)
{
initialisize();

// this is only for testing and development
led_on ^=1 ;
time_counter = 255;

while(1);

return 0
}


Ich gehe davon aus, dass es an den Timer liegt, dass diese sich wahrscheinlich Gegenseitig überholen, doch wie kann ich dem wieder "Herr" werden?
Mir würden Tipps eindeutig reichen, ich möchte nicht, dass hier Jemand für mich einen fertigen Code schreibt.

Was ich vorhabe die LEDs per SoftwarePWM anzusteuern und dann in einer gewissen Zeit aus zu faden.