Software PWM wird zum Ende langsamer

Gast #3726141
Lesenswert?

Hallo, ich wollte PWM über Software erzeugen.

Ich hab mir die einfachste Arte rausgesucht, einfach Ein/Auszeit 
verändert.
Hier bei nehme ich feste 500uS Anzeit und verändere die Auszeit. In 
dieser Zeit-Spanne tritt kein Flimmern auf und die Spannung ist nur 
etwas niedriger als gewollte 15mV aber nicht Schlimm.

Ich habe mir mal die Soft-PWM Einträge angeguckt aber dies war mir fürn 
Anfang zu viel und deswegen wollte ich dies erst mal recht einfach 
lösen, da es mir erst nur ums dunkel und heller machen geht.

Was ist mein Anliegen ? Wie es im Betreff steht, möchte ich die LED 
dunkler machen, wird es zum Ende langsamer dunkel. Beispiel, so bei 4V 
und 3V springt er mit ca. 0.1V Schritten und bei 2V mit ca. 0.01V 
Schritten.

Ich kann die Spannung aber schon genau Einstellen.

Hier mal mein kleiner Code :
1
for (int i=0;i<1500;i++) //Maximale Auszeit
2
    {    
3
    
4
    
5
    for (int i=0;i<10;i++) // Anzeit pro Schritt
6
    {
7
      PORTB = (1<<PB4);
8
      _delay_us(500);
9
      PORTB &= ~ (1<<PB4);
10
      
11
      
12
      if (time==0)
13
      {
14
        _delay_us(0);
15
        
16
      }
17
      
18
      else
19
      
20
      {
21
        
22
        for (int l=0;l<time;l++)
23
        {
24
          _delay_us(1);
25
        }
26
      }
27
          
28
    
29
    
30
    }
31
    
32
    
33
    time++;
34
    
35
    }
Gast #3726146
Lesenswert?

Meinst Du die LED wird langsamer dunkler nach einer bestimmten Zeit?
Wenn ja, dann sei Dir bewusst, daß die Helligkeit der LED logarithmisch 
abnimmt. Das musst Du dann natürlich auch im Code abbilden.
Zum Code: warum tust Du Dir das an? PWM mittels Timer setzen ist 
einfacher als die verschachtelten for-Konstrukte zu verwenden!
Gast #3726160
Lesenswert?

Die Spannaung nimmt nach ner Zeit langsamer ab, folglich auch die 
Helligkeit.

Meinen Sie Hardware PWM oder Soft-PWM

Über Hardware-PWM wollte  ich das nicht machen da ich später min. 3 
Anschlüsse ansteuern wollte.
Gast #3726176
Lesenswert?

3 Anschlüsse gleichzeitig ansteuern mit Deinem Code wird nicht gehen. 
Dazu musst Du entweder Hardware-PWM oder SW-PWM per Interrupt machen.

Daß die Spannung nicht linear abnimmt, ist logisch. Ist das so von Dir 
gewollt oder verstehst Du nicht, warum das so ist?

Gruß, Stefan
#3726177
Lesenswert?

dein Problem ist, dass du die Aus-zeit zwar immer verlängerst, aber die 
An-Zeit nicht verkürzt. Deine Zykluszeit wird also immer größer.

dein Code sieht ziemlich unstrukturiert aus.

Ein Zyklus hat 2 Parameter:
 - die Länge
 - das Tastverhältnis

dieser Zyklus wird einfach mehrmals wiederholt, bis man irgendwann die 
Parameter ändert.
1
int  anzahl_Zyklen_je_Wert = 5000:
2
int  dauer_Zyklus_gesamt_us = 1500;
3

4
for( int dauer_an = 0; dauer_an < dauer_Zyklus_gesamt_us; ++i)
5
{
6
  int dauer_aus = dauer_Zyklus_gesamt_us - dauer_an;
7

8
  for( int i=anzahl_Zyklen_je_Wert; i; --i)
9
  {
10
      PORTB = (1<<PB4);
11
      mydelay(dauer_an);
12
      PORTB &= ~ (1<<PB4);
13
      mydelay(dauer_aus);
14
  }
15
}

mydelay muss ne schleife um _delay_us sein, da da nur konstante werte 
reindürfen. Der schleifencode versaut natürlich das Timing massiv, da 
eine µs nicht wirklich viel ist, im vergleich zu der schleife. 
vielleicht sollte man also eine schleife über _delay_us(10) oder so 
implentieren.

Das lässt aber auch offensichtlich werden, dass es nicht sinnvoll ist 
eine PWM mittels delay zu bauen.
Gast #3726190
Lesenswert?

i   Anzeit   Auszeit  PWM

   0   500     0     100%
 100   500   100      83%
 200   500   200      71%
 300   500   300      62%
 400   500   400      55%

 500   500   500      50%
 600   500   600      45%
 700   500   700      41%
 800   500   800      38%
 900   500   900      35%
1000   500  1000      33%
1100   500  1100      31%
1200   500  1200      29%
1300   500  1300      27%
1400   500  1400      26%
1500   500  1500      25%

Was Du für eine LED eher willst, ist ein logarythmischer PWM-Verlauf. 
Das wirst Du mit einer konstanten Anzeit aber nicht errechen.

Gruß, Stefan
Gast #3726205
Lesenswert?

@ Vlad Tepesch:
1
i   Anzeit   Auszeit  Das An/Aus-Verhältnis, das die 
2
                      obige Software (ca.) liefert
3

4
   0   500     0     100%
5
 100   500   100      83%
6
 200   500   200      71%
7
 300   500   300      62%
8
 400   500   400      55%
9

10
 500   500   500      50%
11
 600   500   600      45%
12
 700   500   700      41%
13
 800   500   800      38%
14
 900   500   900      35%
15
1000   500  1000      33%
16
1100   500  1100      31%
17
1200   500  1200      29%
18
1300   500  1300      27%
19
1400   500  1400      26%
20
1500   500  1500      25%
So zufrieden? ;-)
Gast #3727153
Lesenswert?

Entschuldigung...

Hab jetzt mal den Timer2 und Timer0 genommen.

Timer0 funktioniert einwandfrei, allerdings nur wenn Timer2 nicht läuft.
Timer2 kann ich OCR2 werte geben und er gibt es richtig aus (0 bis 255).
Aber möchte ich nun von 0 bis 255  hoch zählen und meine LED heller 
werden lassen, dauert dies eine Ewigkeit. Timer0 macht es ganz normal, 
aber wenn ich beide parallel laufen lasse brauchen beide eine Ewigkeit.
Hoffe ich hab mich einigermaßen ausgedrückt..und jemand kann mir helfen

Hier mal der Code
1
void PWM_Int(){  
2
  
3
  TCCR0 = (1<<WGM01) | (1<<WGM00) | (1<<CS00) | /*(1<<CS02) |*/ (1<<COM01); //Fast PWM //Zählt von 0 bis OCR0
4
  
5

6
TCCR2 = (1<<WGM21) | (1<<WGM20)  | (1<<COM21) |(1<<CS20) ;
7
}
8

9

10
//Wert: Zwischen 0 - 255
11

12
//0= 0%
13

14
//255= 100%
15
  
16
//      Wert
17
//Vout=  ------ x 5v
18
//        255
19

20
void PWM_Output(uint8_t wert){
21
     OCR0=wert;  
22
     OCR2=wert;
23
}
24

25
//_____________
26

27
   while (1)
28
     {
29
       
30
       
31
       for (Brightness=0;Brightness<255;Brightness++)
32
       {
33
         
34
         PWM_Output(Brightness);
35
         
36
         _delay_ms(50);
37
       }
38
       
39
       _delay_ms(5000);
40
       
41
       for (Brightness=255;Brightness>0;Brightness--)
42
       {
43
         
44
         PWM_Output(Brightness);
45
         
46
         _delay_ms(50);
47
       }
48
         
49
      _delay_ms(5000);
50
              
51
       
52
       
53
     }

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren