hi
ich würde gern vom pc über serial 1-100k daten zu einem µc senden
und der soll die dann auf sd speichern
viele daten vom µc zum pc ist ja kein problem, der pc ist schnell genug
damit das ohne probleme funktioniert, nur umgedreht ?
ein ansatz wie
ralf schrieb:> ich würde gern vom pc über serial 1-100k daten zu einem µc senden
100k innerhalb was für einer Zeit?
ralf schrieb:> kann mir jemand einen tip geben ...
Nimm halt 100k RAM, Speicher es zwischen und du hast Zeit es auf SD zu
speichern.
ralf schrieb:> oh jee, keine andere möglichkeit außer x- oder z-modem ?
Schreib dir halt selber ein Protokoll.
Man kann Pakete so gestalten:
Byte0 = Befehl (wie schreiben, lesen etcpp)
Byte1 = Menge Daten
Byte2 - Byte (Menge+2) enthält die Daten.
Der µC hat dann einen Buffer, wo "Menge" reinpasst. Damit dürfen die
Daten auch Binärdaten sein, weil keine Steuerzeichen nötig sind.
Wenn der µC den Buffer voll hat, hängt das an die Datei in der
Speicherkarte an.
Das muss man dann "ACK" basieren machen:
PC schickt ein Paket
µC sagt "ACK: fertig, mehr bitte"
PC schickt ...
Das umgeht einige Lästige Eigenschaften von der Kommunikation µC <> PC,
insbesondere den Timingprobleme mit dem Scheduler von Windows etcpp.
Auch egal ist damit, wie langsam die Speicherkarte ist, weil der µC erst
dann ein ACK absetzt, wenn er fertig ist.
Dafür ist es halt nicht so schnell. Der PC ist ein arger Flaschenhals,
wie du feststellen wirst - er reagiert VIEL langsamer auf ACKs als der
µC.
Ich Formuliere mal aus, was bisher mehr oder weniger implizit gesagt
wurde.
Das Schreiben auf die SD-Karte dauert zu lange.
Bis das Byte geschrieben ist, ist der Empfangspuffer der seriellen
Schnittstelle bereits überlaufen. Die Restlichen Empfangenen Daten
werden verworfen.
Eine Idee ist es eine Datenflussteuerung zu verwenden. Die xyz-Modems
sind eine Lösung mit einem Protokoll. Als Alternative gibt es noch die
Datenflusssteuerung per Clear to Send und Ready To Send.
Das sind 2 Pins der Seriellen verbindung die für genau diesen Zweck
verwendet wurden.
Aber nicht jeder USB-Rs232 Wandler unterstützt das.
Das ganze nennt man dann Hardware Flow Control.
Es gibt als alternative noch die Software Flow Control mit
Steuerzeichen.
Aber die hat ein paar andere Nachteile.
https://en.wikipedia.org/wiki/Flow_control_(data)#Hardware_flow_control
Außerdem ist das schreiben von einem Byte sehr aufwendig.
SD-Karten, Festplatten, SSDs, USB-Sticks, etc... sind darauf ausgelegt
dass man Blockweise schreibt.
Deshalb solltest du dir einen Puffer anlegen mit z.B. 512 Byte oder
besser 4 Kbyte.
Diesen Puffer füllst du dann und schreibst ihn gleich an einem Stück.
Viele Grüße
Es fehlt noch etwas Info bezüglich der Randbedingungen.
Welcher uC? Wie schnell sendest du? Welches Filesystem? Wie schnell
schreibt dein System auf SD- Karte?
Mit ein paar Tricks lässt sich da natürlich noch optimieren. Z.B.
Filesystem. Vermute mal FAT. Wenn man da die Cluster-Größe entsprechend
wählt (beim Formatieren), dann passt die Datei in einen Cluster. Heißt,
dass man eine Low-level Funktion zum schreiben von Sektoren
zurückgreifen kann, die dann unter Umständen schneller ist.
Also .. Datei öffnen bevor der PC sendet ... der Receiver wird
umgestellt auf Interrupt und schreibt die Bytes in einen Ringbuffer von
mindestens 2 mal Sektor-Größe. Ist ein Sektor voll, dann wird der
geschrieben. Mindestens 2, weil bei noch mehr Buffer einfach mehr Zeit
ist, um bei Problemen nicht gleich in Fehler zu laufen. SD-Karten können
manchmal auch etwas länger brauchen, z.B. weg. Wear-Leveling.
Wenn du bei der Übertragung dann keine Bitfehler hast, dann braucht es
eigentlich keine komplizierte Flusssteuerung. Wird der Ringbuffer nicht
schnell genug weggeschrieben, dann liegt ein Fehler vor und der uC muss
dem PC veranlassen die Daten nochmal zu senden ... oder was auch immer
in der Anwendung Sinn macht.
Jim M. schrieb:> Sende halt im PC langsamer...
Wie langsam willst du denn senden, wenn jederzeit die Möglichkeit
besteht, dass die SD länger mit sich selbst beschäftig ist und keine
weiteren Daten annimmt. Da hilft nur Puffer und Handshake.
ralf schrieb:> while(COM.available() > 0) {> wFile.write(COM.read());> }
das ist natürlich knapp daneben:
es wird abgebrochen sobald nicht schnell genug Daten von der
Schnittstelle kommen
Mal abgesehen vom Abbrechen, das verwendete Write generiert jedesmal
einen Handshake..
Mit z.B. SD.write(buf,index) und einem Buffer von 128 byte generiert man
nur einen Handshake alle 128byte..das macht es eben mal 30 mal
schneller.
Vielleicht würde es schon ausreichen einfach die Schreibgeschwindigkeit
der SD zu messen und alle 128 Zeichen auf dem PC einige wenige
Millisekunden Delay einzubringen.
Oder wie vorher schon vorgeschlagen ein ACK oder baudrate drosseln.
danke für die vielen antworten,
ich glaube ich werde die sache mit einem 4k buffer und
einigen delays auf dem pc mal anschauen
wie lange es dauert die daten zum µc zu schieben ist eigentlich
nebensache, solange es nicht stunden werden
es geht nur darum config-dateien auf der sd abzulegen die der
µc beim starten einliest
@ ralf (Gast)
>ich glaube ich werde die sache mit einem 4k buffer und>einigen delays auf dem pc mal anschauen
AUA!
>wie lange es dauert die daten zum µc zu schieben ist eigentlich>nebensache, solange es nicht stunden werden
Dann mach es GLEICH richtig und führe ein passendes Handshake in dien
Protokoll ein! Es muss ja nicht gleich X oder Z modem sein.
Datenpakte vom PC schicken, z.B. 128 Bytes
Daten auf SD-Karte speichern
OK zum PC senden
PC sendet erst wieder, wenn er OK bekommt.
Alles andere, vor allem Delays, sind MURKS!
>es geht nur darum config-dateien auf der sd abzulegen die der>µc beim starten einliest
Selbst bei Arduino & Co sollte man mit einer SD-Karte auf 10kB/s kommen,
real eher deutlich mehr. So schnell kann der PC selbst bei 115k2 kaum
senden. Natürlich darf man das dann nicht im ultimativen Noob-Style
blockierent programmieren. Siehe Multitasking.
ralf schrieb:> ich glaube ich werde die sache mit einem 4k buffer und> einigen delays auf dem pc mal anschauen
Delays sind schlecht, weil feste Zeiten.
ACK ist besser, weil schneller.
4K Buffer ist überdimensioniert, 128 Byt ist ziemlich nutzlos.
Die meisten SD-Karten arbeiten mit Sectors a 512 Byt, also ist ein
Buffer mit 512 Byt optimal -auch wegen wear leveling und Schnelligkeit.
Mit 128Byt wird ein Sector 4 Mal beschrieben, mit 512Byt nur einmal.
Ein uC ist immer schneller in der seriellen Kommunikation wie der PC.
Dies weil er nahezu ohne Reaktionszeit antworten kann. Deswegen sollte
man zu grossen Blockgroessen, von zB 2..4kB gehen. Eine SD ist sicher
schnell genug wenn man,s richtig macht. Die kann ja meine Digitalbilder
wegpeichern. Wenn man nicht grad die Langsamsten nimmt.
Zwingend darf man weder die Schnittstelle, noch die SD blockierend
bedienen.
Und ja ein Protokoll sollte man sich ausdenken. Ein Modemprotokoll ist
uebertrieben. Etwas im Sinne von :
start length command data[] crc
Und dann sollte man sich ein Filesystem ausdenken, mit den benoetigten
Daten drauf.
dünnwandiger Trog schrieb:> Eine SD ist sicher> schnell genug wenn man,s richtig macht
Nö, ist sie nicht. Die lässt sich beim Schreiben auch mal >300ms Zeit
und die Suche eines neuen freien Clusters in der Fat kann bei
ungünstiger Belegung noch viel länger dauern.
Irgendeine Datenflusskontrolle ist daher Pflicht.
Kommt ja auch immer drauf an was das für ein Projekt ist..
Möchte ich es verschenken oder an andere weitergeben, bzw kann sich
durch die Übertragung ein wichtiger Fehler einschleichen der mir oder
anderen nicht auffallen wird?
Klar, dann CRC,vielleicht Blockweise schreiben, kleines Protokoll
entwickeln... noch ne Woche ans Projekt anhängen mit Ringbuffer etc..
Andererseits.. Flash ich das Teil einmal im Jahr selbst für mich,
bemerke ich sowieso gleich nen Übertragungsfehler der bei normaler
Bedienung von mir selbst eigentlich ausgeschlossen werden kann...
Letzterem würde ich den maximal möglichen Buffer geben welcher bei nem
zB. Atmega328 sowieso nicht riesig ausfallen wird (keine 4K :D) eher
irgendwo zwischen 128 und 1024.. wenn man die PC Seite Selbst
programmiert frei definierbar auf nen "ACK\r\n" warten und dann erst
Bufferblock übertragen und auf das nächste warten..
Bei 512 Byte Sektoren würde ich 1024 Byte FIFO einrichten. Der PC sendet
dann die ersten 1024 Byte und wartet auf ACK für die ersten 512 Byte.
Nach den ersten 512 Byte kann man diese schon auf die SD-Karte
schreiben. Im Idealfall ist die SD-Karte fertig, bevor die nächsten 512
Byte eingetrudelt sind. Ansonsten hat der PC noch kein ACK empfangen und
muß warten.
dünnwandiger Trog schrieb:> Die kann ja meine Digitalbilder wegpeichern. Wenn man nicht grad die> Langsamsten nimmt.
Dann guck dir mal an, in welchem Mode sie dabei betrieben wird -
bestimmt nicht im SPI-Mode.
Peter D. schrieb:> Bei 512 Byte Sektoren würde ich 1024 Byte FIFO einrichten. Der PC sendet> dann die ersten 1024 Byte und wartet auf ACK für die ersten 512 Byte.
Normales schreiben (im SPI-MODE) dauert zwischen 2,5ms und 3ms pro
Sector. Natürlich gibt es manchmal längere Pausen (vor allem an der
Clustergrenze) aber bei ganz neuen Cards ist das nie der Fall.
> Nach den ersten 512 Byte kann man diese schon auf die SD-Karte> schreiben.
Ohne DMA geht das normalerweise in die Hose oder es bringt keinen
Vorteil in Bezug auf die Zeit.
> Im Idealfall ist die SD-Karte fertig, bevor die nächsten 512> Byte eingetrudelt sind. Ansonsten hat der PC noch kein ACK empfangen und> muß warten.
Bei 115,2Kb/s braucht der PC 44,5ms um 512Byt (1 Sector) zu senden.
uC braucht 6% davon um ein Sector zu schreiben.
Also sind 512Byt Buffer mehr als genug.
RAM ist kostbar, vor allem bei kleineren uC...
Marc V. schrieb:> Normales schreiben (im SPI-MODE) dauert zwischen 2,5ms und 3ms pro> Sector. Natürlich gibt es manchmal längere Pausen (vor allem an der> Clustergrenze) aber bei ganz neuen Cards ist das nie der Fall.
Welcher Kartentyp war das?
Ich hatte hier schon Karten, die ca. 1 Sekunde zwischen Blöcken
brauchten. Die war nagelneu, aber vom Supermarkt.
Marc V. schrieb:>> Nach den ersten 512 Byte kann man diese schon auf die SD-Karte>> schreiben.>> Ohne DMA geht das normalerweise in die Hose oder es bringt keinen> Vorteil in Bezug auf die Zeit.
Wenn man den UART+FIFO im Interrupt Betrieb hat, bringt das viel. Man
bedenke auch, das beim Schreiben von kompletten Sektoren diese vorher
nicht eingelesen werden müssen, was ansonsten ebenfalls Zeit kostet.
DMA bringt beim Schreiben auf SDCards kaum Punkte, da man auf ein
einzelnes (Start-) Byte von der Karte warten muss. Das kann auch mal
länger dauern...
ein funktionierendes Protokoll umgeht mehrere Fallstricke. Bei seriellen
Transporten kommst Du ohne blockbasierte CRC/Checksumme nirgendwohin;
ausserdem sollte die MRU (Maximum Receive Unit) im Idealfall verhandel-
oder konfigurierbar sein, weil ein Sender keine Annahmen darüber treffen
sollte, welche Blockgrösse im Empfänger verarbeitet werden kann. Die
Blockgrösse im Header wie im 2. Beitrag angegeben ist ein absolutes
Muss. Das ACKen einzelner Teilblöcke wie schon skizziert ist ebenfalls
wichtig; in dem Zusammenhang lässt sich auch eine Sequenznummer
andenken, die ausgehende Blöcke mit ACKs abgleicht (das ist in strikt
serialisierten Implementationen über ein serielles Protokoll nicht
unbedingt nötig, aber auch hier sollten keine Annahmen getroffen werden;
es kann nämlich sein, dass die seriellen peers über ein Netzwerk
gebrückt werden, und damit geht die strikte Serialiserung flöten).
Timeout Policies für unvollständig gesendete Blöcke sind ebenfalls
essentiell.
Ich weiss, es hat einen faden Beigeschmack, wenn ich mal wieder auf mein
Buch verweise, aber in Kapitel 7 diskutiere ich die Dos and Donts beim
Protokolldesign sehr ausführlich.
Jim M. schrieb:>> Sector. Natürlich gibt es manchmal längere Pausen (vor allem an der>> Clustergrenze) aber bei ganz neuen Cards ist das nie der Fall.>> Welcher Kartentyp war das?
SD / SDHC
Neue Karten hatten niemals (jedenfalls nicht bei mir) eine Pause
grosser +/- 10%
Bei gebrauchten Karten gab es manchmal an der Clustergrenze (etwa
nach 30 Sectors oder so) eine längere Pause, aber nichts, was
auch nur nahe an 1 Sekunde kam.
Allerdings beschreibe ich die FAT-und Directory-sectors ganz anders,
da kann die wear leveling gar nicht erst zuschlagen.
hi,
es ist nett das das thema mal auf den tisch kommt, mir scheint
jeder fummelt sich selber das rad jedesmal neu, gibt es kein klares
vorgehen
um einige *.bin-files via ser auf eine sd zu schieben damit sich
z.b. ein display seine grafiken laden kann
ich kann mir irgendwie nicht vorstellen das es dafür keine lösung
z.b. im form einer lib gibt
ralf schrieb:> es geht nur darum config-dateien auf der sd abzulegen die der> µc beim starten einliest
Dann hätt' ich da noch einen ganz einfachen Tip: wenn's nur darum geht,
warum ziehst Du die Karte nicht einfach am µC raus und steckst sie in
den PC rein?
Die Dinger sind (echt) zum Wechseln gedacht ...
es ist wieder soweit, der erste ganz wichte ist im
thread angekommen
ab hier bin ich weg, die erfahrung zeigt --> jetzt kommt nur noch dünnes
was nicht mehr zum thema gehört