Hallo,
hat schon jemand den kaskadierten 32Bit Timer ausprobiert und zum laufen
gebracht? Bei mir zählt der MSB entweder gar nicht oder er läuft durch.
Es wird nichts ins CCMP kopiert. Eigentlich soll TCB1 übers Eventsystem
nur die Overflows von TCB0 zählen.
Was gar nicht funktioniert ist, wenn ich LSB (TCB0) statt in TCB0.CTRLB
= TCB_CNTMODE_PW_gc in TCB_CNTMODE_CAPT_gc konfiguriere, laut Manual
wäre das zwar richtig, aber dann zählt gar nichts mehr. Laut meiner
Logik muss TCB0 in TCB_CNTMODE_PW_gc konfiguriert sein, ansonsten misst
der nicht die gewünschte Pulsweite.
Ich frage mich auch wofür die CASCADE Einstellung gut ist, wenn man
übers Eventsystem den Timer sagt das er die Overflows von TCB0 zählen
soll, er bleibt ja ein 16Bit Zähler.
Der Interrupt von TCB0 reagiert immer auf die fallende Flanke vom Puls.
Der Interrupt von TCB1 reagiert immer auf die steigende Flanke vom Puls.
Laut meiner Logik müßten beide auf die fallende Flanke reagieren, weil
dann übers Eventsystem der Capture Interrupt ausgelöst wird und beide
Timer ihren Zählerstand in ihr CCMP Register kopieren. Beim TCB1 klappt
das nicht.
Ich werde aus der Beschreibung im Manual nicht schlau.
Könnte bitte jemand Hinweise geben?
Irgendwas muss in der Timer- und/oder Eventkonfiguration falsch sein.
1
/*
2
Arduino IDE 1.8.13
3
AVR128DB48 Curiosity Nano Board
4
https://github.com/SpenceKonde/DxCore
5
32Bit Counter
6
Takteingang Pin PA4
7
Interruptmesspin für Oszi PB3 und PC3
8
*/
9
10
#include<avr/io.h>
11
#include<avr/interrupt.h>
12
#include<util/atomic.h>
13
14
volatileunsignedlongcountTimerTCB0;
15
volatileunsignedlongcountTimerTCB1;
16
volatileunsignedlongcountTimerCCMP_LSB;
17
volatileunsignedlongcountTimerCCMP_MSB;
18
volatileunsignedlongcountTimerTotal;
19
boolfinishTCB0=false;
20
boolfinishTCB1=false;
21
22
constbytepinLedTCB0Int=11;// PB3 onboardLed
23
constbytepinLedTCB1Int=17;// PC3
24
25
voidsetup(void)
26
{
27
Serial1.begin(115200);// Package Pin 10/11 bzw. PC0/PC1, Tx/Rx
Für den Augenblick ist mir das alles zu umfangreich, vielleicht setze
ich mich später in Ruhe dran; vorab nur: ich hatte das mal für den
AVR128DA28 gemacht, die Initialisierung finden Sie in der Anlage
(Assembler, natürlich, können Sie ja aber lesen&verstehen), so ad hoc
sehe ich keinen Unterschied zu Ihrer. Unklar ist mir, weshalb Sie zwei
ISR verwenden, ich habe nur eine, in welcher die 2*2 Bytes ausgelesen
werden.
Hallo,
ich hatte am Anfang auch nur eine ISR vom TCB0. Weil das zu keinem
Ergebnis führte, habe ich eine ISR für TCB1 eingebaut, mit dem Ziel das
beim Capture Event der Zählerstand zum richtigen Zeitpunkt ins CCMP
kopiert und ausgelesen werden kann. Ich schau mir deinen Code an. Danke
vorab. Wird eine Weile dauern.
Edit:
dein Code sieht sehr übersichtlich aus, könnte doch schneller gehen ...
Tja, auch der zweite Blick bringt keine Erleuchtung, außer vielleicht,
dass ich nur eine einzige Interruptquelle habe, nämlich TCB0-Capture,
Sie hingegen sogar drei.
Ich werde nachher mal mein Programm auf den AVR128DB48 bringen, das
kann aber, nun bei mir, eine Weile dauern.
Hallo,
> Wo steht in Ihrem Programm eigentlich das Pendant zu sei?
Das ist bei Arduino standardmäßig im Hintergrund eingeschalten. Da muss
ich immer daran denken wenn ich in AS programmiere, wie letztens.
Bei mir läuft es leider noch nicht. Der TCB0 Interrupt kommt jetzt bei
steigender Messflanke statt bei fallender. Und beide Timer laufen durch,
es wird kein Zählerstand ins CCMP kopiert. Habe mal den Code aufgeräumt.
Habe auch schon alle Timer Register vorher genullt, falls Arduino
Timervoreinstellungen dazwischen funken, wobei laut Beschreibung Timer
TCB0 und TCB 1 sowieso frei sein sollten. Falls dir hier nichts
auffällt, dann muss ich alles erst ins Atmel Studio "schieben" ohne
Arduino Komfortzone.
(Eingangspin auf PA7 geändert)
1
/*
2
Arduino IDE 1.8.13
3
AVR128DB48 Curiosity Nano Board
4
https://github.com/SpenceKonde/DxCore
5
32Bit Counter
6
Takteingang Pin PA7
7
Interruptmesspin für Oszi PB3
8
*/
9
10
#include<avr/io.h>
11
#include<avr/interrupt.h>
12
#include<util/atomic.h>
13
14
volatileunsignedlongcountTimerTCB0;
15
volatileunsignedlongcountTimerTCB1;
16
volatileunsignedlongcountTimerCCMP_LSB;
17
volatileunsignedlongcountTimerCCMP_MSB;
18
volatileunsignedlongcountTimerTotal;
19
boolfinishTCB0=false;
20
21
constbytepinLedTCB0Int=11;// PB3 onboardLed
22
23
voidsetup(void)
24
{
25
Serial1.begin(115200);// Package Pin 10/11 bzw. PC0/PC1, Tx/Rx
Ich sehe keinen Fehler, es scheint meinem Programm zu entsprechen; ich
kann nur vorschlagen, erstmal auf die Arduino-Umgebung zu verzichten
(wusste gar nicht, dass die schon mit der AVR-Dx-Serie arbeiten kann).
Hallo,
Danke fürs prüfen. Dann mach ich das erstmal in Atmel Studio startklar.
In der Arduino IDE läuft das nur, weil User 'SpenceKonde' so fleißig war
und eine Boarderweiterung geschrieben hat. Genauso wie MCUdude für die
megaAVR0 Serie. Ich spreche an der Stelle beiden meinen herzlichsten
Dank aus.
https://github.com/MCUdude/MegaCoreXhttps://github.com/SpenceKonde/DxCore
Sind ähnlich in der Handhabung, aber doch ein klein wenig verschieden.
Bei SpenceKonde kann man noch nicht über USB wie gewohnt flashen. Da bin
ich den Weg übers .hex File per Drag and Drop kopieren aufs Board
Laufwerk gegangen.
Ich melde mich wieder ...
Könnten Sie mal ein paar Zeilen der Ausgabe zeigen?
Also ich versteh's nicht, wenn die ISR mit Capture Interrupt
angesprungen wird, dann muss doch etwas in den ..CCMP.. stehen.
Hallo,
volatile, ja stimmt finishTCB0 muss auch volatile sein. Mit Daten muss
ich dich vertrösten, war gerade am Tisch "aufräumen" und habe wohl mein
Board zerstört. Da muss ich dich auf morgen verdrösten. Leider. Ärgere
mich selbst, gerade jetzt wo es spannend wird. Ich kann das Board zwar
mittlerweile wieder flashen, aber es tut sich nichts mehr.
Die drei anderen schon verkauft? - Prima.
Wie lässt doch Spoerl den Pfeiffer imitieren: "Ech ben ein alter Mann
und gähe leber fröh ins Bette". Also Gute Nacht.
Hallo,
noch sind keine verkauft zum Glück. :-) Wären die verkauft hätte ich
noch 2 in Reserve gehabt. Morgen nochmal ganz in Ruhe von vorn. Für
heute ist erstmal genug. :-) Danke soweit fürs mitmachen.
Hallo,
kurze Rückmeldung, habs mir nicht nehmen lassen heute früh nochmal zu
testen. Kurzfassung ist, Pin PA7 habe ich wahrscheinlich irgendwie
abgeschossen. Teste ich irgendwann nochmal genauer. Nehme ich wieder PA4
funktioniert erstmal technisch alles. Soweit so gut.
Einen Unterschied gibts zwischen unseren Timereinstellungen. Mein TCB0
steht auf CTRLB Countermode Pulsweitenmessung. Aber das wusstest du ja
bestimmt schon.
Anbei noch die Ausgaben von hterm mit meinen und deinen Einstellungen.
Einmal bleibt TCB0/LSB konstant und beim anderen nicht. Konstant wäre
ok. Das begründe ich erstmal mit der CTRLB Einstellung. TCB1/MSB zählt
immer munter hoch, bekommt demnach kein Capture Event mitgeteilt, laut
meiner Überlegung.
Heute Abend mach ich mich an die Atmel Studio Umsetzung ran.
> zählt immer munter hoch
Logisch, was sonst bei Capture?
> Konstant wäre ok
Dafür müssen Sie etwas tun, nämlich die Differenz der Capture-Werte
zwischen zwei Ereignissen berechnen.
Mir scheint, da liegt ein grundlegendes Missverständnis vor; vermutlich
eine Verwechslung mit dem Modus 'Pulsweitenmessung'.
Hallo,
eigentlich möchte ich nichts extra berechnen, weil der Pulsweiten
Messmodus das alles selbst erledigt. Er reagiert selbstständig auf die
Flanke (je nach Edge Einstellung) und kopiert den Zählerstand in sein
CCMP Register. Bei der nächster Start-Flanke wird der Timercounter
genullt und wieder gezählt. So funktionierte das schon einwandfrei mit
einem TCB.
32Bit Counter:
Dann kam mir noch eine Idee, weil der TCB1 irgendwie falsch reagiert.
Kurzerhand TCB1 auch in den "Input Capture Pulse-Width Measurement mode"
gesetzt und ... funktioniert. :-)
So eine ganz schlüssige Erklärung von hinten aufgezäunt habe ich noch
nicht. Ich weiß laut Manual nur das ...
EVCTRL:
Input Capture on Event mode: löst Interrupt an rissing edge aus
Input Capture Pulse-Width Measurement mode: nullt Counter bei rissing
edge und löst Interrupt bei falling edge aus oder umgekehrt je nach Edge
Einstellung
INTFLAGS:
Im CAPT Interrupt wird bei beiden Modi der Zählerstand ins CCMP kopiert.
Im Nachgang betrachtet hat er schon immer die Zählerstände ins CCMP
kopiert. Das durchlaufen des Zählers hatte mich irretiert.
Jetzt bleibt nur die Frage offen, warum TCB1 jetzt richtig zählt und
nicht intern die Pulsweite vom OVF Signal vermisst? Hängt scheinbar mit
dem Event System zusammen. Auf der einen Seite freut es mich das es
funktioniert. Auf der anderen Seite fehlt mir noch die endgültige Logik
dafür warum es so funktioniert wie es funktioniert.
1Hz, 3/4 DutyCycle.
> der Pulsweiten Messmodus das alles selbst erledigt
Schon, aber nicht mit 32 bit.
> und ... funktioniert. :-)
"With a few stupid exceptions, of course" - extrem selten, aber
trotzdem; aus dem Datenblatt:
24.5.1 Control A
Bit 5 – CASCADE Cascade Two Timer/Counters ...
... delayed by one peripheral clock cycle. This compensates ...
Hallo,
es wäre schon blöd wenn der 32Bit Counter nur im CAPT Mode funktionieren
würde, zumindestens offiziell. Habe ich ein Secret gefunden? :-)
Habe mal spassenshalber TCB0 nicht enabled. Der Interrupt von TCB1
reagiert immer noch. Aber alle Counterwerte bleiben 0. TCB1 reagiert
demnach auf den Eingangstakt bedingt durch den PW Mode, kann aber keine
OVF Events zählen, weil vom TCB0 nichts kommt. Wäre erstmal logisch
gesehen korrekt.
Würde mir das derzeit so erklären, dass der CountMode (EVCTRL) nur den
Zähler beeinflusst, wann er startet/stoppt und wann er genullt wird. Was
er zählt wird von Clock Select vorgegeben. Das ist auf Event eingestellt
und reagiert laut Beschreibung nur auf die steigende Flanke. Das ist
mittels Event System mit dem TCB0 Overflow Ausgang verbunden. Vielleicht
klappt das dadurch, weil er hier nicht auf die fallende Flanke reagiert.
Am Ende sagt das Capture Eventsystem zusammen mit dem Interrupts beiden
Timern, dass bei abgeschlossener Pulsweitenerkennung jetzt die
Zählerstände kopiert und die Zähler bei der nächsten Flanke genullt
werden.
Sollte an einer plausiblen Erklärung zumindestens nah dran sein. :-)
> es wäre schon blöd ...
Dem stimme ich zu; und nach erneutem Durchlesen der Datenblattstellen
neige ich auch zu der Ansicht, dass es in den 'Measurement modes'
funktionieren sollte.
Hallo,
32Bit Counter - Pulsweite messen - die Zweite. :-)
Nachdem die Kaskadierung erfolgreich abgeschlossen war wollte ich es
ohne Kaskadierung wissen. Also Overflows zählen und ggf. Ergebnis
korrigieren. Sprich das hier anwenden
Beitrag "Timer Overflow Counter - Wie richtig berücksichtigen?" Warum überhaupt? Damit
man alle TCBn Timer frei hat bzw. hätte.
Problem dabei war, dass im Interrupt der eigentliche Timercounter
ungleich dem Capture Count ist. Denn der Timer läuft bis zur nächsten zu
vermessenden Signal-Startflanke weiter. Erst dabei wird er genullt.
Zudem gibt es keine getrennten Interrupt Vectoren. Man muss also den
ausgelösten Timer Interrupt ermitteln. Ob das jetzt ein Vorteil oder
Nachteil ist wage ich mich nicht zu beurteilen. Beim Overflow filtern
war ich gezwungen andere Wege zu gehen.
Ich musste vom Signaleingang zusätzlich einen Interrupt anlegen um den
Overflow Zähler sicher zu nullen und einen noch alten anstehenden OVF zu
löschen. Damit die nächste Zählung stimmt. Danach galt es die Overflow
Addition im Timer Interrupt zu unterdrücken, wenn ein Capture Interrupt
aktiv und zeitgleich der ausgelesene Capture Zähler im Endbereich liegt.
Also kurz vorm eigenen Überlauf steht.
Hat mich eine Woche Nerven "gekostet". :-)
Bis dahin hatte ich, wenn die Capture Zählung auf Überlauf Kippe stand,
alles dabei. Von Ergebnis 0 bis 131071, obwohl es entweder 65535/65536
sein muss. 1 Takt Restungenauigkeit.
Taktquelle/Signalquelle ist ein ATmega328PB mit 16MHz Quarz, der
glücklicherweise einen Hauch langsamer läuft, sodass ich mit einem CTC
Timer mit Prescaler 1 und im Bereich 65528 - 65531 meinen OVF Kipp-Punkt
provozierbar testen konnte. Wer Verbesserungen am Code sieht ... immer
raus damit. Ich weiß nicht ob man die Bedingung für die Overflow
Addition noch besser schreiben kann. Wenn es jemand testen könnte wäre
ich auch dankbar.
Edit: habs als Datei angehangen statt Text.
Hallo,
ich hatte noch bei Microchip nachgefragt bzw. hingewiesen. Das dauerte
etwas mit hin und her. Ich wollte wissen ob die 32Bit Counter
Funktionalität im "Input Capture Pulse-Width Measurement Mode" Zufall
ist oder nur vergessen wurde im Manual zu erwähnen. Das wurde dann ans
internal Team weitergeleitet. Die ernüchternde Antwort lautet nun. Geht
nicht. Der 32 Bit Counter funktioniert nur im “Input Capture on Event"
Mode.
Hmmm, ich hatte extra meinen Code mitgeliefert damit die das prüfen und
nachvollziehen können. Jetzt stehe ich wieder am Anfang und weiß immer
noch nicht ob es zufällig im PW Mode funktioniert oder nur im Manual
vergessen wurde. An Zufälle glaube ich jedoch weniger. :-) Ich denke
das wird die Zeit zeigen. Oder jemand anders testet das bei sich in Ruhe
wenn er Muse hat.
Meine Vermutung ist, dass es daran liegt:
Beitrag "Re: AVR128DB48 - TCB 32Bit Counter"
Mittlerweile nutze ich diese Funktionalität auch, aber nur für eine
fortlaufende Anzeige, und wenn da alle Schaltjahre mal eine Fehlanzeige
auftritt, bemerke ich das gar nicht.
Hallo Veit Devil,
es ist so, ich kann das Problem jetzt erzeugen: wenn die zu messende
Pulsbreite im Bereich 0000FFFF und 00010000 liegt, treten Fehler auf,
gemessen wird 0001FFFF oder auch 00000001.
Hallo,
den TCA zu nutzen war auch meine Idee, wegen Syncronität. :-)
Es kam gestern noch etwas dazwischen und danach konnte ich das Problem
nicht nachvollziehen. Seltsamerweise kann ich es heute mit verschiedenen
TCA Takteinstellungen auch nicht nachvollziehen. Der 32Bit TCB misst
exakt das was er soll. Ich lasse mir mit 1MBaud LSB, MSB und Total
seriell ausgeben, mit 4ms Pause bremst die nichts aus, sodass ich jede
Pulsmessung angezeigt bekomme. Ich werde nochmal einen externen Takt
anklemmen der dann bedingt immer leicht pendelt, vielleicht sehe ich da
etwas ...
Guten Morgen, Veit Devil,
ich vermute, dass ein externer Takt nur sehr selten den Fall zeigt;
arbeitet man nicht phasenstarr, wird es schwer, diesen einen Systemtakt
zu erwischen, in dem das Event-System das Carry weitergibt.
Im Anhang finden Sie einen größeren Ausschnitt meines Testprogramms,
vielleicht stellen Sie Ihres auch vor. Ich weiß aber nicht, ob ich vor
dem Nachmittag noch dazu komme, mir es auf Unterschiede hin
durchzusehen.
Hallo,
wie oft tritt der Messfehler bei dir auf? Jede Sekunde? Aller paar
Sekunden?
Mit externen Takt habe ich genau die Messschwelle zwischen 65535 und
65536 getroffen. Das Ergebnis pendelt sehr oft zwischen 65535 und 65536
ohne Ausreißer. Das kann ich Minutenlang beobachten.
Ich muss dann auch nochmal weg. Den vom debuggen bereinigten Code zeige
ich selbstverständlich.
Und mach dir keinen Kopf wegen Antwortzeiten. Alles gut. Das Forum ist
schließlich kein Chat. :-)
Hallo,
okay. Ich glaube der Hauptunterschied zwischen unserem Code ist, dass
ich den Interrupt beider Timer zum Zählerstand auslesen verwende. Wie
stellst du fest das beide Timer einen zusammengehörigen neuen Wert
haben? Ich habe nochmal mit 32767 und 32768 probiert. Alles stabil.
Okay, ich hatte es eben schon vermutet, und Ihr Programm bestätigt es:
der Unterschied ist das 'Input Capture Noise Cancellation Filter' im
TCB0_EVCTRL; wenn ich das bei mir abschalte, sehe ich keine Fehler mehr.
Ich bin aber nicht ganz sicher, ob damit das Problem vom Tisch ist.
> Wie stellst du fest ...
Verstehe ich jetzt nicht - es gibt ein Capture-Event, und auf dieses
frage ich TCB0_INTFLAGS ab, danach muss der komplette 32-bit-Wert
verfügbar sein.
Auf die Idee, zwei ISR dafür zu verwenden, kam ich gar nicht. Alles
Weitere später.
Hallo,
mit aktivierten Noise Filter kann ich den Messfehler nachvollziehen. Er
ist dann auch immer vorhanden. Wegen dem TCB0_INTFLAGS, ja okay,
funktioniert auch. Der Capture Event Input wirkt ja auf beide Timer. Ich
habe da Netz und doppelten Boden. :-)
Warum der Filter so eine seltsame Wirkung zeigt? Mal sehen ob man das
aufklären kann.
> Filter für beide Timer aktiviert ...
In der Tat, das hatte ich übersehen.
Dann scheint es wirklich so, als hätten Sie Recht, und es bleibt die
Frage, weshalb Microchip eine gegenteilige Auskunft gibt.
Bleibt mir nur noch, Ihnen ein schönes Wochenende zu wünschen.
Hallo,
ich habe daraufhin nochmal bei Microship nachgefragt was laut ihrer
Meinung bzw. ihres Wissens das Problem ist wenn man einen anderen Modi
verwendet. Welcher Fehler daraus resultieren würde. Bisher heißt es ja
nur kurz "geht nicht". Ich werde berichten.
Wünsche ebenfalls schönes Wochenende.
Hallo,
ich konnte es nicht lassen auch noch den Frequenz und
Frequenz-Pulsweiten Modus zu testen. Du kennst die Antwort.
Funktioniert. :-)
Ich kann auch in der Theorie kein Problem erkennen. Man konfiguriert
beide Timer mit gleichen Modus. Damit reagiert jeder Timer exakt gleich
auf das Event. Demzufolge sichert jeder Timer seinen Zähler zum
richtigen Zeitpunkt ins CCMP bzw. der CNT bleibt stehen. Was der MSB
Timer eigentlich zählt kann ihm auch egal sein, der zählt das was man
ihm übers Event System ankoppelt. Da kann gar nichts schiefen gehen.
:-) Bin gespannt was Microship antwortet.
Das als letzte Anmerkung zum Wochenende.
"We have got confirmation from our design team. You are correct, the 32-bit Input Capture works for all 4 Input Capture modes. Thank you for bringing this to us and we shall update the datasheet accordingly to clarify in the future."
Glückwunsch, bzw: Congratulation!
"... there may be little you can do about it, but at least you can try.
Squawk. Nag. Cajole. Remind. Phone. Write memos. Keep in mind that to
get anything done in this world, you often must be willing to be a bit
obnoxious."
Ediwn C. Bliss