Forum: Mikrocontroller und Digitale Elektronik ser, viele daten zum µc senden


von ralf (Gast)


Lesenswert?

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
1
void storeSdFile(String line) {
2
        String filename = line.substring(line.lastIndexOf("=") + 1);
3
        char c_filename[sizeof(filename)];
4
        filename.toCharArray(c_filename,sizeof(filename));
5
        wFile = SD.open(c_filename, FILE_WRITE);
6
        while(COM.available() > 0) {
7
            wFile.write(COM.read());
8
        }
9
        wFile.flush();
10
        wFile.close();
11
}

funktioniert ja nicht, ich schicke zwar z.b. 1000byte los, aber
auf der sd-card kommen im file nur 68byte an

kann mir jemand einen tip geben ...

von 1N 4. (1n4148)


Lesenswert?


von ralf (Gast)


Lesenswert?

oh jee, keine andere möglichkeit außer x- oder z-modem ?

von Philipp K. (philipp_k59)


Lesenswert?

Vielleicht ist die SD zu langsam und das ganze hakt dann..

: Bearbeitet durch User
von Frank (Gast)


Lesenswert?

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.

von Hmmhmm (Gast)


Lesenswert?

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.

von Dennis R. (dennis_r93)


Lesenswert?

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

von Jim M. (turboj)


Lesenswert?

ralf schrieb:
> oh jee, keine andere möglichkeit außer x- oder z-modem ?

Doch, die gibt es!
Sende halt im PC langsamer...

von MagIO (Gast)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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.

von Walter S. (avatar)


Lesenswert?

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

von Philipp K. (philipp_k59)


Lesenswert?

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.

: Bearbeitet durch User
von ralf (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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.

von ralf (Gast)


Lesenswert?

ok ok, dann also doch ein richtiges protokoll
macht irgendwie sinn

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von dünnwandiger Trog (Gast)


Lesenswert?

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.

von Jim M. (turboj)


Lesenswert?

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.

von Philipp K. (philipp_k59)


Lesenswert?

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..

von Peter D. (peda)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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...

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

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...

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von ralf (Gast)


Lesenswert?

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

von Markus F. (mfro)


Lesenswert?

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 ...

von ralf (Gast)


Lesenswert?

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

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.