Hallo,
trotz vieler Suche bin ich mit meinem Ergebnis für eine
input-capture-Abfrage nicht erfolgreich.
Ich wollte gern die Zeit zwischen ansteigender und fallender Flanke
messen.
Ich hatte angenommen, wenn ich dem Atmega16 in das Register TCCR1B das
ICSE1-Bit = 1 schreibe, startet input capture sofort, indem es den
TCNT1-Wert in ICR1 kopiert und auf das nächste Event wartet, das ich in
der Zwischenzeit geändert habe (ICSE1_Bit gelöscht, also fallende
Flanke).
Wenn ich von dem bei letzterem Event in ICR1 kopierten TCNT1-Zählerstand
den Anfangswert abziehe, sollte ich die gewünschten Counts erhalten.
Leider geschieht dies nicht, obwohl der Sensor passende Signale liefert
und diese auch vom ICP detektiert werden.
Mache ich mir vielleicht das mit dem Auslesen der 16-bit-Werte aus TCNT1
oder meinen Variablen zu einfach?
Ob sich mal jemand den Code ansehen könnte?
Vielen Dank schon mal.
Egon
uint16_t inpucap(void)
{
int16_t mw, mw_alt=0, mw_neu=0;
DDRD &= 191; // ICR=PORTD6 wird Eingang
TCNT1 = 0; // vermeidet zunächst overflow-handling
TCCR1B = (1<<CS10); // CPU-Takt/8
TCCR1B = (1<<ICES1); // steigende Flanke gewählt
// automatischer Start ???
// TCNT1-Wert wird in IRC1 kopiert
mw_alt = ICR1;
TCCR1B &= 191; // fallende Flanke (ICES1-bit gelöscht)
mw_neu = ICR1;
mw = mw_neu - mw_alt;
return (mw);
}
Oha, Du hast überhaupt nicht kapiert, wie Input Capture funktioniert!
Du musst schon auf das Capture-Ereignis warten, bevor Du das Register
ausliest!
Abgesehen davon: Steuerregister in Dezimalzahlen zu setzen ist die
denkbar allerschlechteste Methode. Gewöhne Dir sofort grundsätzlich
die Schreibweise mit Bitnamen oder wenigstens Hexadezimalzahlen an!
STK500-Besitzer wrote:
> Du solltest warten, bis das ICP-Interrupt aufgetreten ist.> Das kann man entweder in einer ISR mache oder per Polling.
Die Interrupts sind abgeschaltet und sollten es auch bleiben. Ich habe
genügend Zeit für Polling. Ich hatte gedacht, man startet Zähler und
wählt die Art der Flanke und die input capture Einheit wartet
automatisch auf die passende Flanke und zählt.
Was muß ich jetzt noch tun?
Gruß
Egon
Johannes M. wrote:
> Egon Müller wrote:>> Was muß ich jetzt noch tun?> Das Flag abfragen!>
Also, ich habe jetzt gleich nach dem Löschen des Flankenauswahlbits
eingefügt
TIFR = (1<<ICF1); // (Manual S. 94)
aber mein mw ist konstant = 0.
> Und beim Polling dran denken, das Flag nach dem Abfragen auch wieder zu> löschen!
Sollte ich also oben in die Funktion das TIFR = (1<<ICF1);
reinschreiben (das Manual schweigt sich dazu aus)?
Nachtrag:
Ich habe mal das mit dem Flankenwechsel weggelassen - wo man lt. Manual
das ICF1-Bit nicht löschen muß das Elend ist unverändert
Grüße
Egon
Du musst erst warten, bis das Flag gesetzt ist!! Erst dann hat die
Capture-Einheit eine Flanke registriert! Schau Dir bitte mal das
AVR-GCC-Tutorial an!
Johannes M. wrote:
> Du musst erst warten, bis das Flag gesetzt ist!! Erst dann hat die> Capture-Einheit eine Flanke registriert! Schau Dir bitte mal das> AVR-GCC-Tutorial an!
Da lese ich doch dauernd darin und finde da als einziges Bit Bit
speziell für Input capture das ICF1, von dem in Manual zu lesen ist ,das
es nach Flankenwechsel unverzüglich zu löschen sei, aber ohne
Flankenwechsel sei das unnötig (S.94). Und dann gibt es noch ein hier
interessierendes Bit für Zählerüberlauf. Aber sonst finde ich nichts,
nicht mal über while-Schleifen.
Hast Du mal meinen Code besehen, ist da vielleicht ein Fehler drin?
Hi STK500-Besitzer:
>Du solltest eine While-Schleife einbauen, die das ICP-Interrupt-Flag>abfragt.
Interrupts wollte ich doch nicht
Gruß
Egon
>Interrupts wollte ich doch nicht
Der Controller meldet "Fertig!" mit setzen des ICF1. Das löscht man dann
wieder und kann wieder auf das Setzen warten.
Das, wovor du Angst hast sind Interrupt Service Routinen. Aber selbst
das ist keine Hexerei...
Hallo STK500Besitzer
Deine Version habe ich schon ausprobiert,
es sieht insofern gut aus, als ein konstanter Wert ungleich null
angezeigt wird.
Aber mit meinen Variablen scheint irgendetwas schief zu laufen, denn die
Anzeige ist immer -2. Vielleicht muß man doch high - und low-Byte
getrennt auslesen?
Egon
Um die Pulslänge zu messen, rufst du jedes Mal diese Funktion auf?
Was'n Stress für den Timer...
Einfach irgendwo (Hauptprogramm/Initalisierung) den Timer starten und
dann zur Pulslängenfeststellung die Routine aufrufen.
STK500-Besitzer wrote:
>>Interrupts wollte ich doch nicht>>> Das, wovor du Angst hast sind Interrupt Service Routinen. Aber selbst> das ist keine Hexerei...
Ich fürchte mich deshalb davor, weil dieses Modul in eine größeres
Programm eingefügt werden soll, das gespickt ist mit undurchschaubaren
Interrupts.
Und wenn ich hier irgendetwas habe, dann ist es Zeit. Deshalb wollte ich
mir zusätzliche Komplikationen ersparen.
Matthias Lipinsky wrote:
>>Aber mit meinen Variablen scheint irgendetwas schief zu laufen>> Mach mal aus>
1
>int16_tmw,mw_alt=0,mw_neu=0;
2
>
> ein>
1
>uint16_t...
2
>
Schade, war schon drin, ist nur beim Kopieren verloren gegangen.
Aber main ist definiert
>int main(void).
Eigentlich hätte ich gern geschrieben
>uint16_t main(void),
aber das mag der Compiler nicht. Aber innerhalb von
main ist mw mit uint16_t bezeichnet.
>Und wenn ich hier irgendetwas habe, dann ist es Zeit. Deshalb wollte ich>mir zusätzliche Komplikationen ersparen.
Muhahaha..
Und du meinst, das wird dan alles funktionieren, wenn du in deiner
Routine
mit der Zeile
1
while(!(TIFR&(1<<ICF1));// auf Interrupt warten
Den Prozessor solange anhälst, bis du mal ein Signal ankam?
Matthias Lipinsky wrote:
>>Und wenn ich hier irgendetwas habe, dann ist es Zeit. Deshalb wollte ich>>mir zusätzliche Komplikationen ersparen.>> Muhahaha..>> Und du meinst, das wird dan alles funktionieren, wenn du in deiner> Routine> mit der Zeile>
1
>while(!(TIFR&(1<<ICF1));// auf Interrupt warten
2
>
> Den Prozessor solange anhälst, bis du mal ein Signal ankam?
Durchaus. Wenn das Signal nicht kommt, ist alles wertlos. Für den
Prozessor gilt dann mitgegangen, mitgehangen...
STK500-Besitzer wrote:
> Um die Pulslänge zu messen, rufst du jedes Mal diese Funktion auf?> Was'n Stress für den Timer...> Einfach irgendwo (Hauptprogramm/Initalisierung) den Timer starten und> dann zur Pulslängenfeststellung die Routine aufrufen.
Hatte ich auch vor, es gibt da ein main und von da wird dann auch die
Meßwerterfassung aufgerufen (z.B. einmal täglich).
Nun muß ich nur noch die Variablen hinbiegen, damit ich irgendetwas
auswerten kann. Leider gibt es input capture nur bei den 16-bit-Zählern.
Mit 8 bit könnte man es leichter testen.
Grüße
Egon
Hallo Matthias
ich habe es für meine Variablen umgeschrieben,
aber das Elend ist nicht anders geworden, es wird für mw immer nur 0
angezeigt.
Ich glaube, es wird langsam Zeit zum Verzweifeln.
Gruß
Egon
Matthias Lipinsky wrote:
> So geht das ohne Interrupt. reagiert immer auf dieselbe Flanke>>
1
>voidmain(void)
2
>{
3
>//-- lokale variablen ------------------------------------
Poste doch mal den kompletten Code von dir. Kopier ihn mal rein.
Ich bin grad an einer Drehzahlmessung per ICP dran. Die Periodendauer
wird schon gemessen mit Interrupt und folgendem Code:
Matthias Lipinsky wrote:
> Poste doch mal den kompletten Code von dir. Kopier ihn mal rein.>> [/c]
Mache ich, hoffentlich gelingt es.
Ich habe die endlosen Passagen weggelassen, wo ein I2C angesprochen wird
und ein PCF8575 (oder so ähnlich), das LCD usw..
Ich habe in der Zwischenzeit getestet, ob vielleicht meine Zahlenausgabe
die Fehlerursache sein könnte. Ist sie wahrscheinlich nicht.
In der Funktion zahl_lcd (ziemlich am Anfang) ist als einziges, was man
vielleicht ändern sollte, die char-Variable. Ist vielleicht mit 8 bit
etwas wenig?
Anderseits werden Zahlen bis zu 0x7FFF korrekt auf meinem LCD angezeigt,
nur, was darüber ist, nicht mehr.
Ich habe probeweise den TCNT1 simuliert mit 0x7FFF, das wird angezeigt,
dann habe ich den Original-TCNT1 anzeigen lassen, das fängt mit 2 an und
zählt sich dann langsam hoch, innerhalb einer Minute auf etwa 100.
Da ist wohl etwas faul, der Zähler scheint nicht zu laufen, aber
anderseits nimmt er langsam zu.
Fehlt vielleicht in meinem Programm ein Starbefehl? ich habe z.B TCCR1A
nicht erwähnt, weil es in der richtigen Weise vorkonfiguriert ist.
Bis morgen
Egon
> Ich glaube, es wird langsam Zeit zum Verzweifeln.
Das glaub ich nicht.
Es wird Zeit, dass du dir jemanden suchst und bezahlst, der wenigstens
ein bischen was von programmieren versteht.
Das ist so ziemlich das schrottigste Programm, das ich in 25 Jahren
gesehen habe.
> In der Funktion zahl_lcd (ziemlich am Anfang) ist als einziges,> was man vielleicht ändern sollte, die char-Variable. Ist vielleicht> mit 8 bit etwas wenig?
Du hast keine Ahnung was du eigentlich machst.
Ja an der Funktion muss man Hand anlegen, allerdings nicht an der
'char-Variablen' (die in Wirklichkeit ein Array ist). Die und der itoa
Aufruf sind so ziemlich das einzig Korrekte in dieser Funktion.
Nichts für ungut. Aber du versuchst gerade in Schuhen zu laufen, die dir
mindestens 5 Nummern zu gross sind.
Edit: Korrektur. Der itoa Aufruf ist auch falsch.
>Ein einzelnes Flag löscht man mit "=".>Mit "|=" werden gleich alle Flags in dem Register gelöscht.
Du bist soeben auf das Feld "Gehe zurück zu Anfang gesprungen"
Matthias Lipinsky wrote:
>>Ein einzelnes Flag löscht man mit "=".>>Mit "|=" werden gleich alle Flags in dem Register gelöscht.>> Du bist soeben auf das Feld "Gehe zurück zu Anfang gesprungen"
Und dabei darf er €2000 einziehen.
(Er hat recht. So seltsam es auch aussieht, aber zb. mit TIFR |= 0
werden alle Flags in TIFR gelöscht. Es spielt keine Rolle was rechts vom
|= steht. Das |= ist der Übeltäter. Remember: Ein Flag in TIFR wird
zurückgesetzt, indem man eine 1 reinschreibt. Welche Bits sind bei |=
auf jeden Fall 1. Genau! Die, die es vorher auch schon waren. Ergo ....
Karl heinz Buchegger wrote:
> Das ist so ziemlich das schrottigste Programm, das ich in 25 Jahren> gesehen habe.>
Das ist kein Programm, sondern der schnell zusammengezimmerte Versuch,
den Problemen des input capture auf die Spur zu kommen. Es enthält
eigene Passagen und parallel eingefügte Sequenzen hier aus dem Forum.
Das hätte man leicht erkennen können.
> Nichts für ungut. Aber du versuchst gerade in Schuhen zu laufen, die dir> mindestens 5 Nummern zu gross sind.
Bleibt auf dem Teppich; es sind höchstens drei Nummern
> Edit: Korrektur. Der itoa Aufruf ist auch falsch.
itoa ist richtig.
Einen konstruktiven Beitrag hast Du nicht? Eigentlich hättest Du aus der
Diskussion feststellen müssen, daß der Zähler nicht läuft.
Einen Vorschlag, wie man ihn starten kann?
mfg
Egon
Egon Müller wrote:
>> Edit: Korrektur. Der itoa Aufruf ist auch falsch.> itoa ist richtig.
Das glaub ich nicht, Tim.
Welchen Datentyp hat denn der Eingangsparameter deiner Funktion?
Und welchen Datentyp erwartet itoa?
Und warum gibt es wohl eine Funktion utoa?
> Bleibt auf dem Teppich; es sind höchstens drei Nummern
Gemessen an so manchen deiner Aussagen hier in diesem Thread, sind 5
Nummern zu gross noch freundlich ausgedrückt.
> Einen konstruktiven Beitrag hast Du nicht?
Doch hatte ich.
Such dir jemanden, der zumindest ein wenig programmieren kann.
Und das ist mein tatsächlicher, wirklicher Ernst! Und ich sag das nicht,
weil ich mich lustig machen will.
Du solltest Dich auch ganz dringend über Gültigkeitsbereiche von
Variablen informieren! Es gibt in Deinem "Programm" einige Stellen, an
denen eine Variable namens mw benutzt wird. Diese Variable existiert
an diesen Stellen aber gar nicht! Das müsste Dir schon allein deswegen
beim compilieren um die Ohren fliegen...
Ich muss Karl heinz Recht geben, auch wenn es vielleicht tatsächlich ein
bisschen übertrieben ist, wenn er schreibt, dass es das "schrottigste
Programm in 25 Jahren" sei. Selbst ich habe schon schlimmeres gesehen,
aber nichtsdestotrotz ist es in weiten Teilen wirklich Schrott.
Und dass Dein Timer nicht läuft, wundert mich auch nicht. Schließlich
schaltest Du ihn jeweils eine Zeile nach seiner Aktivierung schon wieder
aus...
Wenn Du schreibst
1
REGISTER=WERT1;
2
REGISTER=WERT2;
was glaubst Du, was nach der zweiten Anweisung noch von dem übrig ist,
was die erste Anweisung gemacht hat? Genau, die erste Anweisung kannste
dann auch direkt weglassen.
Ehrlich: Dir fehlen absolute Grundlagen, nicht nur was den Controller
und seine Funktionen angeht, sondern auch, was die Programmiersprache
betrifft. Und einer wie Du hat sicher nicht das Recht, dem Karl heinz,
der in Sachen didaktisch wertvoller Beiträge hier der Ansprechpartner
Nummer 1 ist, in einem solchen Ton zu begegnen...