Hallo,
Ich habe am tiny85 (8MHz intern, INT0) einen Frequenzgenerator
angeschlossen, der auf 15Hz eingestellt ist. Ich möchte nun die Zeit in
Mikrosekunden messen, die zwischen zwei Interrupts vergeht. Dabei wird
nur die fallende Flanke ausgewertet. Hier meine Konfiguration:
1
MCUCR|=(1<<ISC01);// The falling edge of INT0 generates an interrupt request.
Was dabei herauskommt ist nicht, wie ich erwartet hätte ca. 66000 us.
Sondern wechselnde Werte unter 2000 us. Was mich glauben lässt, dass es
mehr Interrupts gibt als es eigentlich sein dürften. Wie kann das sein?
Ich hoffe, jemand kann helfen...
VG Matze
Matthias H. schrieb:> Ich habe am tiny85 (8MHz intern, INT0) einen Frequenzgenerator> angeschlossen, der auf 15Hz eingestellt ist. Ich möchte nun die Zeit in> Mikrosekunden messen, die zwischen zwei Interrupts vergeht. Dabei wird> nur die fallende Flanke ausgewertet. Hier meine Konfiguration:
Es gibt keine Konfiguration, wohl aber einen Quelltext. Den sollte mn
VOLLSTÄNDIG bereitstellen. Einfach als Datei anhängen, ist gar nicht
schwer.
> loop() {> if(triggered) {>> newTriggerTime = micros();> triggered = false;>> uint32_t us;> if ( newTriggerTime > oldTriggerTime ) {> us = newTriggerTime - oldTriggerTime;> } else {> us = (4294967295UL - oldTriggerTime + newTriggerTime + 1);> }
Diesen Unsinn braucht man nicht. Wenn die Differenz kleiner als der
halbe Zählerumfang ist, ist die Differenz immer korrekt, auch beim
Überlauf.
1
us=newTriggerTime-oldTriggerTime;
> Was dabei herauskommt ist nicht, wie ich erwartet hätte ca. 66000 us.> Sondern wechselnde Werte unter 2000 us. Was mich glauben lässt, dass es> mehr Interrupts gibt als es eigentlich sein dürften. Wie kann das sein?
Dein triggered ist hoffentlich als volatile deklariert, siehe
Interrupt.
Hallo Matthias,
woher nimmst du denn die new / old Triggertime?
Der Tiny85 hat nur Timer mit 8 Bit (0..255)
Sowas macht man mit Input-Capture, wofür es einen Tiny24/44/84 mit
16-Bit-Timer braucht. Eventuell mit einem Zusatzregister, dass die
Überläufe erfasst.
Reg dich mal wieder ab, Falk!
Bei nem popligen Tiny85 nehm ich keine Hochsprache.
Wie ist micros() definiert - Bitweite?
Woraus gewinnt micros() den Wert?
Ralf K. schrieb:> Reg dich mal wieder ab, Falk!>> Bei nem popligen Tiny85 nehm ich keine Hochsprache.
der OP aber schon . . .
> Wie ist micros() definiert - Bitweite?https://docs.arduino.cc/language-reference/en/functions/time/micros/> Woraus gewinnt micros() den Wert?
Aus einem Timer. Natürlich hat der nicht bei JEDEM Arduino die echte,
volle Auflösung.
Falk B. schrieb:> Dein triggered ist hoffentlich als volatile deklariert, siehe
Ja, natürlich. Viel mehr Code als das, was ich gepostet habe, gibt es
gar nicht.
Ist ein mini Testprogramm, welches zunächst erstmal nur diese eine
Aufgabe erfüllen soll.
Im setup findet man noch diese drei Zeilen:
1
CLKPR|=(1<<CLKPCE);// Aktivieren der Taktprescaler-Änderung
2
CLKPR=(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);// Setzen auf 8 MHz ohne Prescaler
3
OSCCAL=0x89;
mehr ist es nicht...
Was die Wahl des Controllers angeht, das ist leider durch die Hardware
vorgegeben. Um den tiny85 komme ich nicht herum. Da ich normalerweise
auf andere Typen setze und dies meine erste Berührung mit dem Tiny85
ist, kenne ich natürlich auch seine Eigenarten nicht. Ist also gut
möglich, dass ich das völlig falsch angehe und/oder wesentliches
vergessen habe.
Hi
>und dies meine erste Berührung mit dem Tiny85>ist, kenne ich natürlich auch seine Eigenarten nicht.
Faule Ausrede. Wozu gibt es Datenblätter. Und sogar noch von Atmel!
MfG Spess
Du wirst lachen, aber ich habe tatsächlich das Datenblatt zu Rate
gezogen. Dennoch funktioniert es nicht.
Aber vielen Dank für Deinen hilfreichen Beitrag.
Matthias H. schrieb:> Ja, natürlich. Viel mehr Code als das, was ich gepostet habe, gibt es> gar nicht.
Umso einfacher ist es, den Quelltext VOLLSTÄNDIG und im ORIGINAL hier
beizustellen! Du wärst nicht der Erste, der beim Kopieren oder gar
ABSCHREIBEN einen Fehler einbaut.
Man sieht auch nirgends ein sei().
Die Fuses sind bestimmt auch noch interessant. Die also auch gleich noch
auslesen und posten.
Ist die Frage ob es gut ist irgendwie am Takt zu drehen wenn deine
Arduino Lib von etwas anderem ausgeht.
Keine Ahnung ob man der das im Nachhinein mitteilen kann oder ob das
Fest ist.
Wenn das nicht der Defaultwert ist, ist mir klar warum keine Zeiten mehr
passen.
Also evtl Mal alles zurück auf Anfang und NICHT am Takt drehen.
Vielleicht geht's dann. Wäre ein einfacher Test.
Zuerst würde ich mal einen 16-Bit Timer aufsetzen. Das machst du mit dem
Timer Overflow Interrupt, der das obere Byte hochzählt. Zusammengesetzt
mit dem CNT des Timers hast du dann einen 16 Bit Timer. Das kannste
kaskadieren und noch ein Byte hochzählen, wenn du Werte mit mehr als
65535 µs erwartest.
Im flankengesteuerten Interrupt liest du alle 3 Bytes (High, Mid, CNT)
aus und speicherst sie an einen Safeplace. Alles löschen und den Timer
wieder mit 1µs Zykluszeit starten (Prescaler 8).
Damit ist der Arduino Timer raus und du bekommst ganz gute Werte.
Das Ergebnis ergibt sich aus (65536 x High) + (256 x Mid) + CNT.
Der Code sieht prinzipiell o.k. aus.
Es könnte sein, daß Dir die Dauer der seriellen Ausgabe in die Suppe
spuckt.
Ich würde daher die Zeitermittlung direkt im Interrupt machen.
Dabei nicht vergessen, die Übernahme des Wertes in der Loop atomar zu
kapseln.
Dein Generator liefert 5V Rechteck?
Matthias S. schrieb:> Zuerst würde ich mal einen 16-Bit Timer aufsetzen. Das machst du> mit dem> Timer Overflow Interrupt, der das obere Byte hochzählt. Zusammengesetzt> mit dem CNT des Timers hast du dann einen 16 Bit Timer. Das kannste> kaskadieren und noch ein Byte hochzählen, wenn du Werte mit mehr als> 65535 µs erwartest.
Es reicht, die Überläufe mit 32 Bit zu zählen,
1
ISR(TIMER1_OVF_vect)
2
{
3
ueberlauf++;// grobe Zeitmessung mit T1
4
}
und den Wert des 8 Bit Timers dazuzupacken:
1
temp_ueberlauf=ueberlauf;// ueberlauf++ per ISR
2
if(TIFR&BIT(TOV1)&&(TCNT1<0x80))// noch einer offen?
3
temp_ueberlauf++;// dann +1
4
zeitpunkt=temp_ueberlauf*0x100+TCNT1;
Mario M. schrieb:> Dein ssPrintln kann nur 16 Bits.
Dann vielleicht in zwei Hälften ausgeben.
Mi N. schrieb:> Matthias S. schrieb:>> Es reicht, die Überläufe mit 32 Bit zu zählen,ISR (TIMER1_OVF_vect)> {> ueberlauf++; // grobe Zeitmessung mit T1> }> und den Wert des 8 Bit Timers dazuzupacken:temp_ueberlauf = ueberlauf;> // ueberlauf++ per ISR> if(TIFR & BIT(TOV1) && (TCNT1 < 0x80)) // noch einer offen?> temp_ueberlauf++; // dann +1> zeitpunkt = temp_ueberlauf * 0x100 + TCNT1;
Habe das mal so umgesetzt. Habe das Ergebnis erstmal geteilt und
ausgegeben.
32
21
-1
-23
-24
84
-54
51
-23
-23
78
-28
-16
Peter D. schrieb:> Dein Generator liefert 5V Rechteck?
Ja, der liefert ein Rechteck. HighLevel 5,0V ; LowLevel 0mV ; 15Hz
Ich sehe da mehrere Probleme.
#define SENSOR PB2 // pin7
#define LED PB4 // pin3
pinMode (SENSOR, INPUT);
pinMode (LED, OUTPUT);
Das geht so nicht. Die digitalen Ios sind in der Arduino-Welt mit
Nummern versehen, also 1, 2,3,4. PB2 und PB4 sind Namen der "normalen"
avr gcc Welt. Die funktionieren nicht mit der Funktion pinMode() bzw.
man schaltet die falschen IOs.
Wenn deine komische ssPrintln() Funtkion nur 16 Bit ausgeben kann,
probier's mal so.
ssPrintln(us/10);
Ein sei() wird bei Arduino nicht benötigt, denn in der setup-Funktion
sind die Interrupts schon aktiv, das macht die Arduino-Software vorher.
Sie schadet aber auch nicht.
Matthias H. schrieb:> Habe das mal so umgesetzt. Habe das Ergebnis erstmal geteilt und> ausgegeben.>> 32> 21> -1> -23
Kleine Werte sind es ja, aber was Du da gemacht hast, sehe ich nicht.
Es ist vielleicht etwas der Holzhammer, aber die Tage hatte ich hier das
vollständige Programm gezeigt und nicht nur die obigen Schnipsel:
Beitrag "Re: Analoges Fahrrad-Tachymeter mit Dynamo betreiben"
Da wird alles in den Interruptroutinen erledigt und ein PCINT-Pin
verwendet. Die Auswertung in loop() ist immer eine schlechte Idee!
Wenn Du die Endung auf .ino änderst, sollte Arduino das auch Übersetzen
können. Selbst habe ich es nicht probiert.