Forum: Mikrocontroller und Digitale Elektronik Parallelisierung auf µController


von Martin (Gast)


Lesenswert?

Moin, moin,

ich stehe gerade vor einem Timingproblem. Ich muss Messwerte samplen und 
diese auf einem Speichermedium hinterlegen. Aufgrund der hohen 
geforderten Abtastung der Sensoren komme ich jetzt in den kritischen 
Bereich. Damit meine ich, dass Schreiben der Daten dauert länger als der 
zeitliche Abstand zwischen zwei Abtastungen. Momentan habe ich die 
Firmware sequentiell implementiert. Dies bedeutet, während des 
Schreibvorgangs kann nicht gesamplet werden. Rein theoretisch könnte er 
während des Schreibvorgangs aber schon wieder neue Messwerte aufnehmen 
und temporär in einem alternierenden Ringbuffer halten.

Meine Frage ist jetzt, wie schafft man es am saubersten 
Prozesse(Messwererfassung vs. Messwertspeicherung) zu parallelisieren? 
Habt ihr hier schon Erfahrungen gesammelt? Welche eventuellen 
weitergehenden Module könnte ihr für die Lösung des Problems empfehlen?

Danke

von Detlev T. (detlevt)


Lesenswert?

Welchen Mikrocontroller willst du überhaupt einsetzen?

Wenn die Daten wirklich schneller ankommen als sie gespeichert werden 
können, nützt dir eine "Parallelisierung" allein auch nichts. Da 
brauchst du einen ausreichend großen Zwischenspeicher (z.B. RAM). Wie 
wäre es mit einem schnelleren Datenspeicher?

Tendenziell würde ich für so eine Aufgabe (zwei Prozesse) wohl noch 
keinen Scheduler etc. einsetzen, sondern eine der Aufgaben in eine 
Interrupt-Routine auslagern.

von Mike (Gast)


Lesenswert?

Hallo Martin,

die Parallelisierung auf einem Mikrocontroller lässt sich auf 
verschiedene Arten bewerkstelligen. Die einfachste ist die Verwendung 
von Interrupts, d.h. im Hauptprogramm läuft eine Schleife, die auf Daten 
wartet und, falls welche vorhanden sind auf das Medium speichert. Die 
Sensordaten werden von einer Interruptroutine eingelesen, die entweder 
durch einen äusseren Eingang immer dann getriggert wird, wenn der Sensor 
neue Daten hat, oder in regelmässigen Abständen durch einen Timer. 
Wichtig ist, dass die kurzen "Störungen" durch die Interruptroutine den 
Schreibvorgang nicht stören.

Eine Alternative wäre die Verwendung eines 
Multitasking-Echtzeitbetriebssystems, was in Deinem Fall aber 
wahrscheinlich mit Kanonen auf Spatzen geschossen wäre.

Leider ist es schwer, eine genauere Antwort zu geben, da ich die 
Anforderungen Deines Systems (Datenrate, zulässige Latenzzeit, Art des 
Speichermediums, verwendeter Controller, Taktfrequenz etc.) nicht kenne.

Gruss
Mike

von Sven (Gast)


Lesenswert?

> Rein theoretisch könnte er.....

Hilft so für eine Auskunft nix, wie wäre es mit konkreten
Angaben zu den Messwerten.

bsp. Wieviel Bit die Auflösung ?
Wieviel kb/s oder Mb/s an Messwerten welcher Controller, etc.

Gruß Sven

von yalu (Gast)


Lesenswert?

Über welche Schnittstelle werden die Messwerte gelesen? Wie hoch ist
die Samplingrate?

Du könntest die Messwerte vielleicht in einem Timer-Interrupt sampeln
und in den Ringpuffer schreiben. Das Hauptprogramm liest die Daten aus
dem Ringpuffer aus und speichert sie ab.

Wenn es sich um analoge Daten handelt und der Controller (wie bspw.
die AVRs) über einen periodischen ADC-Modus verfügt, kannst du auch
diesen verwenden. Jede abgeschlossene A/D-Umsetzung löst einen
Interrupt aus, in dem der Messwert in den Ringpuffer geschrieben wird.

von Martin (Gast)


Lesenswert?

Hallo,

also, ich habe verschiedenes an Sensorik. ADC, Porteingangänge und 
Sensorik über I2C-Bus. Im WorstCase sind es 14 Messkanäle. Die 
Abtastrate sollte für einzelne Sensoren bei 5kHz liegen. Ich habe einen 
ARM7 den ich mit 55MHz laufen lasse. Als Speichermedium habe ich eine 
SD-Karte. Messwerte werden als in eine FAT32 Datei geschrieben. Ich 
glaube aber, dass das FAT System ein Killer ist.

Gruss

von Jochen M. (taschenbuch)


Lesenswert?

Martin,

Wenn der zeitliche Flaschenhals das schreiben der Daten ist, dann nützen 
Dir auch Ints oder andere Tricks nichts. Auch ein Ringbuffer würde sich 
zukreiseln, wenn Du nicht mindestens genau so schnell schreiben wie 
lesen kannst.
Das geht nur, wenn Du zwischendurch Pausen beim Einlesen der Werte hast, 
in denen der Bufferinhalt geschrieben wird. Dann allerdings wäre ein 
Ringbuffer die richtige Wahl.

Und ja: FAT auf SD Karte ist garantiert der Killer. Ganz besonders, weil 
Du die physikalische Schreibzeit niemals kalkulieren kannst, die kann je 
nach allen möglichen Umständen immer anders sein, die Karte macht da was 
sie will.

Jochen Müller

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

5 kHz? Da sollten sich der Prozessor und die SD-Karte langweilen, du 
darfst nur nicht den Fehler machen jeden Messwert einzeln zu schreiben. 
Lies die Messwerte in einem Interrupt, schieb sie dort in einen FIFO 
(Ringpuffer), und schreib sie erst auf die Karte wenn sich ein paar 
ganze Blöcke (n*512 Byte) angesammelt haben. Wenn du für das Schreiben 
dann noch DMA verwendest hat der Prozessor überhaupt nichts mehr zu tun.

von Jochen M. (taschenbuch)


Lesenswert?

>>5 kHz? Da sollten sich der Prozessor und die SD-Karte langweilen,

Das klingt erstmal nach reichlich Zeit. Aber es sind nur weniger als 
1ms.
Und das ganze auch noch geteilt durch 14 Kanäle, wie der OP schrieb.
Mit FAT Verwaltung -von der niemand weiss wie gut die programmiert ist- 
schafft die SD-Karte das einfach nicht.

Und auf jeden Fall bleibt es dabei, dass das Timing Verhalten der SD 
nicht konkret zu kalkulieren ist.

Jochen Müller

von holger (Gast)


Lesenswert?

>>>5 kHz? Da sollten sich der Prozessor und die SD-Karte langweilen,

>Und das ganze auch noch geteilt durch 14 Kanäle, wie der OP schrieb.
>Mit FAT Verwaltung -von der niemand weiss wie gut die programmiert ist-
>schafft die SD-Karte das einfach nicht.

5kHz bei sagen wir mal 2 Byte pro Kanal. Ergibt 10kB/s pro Kanal.
Mal 14 also 140kB/s. Das machen fast alle Karten mit und der ARM
langweilt sich.

Folgendermassen sollte man das hinkriegen:

Nimm zwei Puffer a 1kB. Der Puffer1 wird per Interrupt gefüllt.
Wenn er voll ist wird auf Puffer2 umgeschaltet. Puffer1 wird dann
auf die Karte geschrieben. Das ganze immer im Wechsel.

Bei 1kB Puffer hast du 7.3ms Zeit Puffer1 auf die SD zu
schreiben bevor Puffer2 voll ist. Wenn das nicht reicht
nimmst halt 2kB pro Puffer. Sollte beim ARM kein Problem sein.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ja, das wäre die einfache Variante des Ringpuffers. Sollte völlig 
ausreichen, zumal man ja bei den meisten ARMs mehr als genug RAM zur 
Verfügung hat.

von Martin (Gast)


Lesenswert?

Hallo,

vielleicht nochmal vorab, jedes Samplepackage(auch bei nur einem 
Messkanal) besteht aus mindestens 14Byte(1Byte Paketlänge + 4Byte 
Prozessorticks + 4Byte Samplenumber + 1 Byte ChannelID + 2 Byte Data). 
Für die Anwendung ist die exakte Zeitzugehörigkeit extrem wichtig. 
Deshalb der gewaltige Overhead.

Die Thematik mit dem Ringpuffer habe ich schon implementiert. Wovor ich 
ein wenig abschrecke ist das Erstellen der Messpakete innerhalb der ISR. 
Sowas ist nach meinen bisherigen Erfahrungen eher kritisch.
Ich kann die Aussagen von "Jochen Müller" nur bestätigen. Habe schon 
einige Versuche mit SD und FAT gemacht. Die realle Datenrate ist 
zeitlich schwierig vorherzusagen. Ich benutze die FAT Library FatFS und 
erreiche in Abhängigkeit von der Buffergröße Datenraten von 100kB bis 
800kB. Es ist aber deutlich erkennbar, das während des Schreibvorgangs 
mitunder größere zeitliche Varianzen von bis zu 500ms erkennbar sind. 
Diese Dinge sind sporadisch, man erkennt also kein festes zeitliches 
Fenster.

Gruss

von Tom (Gast)


Lesenswert?

Da kannst du schon mal ausrechnen, wieviel RAM du brauchst:
5 kHz x 14 Samples x 14 Byte x 500ms Wartezeit = 500 kByte.
Solche großen Buffer lassen sich auch schön effizient auf eine SD-Karte 
schreiben.

von Andreas K. (a-k)


Lesenswert?

Wenn FAT, dann ja wohl weil ein PC die Daten irgendwann lesen soll. Denn 
sonst wäre FAT ja überflüssig und das Problem gegessen. Wobei man mit 
PCs sicherlich auch SDs ohne FAT-Format lesen kann.

Wenn also FAT sein muss, dass sollte es eine Variante sein, die nicht 
erst in der kritischen Phase die Allokation der Datenblöcke durchführen 
muss. Denn das ist der schwer vorhersehbare Teil davon. Das lässt sich 
beispielsweise machen, indem man die SD-Card vorher fest mit 
FAT-Verwaltung und einem einzigen sie komplett belegenden Containerfile 
formatiert. Die Daten liegen dann an bekannter Stelle sequentiell in dem 
Containerfile und damit an bekannter Stelle auf der SD-Card, und der 
Controller kann so schnell schreiben wie die Karte hergibt, weil er die 
FAT selber überhaupt nicht benötigt.

von holger (Gast)


Lesenswert?

>Es ist aber deutlich erkennbar, das während des Schreibvorgangs
>mitunder größere zeitliche Varianzen von bis zu 500ms erkennbar sind.
>Diese Dinge sind sporadisch, man erkennt also kein festes zeitliches
>Fenster.

Das kann ich jetzt leider nur bestätigen.
Ich hab mit 5 Karten mal die maximalen Busy Zeiten gemessen.
Auch mit FatFs (elm-chan) auf LPC2138.
Ging von 40ms bis 310ms.

Präzises Timing mit SD Karten ist unmöglich.

von Martin (Gast)


Lesenswert?

Moin, moin,

Die Aussage von Andreas ist richtig. Die Daten sollen hinterher am PC 
analysiert werden.

@a-k
Habe mal noch ein paar weitergehende Fragen zu deiner Antwort

>Wobei man mit
>PCs sicherlich auch SDs ohne FAT-Format lesen kann.

Welche Möglichkeiten siehst du hier?


>Das lässt sich
>beispielsweise machen, indem man die SD-Card vorher fest mit
>FAT-Verwaltung und einem einzigen sie komplett belegenden Containerfile
>formatiert.

Meinst du damit, dass man im Vorfeld z.B. eine Datei(data.txt) mit 30MB 
anlegt und dann die Messwerte in dieses File schreibt? Aber dann würde 
ich ja trotzdem wieder die FAT Library brauchen.


Wäre über Anregungen dankbar

Gruss

von Wolfgang Mües (Gast)


Lesenswert?

Wobei ich zu bedenken gebe, dass die Größe der einzelnen 
wegzuschreibenden Datenblöcke eine entscheidende Rolle für die 
Geschwindigkeit spielt. Ich habe neulich ein Paper gesehen, bei dem 
jemand das Verhalten genauer untersuchte. Die Schreibgeschwindigkeit 
stieg bis 64 KByte Blockgröße linear an und blieb dann konstant.

von Andreas K. (a-k)


Lesenswert?

Martin wrote:

> Welche Möglichkeiten siehst du hier?

Ich habe noch keine SDs so gelesen, aber das dürfte nicht anders sein 
als bei Floppy-Disks, und da habe ich das vor langer Zeit schon gemacht. 
Das File "\\.\A:" bezeichnet unter Windows die Floppy als Raw Device, 
d.h. formatfrei wird alles von vorne bis hinten gelesen. Allerdings 
werden sich diverse Microsoft-Tools dabei weigern, musst du ggf. mit 
eigenem Programm ran. Unter Linux ist es noch viel einfacher.

Will du darauf auch schreiben, musst du das Device allerdings dazu 
sperren: DosDevIOCtl(..., IOCTL_DISK, DSK_LOCKDRIVE, ...).

> Meinst du damit, dass man im Vorfeld z.B. eine Datei(data.txt) mit 30MB
> anlegt und dann die Messwerte in dieses File schreibt?

Im Grunde ja, aber ohne FAT-Lib.

Du würdest das File nicht jedesmal per FAT-Lib anlegen. Sondern ein 
einziges Mal in der Entwicklungsphase und daraus den Inhalt der so 
erzeugten Verwaltungsstrukturen der FAT gewinnen (Info zum 
FAT-Filesystem findet sich im Internet). Was sich auch per PC erledigen 
lässt, sie oben.

Diese Verwaltungsinformation besteht aus ein paar Blöcken vorneweg und 
der FAT selber, die dabei recht schematisch aussieht. Wenn dann ein SD 
Medium formatiert werden muss, schreibst du einfach diesen Kram exakt so 
drauf und hast damit ein FAT-formatiertes Medium von genau definiertem 
Inhalt, von dem der Controller nun implizit weiss, dass das 
Containerfile an Block 1234 anfängt und 60000 Blöcke gross ist. Eine 
FAT-Lib wird dazu also nicht benötigt. Die Timestamp von dem Container 
ist dabei natürlich nicht aktuell, auch die Anzahl geschriebener Bytes 
nicht, aber damit solltest du leben können.

von Martin (Gast)


Lesenswert?

Hallo Andreas,

danke für deine Info. Werde mich dann mal weiter umschauen

Gruss

von Andreas K. (a-k)


Lesenswert?

Du kannst das auch mit FAT-Lib machen, indem du vorneweg per FAT-Lib die 
SD komplett löschst (sonst droht Fragmentierung), das File anlegst und 
dann den Inhalt an der Lib vorbei daraufhin analysiert, wo das File 
liegt. Hat gegenüber der vorher beschriebenen Methode den Vorteil, dass 
es bei SDs unterschiedlicher Grösse funktioniert. In beiden Fällen musst 
du dich natürlich etwas in den Aufbau eines FAT-Filesystems einlesen.

von Andreas K. (a-k)


Lesenswert?

Andreas Kaiser wrote:

> Will du darauf auch schreiben, musst du das Device allerdings dazu
> sperren: DosDevIOCtl(..., IOCTL_DISK, DSK_LOCKDRIVE, ...).

Sorry, dieser Teil des Codes war für OS/2... Ich weiss nicht mehr, ob 
man unter Windows irgendwas für's Schreiben tun muss oder ob das ohne 
geht. Lesen jedenfalls geht wie beschrieben.

von Martin (Gast)


Lesenswert?

Hallo,

habe noch Verständnisprobleme. Schreibe mit dem µC die Blöcke 
entsprechend auf die SD-Karte(z.B. @ Sektor 1000, @ Sektor 1001, usw.) 
Hierfür gibt es spezielle SD Kommandos. Kann die Blöcke auch 
ordnungsgemäß wieder mit dem µC auslesen. Jetzt habe ich aber Probleme, 
die selben Blöcke am PC auszulesen.
Ich lese die Daten wie im Artikel 
http://support.microsoft.com/kb/q100027/ beschrieben. Im ersten Block 
finde ich die allgemeinen Informationen. Gehe ich jetzt aber zu den 
Sektoren 1000, ... kann ich meine geschriebenen Blöcke nicht erkennen.
Mache ich noch einen gedanklichen Fehler?

Gruss

von I_ H. (i_h)


Lesenswert?

Martin wrote:
> Hallo,
>
> vielleicht nochmal vorab, jedes Samplepackage(auch bei nur einem
> Messkanal) besteht aus mindestens 14Byte(1Byte Paketlänge + 4Byte
> Prozessorticks + 4Byte Samplenumber + 1 Byte ChannelID + 2 Byte Data).
> Für die Anwendung ist die exakte Zeitzugehörigkeit extrem wichtig.
> Deshalb der gewaltige Overhead.


Du kannst das doch sicher so abspeichern, dass du das aus weniger Daten 
rekonstruieren kannst. Lass die Kanäle einfach in einem vorgegebenem 
Raster abtasten (reihum Kanal 1 bis 14), aus dem Zeitstempel vom ersten 
Kanal, der Abtastrate und der Anzahl der Kanäle kannst du doch wunderbar 
den exakten Zeitpunkt für jeden Kanal zurückrechnen.
Wichtig ist nur, dass du die ADC Werte in einem festen Zeitraster 
anfertigst.

Dann hast du für 14 Werte 1Byte Paketlänge (kannst du auch weglassen, 
ganz am Anfang einmal speichern wieviele Kanäle abgetastest werden), 
4Byte Prozessornummer, 4Byte Samplenummer (auch redundant, oder lässt du 
unterwegs samples weg?? - wär auch wurscht, hast ja Zeitstempel) und 
schließlich 28 Byte Daten aufsteigend für Kanal 1 bis 14.

Das macht dann nur noch 2.65 Byte pro Sample, bzw. weniger als 1/5tel 
der Ausgangsdatenrate. Einzige Anforderung ist, dass du bei jeder 
Messung alle Kanäle hintereinander mit festem Zeitabstand durchmisst.

Kann man auch noch weiter reduzieren (Samplenummer und Paketlänge 
weglassen, dafür vor jeden Datensatz einen Header der Auskunft über 
Anzahl Samples und Reihenfolge und Anzahl der aufgezeichneten Kanäle 
gibt), aber unter 2 Byte / Sample geht dann nur noch mit Kompression 
(... hat der ADC wirklich 16 Bit?).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.