Hallo zusammen
Ich habe ein komisches Phänomen auf welches ich keine Antwort finde.
Es geht um eine Berechnung welche ich zur Ansteuerung eines
PWM-Controllers mittels eine Interrupt-Timers mache.
Nun habe ich eine Berechnungszeile, welche mir die Anzahl Überläufe des
Timers berechnet. Ist die Anzahl Überläufe erreicht, setze ich den
PWM-Ausgang.
Dabei verwende ich folgende Variablen:
1
// general data
2
doubledPwm_freq=1975;// requested frequency
3
constunsignedlongulCycleTime=125;// cycle time in nano seconds
4
constunsignedlongulCpuFrequency=8000000;// Cpu freqnecy in Hz
5
6
//pwm data
7
constunsignedintiPrescaler=1;// prescaler of timer0
8
constunsignedintnTimer=256;// resolution of timer0
9
volatileunsignedlongulTimeOvfl;// Time for Overflow of timer0 in nano seconds
10
volatileunsignedlongulTmrOvflCntr=0;// counter for number of overflows
11
volatileunsignedlongulPwm_EndCntr=0;// end value until time of pwm-cycle has reached
Die Berechnung selbst im Code sieht dann folgendermassen aus:
Wenn ich dies nun in einem C-Projekt in Eclipse laufen lasse, dann
funktioniert diese Berechnung tadellos. Ich kann danach den korrekten
Wert in der Konsole ausgeben.
Sobald ich dies jedoch auf den Controller (Attiny85) lade, dann bleibt
die Applikation an dieser Berechnung hängen.
An was kann das liegen? Was ist Unterschiedlich bei der Berechnung auf
dem PC und auf dem Controller?
Liegt das daran, dass es sich beim Controller um eine 8bit CPU handelt,
bei meinem PC jedoch um einen 32bit Prozessor?
Wie kann ich dies umgehen?
Danke für die Antworten und einen schönen Abend wünscht
hafisch
H. Fisch schrieb:> Sobald ich dies jedoch auf den Controller (Attiny85) lade, dann bleibt> die Applikation an dieser Berechnung hängen.
Wie kommst Du darauf?
H. Fisch schrieb:> Was ist Unterschiedlich bei der Berechnung auf> dem PC und auf dem Controller?
Die Größe des Stack.
Ich schätze, dein Stack ruscht in den Variablen-Bereich und wird
überschrieben. Dass der Controller scheinbar genau an dieser Berechnung
hängen bleibt, hat nichts mit der Berechnung selber zu tun, sondern ist
eher Zufall.
Nur so eine Idee.
H. Fisch schrieb:> Liegt das daran, dass es sich beim Controller um eine 8bit CPU handelt,> bei meinem PC jedoch um einen 32bit Prozessor?> Wie kann ich dies umgehen?
Einen 32bit-controller nehmen, z.B. Atmel SAM3X8E (Arduino Due,
Cortex-M3) oder einen STM32F4 (Cortex-M4), was aber nichts mit deinem
Problem zu tun hat.
Bei mir kommt aber sowohl im Atmel Studio mit dem Simulator, als auch in
Visual Studio jeweils 7 raus...
Ich werf mal noch die Begriffe "Wertebereiche" und "Overflow" in den
raum.
Ein Stück Code mit dem es auf jedenfall gehen sollte:
Ungenutze Variablen hab ich mal entfernt, Compiler Optimierung ist
ausgeschaltet.
Der Cast ist genaugenommen unnötig, da in deiner Version die Variable
dPwm_freq vom Typ double und damit mind. 4Byte groß ist.
H. Fisch schrieb:
Warum versuchst du nicht, dem Compiler die Berechnung anzuhängen?
Oder musst du die Frequenz zur Laufzeit ändern können?
> double dPwm_freq = 1975; // requested> frequency
double ist zwar nett, ist aber auf einem AVR effektiv nur ein float. Mit
allen Problemen, wie etwa dem, dass du nur 5 bis 6 signifikante Stellen
hast. Im Gegensatz zu den 15 bei echten double auf einem PC.
Hallo danke für die schnelle Antwort
Ich habe nun herausgefunden dass es am Datentyp des Divisors lag,
welcher als double definiert war.
Definiere ich diesen als float funktioniert alles.
Nun habe ich jedoch noch ein kleines Problem.
Ich habe ein Array mit einigen Elementen welche ich in einer Schleife
abfrage.
Nun habe ich einen Zugriff auf das Array innerhalb der Schleife mit
folgendem Effekt.
Ist die Arrayindexvariable innerhalb der SChleife definiert,
funktioniert der Zugriff. Verwende ich jedoch den Schleifenindex oder
eine ausserhalb definierte Variable, so funktioniert der Zugriff nicht.
folgendes Beispiel funktioniert
1
for(iAtBeat=0;iAtBeat<uiNumOfBeats;iAtBeat++){
2
3
intiTemp=0;
4
fPwm_freq=aMySongNotes[iTemp];
5
6
}
folgendes Beispiel funktioniert nicht
1
intiTemp=0;
2
for(iAtBeat=0;iAtBeat<uiNumOfBeats;iAtBeat++){
3
4
fPwm_freq=aMySongNotes[iTemp];
5
6
}
auch dieses Beispiel funktioniert nicht
1
for(iAtBeat=0;iAtBeat<uiNumOfBeats;iAtBeat++){
2
3
fPwm_freq=aMySongNotes[iAtBeat];
4
5
}
Ist dies erklärbar? Wenn ja, wie?
Danke und Gruss
hafisch
H. Fisch schrieb:> Ist dies erklärbar?
nein.
Iregendwas ist in deinem Code anscheinend mächtig faul. Und dieses
'irgendwas' muss mit dieser Berechnung noch nicht mal in Zusammenhang
stehen.
Hallo zusammen
alse erstmal herzlichen Dank für die Antworten.
Ich habe nun erst einmal einen anderen Controller genommen, jedoch mit
dem gleichen Effekt.
Danach habe ich das Projekt auf das minimalste reduziert um den Fehler
genau definieren zu können.
Das Projekt besteht eigentlich nur aus einer for-Schleife welche 10 mal
durchlaufen wird, und einen Ausgang mit einer LED steuert.
Nun ist es so, dass wenn ich in dieser Schleife einen Array-Wert mit
einem Konstanten Arrayindex abfrage, funtioniert dies einwandfrei und
die LED blinkt 5 mal.
Sobald ich jedoch den Schleifenindex verwende um den Arrayinhalt
abzufragen, bleibt mir der Controller hängen.
Dies äussert dich so, dass nach dem Start die LED auf etwa 5% leicht
leuchtet ohne zu blinken.
Die entsprechenden Zeilen sind unten im Code beschrieben.
Hier das entsprechende Programm
1
#include<avr/io.h>
2
#include<stdio.h>
3
4
// --- main routine ---
5
intmain(){
6
7
// --- local declarations ---
8
constunsignedintuiNumOfLoops=10;
9
volatileunsignedlongi;
10
volatileunsignedlongj;
11
volatileunsignedintmyVal;
12
13
unsignedlongaMyArray[75]={0,1,2,3,4,5,6,7,8,9};
14
15
// --- define IO's ---
16
DDRB=(1<<PB4);
17
18
// --- main loop ---
19
for(i=0;i<uiNumOfLoops;i++){
20
21
// get array variable
22
myVal=aMyArray[0];// <--- works
23
//myVal = aMyArray[i]; // <-- controller stops, does not work
24
25
// blink output
26
if((PORTB&(1<<PB4))==0){
27
PORTB|=(1<<PB4);// set output
28
}else{
29
PORTB&=~(1<<PB4);// reset output
30
}
31
32
// delay loop
33
for(j=0;j<10000;j++){
34
35
}
36
37
}
38
39
return1;
40
}
Was mache ich noch falsch? Es muss an der Applikation liegen da dies bei
verschiedenen Controllern gleich auftritt.
Gibt es irgendwelche Compilereinstellungen welche dies verursachen
könnten?
Ich arbeite unter Ubuntu mit Eclipse und dem AvrDude.
Danke für die Hilfe und einen schönen Samstag wünscht
hafisch
H. Fisch schrieb:> volatile unsigned long i;> volatile unsigned long j;
Gibt es irgendeinen Grund, dein Array über eine 32-Bit Variable zu
indizieren?
Gleiches gilt für den Variablentyp deine Array-Elemente. Spätestens wenn
du dir die Frequenz deines PWM-Signals anguckst, wird sich rausstellen,
dass es selten sinnvoll ist, hier mehr als 16 Bit zu verwenden.
H. Fisch schrieb:> double dPwm_freq = 1975; // requested frequency
Welche Dynamik erwartest du, dass du zu Gunsten der Dynamik ein
float-Variable verwendest und damit auf Auflösung verzichtest.
Frequenzen im Millihertz-Bereich sind für PWM selten sinnvoll. Nimm
lieber eine solide Festkommaarithmetik und achte auf die Größe der
Zwischenergebnisse, i.e. auf die Reihenfolge der Operationen.
Hallo Wolfgang
Zu diesen beiden Punkten gebe ich dir absolut recht.
Die Variablengössen sind nicht optimiert und zu gross oder noch falsch
gewählt.
Den float Datentyp habe ich erst einmal so gewählt, da ich nicht sicher
bin, wie genau die Frequenzen sein müssen so dass Fehler nicht hörbar
sind. Dies werde ich jedoch erst anpassen, wenn ich dies mit dem Buzzer
und der ganzen Melodie getestet habe.
Die grossen Datentypen habe ich allerdings hauptsächlich aus dem Grund
so gewählt, dass ich aufgrund des oben genannten Problems ziemlich viel
schon versucht habe um die Ursache zu finden. Entsprechend habe ich
alles auf sehr grosse Datentypen gestellt habe, um irgendwelche
Überläufe ausschliessen zu können.
Sobald ich das Schleifen-Problem gefunden habe und das Programm so läuft
werde ich den Rest optimieren.
Danke für die Hilfe und Gruss
hafisch
Hallo zusammen
Ich habe noch eine weitere Erkenntnis bezüglich des Zugriffs auf das
Array mit einer Variable.
Ich habe das gleiche Problem, wenn ich eine Variable ausserhalb der
Schleife definiere, und diese in der Schleife inkrementiere.
Das heisst das Programm bleibt bei folgendem Code ebenfalls hängen:
1
// --- main loop ---
2
volatileintarrayIdx=0;
3
4
for(i=0;i<uiNumOfLoops;i++){
5
6
// get array variable
7
arrayIdx++;
8
myVal=aMyArray[arrayIdx];// <-- controller stops, does not work
9
//myVal = aMyArray[i]; // <-- controller stops, does not work
Es funktioniert nur, wenn ich die Variable innerhalb der Schleife
definiere, oder einen konstanten Wert eintrage.
Hat noch jemand eine Idee?
Danke und Gruss
hafisch
Ich denke der fehler ist nicht im code. Es gibt keine Rekursionen oder
zu grosse locale Arrays, welche einen Stackoverflow auslösen könnten,
zudem gibt es auch keine bufferoverflows oder änliches.
Compilierst du für den richtigen uc, hat dieser eine zuverlässige
stromversorgung?
H. Fisch schrieb:> volatile unsigned int myVal;>> unsigned long aMyArray[75] = {0,1,2,3,4,5,6,7,8,9};
Warum liest du die ganze Zeit einen integer aus einem long Array
heraus ?
H. Fisch schrieb:> Das heisst das Programm bleibt bei folgendem Code ebenfalls hängen:> // --- main loop ---> volatile int arrayIdx = 0;>> for (i=0; i<uiNumOfLoops; i++){>> // get array variable> arrayIdx ++;> myVal = aMyArray[arrayIdx]; // <-- controller stops, does not work> //myVal = aMyArray[i]; // <-- controller stops, does not work>> Es funktioniert nur, wenn ich die Variable innerhalb der Schleife> definiere, oder einen konstanten Wert eintrage.>> Hat noch jemand eine Idee?
Ja.
Überprüfe deine Einstellungen, wähle richtigen uC.
Es gibt absolut keinen Grund warum das nicht funktionieren sollte.
Hallo
Ich denke auch dass es Applikativ stimmt, da ich dasselbe auf dem
Rechner in einer lokalen C-Applikation problemlos ausführen konnte.
Es muss also entweder an einer Compilereinstellung, einen applikativen
Fehler zu dieser speziellen HW oder an der HW selbst liegen.
Das auslesen des Integers aus einem long-Array kommt daher, dass ich
meine Applikation zu Beispielzwecken reduziert habe. Dies ist jedoch
kein Problem da es sich um eine impliziten konvertierung handelt.
Muss HW-mässig etwas beachtet werden?
Muss im AvrDude ausser dem Typ den Fuses, den Lockbits noch etwas
anderes eingestellt werden was hardwareabhängig ist?
Könnte es an bestimmten Compilereinstellungen liegen?
Werde dies noch mit einem Atmega und im Win Avr versuchen.
Gruss
hafisch
H. Fisch schrieb:> Nun ist es so, dass wenn ich in dieser Schleife einen Array-Wert mit> einem Konstanten Arrayindex abfrage, funtioniert dies einwandfrei und> die LED blinkt 5 mal.> Sobald ich jedoch den Schleifenindex verwende um den Arrayinhalt> abzufragen, bleibt mir der Controller hängen.
Wie erzeugst du das HEX-File?
Vermutlich hast du die data-Section nicht mit in dieses exportiert.
Hallo
Das tönt mal nach einer möglichen Ursache.
Was ist denn die Data section? Was ist darin enthalten, so dass es einen
Einfluss auf den Arrayzugriff haben kann?
Weiss jemand wie dies im Eclipse mit AvrDude konfiguriert werden kann.
vielen herzlichen Dank und einen schönen Abend wünscht
hafisch
H. Fisch schrieb:> Was ist darin enthalten, so dass es einen> Einfluss auf den Arrayzugriff haben kann?
Die Initialisierungsdaten deines Arrays.
H. Fisch schrieb:> Weiss jemand wie dies im Eclipse mit AvrDude konfiguriert werden kann.
AvrDude hat damit schon mal überhaupt nichts zu tun. Was man in Eclipse
einstellen kann/muss, kann ich dir nicht sagen. Aber wenn du ein
automatisch generiertes Makefile verwendest, dann würde ich erwarten,
dass das nicht das Problem ist.
Es wäre hilfreich, wenn du mal den kompletten Output eines Builds posten
würdest.
Hallo
Ich habe zu Testzwecken, um einen defekten Controller ausschliessen zu
können, auf einen attiny25 gewechselt.
Doch inzwischen habe ich einmal auf einen Atmega8515 gewechselt.
Bei diesem scheint dies ohne Probleme zu funktionieren.
Ist es möglich, dass mir bei einem tiny der Speicher ausgeeht sobald
dies mit einem Schleifenindex abgerufen wird?
Hat diese einen Einfluss auf den zu verwendenen Speicher?
Danke und Gruss
hafisch
H. Fisch schrieb:> Ist es möglich, dass mir bei einem tiny der Speicher ausgeeht sobald> dies mit einem Schleifenindex abgerufen wird?
Dir geht auf einen Tiny25 in jedem Fall der Speicher aus.
(Wie viel Bytes braucht das Array und wie viel hast du auf einem
Tiny25?)
Bei Zugriffen mit konstantem Index fällt das nur nicht auf, weil dann in
Wirklichkeit gar kein Zugriff auf das Array stattfindet.