Hey Leute,
ich erinnere mich mal gehört zu haben, dass man bei µC Programmierung
keine for-Schleifen verwendet, da diese zu langsam sind (oder so).
Folgendes Problem..
Ich habe ein Programm, das mir 6 verschiedene PWM-Signale erzeugt.
sprich manche Funktionen werden 6 mal aufgerufen.
Dies geschieht bei manchen Aufgaben mit switch-Anweisungen und bei
anderen in for-Schleifen. Je nach dem, was gefragt ist.
Beispielcode (aufs wesentliche komprimiert der richtige Code hat 220
Zeilen):
1
// increase PWM-Time
2
voidstepPWM(){
3
for(unsignedchari=0;i<numberOfMags;i++){
4
mag[i].currentTime+=1;
5
}
6
}
7
8
//Timer Interrupt
9
ISR(TIMER0_COMPA_vect){
10
TCNT0=0x00;
11
stepPWM();
12
}
13
14
intmain(void){
15
..........// Initialisierungen usw.
16
while(1){
17
18
// Kontrolle, ob Einstellungen für PWM geändert werden müssen
19
if(PORTB&0x3F){
20
process();// hier wird geschaut, welche PWM geändert werden müssen, um welche Werte diese geändert werden müssen(2x ADC für (Frequenz oder Phase wird an einem Eingang gemultiplext) und Tastverhältnis) dann werden die Einstellungen aktualisiert
21
//hier wird eine Funktion mit for-Schleife aufgerufen und zusätzlich in einer for-Schleife eine weitere Funktion aufgerufen
22
};
23
// Kontrolle, ob die Phasen aller PWM zurückgesetzt werden sollen
24
if(PORTB&1<<PORTB7){
25
for(unsignedchari=0;i<numberOfMags;i++){
26
synchronizePhase(&mag[i]);// hier werden die Variablen für die Phasenverschiebungen auf 0 gesetzt (in einer for Schleife)
27
}
28
};
29
for(unsignedchari=0;i<numberOfMags;i++){
30
checkPWM(&mag[i],i);// hier wird für die i te PWM überprüft, ob Phasenverschiebung, Tastverhältnis, Frequenz(Periodenende) erreicht ist, um dann den Output festzulegen.
31
}
32
}
33
return0;
34
}
Mein Problem ist, einfach dass der Ablauf der Mainschleife viel zu lange
dauert. Meine erste Optimierung wäre den Code effizienter zu gestalten,
indem ich die for-Schleifen umgehe, wenn das denn möglich ist.
Ich hoffe mein Problem ist verständlich erklärt.
Kaan Ayhan schrieb:> Hey Leute,> ich erinnere mich mal gehört zu haben, dass man bei µC Programmierung> keine for-Schleifen verwendet, da diese zu langsam sind (oder so).
Die meisten Aussagen die mit 'Ich habe mal gehört' beginnen, sind
kompletter Unsinn.
@ Karl Heinz (kbuchegg) (Moderator)
>Die meisten Aussagen die mit 'Ich habe mal gehört' beginnen, sind>kompletter Unsinn.
Das hab ich auch mal gehört! ;-)
Peter II schrieb:> die Schleifen werden wohl nicht das Problem sein. (Wie gross ist> numberOfMags überhaupt?)>> sondern die Funktionen (synchronizePhase,checkPWM).
Jepp
@TO: Bitte IMMER den kompletten Code posten. So ist das ein
"Rate-Rate-Was-ist-das".
Das Problem ist in checkPWM.
...
oder in sonst einem Teil, den du nicht gepostet hast.
Kaan Ayhan schrieb:> ich erinnere mich mal gehört zu haben, dass man bei µC Programmierung> keine for-Schleifen verwendet, da diese zu langsam sind (oder so).
"Oder so" sollte man nie vertrauen solange man keinen plausiblen Grund
hat warum das so sein sollte.
Die for Schleife selbst ist zu 99,999% NICHT dein Problem.
Schon mal bei Eintritt und verlassen von Funktionen einen Port
gesetzt/gelöscht und mit dem Oszi geschaut wie lange die Funktionen
brauchen?
Die Funktionen auf die es ankommt hats du ja zum Glück im Listing
unterschlagen. Die müssen wir ja nicht anschauen .....
Wo "viel" Zeit draufgeht ist der Funktionaufruf (Register retten
und Parameter kopieren) selbst und die Rückkehr aus der Funktion.
> Beispielcode (aufs wesentliche komprimiert der richtige Code hat 220 Zeilen):
Zeig den Code und beschreibe, inwiefern er zu langsam ist.
Alles andere ist Kaffeesatzleserei.
Das Wahrscheinlichste ist, dass dein Zeitproblem in der Progammstruktur
enthalten ist. D.h. man kann nicht eine bestimmte Stelle dafür
verantwortlich machen, sondern muss das Programm entsprechend
strukturieren bzw. umstrukturieren.
Zb sieht es seltsam aus, wenn du von 6 PWMs redest, in der einzigen ISR
aber gar kein PWM Code enthalten ist (ich geh mal davon aus, dass du
Software-PWM machen willst, weil du nicht genügend Hardware Einheiten
für 6 PWM hast).
Ja, an meiner Programmierung wird es natürlich eher liegen, da ich noch
nicht besonders viel Erfahrung darin habe. Ich habe den Mikrocontroller
noch garnicht. Das ganze läuft im Moment nur im Debugger des AtmelStudio
6.2 bei mir.
Ich habe das Programm mal gepackt und hochgeladen. Ich hoffe, ihr könnt
etwas damit anfangen. Wichtig ist mir halt insbesondere, dass die
Funktion checkPWM() zwischen jedem Timerinterrupt aufgerufen werden
kann. das packe ich aber nicht. Der Timerinterrupt wird, wenn ich mich
nicht irre, 3 mal pro Mainschleifendurchlauf aufgerufen.
Im Moment wird der Timerinterrupt mit 500Hz geschmissen und der
Systemtakt liegt bei 1Mhz.
Wenn das Board fertig ist, wird ein externes Quarz angeschlossen, um
16MHz Systemtakt zu erhalten und der TimerInterrupt soll mit 200kHz
aufgerufen werden... sodass eine PWM-Frequenz von 2kHz bei einem
Tastverhältnis von 1% Genauigkeit möglich ist.
Ich habe mir überlegt, die checkPWM()-Funktion im Interrupt auszuführen,
aber das ist ja auch nicht gerade gut. Vor allem weil die Funktion zu
viele Takte braucht >.<
...
Ich bin für jede Hilfe dankbar.
Kaan Ayhan schrieb:> um> 16MHz Systemtakt zu erhalten und der TimerInterrupt soll mit 200kHz
Das ist natürlich mal ne Ansage, viel Takte sind das nicht.
Gerade mal 80 minus der Zeit, die die Interrupt Funktion selbst braucht.
Kaan Ayhan schrieb:> Funktion checkPWM()zwischen jedem Timerinterrupt aufgerufen werden> kann. das packe ich aber nicht. Der Timerinterrupt wird, wenn ich mich> nicht irre, 3 mal pro Mainschleifendurchlauf aufgerufen.
Kann oder muss die Funktion aufgerufen werden.
Wenn sie nach jedem Timerinterrupt aufgerufen werden MUSS dann ist es
vieleicht sinnvoll sie am Ende der Timerinterruptfunktion direkt
aufzurufen.
Denn der Zusammenhang zwischen Timerinterruptfunktion und Hauptschleife
ist per se erst mal asynchron.
Kaan Ayhan schrieb:> Hey Leute,> ich erinnere mich mal gehört zu haben, dass man bei µC Programmierung> keine for-Schleifen verwendet, da diese zu langsam sind (oder so).
Nein, das ist Unsinn. Wenn man über eine bestimmte Anzahl von Elementen
iterieren soll, so kann man dies hervorragend mit einer for-Schleife
tun. Oder auch mit einer while-Schleife.
Wenn Du etwas X-Mal machen willst, so kommst Du um die grundlegende
Frage: "Wie oft habe ich es schon getrieben", nicht herum.
Dies wiederum bedeutet, dass Du auch jemanden hast den Du fragen kannst
- meist eine Variable - und etwas, das diese, bei jedem Mal,
inkrementiert - alternativ dekrementiert.
Eine minimale Verkürzung würde eine Endlosschleife bringen. Aber nur,
wenn die Anzahl unwichtig ist.
Moderne Compiler "wissen" auch, ob der jeweilige Prozessor
Sondermöglichkeiten besitzt, die es ermöglichen Sonderbefehle zu
verwenden.
Also solche, die die Dekrementierung oder Inkrementierung mit
verkürzenden Sprunganweisungen verbinden. Oder explizite Vergleiche nach
dem Zählen sparen.
Kaan Ayhan schrieb:> ich erinnere mich mal gehört zu haben, dass man bei µC Programmierung> keine for-Schleifen verwendet, da diese zu langsam sind (oder so).
Also dein
> void stepPWM(){> for (unsigned char i=0; i<numberOfMags; i++){> mag[i].currentTime += 1;> }> }
wäre als
1
voidstepPWM(){
2
mag[0].currentTime+=1;
3
mag[1].currentTime+=1;
4
mag[2].currentTime+=1;
5
mag[3].currentTime+=1;
6
mag[4].currentTime+=1;
7
mag[5].currentTime+=1;
8
}
ungefähr doppelt so schnell (vorausgesetzt, mag ist global).
Aber mit doppelt so schnell bekommt man kein VIEL zu langsamen Programm
schnell genug. Meistens sind die Algorithmen schlecht gewählt. Irgendwas
lernen die Leute in ihren Informatikstudium schon.
Udo Schmitt schrieb:> Kann oder muss die Funktion aufgerufen werden.> Wenn sie nach jedem Timerinterrupt aufgerufen werden MUSS dann ist es> vieleicht sinnvoll sie am Ende der Timerinterruptfunktion direkt> aufzurufen.
Ja.
Aber bitte jetzt nicht die vorhandene Funktion.
Im Timer Interrupt soll nur die PWM erzeugt werden. Nichts anderes. Für
6 Ausgänge sollte das auch mit der beschränkten Taktzahl noch machbar
sein.
Laufen die einzelnen PWM eigentlich alle mit derselben Frequenz?
Karl Heinz schrieb:> Im Timer Interrupt soll nur die PWM erzeugt werden. Nichts anderes. Für> 6 Ausgänge sollte das auch mit der beschränkten Taktzahl noch machbar> sein.>> Laufen die einzelnen PWM eigentlich alle mit derselben Frequenz?
1
structpwm_t
2
{
3
uint8_tcnt;
4
uint8_tsetCnt;
5
uint8_tsetMask;
6
uint8_tclrMask;
7
}
8
9
volatilestructpwm_tPwm[6]=
10
{
11
{0,(1<<PORTD0),~(1<<PORTD0)},
12
{0,(1<<PORTD1),~(1<<PORTD1)},
13
{0,(1<<PORTD2),~(1<<PORTD2)},
14
{0,(1<<PORTD3),~(1<<PORTD3)},
15
{0,(1<<PORTD5),~(1<<PORTD5)},
16
{0,(1<<PORTD6),~(1<<PORTD6)},
17
};
18
19
ISR(...)
20
{
21
staticuint8_tpwmCount=0;
22
uint8_ti;
23
uint8_tportShadow;
24
25
pwmCount++;
26
if(pwmCount==100){
27
pwmCount=0;
28
for(i=0;i<6;i++)
29
Pwm[i].cnt=Pwm[i].setCnt;
30
}
31
32
portShadow=PORTD;
33
34
for(i=0;i<6;i++){
35
if(Pwm[i].cnt<pwmCount)
36
portShadow|=Pwm[i].setMask;
37
else
38
portShadow&=Pwm[i].clrMask;
39
}
40
41
PORTD=portShadow;
42
}
damit laufen mal die 6 PWM Stufen und alles andere arbeitet diesen zu.
wenn das unlösbare Zeitprobleme ergibt, dann müsste man an den Masken
noch feilen, und eventuell die Schleife aufdröseln, damit der Compiler
die schnellen Bitinstruktionen benutzen kann
1
volatileuint8_tPwm[6];// die Werte der einzelnen PWM Stufen
2
uint8_tPwmWork[6];
3
4
#define CHECK_PWM(i, pin) \
5
if( PwmWork[i] < pwmCount ) \
6
PORTD |= ( 1 << pin ); \
7
else \
8
PORTD &= ~( 1 << pin );
9
10
ISR(...)
11
{
12
staticuint8_tpwmCount=0;
13
uint8_ti;
14
15
pwmCount++;
16
if(pwmCount==100){
17
pwmCount=0;
18
for(i=0;i<6;i++)
19
PwmWork[i]=Pwm[i];
20
}
21
22
CHECK_PWM(0,PORTD0);
23
CHECK_PWM(1,PORTD1);
24
CHECK_PWM(2,PORTD2);
25
CHECK_PWM(3,PORTD3);
26
CHECK_PWM(4,PORTD5);
27
CHECK_PWM(5,PORTD6);
28
}
Das ist der Kern der ganzen Sache. Die einzelnen PWM müssen mit der
angestrebten Frequenz laufen. Alles andere hat sich dem unterzuordnen.
Es gäbe auch noch eine cleverere Variante der PWM Erzeugung, die um
einiges weniger CPU-Laufzeit benötigt. Die ist allerdings um einiges
komplexer.
Und da rundherum konstuierst du jetzt deinen Code, der die Veränderung
der jeweiligen PWM Werte realisiert.
Disclaimer: Ich hab jetzt die einzelnen ISR nicht kontrolliert, ob sich
das mit der Taktzahl noch ausgeht. Es sollte aber zumindest nahe drann
sein. Wenn es sich nicht ausgeht, könntest man mal darüber nachdenken,
ob man die 200kHz nicht etwas lockert. Mit 100kHz (und damit 2% anstelle
von 1%) ist man mit 16Mhz auf jeden Fall im grünen Bereich.
@MaWin
>ungefähr doppelt so schnell (vorausgesetzt, mag ist global).
Stimmt bei kurzen Anweisungen und bei überschaubarer Anzahl an
Schleifendurchläufen.
Andernfalls werden hauptsächlich die Fingerkuppen strapaziert und der
Code gerät aus der Form. Vielleicht springt auch der Compiler aus dem
Fenster, weil ihm dauernd jemand den Speicher klaut.
MaWin schrieb:> ungefähr doppelt so schnell (vorausgesetzt, mag ist global).
Nur als Beispiel, auf welche Ideen Compiler schon von sich aus kommen,
wenn man sie nicht dran hindert:
1
externcharmag[];
2
3
voidstepPWM(void){
4
for(unsignedi=0;i<256;i++){
5
mag[i]+=1;
6
}
7
}
wird bei GCC 4.7.2 und -O3 für x86-64 im Kern zu
1
.L5:
2
movdqa (%rsi,%rax), %xmm0
3
addl $1, %ecx
4
paddb %xmm1, %xmm0
5
movdqa %xmm0, (%rsi,%rax)
6
addq $16, %rax
7
cmpl %r8d, %ecx
8
jb .L5
und falls jemandem das nichts sagt: Das ist gepackter SSE Code mit 16
mag[] Elementen pro Iteration. Mit -funroll-loops wird das dann zu 128
pro Iteration:
1
.L5:
2
movdqa (%rdx,%rax), %xmm9
3
addl $8, %ecx
4
movdqa 16(%rdx,%rax), %xmm10
5
paddb %xmm0, %xmm9
6
movdqa 32(%rdx,%rax), %xmm11
7
paddb %xmm0, %xmm10
8
movdqa 48(%rdx,%rax), %xmm12
9
paddb %xmm0, %xmm11
10
movdqa 64(%rdx,%rax), %xmm13
11
paddb %xmm0, %xmm12
12
movdqa 80(%rdx,%rax), %xmm14
13
paddb %xmm0, %xmm13
14
movdqa 96(%rdx,%rax), %xmm15
15
paddb %xmm0, %xmm14
16
movdqa 112(%rdx,%rax), %xmm1
17
paddb %xmm0, %xmm15
18
movdqa %xmm9, (%rdx,%rax)
19
paddb %xmm0, %xmm1
20
movdqa %xmm10, 16(%rdx,%rax)
21
movdqa %xmm11, 32(%rdx,%rax)
22
movdqa %xmm12, 48(%rdx,%rax)
23
movdqa %xmm13, 64(%rdx,%rax)
24
movdqa %xmm14, 80(%rdx,%rax)
25
movdqa %xmm15, 96(%rdx,%rax)
26
movdqa %xmm1, 112(%rdx,%rax)
27
subq $-128, %rax
28
cmpl %r8d, %ecx
29
jb .L5
Zwar ist x86-64 kein Mikrocontroller und AVRs haben keine SSE Befehle,
aber das Prinzip ist gleich: Erst einmal sehen, was der Compiler von
sich aus zustande bekommt, bevor man versucht, von Hand zu optimieren.
Hey Leute danke erstmal für die vielen Antworten in der kurzen Zeit..
Ich bin ja mit dem lesen fast garnicht nachgekommen xD
Ich hoffe aus meinem angehängten Quelltext könnt ihr heraussehen was ich
falsch mache bzw grundsätzlich ändern sollte.
Und den Namen der Datei nicht beachten, das war ursprünglich nur zum
Testen der ADC Funktion. Habe sie nachträglich einfach erweitert.
CCodeSchauer schrieb:> Wo "viel" Zeit draufgeht ist der Funktionaufruf (Register retten> und Parameter kopieren) selbst und die Rückkehr aus der Funktion.
Heißt das, ich soll nach Möglichkeit Funktionsaufrufe vermeiden um nicht
unnötig "Takte zu verlieren"?
sdg schrieb:> ich hab mal gehört µCs besitzen Timer in Hardware die sich als PWM> gebrauchen lassen, aber vielleicht ist das ja nur ein Gerücht :)Karl Heinz schrieb:> Laufen die einzelnen PWM eigentlich alle mit derselben Frequenz?
Es sollen 6 PWM mit jeweils von einander unabhängig variablen
Frequenzen, Phasenverschiebungen und Tastverhältnissen erzeugt werden.
Der MikroController besitzt nur 3 Timer. Also kann ich auch nur 3
unterschiedliche PWM erzeugen. Also muss das softwareseitig gelöst
werden.
Aber eben weil die Phasen und Frequenzen verschieden sind, kann ich
deine Variante leider nicht benutzen Karl :/
Udo Schmitt schrieb:> Das ist natürlich mal ne Ansage, viel Takte sind das nicht.> Gerade mal 80 minus der Zeit, die die Interrupt Funktion selbst braucht.
Ja, genau das ist ja mein Problem, warum ich das optimieren muss.
> Wenn sie nach jedem Timerinterrupt aufgerufen werden MUSS dann ist es> vieleicht sinnvoll sie am Ende der Timerinterruptfunktion direkt> aufzurufen.
Das kann ich ja nicht, da erstens der Funktionsdurchlauf zu lange
dauert, sodass er nicht zwischen 2 Interruptaufrufe passt und zweitens
noch etwas Zeit übrig bleiben muss, um die anderen Operationen
durchzuführen.
MaWin schrieb:> Aber mit doppelt so schnell bekommt man kein VIEL zu langsamen Programm> schnell genug. Meistens sind die Algorithmen schlecht gewählt.
Ich weiß, dass es mehr an den Algorithmen liegt, aber jeder Zeitgewinn
ist Gold wert. Wie Udo ja auch schon festgestellt hat, habe ich nur 80
Takte - Interruptaufwand zur verfügung.
Bzw. muss hier mein PWMcheck hineinpassen. Wenn der rest etwas länger
dauert ist das nicht schlimm.
Ich bin am überlegen ob wir vielleicht sogar einen 20MHz Quarz anbauen,
um etwas mehr Takte zur verfügung zu haben.
Peter II schrieb:> float scaledTime;> warum muss es denn float sein?
Das war float, da ich an der Stelle zuvor eine Division hatte. Das hat
sich jett geändert. Aber danke für den Hinweis hab das jetzt geändert.
Kaan Ayhan schrieb:>> Laufen die einzelnen PWM eigentlich alle mit derselben Frequenz?> Es sollen 6 PWM mit jeweils von einander unabhängig variablen> Frequenzen, Phasenverschiebungen und Tastverhältnissen erzeugt werden.> Der MikroController besitzt nur 3 Timer. Also kann ich auch nur 3> unterschiedliche PWM erzeugen. Also muss das softwareseitig gelöst> werden.> Aber eben weil die Phasen und Frequenzen verschieden sind, kann ich> deine Variante leider nicht benutzen Karl :/
Kannst du nach wie vor.
Du hast dann eben 6 durchlaufende pwmCount und nicht nur einen, so dass
jede PWM ihren eigenen Maximalwert haben kann und nicht, wie bei nur
einem derartigen Counter alle bei 100 den nächsten Zyklus beginnen.
1
ISR(...)
2
{
3
staticuint8_tpwmCount[6]=0;
4
uint8_ti;
5
6
for(i=0;i<6;i++)
7
pwmCount[i]++;
8
if(pwmCount[i]==pwmMax[i]){
9
pwmCount=0;
10
PwmWork[i]=Pwm[i];
11
}
12
}
13
14
CHECK_PWM(0,PORTD0);
15
CHECK_PWM(1,PORTD1);
16
CHECK_PWM(2,PORTD2);
17
CHECK_PWM(3,PORTD3);
18
CHECK_PWM(4,PORTD5);
19
CHECK_PWM(5,PORTD6);
20
}
und wenn du die Counter auch noch aus der ISR rausnimmst, dann kannst du
mit ihnen auch noch eine Phasenverschiebung erreichen, in dem du den
jeweiligen pwmCount manipulierst.
Ja meine Lösung für die Phasenverschiebung war folgende:
Ich setze den pwmCount auf 0 - Phasenverschiebung (gezählt wird ja
sowieso immer mit +1 da ist es egal wie der Wert wirklich aussieht).
Der Output sieht dann so aus:
Aber was ist, wenn durch meine Phasenverschiebung mein Tastverhältnis in
die nächste Periode über geht? Dann kann ich das so ja nicht mehr
machen.
Dann sieht das bei mir so aus:
1
if((phase+tastverhalten)>frequenz){// wenn es einen Überlauf gibt
Kaan Ayhan schrieb:> Der Output sieht dann so aus:
Du versuchst viel zu viel während des Outputs auf die Pins zu erledigen.
Das ist eine Sackgasse!
Der Teil des Programms, der die Pins dann tatsächlich bedient, darf sich
nicht mehr um Sonderfälle kümmern müssen. Dieser Programmteil arbeitet
nur noch seine simple PWM Erzeugung ab. Alle Sonderfälle und sonstigen
Dinge müssen von diesem Teil des Programmes fern gehalten werden, indem
man die Intelligenz in die Generierung der Steuerdaten der einzelnen PWM
Stufen steckt. Während der Auswertung dieser Daten zur Generierung der
eigentlichen PWM darf da nichts mehr auftreten.
Wenn du dieses Timing hinkriegen willst, dann geht das nicht anders. Die
6 PWM Stufen sind der zentrale Kern deines Programms.
> Und das würde wiederum zu lange dauern, um im Interrupt ausgeführt zu> werden. Oder nicht?
Was ist eigentlich die genaue Aufgabenstellung?
>> Aber mit doppelt so schnell bekommt man kein VIEL zu langsamen>> Programm schnell genug. Meistens sind die Algorithmen schlecht gewählt.> Ich weiß, dass es mehr an den Algorithmen liegt, aber jeder> Zeitgewinn ist Gold wert.
reichlich naiv.
Wenn die Aufgabe lautet, von hier aus möglichst schnell zum Mond zu
kommen, dann ist es völlig wurscht, ob du an deiner Haustür ein schnell
öffnendes Schloss hast oder nicht. Die 3 Sekunden, die du hier einsparen
kannst, sind nichts im Vergleich zu den 4 Tagen, die du zum Mond
brauchst.
Nur Laien glauben immer, man könne mit einem schnelleren Prozessor oder
winzigen Mikrooptimierungen den Laden noch herumreissen. Das bringt was,
wenn du knapp drann bist. Dein jetziges Timing ist aber so weit daneben,
das du mit derartigen Ansätzen maximal die goldene Himbeere gewinnen
kannst. Um von Deutschland aus in 24 Stunden nach Peking zu kommen,
kannst du dein Fahrrad pimpen so viel du willst, ohne grundsätzlichen
Wechsel zu einem FLugzeug wird das nichts.
Karl Heinz schrieb:> Was ist eigentlich die genaue Aufgabenstellung?
Kann man diesen Satz bitte in Stein gemeißelt vor dem Eingang zu diesem
Forum aufhängen? :-)
Ok, ich verstehe was du meinst. Dass ich das noch nciht so gut hinkriege
liegt einfach an der mangelnden Erfahrung. Aber ich werde versuchen, das
Programm umzustrukturieren.
Die Aufgabenstellung habe ich ja ziemlich weit oben schon erläutert.
Ich versuche ein Programm zu schreiben, das mir PWM bei einer Frequenz
von bis zu 2kHz erzeugen kann. D.h. ich muss es schaffen, die PWM im
200kHz Takt zu überprüfen und den Output dem entsprechend zu setzen. So
habe ich für die Phasenverschiebung und das Tastverhältnis eine
Genauigkeit von 1%.
Der µC soll später mit einem externen Quarz auf 16MHz getaktet werden.
Mark Brandis schrieb:> Karl Heinz schrieb:>>> Was ist eigentlich die genaue Aufgabenstellung?>> Kann man diesen Satz bitte in Stein gemeißelt vor dem Eingang zu diesem> Forum aufhängen? :-)
Gleich darunter würde ich noch einmeisseln:
Leute, nehmt keine Aufträge an, von denen im Vorfeld schon feststeht,
dass ihr sie nicht stemmen könnt, weil eure Kenntnisse hinten und vorne
nicht ausreichen.
Wenn das Signal sich nach wenigen Zyklen wiederholt gibt es auch die
Möglichkeit die Ausgabesignale im Speicher für einen kompletten Zyklus
zu berechnen und in der ISR nur den Wert zu Laden, Auszugeben und
Counter um eins erhöhen
deine ISR würde dann ungefähr so aussehen:
1
Void ISR(){
2
static unsigned char i;
3
PORTD = data[i];
4
i++;
5
}
Außerhalb der ISR musst du dann die werte für das Ram berechnen.
Der Aufwand zum Berechnen fällt dann aber nur dann an, wenn sich etwas
ändert.
Oder wenn es viele werte sind kann man auch die Datenstruktur um einen
Zeitstempel erweitern mit dem der aktuelle Zyklus verglichen wird, so
muss nur ein Bruchteil der Zyklen im Ram gespeichert werden.
@ Kaan Ayhan (deranfaenger)
>Ich versuche ein Programm zu schreiben, das mir PWM bei einer Frequenz>von bis zu 2kHz erzeugen kann. D.h. ich muss es schaffen, die PWM im>200kHz Takt zu überprüfen und den Output dem entsprechend zu setzen. So>habe ich für die Phasenverschiebung und das Tastverhältnis eine>Genauigkeit von 1%.>Der µC soll später mit einem externen Quarz auf 16MHz getaktet werden.
Schon mal 5 Minuten gerechnet und nachgedacht?
Bei 16 MHz macht dein AVR pro us 16 Takte, wenn men es halbwegs
intelligent macht 16 Einzelbefehle. 200 kHz sind 5us, sprich du hast 80
CPU Takte pro PWM Takt. Das ist nicht allzu viel! Selbst mit einer guten
ASM-Interruptroutine muss man sich da schon SEHR anstrengen!
Mach dir das Leben leicht und nimm einen großen AVR, der 6 PWMs in
Hardware erzeugen kann.
@Karl Heinz (kbuchegg) (Moderator)
>Leute, nehmt keine Aufträge an, von denen im Vorfeld schon feststeht,>dass ihr sie nicht stemmen könnt, weil eure Kenntnisse hinten und vorne>nicht ausreichen.
Sowas hier ?
Beitrag "Überleben auf dem Mars"
;-)
Falk Brunner schrieb:> @Karl Heinz (kbuchegg) (Moderator)>>>Leute, nehmt keine Aufträge an, von denen im Vorfeld schon feststeht,>>dass ihr sie nicht stemmen könnt, weil eure Kenntnisse hinten und vorne>>nicht ausreichen.>> Sowas hier ?>> Beitrag "Überleben auf dem Mars">> ;-)
;-)
Das würde ich noch als Grundlagenforschung einstufen. Neuland.
Hier gehts eher um den x-ten, der seinem PKW-Motor 200 zusätzliche PS
verpassen will, aber keinen Schraubenzieher richtig rum in die Hand
nehmen kann.
Karl Heinz schrieb:> Leute, nehmt keine Aufträge an, von denen im Vorfeld schon feststeht,> dass ihr sie nicht stemmen könnt, weil eure Kenntnisse hinten und vorne> nicht ausreichen.
Wie war der Spruch doch? Um feststellen zu können, dass die Kenntnisse
nicht ausreichen, reichen die Kenntnisse nicht aus. Oder so ähnlich.
Addiere darauf dann noch die Hybris der Jugend.
@Falk
Ja, natürlich habe ich das durchgerechnet und bin mir dessen bewusst.
Deshalb brauche ich ja die Hilfe hier im Forum.
Aber die 2kHz PWM-Frequenz sind kein muss. Es ist das Ziel. Die Vorgabe
ist, 500Hz auf jeden Fall zu schaffen (absolutes minimum) und für die
Zukunft bis auf 2kHz gehen zu können. D.h. wenn es technisch nicht oder
nur sehr schwer machbar ist, kann man sich auch mit etwas weniger
zufrieden geben. 1kHz würden es theoretish auch tun. Aber ich möchte
natürlich versuchen, das Beste herausholen.
Vorerst geht es ja nur darum eine PWM Generierung hinzukriegen die
überhaupt funktioniert und effizient ist danach kommt die Optimierung um
zu sehen wie viel wirklich geht.
@Dennis
Das ist ein guter Vorschlag, danke.
Aber es wären glaube ich zu viele Werte um alle zu speichern.
Wie meinst du das mit dem Zeitstempel? Dass ich z.B. bestimmte
Zeitintervalle herausnehme und diese vorberechne?
Ich glaube die Berechnungen würden insgesamt zu lange dauern.
@Peter
Danke für den Link. Den gehe ich gerade durch. In dem Beispiel wird
leider die Phasenverschiebung nicht berücksichtigt, aber ich kann mir
dort einiges auch an Ideen abgucken.
@Karl @Mark
Ich bin halt ein absoluter Anfänger(so wies in meinem Nickname auch
steht haha). Tut mir leid, dass ich nicht so viel Erfahrung hab wie ihr,
aber bis vor 1 Monat hatte ich auch nie mit C- bzw. µC Programmierung zu
tun gehabt.
Und ich habe keinen Auftrag angenommen, um damit Geld zu verdienen oder
so, sondern das ist eine Aufgabenstellung von meinem "Ausbilder". Neben
dem eigentlichen Nutzen soll das Projekt für mich einen Lerneffekt
bieten. Bei mir im Institut habe ich nur leider keinen direkten
Ansprechpartner, da alles Elektrotechniker usw. sind und keine
Informatiker. Ich bin hier weil ich denke, dass ich hier Hilfe kriege
und nicht um mich runterziehen zu lassen weil ich nicht so viel Ahnung
habe.
Wenn man als Anfänger mit wenig Erfahrung und vielen Fragen nicht
erwünscht ist, werde ich mir halt ein anderes Forum suchen müssen.
- dennoch, danke für die bisherige Hilfe.
@A. K. (prx)
>Wie war der Spruch doch? Um feststellen zu können, dass die Kenntnisse>nicht ausreichen, reichen die Kenntnisse nicht aus. Oder so ähnlich.
"Der Weise weiß vor allem, was er nicht weiß."
Laotse
Falk Brunner schrieb:> "Der Weise weiß vor allem, was er nicht weiß."> Laotse
Zu dieser Erkenntis wird aber auch Laotse vermutlich nicht in früher
Jugend gekommen sein. Ausserdem weiss man noch nicht einmal sicher, ob
es Laotse überhaupt gab.
Falk Brunner schrieb:> Schon mal 5 Minuten gerechnet und nachgedacht?> Bei 16 MHz macht dein AVR pro us 16 Takte, wenn men es halbwegs> intelligent macht 16 Einzelbefehle. 200 kHz sind 5us, sprich du hast 80> CPU Takte pro PWM Takt. Das ist nicht allzu viel! Selbst mit einer guten> ASM-Interruptroutine muss man sich da schon SEHR anstrengen!
Sorry, aber 6 Kanäle Software-PWM mit 5us Auflösung sind Kinderkram,
das schafft ein AVR locker nebenbei wenn man sich nicht zu blöd
anstellt.
Wer es nicht kann, muss zahlen:
> Mach dir das Leben leicht und nimm einen großen AVR, der 6 PWMs in> Hardware erzeugen kann.
@ MaWin (Gast)
>Sorry, aber 6 Kanäle Software-PWM mit 5us Auflösung sind Kinderkram,>das schafft ein AVR locker nebenbei wenn man sich nicht zu blöd>anstellt.
Jaja, der allwissende MaWin mal wieder.
ZEIG DEIN LAUFFÄHIGES PROGRAMM MIT DEN ENDLOSEN RESERVEN ODER HALT DEN
MUND!
Mit einer geforderten Genauigkeit von 1% sollten 256 Werte ausreichen.
D.h. du musst im Ram 256*6 bit vorhalten, oder besser 256* 1 byte.
Dann hast du einen unsigned Char Counter der automatisch überlauft -> +1
reicht, keine Zyklen zum Prüfen ob das ende erreicht ist.
Du kannst aber auch nur 100 Werte nehmen, dann sinkt dein
Speicherverbrauch auf 100 byte, du musst aber nach jedem hochzählen
prüfen ob du bei 100 angekommen bist.
Beim Ändern der PWM-Einstellungen musst du dann in diesem
Speicherbereich die Bits für deinen Kanal ändern.
Das mit dem Zeitstempel ist so gedacht, dass du neben den Werten einen
Zeitstempel hast der dir sagt, ab wann dieser wert übernommen werden
soll.
Damit hast du bei jeder Änderung 2 Werte.
Die neuen Portwerte und einen Zeitstempel ab wann dieser Wert gilt.
Dabei solltest du dir aber mit einem Index merken, bei welchen WertZeit
Paar du gerade bist, damit du dir das Suchen sparen kannst. damit kannst
du z.B. mit 7 Paaren a 2 byte für 6 Kanäle die zeit merken.
Bsp:
Zeit wert
0 3F --Start -> alle An
12 1F --6. bit 0 setzen
108 18 --nur noch bit 4 und 5 an
250 00 -- letzten beiden bits auf 0 setzen
Dennis R. schrieb:> Damit hast du bei jeder Änderung 2 Werte.> Die neuen Portwerte und einen Zeitstempel ab wann dieser Wert gilt.
So isses
1
struct
2
{
3
uint8_tocr;
4
uint8_tportb;
5
}
6
times[13];
7
8
uint8_t*ptr;// Y
9
uint8_t*endptr;// X
10
11
ISR(TIMER0_COMPA_vect)
12
{
13
OCR0A=*ptr++;// LD R4,Y+ ; OUT OCR0A,R4
14
PORTB=*ptr++;// LD R4,Y+ ; OUT PORTB,R4
15
if(ptr==endptr)ptr=×// CPSE Y,X ; RETI ; LDI Y,@times ; RETI
16
}
Und da reichen 9 Takte für die Interrupt-Routine, bei 16Mhz und
minimaler Zeit von 5us also locker ausreichend, vermutlich passt sogar
die C-Version rein. Mittlere CPU-Belastung maximal 12 Interrupts in
0.5msec, also unter 10 Prozent, vermutlich reichen sogar 7 (weil alle
PWM Ausgänge gleichzeitig auf 0 gehen werden).
Falk Brunner schrieb:> ZEIG DEIN LAUFFÄHIGES PROGRAMM MIT DEN ENDLOSEN RESERVEN ODER HALT DEN> MUND!
Nicht schreien, selber denken.
@ MaWin (Gast)
>Und da reichen 9 Takte für die Interrupt-Routine, bei 16Mhz und>minimaler Zeit von 5us also locker ausreichend, vermutlich passt sogar>die C-Version rein.
BLA! Reine Theorie! Nicht nur, dass ein Interrupt noch ein Einsprung und
eine reti braucht, es braucht auch Register, die gesichter werden
wollen. jaja, in ASM kann man die exklusiv nutzen, in C eher nicht.
>Nicht schreien, selber denken.
Falsch! Ich habe es sogar VOLLSTÄNDIG und LAUFFÄHIG gemacht, und das
schon vor Jahren!
Soft-PWM
Es ist nicht der Weisheit letzter Schluß, zeigt aber Grenzen einer
einfachen C-Umsetzung!
Hey Leute das hab ich jetzt zwar verstanden, aber hier habe ich doch
dann immer die gleiche Frequenz oder etwa nicht?
Denn ich definiere Masken für jeden Zeitabschnitt.. ok aber so habe ich
nur einen Zähler (also bis OCR0A). Aber bei 6 verschiedenen Frequenzen
habe ich ja 6 verschiedene Zähler
Vielleicht bin ich ja einfach zu blöd Oo
@ Kaan A. (deranfaenger)
>Hey Leute das hab ich jetzt zwar verstanden, aber hier habe ich doch>dann immer die gleiche Frequenz
Ja, das ist normal bei PWM.
>Denn ich definiere Masken für jeden Zeitabschnitt.. ok aber so habe ich>nur einen Zähler (also bis OCR0A). Aber bei 6 verschiedenen Frequenzen>habe ich ja 6 verschiedene Zähler
Warum solltest du 6 verschiedene Frequenzen brauchen?
Ja das ist doch schon die ganze Zeit mein Problem ich habe ganz oben
schon erläutert, dass die Phase, Frequenz und Tastverhältnis von
einander unabhängig variabel sind.
Der Nutzen ist hier eigentlich nicht wichtig, aber wenn du schon fragst
und es vielleicht andere auch interessiert:
Der Mikrocontroller soll die Netzteile von Magnetrons eines
Mikrowellenofens ansteuern. Die flexible Ansteuerung soll dazu dienen,
den Heizprozess zu optimieren.
So als grobe Vorstellung. Auf genaueres möchte ich jetzt nicht eingehen.
Meine Kollegen sind aber Elektrotechniker und keine Informatiker und ich
im dritten Semester ohne große Vorkenntnisse, weshalb ich auf Hilfe aus
Foren angewiesen bin.
Wie gesagt erstmal soll das Programm problemlos bei mindestens 500 Hz
PWM-Frequenz sprich 50 kHz PWM-Takt laufen. Dann muss ich schauen, wie
hoch ich mit der Frequenz kommen kann. 2 kHz wäre das gewünschte Ziel.
Durch diesen und weitere Threads habe ich schon einiges gelernt. Danke
dafür nochmal.
Dieses Wissen werde ich dann versuchen anzuwenden, um ein bestmögliches
Ergebnis zu erhalten.
Die Aufgabe verlangt von mir halt schon einiges an Hirnschmalz aber da
muss ich durch xD
@ Kaan A. (deranfaenger)
>Der Nutzen ist hier eigentlich nicht wichtig,
DOCH! Siehe Netiquette!!!
>Der Mikrocontroller soll die Netzteile von Magnetrons eines>Mikrowellenofens ansteuern. Die flexible Ansteuerung soll dazu dienen,>den Heizprozess zu optimieren.facepalm>So als grobe Vorstellung. Auf genaueres möchte ich jetzt nicht eingehen.>Meine Kollegen sind aber Elektrotechniker und keine Informatiker und ich>im dritten Semester ohne große Vorkenntnisse, weshalb ich auf Hilfe aus>Foren angewiesen bin.
Also ein Expertengemium ;-)
Warum um alles in der Welt glaubst du
a) dafür 2 kHz PWM,
b) dieser mit Phasenverschiebung und
c) mit 6 unabhängigen Frequenzen zu benötigen?
>Durch diesen und weitere Threads habe ich schon einiges gelernt. Danke>dafür nochmal.
Naja. Dein eigentliches Problem liegt tiefer.
>Dieses Wissen werde ich dann versuchen anzuwenden, um ein bestmögliches>Ergebnis zu erhalten.
Falsch. Bei einer Problemlösung sollte man zuerst das Problem gut
analysieren und dann erst mögliche Lösungen betrachten. Du greifst
einfach die nächstbeste Lösung, ohne zu wissen, ob sie sinnvoll und
brauchbar ist.
>Die Aufgabe verlangt von mir halt schon einiges an Hirnschmalz aber da>muss ich durch xD
Viel wichtiger als so ein technisches Detail ist ein gutes Grundkonzept.
Das entscheidet über Erfolg oder Niederlage einers Projekt. Dabei darf
man sich am Anfang nicht in technische Details verlieren. Genau das tust
du aber.
> DOCH! Siehe Netiquette!!!
Ok mein Fehler, die hab ich nicht gelesen.
> Warum um alles in der Welt glaubst du>> a) dafür 2 kHz PWM,> b) dieser mit Phasenverschiebung und> c) mit 6 unabhängigen Frequenzen zu benötigen?
Weil wir in der Forschung tätig sind und dies die Vorgaben von meinem
"Ausbilder" sind. Wie gesagt 500 Hz sind das Minimum, da in dem Bereich
bis 1 kHz gearbeitet wird. Aber da das zu entwickelnde Board flexibel
und für die zukunftsorientiert (wenn man mit der Frequenz hoch gehen
möchte) einsetzbar sein soll, soll eine mögliche maximale Frequenz von 2
kHz erreicht werden. Wenns nicht geht muss man eben auf diesen "Luxus"
verzichten und sich mit weniger zufrieden geben. Mindestens 1 kHz
sollten aber drin sein.
> Falsch. Bei einer Problemlösung sollte man zuerst das Problem gut> analysieren und dann erst mögliche Lösungen betrachten. Du greifst> einfach die nächstbeste Lösung, ohne zu wissen, ob sie sinnvoll und> brauchbar ist.
Wie meinst du das mit dem analysieren. Ich denke das ist schon klar
Oo...
Ja da hast du wohl recht. Die Mischung aus Zeitmangel, Stress und
fehlender Erfahrung hat mir wohl einen Tunnelblick verpasst.
Vorschläge, wie ich es denn das nächstes mal besser machen kann sind
willkommen :)
> Viel wichtiger als so ein technisches Detail ist ein gutes Grundkonzept.> Das entscheidet über Erfolg oder Niederlage einers Projekt. Dabei darf> man sich am Anfang nicht in technische Details verlieren. Genau das tust> du aber.
Verstehe. Ich soll mir zuerst so ein Grundgerüst bauen, wie das Ganze
denn aufgebaut werden soll bevor ich mich an das technische und die
Implementierung mache.
Aber um nochmal zum Thema zurückzukommen:
Ist mein Vorgehen grundsätzlich falsch bzw. schlecht?
Da ich ja (im worst case) 6 verschiedene Frequenzen habe, aber nur mit
einem Timer inkrementiere, Takten alle pwmCounter in der Timer Frequenz.
Der pwmCounter wird jedesmal umgerechnet(/Timerfrequenz *pwmFrequenz),
um herauszufinden, ob sie das Tastverhältnis oder das Periodenende
erreicht hat. Diese Berechnung nimmt leider die meiste Zeit in Anspruch,
ist in meinen Augen aber unumgänglich. Um das Dividieren zu verhindern,
werden Konstanten vordefiniert mit denen ich multiplizieren kann.
Eine Lösung, die mir gerade einfällt wäre:
Werte (abhängig von der jeweiligen PWM-Frequenz) zu definieren, um die
ich dann den zugehörigen pwmCounter inkrementiere.
@ Kaan A. (deranfaenger)
>Weil wir in der Forschung tätig sind und dies die Vorgaben von meinem>"Ausbilder" sind.
Man braucht 500-2000 Hz PWM um eine HEIZUNG zu steuern? Und 6
verschiedene Frequenzen? Glaub ich nicht so ganz. Ich wette, in der
Heizungssteuerung wird die PWM über einen einfachen Filter in
Gleichspannung gewandelt und gut.
> Wie gesagt 500 Hz sind das Minimum, da in dem Bereich>bis 1 kHz gearbeitet wird. Aber da das zu entwickelnde Board flexibel>und für die zukunftsorientiert (wenn man mit der Frequenz hoch gehen>möchte) einsetzbar sein soll, soll eine mögliche maximale Frequenz von 2>kHz erreicht werden. Wenns nicht geht muss man eben auf diesen "Luxus">verzichten und sich mit weniger zufrieden geben. Mindestens 1 kHz>sollten aber drin sein.
Wenn es denn WIRKLICH min. 1 kHz und 6 unabhängige Frequenzen sein
müssen, solltest du erst recht einen passenen Mikrocontroller nutzen,
der genügen (6) Timer hat, die deine unabhängigen PWMs ereugen kann.
Z.B. einer der neueren ATXmegas oder einen noch leistungsfähigeren ARM.
In Software wird as nix gescheites, zum du als Anfänger genügend andere
Sachen zu tun hast. Und da es um wenige Einzelexemplare geht, ist auch
der Preis des Controllers vollkommen egal.
@ Kaan A. (deranfaenger)
>Ist mein Vorgehen grundsätzlich falsch bzw. schlecht?
Ja.
>Da ich ja (im worst case) 6 verschiedene Frequenzen habe, aber nur mit>einem Timer inkrementiere, Takten alle pwmCounter in der Timer Frequenz.>Der pwmCounter wird jedesmal umgerechnet(/Timerfrequenz *pwmFrequenz),>um herauszufinden, ob sie das Tastverhältnis oder das Periodenende>erreicht hat. Diese Berechnung nimmt leider die meiste Zeit in Anspruch,>ist in meinen Augen aber unumgänglich. Um das Dividieren zu verhindern,>werden Konstanten vordefiniert mit denen ich multiplizieren kann.
Vergiss die Softwarelösung. Du steckst sinnlos Energie und Zeit in eine
Nebensächlichkeit, die du mit dem passenden Controller am einem Tag
fertig hast.
Wie andere schon sagten:
Ich persönlich würd ja einen Controller mit OC-Timern oder PWM-Blöcken
nehmen.
Schöne Beispiele sind viele STM32 oder diverse PICs.
Die STM32 haben diese praktischen Flex-Timer, von denen macht 1 Timer 4
PWMs (mit gleicher Frequenz).
Viele PICs haben mehrere OC-Timer, die sich auch hervorragend für PWM
eignen.
Beide generieren die PWM in Hardware, schnell und mit wenig Software
Overhead.
Merke: spezialisierte Hardware schlägt jede Software um Kilometer. Und
weil PWM-Blöcke Standardfeatures in Controllern sind, warum sich damit
in Software abplagen?
Für eine Heizung würde ich das allerdings tatsächlich in Softare lösen.
Mit 0,5Hz, was schon übertrieben schnell ist ;-)
Eine Heizung muss nicht angesteuert werden, sondern eine
Mikrowelle(keine gewöhnliche Haushaltsmikrowelle). Glaubt mir die
Aufgabenstellung lautet wirklich, dass alle Einstellungen der PWM
variabel sein sollen.
Und ja, das mit der Hardwarelösung hatte ich zu Beginn auch
vorgeschlagen. Doch das würde den Sinn der Sache verfehlen (nämlich das
Programmieren an sich zu üben) hieß es. Und eine Softwarelösung war
erwünscht.
Ich hatte erst ATXmega im Sinn. Aber wie gesagt da eine Softwarelösung
erwünscht war hätte auch der ATMega88pa gereicht...
Jetzt merke ich ja, dass das nicht gerade easy ist.
Naja ich werde trotzdem schauen wie viel maximal geht um dann Begründen
zu können, warum das Ganze hardwaretechnisch gelöst werden sollte.
Danke trotzdem für eure Hilfe und Zeit.
Wenn jemand trotzdem eine Anregung hat, wie man die Frequenz variabel
gestalten kann, nehme ich sie gerne an :)
Ich denke der Code von MaWin ist gut.
An seinem Umgangston sollte er noch etwas arbeiten.
Hast du ihn mal ausprobiert?
Ich habe leider keine AVR's, kann mir aber vorstellen, dass er
weit unter den 80 Zyklen bleibt.
Die Struktur times ist 13 Felder lang, das reicht um 6 PWMs
Phasenmoduliert abzuspeichern.
Wenn die die Struktur im RAM ist kannst du sie auch zur Laufzeit
außerhalb der ISR anpassen.
MaWin schrieb:> struct> {> uint8_t ocr;> uint8_t portb;> }> times[13];>> uint8_t *ptr; // Y> uint8_t *endptr; // X>> ISR (TIMER0_COMPA_vect)> {> OCR0A=*ptr++; // LD R4,Y+ ; OUT OCR0A,R4> PORTB=*ptr++; // LD R4,Y+ ; OUT PORTB,R4> if(ptr==endptr) ptr=× // CPSE Y,X ; RETI ; LDI Y,@times ; RETI> }
Ansonsten kannst du auch auf Prozessoren wechseln die 6 Hardwaretimer
haben oder ein schnelleren Prozessortakt.
Die STM32 Serie kann ich auch nur empfehlen.
Viele Grüße
Dennis
Den Code selbst hab ich zwar nicht verstanden(insbesondere die letzte
Zeile, die mit der if-Bedingung), aber ich nehme an dass er zu deinem
vorangehenden Beitrag gehört.
> Das mit dem Zeitstempel ist so gedacht, dass du neben den Werten einen> Zeitstempel hast der dir sagt, ab wann dieser wert übernommen werden> soll.> Damit hast du bei jeder Änderung 2 Werte.> Die neuen Portwerte und einen Zeitstempel ab wann dieser Wert gilt.> Dabei solltest du dir aber mit einem Index merken, bei welchen WertZeit> Paar du gerade bist, damit du dir das Suchen sparen kannst. damit kannst> du z.B. mit 7 Paaren a 2 byte für 6 Kanäle die zeit merken.
Aber hierbei habe ich ja wieder für alle PWM Ausgänge die gleiche
Frequenz. Wenn ich mich nicht irre, ist das ja sogar der "intelligente
Lösungsweg" aus dem Soft-PWM Tutorial
http://www.mikrocontroller.net/articles/Soft-PWM#Erster_Versuch
@ Kaan A. (deranfaenger)
>Eine Heizung muss nicht angesteuert werden, sondern eine>Mikrowelle(keine gewöhnliche Haushaltsmikrowelle).
Schon klar.
> Glaubt mir die>Aufgabenstellung lautet wirklich, dass alle Einstellungen der PWM>variabel sein sollen.
Glaub ich dir. Ersten, weil man flexibel bleiben will und zweitens weil
die Leute wahrscheinlich auch nicht den vollen Durchblick haben, was sie
WIRKLICH BRAUCHEN.
>Und ja, das mit der Hardwarelösung hatte ich zu Beginn auch>vorgeschlagen. Doch das würde den Sinn der Sache verfehlen (nämlich das>Programmieren an sich zu üben) hieß es.
Programmieren üben ist gut, im Lehrbereich ist es schließlich der
wesentliche zweck. ABER!
> Und eine Softwarelösung war erwünscht.>Ich hatte erst ATXmega im Sinn. Aber wie gesagt da eine Softwarelösung>erwünscht war hätte auch der ATMega88pa gereicht...
HIER beiginnt das Problem! Denn es ist NIE sinnvoll, einen Lösungsweg
vorzugeben! Dieser muss sich aus der Problemanalyse und Lösungssysthese
ergeben! WENN dann mehrere Lösungen aufgezeigt werden UND die
Softwarelösung als machbar, wenn gleich aufwändiger erscheint, DANN kann
man sich dafür entscheiden.
Wenn es nur um 6 Kanäle mit gleicher Frequenz gehen würde, könnte man es
per Software und etwas Anstrengung (ISR in reinem Assembler) hinkriegen.
Mit verschiedenen Frequenzen ist das deutlich schwieriger. Damit übst du
nicht wirklich das Programmieren sonder brichst dir sinnlos einen ab,
beim Versuch, eine bestimmte Hardware bis an die Grenze des Machbaren
auszureizen. Das ist kein Job für Anfänger und Lernende, sondern für
Fortgeschrittene und Profis. Lernen wirst du dabei nicht so viel, wohl
aber
viel fluchen.
>Naja ich werde trotzdem schauen wie viel maximal geht um dann Begründen>zu können, warum das Ganze hardwaretechnisch gelöst werden sollte.
Oder eben halt so. Der akademische Weg . . .
>Wenn jemand trotzdem eine Anregung hat, wie man die Frequenz variabel>gestalten kann, nehme ich sie gerne an :)
Du musst in gewisser Weise mit deinem 200kHz Interrupt eine Tabelle
ausgeben, genau so, wie es ein programierbarer Funktionsgenerator macht.
Ein anderes Stück Software muss diese Tabelle sinnvoll mit Inhalten
füllen. Der Knackpunkt dabei ist, dass die Periodendauer deiner Ausgabe
konstant ist, und zwar für alle Kanäle. Also muss sie ein ganzzahliges
Vielfaches der einzelnen Frequenzen sein. Wenn man nur 2, 1, 0,5 und
0,25 kHz zulässt ist das kein Problem. Ansonsten, viel Spaß.
@ Udo Schmitt (urschmitt)
>Kann man Mikrowellen-Magnetrons überhaupt so schnell schalten?
Er schaltet doch nicht das Magnetron, sondern diverse Steuereingänge
einer Steuerelektronik. Dort sitzen mit hoher Wahrscheinlichkeit
Tiefpässe, die daraus wieder Gleichspannung zu Ansteuerung machen. Und
selbst wenn nicht, kann man ein Magnetrom auch im Burstbetrieb der PWM
Du kannst dir Ideen von DDS klauen:
http://en.wikipedia.org/wiki/Direct_Digital_Synthesis
Damit kann man z.B. schön die Ansteuerung von Servos lösen.
Deine konkrete Aufgabe kann man herunterbrechen auf events, die in einem
bestimmten Zeitabstand von einander passieren sollen.
Falk Brunner schrieb:> Dort sitzen mit hoher Wahrscheinlichkeit> Tiefpässe, die daraus wieder Gleichspannung zu Ansteuerung machen.
Zumindest Magnetrons, die in Mikrowellengeräten verbaut sind kann man
nicht im Teillastbetrieb laufen lassen, also sehe ich hier keinen Sinn
in Tiefpass und lineare Spannung zur Steuerung.
Falk Brunner schrieb:> Und> selbst wenn nicht, kann man ein Magnetrom auch im Burstbetrieb der PWM
Das ist ja meine Frage:
Bei einem herkömmlichen Mikrowellengerät für die Küche geschieht das
Ein/Ausschalten für reduzierte Leistung aber im Bereich von einigen
Sekunden.
Was wird denn da an oder abgeschaltet? Die Hochspannung?
Und wie schnell kann man das machen? Wirklich im Bereich von bis zu
einigen 10kHz?
@ Udo Schmitt (urschmitt)
>Zumindest Magnetrons, die in Mikrowellengeräten verbaut
Es geht nicht um Küchenmikrowellenherde!
>Bei einem herkömmlichen Mikrowellengerät für die Küche geschieht das>Ein/Ausschalten für reduzierte Leistung aber im Bereich von einigen>Sekunden.>Was wird denn da an oder abgeschaltet? Die Hochspannung?
Wahrscheinlich.
>Und wie schnell kann man das machen? Wirklich im Bereich von bis zu>einigen 10kHz?
Magnetrons werden u.a. im Radar für kurze Pule im us Bereich eingesetzt.
Magnetrons sind modulierbar.
Falk Brunner schrieb:> Du musst in gewisser Weise mit deinem 200kHz Interrupt eine Tabelle> ausgeben, genau so, wie es ein programierbarer Funktionsgenerator macht.> Ein anderes Stück Software muss diese Tabelle sinnvoll mit Inhalten> füllen. Der Knackpunkt dabei ist, dass die Periodendauer deiner Ausgabe> konstant ist, und zwar für alle Kanäle. Also muss sie ein ganzzahliges> Vielfaches der einzelnen Frequenzen sein. Wenn man nur 2, 1, 0,5 und> 0,25 kHz zulässt ist das kein Problem. Ansonsten, viel Spaß.
Danke, die Lösung funktioniert ganz gut, jedoch schränkt sie die
Flexibilität der wählbaren Frequenzen ein. Ist also leider nicht
erwünscht.
Es scheint, dass wir eine mögliche Implementierung gefunden haben. Ich
werde sie demnächst ausprobieren und hier berichten, falls jemand
Interesse daran hat.
Für den äußersten Notfall habe ich auch einen geeigneten Mikrocontroller
gefunden. Nämlich den AT32UC3L016. Das ist der "kleinste" µC mit 6
Timern den ich von Atmel gefunden habe.
Danke nochmal für eure Zeit.
Grüße
Kaan A. schrieb:> Für den äußersten Notfall habe ich auch einen geeigneten Mikrocontroller> gefunden. Nämlich den AT32UC3L016. Das ist der "kleinste" µC mit 6> Timern den ich von Atmel gefunden habe.
Warum sollte dies den "äußersten Notfall" darstellen?