Den Timer mal mit'm Oszi messen ist eine super Idee. Das werde ich gleich mal machen!
Welche Abweichung? Klingt irgendwie unlogisch und verdächtig - ich bring das Auto zum Schleudern und wunder mich nachher, dass es nicht geradeaus fährt.Zitat von helipaddi
Meine ursprüngliche Vermutung ist also richtig.Zitat von oberallgeier
Vorschlag: Zu Beginn der ISR - VOR der Abspeichergeschichte - einen Port einschalten (dazu gibts bei mir IMMER eine TestLED) und vor dem RETI diesen Port ausschalten. Oskar dranhalten und anschauen, wie lange die ISR dauert. Damit habe ich sehr viele ISR auf die Laufzeit überprüft - auch wenn der Controller vor- und nachher noch etliche organisatorische Dinge einfügt (Register retten und so).
Ciao sagt der JoeamBerg
Den Timer mal mit'm Oszi messen ist eine super Idee. Das werde ich gleich mal machen!
Das Schreiben auf die SD-karte und das LCD Display könnte schon etwas zu lange dauern, zumindest bei 50 Hz. Wenn man die Rate reduziert sollte es dann aber irgendwann funktionieren. Idealerweise schreibe man nicht jeden Datensatz aufs LCD, denn schneller als etwa 3-5 Hz kann man nicht ablesen. Auch das schreiben aufs LCD sollte man eher ins Hauptprogramm verlegen, oder aufgeteilt in kleine Häppchen in eine andere ISR.
Das Schreiben auf die SD Karte sollte wenn möglich außerhalb der ISR ablaufen, denn das kann im ungünstigen Fall lange dauern. Es ist auch nicht klar wie die Routinen geschreiben sind. Je nach Aufbau, kann es Probleme in der ISR oder außerhalb geben.
Kleiner Tipp wie man solche Probleme auch ohne Oszi erkennen kann:
Bei diesem Code wird ErrCnt um 1 inkrementiert falls ein Interrupt ausgelöst wird, bevor die Datenverarbeitung abgeschlossen ist.Code:bool bNewData = false; uint8_t ErrCnt = 0; void ISR() { if (!bNewData) bNewData = true; else ErrCnt++; } void main() { while(1) { if (bNewData) { // Hier Daten abholen und auf SD-Karte speichern ... // Dann Flag zurücksetzen bNewData = false; } } }
Auf dem Display könntest du dann z.B. ausgeben lassen wie viele Interrupts pro Sekunde du "verpasst" weil das Speichern zu lange dauert. Ist der Wert größer als 0, könnte ein Ringpuffer (FIFO) eventuell Abhilfe schaffen.
So viele Treppen und so wenig Zeit!
Erstmal vielen Dank für eure Tipps! Werde es mal austesten und dann berichten.
Meint ihr es ist sinnvoll, statt 9 mal die Funktion zum schreiben auf die SD aufzurufen erst alles zu einen String zusammen zu fassen und dann komplett auf die Karte zu schreiben? Komme leider aus der C# Welt und da macht man sich nicht so viele Gedanken über die Performance...
EDIT: Benutze übrigends diese SD Lib:
http://www.mikrocontroller.net/articles/AVR_FAT32
Das kann durchaus sinnvoll sein, viele Speichermedien sind beim Schreiben von großen Datenblöcken am Stück schneller. Wie das bei SD-Karten ist kann ich dir allerdings nicht sagen, da ich selbst bisher noch keine verwendet habe.Zitat von helipaddi
Der von mir angesprochene Ringpuffer kann dir bei sowas übrigens auch helfen:
Die ISR muss nur die Werte auslesen und im Puffer speichern, was natürlich möglichst schnell erfolgen sollte (wie werden die Werte eingelesen?). Und die Hauptschleife entleert den Puffer in regelmässigen Abständen, oder sobald er voll genug ist, auf die SD-Karte.Code:void ISR() { // Daten abholen und in Ringpuffer speichern } void main() { while(1) { if (Ringpuffer Füllstand > 0) { if ((Ringpuffer Füllstand > x) || (mehr als y Sekunden seit letztem Speichern)) { Gesamten Inhalt des Ringpuffers auf SD-Karte schreiben } } } }
Alternativ zu dieser Implementierung kann man es auch wieder so machen wie in meinem ersten Beispiel, also in der ISR nur ein Flag setzen. In diesem Fall hätte man in der Hauptschleife einen Teil der mit der ISR synchronisiert ist und in dem die Daten abgeholt werden, und einen Teil der asynchron nebenher läuft und die Daten bei Gelegenheit auf die SD-Karte schreibt.
edit:
das schaut dann etwa so aus
Code:void ISR() { if (!bNewData) bNewData = true; else ErrCnt++; } void main() { while(1) { if (bNewData) // ISR synchron { // Daten abholen und in Ringpuffer speichern bNewData = false; } if (Ringpuffer Füllstand > 0) // asynchron { if ((Ringpuffer Füllstand > x) || (mehr als y Sekunden seit letztem Speichern)) { // Gesamten Inhalt des Ringpuffers auf SD-Karte schreiben } } } }
So viele Treppen und so wenig Zeit!
Die Werte kommen als PWM mit einer Frequenz von ca. 50hz in den MC. Ist übrigens ein RC Servo Signal. Da die Funktion zum messen daher eventuell 22ms braucht (20ms bis das HIGH kommt und 2ms bis wieder LOW kommt) habe ich diese ausgelagert.wie werden die Werte eingelesen?
Die Werte werden also in main() gemessen?
Na das ist doch optimal, denn dann läuft der Teil ja ohnehin schon asynchron nebenher. Wenn man das dann mit dem Speichern genauso macht, sollte man die Daten auch irgendwie auf die SD-Karte geschaufelt kriegen, ohne Interrupts zu verlieren.
So viele Treppen und so wenig Zeit!
Genau, sollte funktionieren Bin gerade mal deine Vorschlaege am einbauen!Zitat von Felix G
Die Herausforderung beim Speichern ist eigentlich, dass die einzelnen Datensätze genau mit 25hz auf die Karte müssen. Diese werden nämlich später mit Hilfe von FFMPEG zu einer Videodatei, welche mit 25hz abgespielt wird, zusammen gesetzt. Und da sollte alles synchron sein.
Aber mit einem Timer der genau läuft sollte dies ja kein Problem sein
Es sollte nicht so wichtig sein, wann die Daten geschreiben werden, wichtig ist vielmehr, wann die Daten gemesser werden, und das genau die Richtige Zahl an Daten geschreiben wird, also nichts ausgelassen wird.
Es wäre besser das schreiben auf die Karte ins Hauptprogramm zu verlegen, und die Messung in den Interrupt. Die Messung sollte dann aber nicht durchgängig Warten, sondern nur bei Flanken je einen kurzen Interrupt auslösen.
Lesezeichen