Forum: Mikrocontroller und Digitale Elektronik PWM mit zufälligem Duty cycle


von Anonym (Gast)


Lesenswert?

Moin,
ich möchte mit meinem Atmega 8515 zwei unterschiedliche PWM Signale 
erzeugen deren Duty-cycle sich alle 5 sec. auf einen (mehr oder weniger) 
zufälligen Wert ändert. Leider bekomme ich zwei Signale mit einem 
konstanten Duty-cycle heraus. Ich hoffe jmd findet meinen Fehler im 
Quellcode.
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <avr/interrupt.h>
4
#include <stdio.h>
5
#include <util/delay.h>
6
#define F_CPU 1000000UL
7
8
int main(void)
9
{
10
int i11, i12, i21, i22;
11
DDRD = 0xff;
12
DDRE = 0xff;
13
ICR1 = 64000;    
14
15
TCCR1A = (1<<WGM11)|(1<<COM1A1)|(1<<COM1B1);
16
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10)|(1<<CS11);
17
TIMSK = (1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1);
18
19
sei();                      
20
while(1)
21
{  
22
  i11=rand()%64;    //Zufall 0-63
23
  i12=rand()%1000;  //Zufall 0-999
24
  OCR1A = i11*1000 + i12;
25
  
26
  i21=rand()%64;    //Zufall 0-63
27
  i22=rand()%1000;  //Zufall 0-999
28
  OCR1B = i21*1000 + i22;
29
  
30
  _delay_ms(5000);
31
}}

von Jürgen S. (jurs)


Lesenswert?

Anonym schrieb:
> ich möchte mit meinem Atmega 8515 zwei unterschiedliche PWM Signale
> erzeugen deren Duty-cycle sich alle 5 sec. auf einen (mehr oder weniger)
> zufälligen Wert ändert. Leider bekomme ich zwei Signale mit einem
> konstanten Duty-cycle heraus.

Möchtest Du "zufällige duty cycle Werte" oder "zufällige 
Helligkeitswerte" steuern?

Falls es um Helligkeit geht, wäre zu beachten, dass die Helligkeit NICHT 
linear mit dem duty cycle steigt:
http://www.mikrocontroller.net/articles/LED-Fading

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Anonym schrieb:
> TIMSK = (1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1);

Du gibst zwar alle Interrupts des Timers frei, diese werden aber in dem 
sichtbaren Teil deines Programmes gar nicht behandelt. Vermutlich wird 
also der MC bei jedem Versuch, eine ISR anzuspringen, bei Reset wieder 
neu anfangen.
Für so etwas braucht man auch gar keine Interrupts. Du schreibst 
lediglich in OC1A und OC1B werte, den Rest macht der MC alleine. Auch 
der Overflow Interrupt ist unnötig.

von Anonym (Gast)


Lesenswert?

Ich habe die Zeile mal auskommentiert und siehe da der Duty cycle ist 
zufällig.
>> TIMSK = (1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1);

Allerdings bleibt dieser nicht wie erwünscht über 5 sec konstant. Hat 
die "delay" funktion eine zeitliche Beschränkung

von Karl H. (kbuchegg)


Lesenswert?

Anonym schrieb:

> Allerdings bleibt dieser nicht wie erwünscht über 5 sec konstant. Hat
> die "delay" funktion eine zeitliche Beschränkung

Nicht im Bereich 5 Sekunden. Ok, auf die Mykrosekunde wird die 
Verzögerung nicht stimmen, aber ich glaube, darum gehts dir nicht.

Da wird halt das
1
#define F_CPU 1000000UL
nicht mit der Realität übereinstimmen.

von Anonym (Gast)


Lesenswert?

Du hast recht, mir kommt es nicht auf die millisekunde an. Aber das 
auskommentieren von
#define F_CPU 1000000UL
bringt auch keinen Erfolg

von Karl H. (kbuchegg)


Lesenswert?

Anonym schrieb:
> Du hast recht, mir kommt es nicht auf die millisekunde an. Aber das
> auskommentieren von
> #define F_CPU 1000000UL
> bringt auch keinen Erfolg

Es geht nicht ums auskommentieren.
Es geht darum, dass die 1 Million, die du da hinschreibst mit der realen 
Taktfrequenz des µC übereinstimmen muss!

Die Angabe bei F_CPU ist die Information an den Compiler wie schnell der 
µC tatsächlich läuft und nicht die Vorgabe wie schnell du den µC gerne 
laufen hättest.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Die Angabe bei F_CPU ist die Information an den Compiler wie schnell der
> µC tatsächlich läuft und nicht die Vorgabe wie schnell du den µC gerne
> laufen hättest.

Beispiel:
Schreibst du da
1
#define F_CPU 1000000UL
dann berechnet der Compiler die Anzahl an Umdrehungen, die der µC beim 
Däumchen drehen für
1
   _delay_ms( 5000 );
machen muss für diese Taktfrequenz von 1Mhz, da er ja durch die 1Mhz 
weiß, wie lange der µC für einmal Däumchen drehen braucht.

Ist der µC aber tatsächlich 4 mal schneller, weil er mit 4Mhz getaktet 
wird und nicht mit 1Mhz, dann stimmt die errechnete Zahl an notwendigen 
Umdrehungen natürlich nicht. Der µC muss jetzt wesentlich mehr 
Umdrehungen des Daumens machen (4 mal so viele), damit das wieder 5 
Sekunden dauert.

von Anonym (Gast)


Lesenswert?

D.h. wenn ich den Takt zu niedrig angebe braucht er weniger als 5 sec, 
wenn ich ihn zu groß angebe braucht er mehr als 5sec? Ich habe 
verschiedene Takte durchprobiert und es tritt nicht die geringste 
Zeitverzögerung ein.

von Karl H. (kbuchegg)


Lesenswert?

Anonym schrieb:
> D.h. wenn ich den Takt zu niedrig angebe braucht er weniger als 5 sec,
> wenn ich ihn zu groß angebe braucht er mehr als 5sec? Ich habe
> verschiedene Takte durchprobiert und es tritt nicht die geringste
> Zeitverzögerung ein.


Dann zeig dein Programm, so wie es jetzt ist.
Das klingt dann stark danach, als ob du immer noch Resets im Programm 
hast, was auf einen weiteren Fehler hindeutet.

ALternativ probiere mal folgendes
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <util/delay.h>
4
5
#define F_CPU 1000000UL
6
7
int main(void)
8
{
9
  DDRD = ( 1 << PD5 );
10
11
  while(1)
12
  {
13
    PORTD |= ( 1 << PD5 );
14
    _delay_ms( 1000 );
15
16
    PORTD &= ~( 1 << PD5 );
17
    _delay_ms( 1000 );
18
  }
19
}

an PD5 hast du offenbar irgendeine Möglichkeit was zu messen (eine 
LED?). Der Ausgang muss 1 Sekunde High und 1 Sekunde Low sein.
WEnn er das ist, dann ist die Taktfrequenz des µC tatsächlich 1Mhz. Wenn 
nicht, dann musst du eben rausfinden, wie schnell der µC wirklich 
taktet. Hast du einen QUarz drann, dann wird der wohl aktiv sein und es 
gilt die Quarzfrequenz. Hast du .... das kann ich aber von hier aus 
nicht sehen.

von Anonym (Gast)


Lesenswert?

So sieht mein Programm jetzt aus:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <avr/interrupt.h>
4
#include <stdio.h>
5
#include <util/delay.h>
6
#define F_CPU 16000000UL
7
8
int main(void)
9
{
10
int i11, i12, i21, i22, zahl;
11
DDRD = 0xff;
12
DDRE = 0xff;
13
ICR1 = 64000;    
14
15
TCCR1A = (1<<WGM11)|(1<<COM1A1)|(1<<COM1B1);
16
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10)|(1<<CS11);
17
//TIMSK = (1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1);
18
19
sei();                      
20
while(1)
21
{  
22
  i11=rand()%64;    //Zufall 0-63
23
  i12=rand()%1000;  //Zufall 0-999
24
  OCR1A = i11*1000 + i12;
25
  
26
  i21=rand()%64;    //Zufall 0-63
27
  i22=rand()%1000;  //Zufall 0-999
28
  OCR1B = i21*1000 + i22;
29
  
30
  _delay_ms(5000);
31
}}
keine Verzögerung zu sehen.
Dein anderer Tipp hat mich bislang auch nicht weitergebracht. Habe 1, 
8,16 und 3,68 MHz probiert und die LED blinkt zu schnell

von Karl H. (kbuchegg)


Lesenswert?

Anonym schrieb:

> Dein anderer Tipp hat mich bislang auch nicht weitergebracht. Habe 1,
> 8,16 und 3,68 MHz probiert und die LED blinkt zu schnell


Das stinkt für mich danach als ob dein µC Resets macht.

Was ist dann an den Pins angeschlossen?
LED?
Hoffentlich mit Vorwiderstand.

von Anonym (Gast)


Lesenswert?

Ja led´s und na klar mit Vorwiderstand

von Karl H. (kbuchegg)


Lesenswert?

Blöde Frage:
Der OPtimizer vom Compiler steht aber schon auf -Os

von Anonym (Gast)


Lesenswert?

Kann ich dir nicht sagen, ich benutze das STK500 zum programmieren

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Angehängte Dateien:

Lesenswert?

Anonym schrieb:
> #include <util/delay.h>
> #define F_CPU 16000000UL

Ist da nicht die Reihenfolge falsch? Ich definiere meine F_CPU über AVR 
Studio, aber ich kann mich erinnern, das man delay.h erst einbinden 
sollte, nachdem F_CPU definiert ist, damit delay.h eine Chance hat, sich 
zu justieren.

Anonym schrieb:
> Kann ich dir nicht sagen, ich benutze das STK500 zum programmieren

Das hat damit nichts zu tun, die Optimierung wird in den 
Compileroptionen eingestellt, der Programmer kregt nur noch das Ergebnis 
zu sehen. Ein guter Anhaltspunkt ist die Grösse des Codes, falls dir das 
nach dem Kompilieren angezeigt wird.

Hier mal ein Screenshot vom AVR Studio 4

von Anonym (Gast)


Lesenswert?

Das AVR Studio benutze ich auch

von Anonym (Gast)


Lesenswert?

Aber 5.0

von Anonym (Gast)


Lesenswert?

Das Problem ist gelöst. Die Verschiebung von F_CPU und delay.h war der 
Knackpunkt.

Vielen Vielen Dank

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.