Ich wollte mit dem Attiny10 eine Frequenzmessung durchführen.
Leider gibt es da beim Compilieren Probleme.
Um meinen Code weitesgehend auszuschließen habe ich hier einen fertigen
Code aus dem Forum mal getestet.
Leider kommt es hier ebenfalls zu einem Problem.
Ich möchte mit der If Abfrage ganz unten den Pin PB0 auf High setzen
sobald die Frequenz größer als 50 Hz ist.
1
2
Erg=F_CPU/Erg;// f = 1 / t
3
4
Freq=Erg;
5
6
7
if(Freq>50)
8
{
9
PORTB|=(1<<PORTB0);
10
}
Beim Compilieren mit dem aktuellen AVR Studio 6.1 erhalte ich allerdings
folgende Fehlermeldung.
ld returned 1 exit status collect2.exe
Das setzen des Portpins scheint dieses Problem zu verursachen.
Ein setzen des Portpins außerhalb der If Abfrage mit der selben
Anweisung funktioniert ohne Probleme, aber nicht innerhalb der
verschachtelten If Abfrage.
Schreibe ich aber z.B.
1
Freq=45;
2
3
4
if(Freq>50)
5
{
6
PORTB|=(1<<PORTB);
7
}
geht es auch ohne Probleme.
An was könnte dies liegen? Irgendwo ist doch der Wurm drin?
Das Ziel "PreBuildEvent" wurde übersprungen, da die Bedingung "false" war . ('$(PreBuildEvent)'!='') wurde als (''!='') ausgewertet.
6
Ziel "CoreRebuild" in Datei "C:\Program Files (x86)\Atmel\Atmel Studio 6.1\Vs\Compiler.targets" aus Projekt "C:\Users\Admin\Desktop\Projekt\1\Fan\Fan.cproj" (Ziel "ReBuild" ist davon abhängig):
7
RunCompilerTask-Aufgabe
8
C:\Program Files (x86)\Atmel\Atmel Studio 6.1\shellUtils\make.exe clean all
Jürgen F. schrieb:> Hat jemand eine Idee wie man das beheben könnte, bzw an was es liegt?
Schreib deinen Code in Assembler.
Die ganze C-Implementierung dafür ist völlig halbherzig, teilweise
meiner Erinnerung nach auch buggy, und praktisch die gesamte avr-libc
(außer den Headerfiles) wird vom Bauen ausgeschlossen, wenn das Target
ein "tiny core"-AVR ist, da sich nie einer die Mühe gemacht hat, den
Bibliothekscode auf diesen "halben AVR" anzupassen.
Jörg Wunsch schrieb:> Schreib deinen Code in Assembler.
Das wird es auch nicht einfacher machen, floating-point Operationen auf
einem ATtiny10 durchzuführen.
Jürgen F. schrieb:> Ich wollte mit dem Attiny10 eine Frequenzmessung durchführen.> Leider gibt es da beim Compilieren Probleme.
Das Problem liegt hier:
1
doubleErg=0.0;
2
uint8_tFreq;
3
4
...
5
Erg=F_CPU/Erg;// f = 1 / t
6
7
Freq=Erg;
Der Code verlangt hier eine floating-point Division mit anschließendem
casting nach int. Das Einbinden der entsprechenden Libraries erzeugt die
Fehlermeldungen. Ich vermute dass es die Library entwedner für den
Attiny10 nicht gibt, oder sie zu groß für die 1kb Programmspeicher sind.
Du solltest den Code so umschreiben, dass er nur mit integer-Variablen
arbeitet. Am besten eliminierst Du auch Multiplikationen und Divisionen,
so weit es geht. Der ATtiny ist für komplexe Arithmetik ungeeignet, da
er nur 16 Register hat.
Tim schrieb:> Das wird es auch nicht einfacher machen, floating-point Operationen auf> einem ATtiny10 durchzuführen.
Für einen ATtiny40 würde ich das ja zur Not noch gelten lassen, aber
auf einem 10er ist das aussichtslos. Wer's nicht glaubt, kann das
Projekt ja für den Anfang versuchen, für einen ATtiny13 zu compilieren:
gleiche Menge Flash, aber einen Core, der zumindest von den Libs
unterstützt wird. Selbst, wenn es diese Libs für den 10er gäbe (bzw.
man einen anderen Compiler nimmt, der sowas hat): der Code kann mit
dem "halben Core" nur größer werden.
Jörg Wunsch schrieb:> Tim schrieb:>> Das wird es auch nicht einfacher machen, floating-point Operationen auf>> einem ATtiny10 durchzuführen.>> Für einen ATtiny40 würde ich das ja zur Not noch gelten lassen, aber> auf einem 10er ist das aussichtslos. Wer's nicht glaubt, kann das> Projekt ja für den Anfang versuchen, für einen ATtiny13 zu compilieren:> gleiche Menge Flash, aber einen Core, der zumindest von den Libs> unterstützt wird. Selbst, wenn es diese Libs für den 10er gäbe (bzw.> man einen anderen Compiler nimmt, der sowas hat): der Code kann mit> dem "halben Core" nur größer werden.
Ja, nur das Problem ist doch nicht die Programmiersprache, sondern die
Tatsache dass der ATtiny10 nur die halbe Anzahl an Registern und kaum
Speicher hat :)
Ich habe die float Variable durch eine Integer ersetzt, so lässt sich
der Code zwar Compilieren allerdings funktioniert das ganze trotzdem
noch nicht so wirklich.
Ich möchte in Abhängigkeit der gemessenen Frequenz (Rechteck 50-150Hz)
ein neues um 20Hz erhöhtes Signal erzeugen.
Leider funktioniert das so wie ich es gemacht habe nicht.
1. Die ausgegebene Frequenz schwankt dauernd sehr stark.
2. Die zusätzlichen 20 Hz sind gar nicht bemerkbar.
Hat jemand eine Idee wie ich das stabil hinbekommen kann?
Jürgen F. schrieb:> Ich habe die float Variable durch eine Integer ersetzt, so lässt sich> der Code zwar Compilieren allerdings funktioniert das ganze trotzdem> noch nicht so wirklich.
Und bist Du Dir sicher, dass die gleichen Berechnungen ohne Änderung
auch in Integer-Arithmetik durchgeführt werden? Vermutlich musst Du noch
mehr anpassen.
1
for(i=0;i<j;i++)
2
{
3
Mittelwert=Mittelwert+Erg;
4
}
5
6
Mittelwert=Mittelwert/j;
Diese Schleife wird wesentlich häufiger aufgerufen als der Interrupt.
Daher hat die Mittelwertbildung hier keine Funktion.
Tim schrieb:> Ja, nur das Problem ist doch nicht die Programmiersprache, sondern die> Tatsache dass der ATtiny10 nur die halbe Anzahl an Registern und kaum> Speicher hat :)
Das mit dem "kaum Speicher" wäre für den ATtiny13 aber das gleiche.
Jürgen F. schrieb:> Ich habe die float Variable durch eine Integer ersetzt, so lässt sich> der Code zwar Compilieren allerdings funktioniert das ganze trotzdem> noch nicht so wirklich.
Siehe oben: meiner Erinnerung nach ist das, was die Leute bei Atmel da
in den Compiler gehackt haben, um den tiny-Core unterstützt zu bekommen,
alles andere als vertrauenswürdig. Daher mein Rat, das alles komplett
in Assembler zu schreiben. Für die 512 Befehlsworte, die du maximal
hast, sollte das überschaubar bleiben. (Versteh' mich recht: du wirst
diesen Ratschlag von mir sonst eher nicht hören.)
Jörg Wunsch schrieb:> Tim schrieb:>> Ja, nur das Problem ist doch nicht die Programmiersprache, sondern die>> Tatsache dass der ATtiny10 nur die halbe Anzahl an Registern und kaum>> Speicher hat :)>> Das mit dem "kaum Speicher" wäre für den ATtiny13 aber das gleiche.
Naja, das sind jetzt nur noch Spitzfindigkeiten: Aber der ATtiny10 hat
nur halb so viel SRAM wie der ATtiny13 und mit halber Registeranzahl
steigt die Stacknutzung...
> Jürgen F. schrieb:>> Ich habe die float Variable durch eine Integer ersetzt, so lässt sich>> der Code zwar Compilieren allerdings funktioniert das ganze trotzdem>> noch nicht so wirklich.>> Siehe oben: meiner Erinnerung nach ist das, was die Leute bei Atmel da> in den Compiler gehackt haben, um den tiny-Core unterstützt zu bekommen,> alles andere als vertrauenswürdig. Daher mein Rat, das alles komplett> in Assembler zu schreiben. Für die 512 Befehlsworte, die du maximal> hast, sollte das überschaubar bleiben. (Versteh' mich recht: du wirst> diesen Ratschlag von mir sonst eher nicht hören.)
Ja, nur das Problem vom Fragesteller hat ziemlich wenig damit zu tun das
er nicht Assembler benutzt, sondern das er seinen Code nicht versteht.
Da ist ein Tip wie "Mach alles in Assembler" wenig hilfreich.
Wenn man Assembler kann, kann man übrigens auch immer ins *.lss file
schauen und überprüfen ob der Compiler alles richtig macht. Das ist
immer noch wesentlich effizienter als gleich alles in Assembler zu
programmieren.
Ich habe den ATiny10 bisher ausschließlich in C programmiert und bin
noch nicht auf Compilerfehler gestossen. Allerdings habe ich auch eine
ziemlich gute Vorstellung davon, was mit dem Code auf Maschinenebene
passiert und probiere gar nicht erst so etwas wie float-Divisionen :)
Tim schrieb:> Ich habe den ATiny10 bisher ausschließlich in C programmiert und bin> noch nicht auf Compilerfehler gestossen.
Dann hast du einfach nur Glück gehabt.
Jörg Wunsch schrieb:> Siehe oben: meiner Erinnerung nach ist das, was die Leute bei Atmel da> in den Compiler gehackt haben, um den tiny-Core unterstützt zu bekommen,> alles andere als vertrauenswürdig. Daher mein Rat, das alles komplett> in Assembler zu schreiben. Für die 512 Befehlsworte, die du maximal> hast, sollte das überschaubar bleiben. (Versteh' mich recht: du wirst> diesen Ratschlag von mir sonst eher nicht hören.)
Ich fürchte Du hast Recht mit dem Assembler, aber dann werde ich das
Programm erst in 10 Jahren fertig haben.
Tim schrieb:> Und bist Du Dir sicher, dass die gleichen Berechnungen ohne Änderung> auch in Integer-Arithmetik durchgeführt werden? Vermutlich musst Du noch> mehr anpassen.
Wie meinst Du das? Denkst Du dass so etwas anderes berechnet wird als
mit float, abgesehen von den Rundungsfehlern?
Tim schrieb:> for( i=0; i<j; i++)> {> Mittelwert = Mittelwert+Erg;> }>> Mittelwert = Mittelwert/j;>> Diese Schleife wird wesentlich häufiger aufgerufen als der Interrupt.> Daher hat die Mittelwertbildung hier keine Funktion.
Ich hatte es vorher ohne Mittelwertbildung, das Ausgangssignal hatte da
das gleiche Verhalten. Das mit der Mittelwertbildung war nur ein
Versuch, der Code dazu stammt hier aus dem Forum.
Brauche ich den überhaupt eine Mittelwertbildung? Wenn ich zB. 50Hz
anlege dann dürfte er doch nicht so große Messfehler bekommen, oder?
Die Ausgangsfrequenz schwankt bei angelegten 50Hz zwischen 20Hz und
50Hz.
Ich denke mein Ansatz passt nicht so recht. Wie sollte ich da besser
vorgehen?
Da ich leider weder Display noch Serielle Schnittstelle habe kann ich
mir auch nicht wirklich ausgeben lassen was er bei der Frequenzmessung
als Ergebnis bekommt :(
Jürgen F. schrieb:>Wie meinst Du das? Denkst Du das so etwas anderes berechnet wird als mit
float, abgesehen von den Rundungsfehlern?
Es könnte Überläufe geben usw.
> Brauche ich den überhaupt eine Mittelwertbildung? Wenn ich zB. 50Hz> anlege dann dürfte er doch nicht so große Messfehler bekommen, oder?> Die Ausgangsfrequenz schwankt bei angelegten 50Hz zwischen 20Hz und> 50Hz.
Ich denke das hängt von der Stabilität Deines Eingangssignal ab.
>> Ich denke mein Ansatz passt nicht so recht. Wie sollte ich da besser> vorgehen?>> Da ich leider weder Display noch Serielle Schnittstelle habe kann ich> mir auch nicht wirklich ausgeben lassen was er bei der Frequenzmessung> als Ergebnis bekommt :(
Das könnte das Hauptproblem sein. Wahrscheinlich verbergen sich irgendwo
noch logische Fehler. Kannst Du zum testen nicht erst einmal einen
größeren Controller mit entsprechenden Debug-Möglichkeiten nutzen?
Ansonsten nutze ich zum Debuggen manchmal einfach einen Soft-UART über
einen Pin.
Tim schrieb:>>Wie meinst Du das? Denkst Du das so etwas anderes berechnet wird als mit> float, abgesehen von den Rundungsfehlern?>> Es könnte Überläufe geben usw.
Kann das trotz der long int Variablen passieren?
Tim schrieb:>> Brauche ich den überhaupt eine Mittelwertbildung? Wenn ich zB. 50Hz>> anlege dann dürfte er doch nicht so große Messfehler bekommen, oder?>> Die Ausgangsfrequenz schwankt bei angelegten 50Hz zwischen 20Hz und>> 50Hz.>> Ich denke das hängt von der Stabilität Deines Eingangssignal ab
Das Signal stammt hier für die Versuche aus meinem Funkionsgenerator und
ist sehr stabil. Daran kann es eigentlich nicht liegen.
Könnte es sein dass er für die Berechnung zu lange braucht?
Kann ich das OCR0A überhaupt direkt so beschreiben?
Das schwanken könnte aber auch doch auf Überläufe zurückzuführen sein?
Ich habe herausgefunden dass die Frequenzmessung über den Capture Pin
nicht mehr funktioniert sobald ich Fast PWM Mode 15 aktiviere.
Kann mir jemand sagen weshalb das dann nicht mehr richtig arbeitet?
Geht Fast PWM und Input Capture nicht gleichzeitig?
Ok, also man sollte das Datenblatt doch mal genau lesen :)
Die Zeitmessung ging ja davon aus dass der Zähler erst bei 65536
überläuft.
Da ich ja aber im Fast PWM Mode 15 mit OCR0A vorgebe bis wie weit er
zählen soll muss ich natürlich auch für die Zeitmessung mit diesem Wert
rechnen.
Jetzt habe ich das Problem dass sich das ganze natürlich aufschauckelt,
und dann bis hoch in den kHz ausgibt.
Wie gehe ich da am besten vor um ein aufschauckeln zu vermeiden?
Jürgen F. schrieb:> Jetzt habe ich das Problem dass sich das ganze natürlich aufschauckelt,> und dann bis hoch in den kHz ausgibt.>> Wie gehe ich da am besten vor um ein aufschauckeln zu vermeiden?
Da schaukelt sich nichts auf, wenn die Berechnung der Pulslänge stimmen
würde.
1
Erg=(NrOverflows*OCR0A)+EndTime-StartTime;
Zum einen ist der Multiplikator für die Überläufe nicht OCR0A, sondern
OCR0A+1, zum anderen funktioniert das "EndTime - StartTime" jetzt nicht
mehr für EndTime<StartTime.
Stefan Ernst schrieb:> zum anderen funktioniert das "EndTime - StartTime" jetzt nicht> mehr für EndTime<StartTime.
Könnte das jemand erklären? Ich bekomme es nicht hin, egal was ich mache
es schwingt sich sehr schnell auf.
noch eine Frage zum Verständis:
Wird der Timer beim Wert aus OCR0A auf 0 zurückgesetzt oder nur das
Overflow Bit gesetzt?
Danke