Forum: Mikrocontroller und Digitale Elektronik Problem LED-PWM in C Mega8


von Andreas Kramer (Gast)


Lesenswert?

Ich habe ein Problem mit einer Software PWM für bisher eine LED ich weiß 
allerdings nicht woher der Fehler kommt. Der fehler ist die LED sollte 
ein und aus faden, was im groben auch geht allerdings leuchtet sie nicht 
wirklich regelmäßig sondern es mischen sich immer mal wieder Fehler ein. 
D.h die LED wir dunkler und plötzlich ist sie nochmal kurz wieder heller 
und dann wird sie wieder normal dunkler

Der Code ist leider kaum ausdokumentiert da ich noch am testen bin. Ziel 
sollen später mal 6 variable Fade in und Fade out Kanäle für LED´s 
werden. Dafür müsste aber erst mal ein simpler Kanal gehen =)

Hardware ist STK 500 LED´s an PORTB momentan nur eine.

Code ist hier die timer2.h
1
volatile uint16_t PWM_timer = 0;
2
volatile uint16_t msec8 = 0;
3
volatile uint8_t Prescale = 0;
4
void Timer_Init(void);
5
6
void Timer_Init(void)
7
{
8
  TCCR0 |= (1<<CS00);
9
  TIMSK |= (1<<TOIE0);
10
  DDRB = 0xff;
11
}
12
13
ISR(TIMER0_OVF_vect)
14
{
15
cli();
16
  PWM_timer++; //Timer für PWM-Frequenz
17
  Prescale++;
18
  if(Prescale==250) //Bei 8Mhz:256 :250 = 8ms rest
19
  {
20
  Prescale=0;
21
  msec8++; //Alle 8ms +1   maximalwert = 8,738 min
22
  }
23
  if(PWM_timer==401) PWM_timer=0;  
24
 sei();
25
}

Der Hauptcode ist der hier :
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <avr/interrupt.h>
4
#include "timer2.h"
5
#define FOSC 8000000// Clock Speed
6
7
void fade(void);
8
9
volatile uint16_t wert =0;
10
volatile uint8_t wert1 =0;
11
volatile uint8_t temp =0;
12
13
int main(void)
14
{
15
16
  Timer_Init();
17
  sei();
18
  while(1)
19
  {
20
21
    if(msec8==1)
22
  {
23
  fade();
24
  msec8=0;
25
  }
26
  
27
28
  if((PWM_timer==0)&(wert!=0))
29
  {
30
  PORTB= 0b11111110;
31
  }
32
  else if(PWM_timer == wert)
33
  {
34
  PORTB= 0b11111111;
35
  }
36
  }
37
}
38
39
40
void fade(void)
41
{
42
  if(temp==0)
43
  {
44
   wert1++;
45
   wert=(wert1 * wert1);
46
    if(wert==400)
47
    {
48
     temp++;
49
    }
50
  }
51
  else
52
  {
53
  wert1--;
54
  wert=(wert1 * wert1);
55
  if(wert==0)
56
  {
57
  temp--;
58
  }
59
  }
60
}

Ich hoffe mir kann einer sagen was ich da für nen Fehler hab muss ja 
irgendwas dummes sein oder aber ich bin blind und bilde mir das komische 
Blinken nur ein.

Ach der Atmega läuft mit internem Takt auf 8Mhz und ist ein normaler 
also keine "light" version.

Gruß Andreas

von Rahul D. (rahul)


Lesenswert?

Das cli und sei kann/sollte man sich in der ISR sparen. Darum kümmert 
sich der Compiler. (Das SEI sollte an der Stelle nicht kommen, weil 
sonst u.U. sogar der gleiche Interrupt noch mal zu schlägt, wenn das 
Interrupt-FLag noch nicht zurückgesetzt worden ist!)

Hast schon was vom CTC-Mode gehört/gelesen? Damit kann man sehr fein 
feste PWM-Frequenzen basteln, die nichts mit dem Overflow zu tun haben.

Und dann solltest du nur so große Variablen verwenden, wie du wirklich 
brauchst. Ein AVR kann 16bittige Variablen nicht atomar bearbeiten, was 
dazu führen kann, dass während der Bearbeitung ein Interrupt auftritt, 
der auf diese Variable zugreift. Schon kommt Mist dabei heraus.

Das sind jetzt alles recht allgemein gehaltene Hinweise, da ich dein 
Programm nicht verstehe.

von Falk B. (falk)


Lesenswert?

@  Andreas Kramer (Gast)

>Der Code ist leider kaum ausdokumentiert da ich noch am testen bin.

FALSCH!!!

Man sollte den Code SOFORT kommentieren, dann nie wieder wird man so 
sehr mit jeder einzelnen Zeile/Funtion uaf "du un Du2 sein wie in diesem 
Moment. Es erleichter vor allem die Fehlersuche immens. Ausserdem habe 
ich sowieso eine Denkweise, wo quasi Code und funktionale Beschreibung 
während des Programmieres parallel im Kopf laufen. Das sollte man nutzen 
und sofort hinschreiben.

>sollen später mal 6 variable Fade in und Fade out Kanäle für LED´s
>werden. Dafür müsste aber erst mal ein simpler Kanal gehen =)

Soft-PWM

MfG
Falk

von Andreas Kramer (Gast)


Lesenswert?

Hm ich hab mir den link mal angesehen leider verstehe ich es noch nicht 
so ganz wie es dort funktioniert und leider finde ich den Fehler in 
meinem Code auch nicht. Das mit dem cli und sei hab ich erst später 
eingefügt um zu schauen ob sich der Fehler dadurch beheben lässt. Leider 
gings auch mit nicht und ich hab versucht alle 16bit variablen zu 
vermeiden leider sind einige nötig oder ich müsste das Programm ganz neu 
aufsetzen ich weiß nur nicht woher der dumme blinker kommt -.- ich hab 
inzwischen vor jeden Teil mit den 16bit var mit cli und sei umschlossen. 
Ich versuche heute Abend mal den Code etwas ausdokumentieren aber die 
Funktion ist recht einfach. Es gibt einen zähler der bei overfolw einen 
interrupt auslöst dabei einige variabeln hochsetzt. Im normalen Programm 
ist eine schleife die die werte mit einer Variablen vergleicht. Wenn der 
Timer 0 ist dann wird die Led angeschaltet und wenn der Wert des Timer 
dann auf dem vorbestimmten Wert ist dann wird die Led wieder 
ausgeschaltet. Der Wert wird alle 8ms um eins erhöht und die Led 
leuchtet dann etwas länger usw bis die Led auf max ist dann wird wieder 
abwärts gezählt. Also recht Ideotensicher aber irgendwas ist da dennoch 
faul und geht nicht immer richtig nur fast sozusagen leider ist der 
fehler auch unregelmäßig das ich keine ahnung hab wodurch er ausgelöst 
wird. Falls einer irgendwas findet einfach sage. Gegen verbesserungen 
hab ich nie was =)

Gruß Andreas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.