Forum: Mikrocontroller und Digitale Elektronik Lange Rechenzeit von kurzem C-Code


von EGSler (Gast)


Lesenswert?

Ich habe einen (wie ich dachte) recht kurzen C-Code geschrieben, der auf 
meinem Raspberry Pi läuft. Da die CPU mit 700Mhz rennt, bin ich davon 
ausgegangen, dass ich mir um die Rechenzeit keine Sorgen machen brauche!

Nun war mein Plan, die Funktion alle 100ms aufzurufen. Da ich keine 
besonders berühmten C-Kentnisse besitze und es bei Nutzung eines 
Betriebssystems nicht so leicht zu sein scheint, einen Timerinterrupt 
die Funktion aufrufen zu lassen, habe ich einfach am Ende der Funktion 
ein "usleep (100000)" eingefügt, um 100ms schlafen zu gehen.
Dabei habe ich bemerkt, dass pro Sekunde nur 8 Durchläufe stattfinden, 
ich habe also eine betrachte Zusatzzeit durch die Programmausführung.
Dann habe ich einfach mal den Sleepbefehl gelöscht und das Programm "so 
schnell es geht" laufen lassen, um die Einträge in der .txt pro Sekunde 
zu zählen - und komme auf etwa 44 Durchläufe/s -> über 20ms für einen 
Durchlauf!


Kleine Erklärung zum Programm: Es wird ein 8-Kanal 18-bit-AD-Wandler 
über SPI abgefragt und die 18 empfangenenen Bytes werden dann jeweils 
wieder in eine Long-Variable mit Bitmanipulation zusammengesetzt.
Zum Schluss werden die Werte zusammen mit dem aktuellen Zeitstempel in 
eine .txt-Datei geschrieben (jeweils getrennt durch ein Tabstop, damit 
Excel die Daten gut importieren kann).

Kann mir jemand sagen, was an meinem Programm soviel Zeit schluckt? Die 
Ausführungsgeschwindigkeit ist zwar bisher ausreichend, aber das 
Programm soll noch um einen zweiten 8-Kanal AD-Wandler (allerdings nur 
mit 14bit-Auflösung) erweitert werden und dann müssen immernoch 10 
Werte/s pro Kanal abgefragt werden können...
1
    time_t tnow;
2
    time(&tnow);
3
    tmnow = localtime(&tnow);
4
    
5
    bcm2835_spi_chipSelect(BCM2835_SPI_CS0);
6
    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);
7
    uint8_t mosi[18] = {125,17,45,13,42,51,64,72,83,91,101,101,112,119,1,64,82,91};
8
    uint8_t miso[18] = {0};
9
    bcm2835_spi_transfernb(mosi, miso, 18);
10
    
11
    
12
    // Zusammensetzen der 18bit-Daten aus den einzelnen Empfangenen Bytes
13
    long AD1_Ch1 = ( miso[0]      << 10) + (miso[1] << 2) + (miso[2] >> 6);
14
    long AD1_Ch2 = ((miso[2] & 63) << 12) + (miso[3] << 4) + (miso[4] >> 4);
15
    long AD1_Ch3 = ((miso[4] & 15) << 14) + (miso[5] << 6) + (miso[6] >> 2);
16
    long AD1_Ch4 = ((miso[6] &  3) << 16) + (miso[7] << 8) +  miso[8];
17
    long AD1_Ch5 = ( miso[9]     << 10) + (miso[10] << 2) + (miso[11] >> 6);
18
    long AD1_Ch6 = ((miso[11] & 63) << 12) + (miso[12] << 4) + (miso[13] >> 4);
19
    long AD1_Ch7 = ((miso[13] & 15) << 14) + (miso[14] << 6) + (miso[15] >> 2);
20
    long AD1_Ch8 = ((miso[15] &  3) << 16) + (miso[16] << 8) +  miso[17];
21
    
22
    
23
    // Schreiben der Werte in eine .txt-Datei
24
    Ziel = fopen ("Werte.txt", "a");
25
    if (Ziel != NULL)    
26
    {
27
      fprintf(Ziel, "%d.%d.%d %02d:%02d:%02d \t", 
28
        tmnow->tm_mday, tmnow->tm_mon + 1, tmnow->tm_year + 1900, tmnow->tm_hour, tmnow->tm_min, tmnow->tm_sec);
29
      fprintf(Ziel, "%d \t", AD1_Ch1);
30
      fprintf(Ziel, "%d \t", AD1_Ch2);
31
      fprintf(Ziel, "%d \t", AD1_Ch3);
32
      fprintf(Ziel, "%d \t", AD1_Ch4);
33
      fprintf(Ziel, "%d \t", AD1_Ch5);
34
      fprintf(Ziel, "%d \t", AD1_Ch6);
35
      fprintf(Ziel, "%d \t", AD1_Ch7);
36
      fprintf(Ziel, "%d \n", AD1_Ch8);
37
      fclose(Ziel);
38
    }

Im Endeffekt komme ich aber wohl nicht umhin, die Funktion irgendwie 
automatisiert über einen Timer aufzurufen, nicht wahr...? Und außerdem 
stört mich, dass ich durch abfragen der Unix-Zeit auf 1s Genauigkeit 
beschränkt bin, bei 10 Werten/s haben immer 10 Werte den gleichen 
Zeitstempel. Naja, da muss man dann eben abzählen :p

: Verschoben durch User
von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

EGSler schrieb:
> ...in eine .txt-Datei geschrieben...

vor allem das wird etwas dauern...

EGSler schrieb:
> Und außerdem
> stört mich, dass ich durch abfragen der Unix-Zeit auf 1s Genauigkeit
> beschränkt bin, bei 10 Werten/s haben immer 10 Werte den gleichen
> Zeitstempel.

schaue dir das mal an:
http://man7.org/linux/man-pages/man2/gettimeofday.2.html

Grüße Uwe

von Daniel H. (Firma: keine) (commander)


Lesenswert?

EGSler schrieb:
> Ich habe einen (wie ich dachte) recht kurzen C-Code geschrieben, der auf
> meinem Raspberry Pi läuft.

Kurz != schnell.

EGSler schrieb:
> // Schreiben der Werte in eine .txt-Datei
>     Ziel = fopen ("Werte.txt", "a");
>     if (Ziel != NULL)
>     {
>       fprintf(Ziel, "%d.%d.%d %02d:%02d:%02d \t",
>         tmnow->tm_mday, tmnow->tm_mon + 1, tmnow->tm_year + 1900,
> tmnow->tm_hour, tmnow->tm_min, tmnow->tm_sec);
>       fprintf(Ziel, "%d \t", AD1_Ch1);
>       fprintf(Ziel, "%d \t", AD1_Ch2);
>       fprintf(Ziel, "%d \t", AD1_Ch3);
>       fprintf(Ziel, "%d \t", AD1_Ch4);
>       fprintf(Ziel, "%d \t", AD1_Ch5);
>       fprintf(Ziel, "%d \t", AD1_Ch6);
>       fprintf(Ziel, "%d \t", AD1_Ch7);
>       fprintf(Ziel, "%d \n", AD1_Ch8);
>       fclose(Ziel);
>     }

Dateizugriffe fressen vergleichsweise viel Zeit. Warum machst du vor 
jedem Schreibzugriff ein "fopen"? Öffne die Datei doch nur einmal und 
speicher dir das Dateihandle irgendwo. Und warum schreibst du nicht alle 
Daten mit einem einzigen "fprintf"?

: Bearbeitet durch User
von EGSler (Gast)


Lesenswert?

Naa, nevermind... Kaum hab ich mir nach ewigem Überlegen diesen Text von 
den Fingern getippt und auf Absenden geklickt, da fällt mir auf, dass es 
die SPI-Übetragung selber ist... ;/
Ich hatte die Frequenz auf 7,6kHz gestellt, kein Wunder dass alleine 
diese schon knapp 20ms dauert oO

Ok, aber mein letzter Absatz ist trotzdem gültig - um einen Timer komme 
ich wohl nicht rum!

von EGSler (Gast)


Lesenswert?

Uwe Berger schrieb:
> schaue dir das mal an:
> http://man7.org/linux/man-pages/man2/gettimeofday.2.html
Das werde ich mir mal anschaun, danke!

Daniel H. schrieb:
> Warum machst du vor
> jedem Schreibzugriff ein "fopen"? Öffne die Datei doch nur einmal und
> speicher dir das Dateihandle irgendwo. Und warum schreibst du nicht alle
> Daten mit einem einzigen "fprintf"?
Ich habe irgendwo gelesen, dass die geschriebenen Daten ggf. verloren 
gehen können, wenn die Datei vom Programm noch geöffnet ist und dieses 
dann unregelmäßig beendet wird. Daher schließe ich sie immer zur 
Sicherheit... Ist das unnötig?
Ja, du hast Recht, ein einzelnder fprintf würde wohl genügen, ich fand 
das nur unübersichtlicher. Würde das Zusammenlegen in einen Befehl die 
Geschwindigkeit erhöhen?

Viele Grüße

von Daniel H. (Firma: keine) (commander)


Lesenswert?

EGSler schrieb:
> Ok, aber mein letzter Absatz ist trotzdem gültig - um einen Timer komme
> ich wohl nicht rum!

Schau dir mal Wiring Pi an: http://wiringpi.com/reference/timing/

von Daniel H. (Firma: keine) (commander)


Lesenswert?

EGSler schrieb:
> Ich habe irgendwo gelesen, dass die geschriebenen Daten ggf. verloren
> gehen können, wenn die Datei vom Programm noch geöffnet ist und dieses
> dann unregelmäßig beendet wird. Daher schließe ich sie immer zur
> Sicherheit... Ist das unnötig?

Mit "fflush" kannst du jederzeit den aktuellen Bufferinhalt in die Datei 
schreiben lassen, dadurch reicht dann ein "fopen" zu Beginn deines 
Programms und ein "fclose" am Ende.

EGSler schrieb:
> Würde das Zusammenlegen in einen Befehl die Geschwindigkeit erhöhen?

Theoretisch ja, praktisch ist die Frage, was der Compiler alles 
optimiert. Im Zweifel muss man Messungen durchführen.

von Conny G. (conny_g)


Lesenswert?

EGSler schrieb:
> Naa, nevermind... Kaum hab ich mir nach ewigem Überlegen diesen Text von
> den Fingern getippt und auf Absenden geklickt, da fällt mir auf, dass es
> die SPI-Übetragung selber ist... ;/
> Ich hatte die Frequenz auf 7,6kHz gestellt, kein Wunder dass alleine
> diese schon knapp 20ms dauert oO
>
> Ok, aber mein letzter Absatz ist trotzdem gültig - um einen Timer komme
> ich wohl nicht rum!

In einem Timer solltest aber keine Dateien schreiben, das dauert 
"unabsehbar" lange.
Oder mach dafür eine RAM disk, dort schreibst Du die Einträge in jeweils 
separate Files und ein Cronjob oder dauernd laufendes Shell-Script 
verarbeitet diese in eine Datei auf der physischen Platte oder SD-Karte.

von Amateur (Gast)


Lesenswert?

Irgendwie ist das Bauklötzchen-Code.
Immer Einen nach dem Anderen.

Warum nicht mal zwei auf einmal?
Z.B. fprintf(Ziel, "%d \t%d \t", AD1_Ch1, AD1_Ch1); oder mehr.

open und close bei jedem Zugriff zeugt von: "Ich weiß nicht was ich 
mache, aber das mache ich gründlich".

von EGSler (Gast)


Lesenswert?

Daniel H. schrieb:
> Schau dir mal Wiring Pi an: http://wiringpi.com/reference/timing/
Das gibt leider Konflikte mit der bcm2835.h. Beide definieren ähnliche 
Punkte.
Ich versuche momentan mit gettimeofday, auch wenn ich da irgendwie 
ebenfalls Probleme habe...

Amateur schrieb:
> Warum nicht mal zwei auf einmal?
Ist doch alles schon besprochen (und mittlerweile geändert)! ;)

von Daniel H. (Firma: keine) (commander)


Lesenswert?

EGSler schrieb:
> Ich versuche momentan mit gettimeofday, auch wenn ich da irgendwie
> ebenfalls Probleme habe...

Was für Probleme denn?

von Purzel H. (hacky)


Lesenswert?

Erstens, mach den Printf weg, schreib binaer. Ohne Formatierung.

Zweitens. Wenn die Daten sowieso auf dem Controller sind, schreib in ein 
Array, die kann man beim Beenden des Programmes immer noch in einen 
Datei schreiben.

Man kann ein Fileschreib auch erzwingen, ohne zu schliessen, das waere 
dann etwas wie flush()

von Rolf M. (rmagnus)


Lesenswert?

EGSler schrieb:
> Da ich keine besonders berühmten C-Kentnisse besitze und es bei Nutzung
> eines Betriebssystems nicht so leicht zu sein scheint, einen
> Timerinterrupt die Funktion aufrufen zu lassen, habe ich einfach am Ende
> der Funktion ein "usleep (100000)" eingefügt, um 100ms schlafen zu gehen.

Besser geeignet für sowas ist die Funktion clock_nanosleep().

EGSler schrieb:
> Im Endeffekt komme ich aber wohl nicht umhin, die Funktion irgendwie
> automatisiert über einen Timer aufzurufen, nicht wahr...?

Kann man auch machen:
man setitimer
man signal

Uwe Berger schrieb:
> EGSler schrieb:
>> Und außerdem
>> stört mich, dass ich durch abfragen der Unix-Zeit auf 1s Genauigkeit
>> beschränkt bin, bei 10 Werten/s haben immer 10 Werte den gleichen
>> Zeitstempel.
>
> schaue dir das mal an:
> http://man7.org/linux/man-pages/man2/gettimeofday.2.html

Die Funktion clock_gettime() ist noch etwas flexibler und genauer.

von EGSler (Gast)


Lesenswert?

Daniel H. schrieb:
> Was für Probleme denn?

Ich habe oben geposteten Code (nur mittlerweile mit zusammengefasten 
fprintf) in eine If-Abgrafe gepackt, um das Programm alle 100ms zu 
starten:
1
struct timeval tv;
2
lonng currentmicros = 0;
3
long previousmicros = 0;
4
long interval = 100000;
5
while(1)
6
{
7
    gettimeofday(&tv, NULL);
8
    currentmicros = tv.tv_usec;
9
    if(currentmicros-previousmcicros > interval)
10
    {
11
        previousmicros = currentmicros;
12
        ...
13
        ...
14
    }
15
}
Aber der Code in meiner If-Abfrage wird deutlich häufiger ausgeführt, 
eigentlich so schnell wie das Programm ansich durchlaufen kann.
Das wird sicherlich wieder nur ein dummer Fehler sein, aber ich finde 
ihn nicht... ;(

@ Siebzehn Zu Fuenfzehn
Das werde ich mir alles mal anschaun, wenn das Programm ansich läuft. 
Das sind ja eher "Optimierungen". Als Hardware-Mensch bin ich froh, wenn 
das Program erstmal tut was es soll, denn bis Mitte Dezember sollte das 
Projekt weitesgehend fertiggestellt sein.

von Karl H. (kbuchegg)


Lesenswert?

EGSler schrieb:

> lonng currentmicros = 0;
> long previousmicros = 0;

unsigned long !

Wenn du so arbeiten willst

>     if(currentmicros-previousmcicros > interval)

dann willst du auf jeden Fall unsigned haben.

von Karl H. (kbuchegg)


Lesenswert?

Wenns das nicht ist, dann poste deinen kompletten Code und nicht nur ein 
für das Forum zurechtgeschnittenes Schnipselchen. Du tust damit dir und 
uns einen Gefallen. Häng das File einfach an das Posting an. Das ist für 
dich und für uns am allereinfachsten.

von Karl H. (kbuchegg)


Lesenswert?

Da ist auch noch ein Fehler
1
    long AD1_Ch1 = ( miso[0]      << 10) + (miso[1] << 2) + (miso[2] >> 6);
2
3
...
4
      fprintf(Ziel, "%d \t", AD1_Ch1);

das korrekte Formatierzeichen für einen long ist "%ld" und nicht "%d"

von Tim S. (tim_seidel) Benutzerseite


Lesenswert?

EGSler schrieb:
> Das wird sicherlich wieder nur ein dummer Fehler sein, aber ich finde
> ihn nicht... ;(

Bitte kopiere den Code und tippe Ihn nicht ab. Meim Abtippen machst du 
neue Fehler oder tippst den eigentlichen Fehler gar nicht ab. (Siehe das 
"lonng")

So können wir nicht sehen wo im Orginal die Fehler liegen, sondern nur 
raten: z.B.
 * ein zusätzliches Semikolon hinter der if.
 * long statt unsigned long, aber das sollte nicht greifen, da in usec 
auch so 35 Minuten Platz finden würden aber nur 1 Sekunde gebraucht wird 
(danach zählt der andere u_sec hoch.

von Rolf M. (rmagnus)


Lesenswert?

EGSler schrieb:
> Ich habe oben geposteten Code (nur mittlerweile mit zusammengefasten
> fprintf) in eine If-Abgrafe gepackt, um das Programm alle 100ms zu
> starten:
> struct timeval tv;
> lonng currentmicros = 0;

Ich glaube dir nicht, daß du dieses Programm hast laufen lassen, denn 
einen Typ namens lonng gibt es nicht. Bitte den ECHTEN Code zeigen! 
Vorher brauchen wir eigentlich nicht weiter diskutieren.

> long previousmicros = 0;
> long interval = 100000;
> while(1)
> {
>     gettimeofday(&tv, NULL);
>     currentmicros = tv.tv_usec;
>     if(currentmicros-previousmcicros > interval)
>     {
>         previousmicros = currentmicros;
>         ...
>         ...
>     }
> }
> Aber der Code in meiner If-Abfrage wird deutlich häufiger ausgeführt,
> eigentlich so schnell wie das Programm ansich durchlaufen kann.

Erstens mal ist das sehr schlecht. So produziert dein Programm dauerhaft 
100% CPU-Last, zweitens kann das so nicht richtig funktionieren.  Dei 
Zeit, die gettimeofday liefert, besteht aus zwei Komponenten, und du 
mußt auch beide nutzen.

von Eric B. (beric)


Lesenswert?

EGSler schrieb:
>
1
> struct timeval tv;
2
> lonng currentmicros = 0;
3
> long previousmicros = 0;
4
> long interval = 100000;
5
> while(1)
6
> {
7
>     gettimeofday(&tv, NULL);
8
>     currentmicros = tv.tv_usec;
9
>     if(currentmicros-previousmcicros > interval)
10
>     {
11
>         previousmicros = currentmicros;
12
>         ...
13
>         ...
14
>     }
15
> }
16
>

Du hast hier Überlaufprobleme. tv_usec wird jede Sekunde wieder auf 0 
gesetzt. "currentmicros" kann also durchaus kleiner sein als 
"previousmicros" und trotzdem wären mehr als "interval" usecs vergangen.
(z.B mit currentmicros == 999999)

von Rolf M. (rmagnus)


Lesenswert?

Nochmal: Besser geeignet ist die Funktion clock_nanosleep, mit einem 
Aufruf in der Art:
1
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &this_tick, NULL);

wobei this_tick eine Struktur vom Typ struct timespec ist, die am Anfang 
mal passend initialisiert werden (clock_gettime) und dann vor jedem 
Warten um 100 Millisekunden erhöht werden muß, etwa so:
1
this_tick.tv_nsec += 100 * 1000 * 1000;
2
if (this_tick.tv_nsec > 1000 * 1000 * 1000)
3
{
4
    this_tick.tv_nsec -= 1000 * 1000 * 1000;
5
    this_tick.tv_sec++;
6
}

: Bearbeitet durch User
von EGSler (Gast)


Angehängte Dateien:

Lesenswert?

Ich hab den Code von Hand abgeschrieben, da ich ihn sonst immer mit 
einem USB-Stick auf den Rechner mit Internet kopieren muss.
Im Anhang ist mal mein komplettes Programm, aber ich habe nun den Fehler 
gefunden:
1
if ((currentmicros - previousmicros) > interval)
Hier brauche ich eine Klammer um meine Division! Wie kommt das? Ich habe 
hier ein Buch über C liegen, in dem steht eine Tabelle über die 
Reihenfolge von Bearbeitungsschritten. In dieser Tabelle sind die 
Rechenoperatoren (wie in diesem Fall Minus) vor den Vergleichern 
aufgelistet, sie werden also mit einer höheren Priorität ausgeführt. In 
meinem Falle aber scheinbar nicht ;/

Dass ich ein Überlaufproblem nach 1s habe ist mir bewusst, da arbeite 
ich noch dran...

@ Rolf Magnus
Ok, das ist auch interessant. Behebt zumindest mein Problem mit der 
100%-igen CPU-Last. Allerdings bin ich dann wieder abhänig von der 
Durchlaufzeit des Programms...

Maan, auf einem Atmega ist es so schön leicht, einen Compare-Interrupt 
auf 100ms einzustellen^^
Mit C und Linux kommt wohl noch nen bissel was auf mich zu, zumal ich 
fürchte, dass ihr auch über den Rest des Codes schimpfen werdet, da das 
mit Sicherheit kein guter Stil ist^^

von Karl H. (kbuchegg)


Lesenswert?

EGSler schrieb:

>
1
if ((currentmicros - previousmicros) > interval)
> Hier brauche ich eine Klammer um meine Division!

Subtraktion. Aber egal.

Nein, du brauchst keine Klammern.
Was immer der tatsächliche Fehler war, die Klammern lösen ihn nicht.

von Karl H. (kbuchegg)


Lesenswert?

[/c]
       fprintf(Ziel, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t",
 [/c]

Immer noch falsch.
Für long ist die korrekte Angabe ein %ld!
Du musst das ernster nehmen. Das sind schwere Fehler, wenn man sich hier 
vertut!

von Rolf M. (rmagnus)


Lesenswert?

EGSler schrieb:
> @ Rolf Magnus
> Ok, das ist auch interessant. Behebt zumindest mein Problem mit der
> 100%-igen CPU-Last. Allerdings bin ich dann wieder abhänig von der
> Durchlaufzeit des Programms...

Nein, eben nicht. Das ist ja gerade der große Vorteil von 
clock_nanosleep! Schau dir meinen Codeausschnitt nochmal genau an und 
denke darüber nach.

EGSler schrieb:
> Maan, auf einem Atmega ist es so schön leicht, einen Compare-Interrupt
> auf 100ms einzustellen^^

Wie schon gesagt lässt sich das mit setitimer() und signal() auf einem 
Linux-System sehr ähnlich umsetzen. Man definiert einen Timer mit einem 
vorgegebenen Intervall, und der löst ein Signal aus. Dann braucht man 
noch einen Signalhandler, der im Prinzip einer ISR sehr ähnlich ist.

von Karl H. (kbuchegg)


Lesenswert?

Du hast ja immer noch einen fopen und einen fclose alle 100ms!
Nichts aus dem bisher gesagten gelernt?

von EGSler (Gast)


Lesenswert?

@ Rolf Magnus
Dann wird wohl eines der beiden der richtige Weg sein, ich lese mir mal 
beides genauer durch und probiere das aus.

@ Karl Heinz
Sicher habe ich die Hinweise dankend aufgenommen, aber da liegt ja 
gerade nicht mein Problem, diese Ausführungen funktionieren ja.
Das werde ich dann umschreiben, wenn der Rest klappt.
Andererseits sind die "%ld" natürlich auch schnell umgeschrieben, das 
kann ich gerade machen.

von Karl H. (kbuchegg)


Lesenswert?

Kleiner Tip

Das hier
1
  if (Ziel == NULL || fgetc(Ziel) != 90)  // Wenn Datei nicht geöffnet werden konnte oder das erste Zeichen in der Datei kein "Z" ist

schreib das so
1
  if (Ziel == NULL || fgetc(Ziel) != 'Z')

es gibt wirklich keinen Grund, hier den ASCII Code von 'Z' selber 
hinschreiben zu müssen.
Dann kannst du dir auch den Kommentar sparen.
Denn was eine Abfrage des File Handles auf NULL bedeutet, muss man einem 
C Programmierer nicht erklären. Und der Vergleich mit 'Z' ist auch 
selbst erklärend.

Grundsätzlich: Wenn du versucht bist, derartige Kommentare zu schreiben, 
solltest du immer nach einer Möglichkeit suchen bzw. dir überlegen wie 
du den Code anders schreiben kannst, so dass du diesen Kommentar nicht 
benötigst. Wenn du die Zeit fürs Schreiben des Kommentars bzw. die 
Anschläge beim Tippen in eine derartige Modifikation steckst, dann hast 
du wesentlich mehr davon, als von solchen Kommentaren. Der beste 
Kommentar ist immer noch derjenige, der nicht gebraucht wird, weil alles 
was im Kommentar stehen würde, schon im Code ersichtlich ist. 
Gegebenenfalls muss man dann eben Variablennamen ein wenig ändern oder 
Funktionsnamen ein wenig ändern oder sich die jeweils beste Darstellung 
von konstanten Werten raussuchen (wie hier die Angabe des 'Z' anstelle 
der gleichwertigen 90). Das alles rechnet sich aber für die Zukunft. Du 
wirst sehen, dass du signifikant weniger blödsinnige Fehler machst, weil 
du dir die Informationen nicht mehr aus Kommentaren holst, die aufgrund 
Programmänderungen schon längst nicht mehr stimmen, sondern aus dem Code 
selber, den du so formuliert hast, dass du in wenigen Sekunden den Sinn 
erfassen kannst.

von Karl Käfer (Gast)


Lesenswert?

Hi Daniel,

Daniel H. schrieb:
> Mit "fflush" kannst du jederzeit den aktuellen Bufferinhalt in die Datei
> schreiben lassen, dadurch reicht dann ein "fopen" zu Beginn deines
> Programms und ein "fclose" am Ende.

Das fflush(3) macht aber noch kein fsync(2). Anders gesagt: nach einem 
fflush(3) stehen die Daten immer noch nicht auf der Festplatte (hier: 
SD-Card), sondern nur im Dateipuffer des Betriebssystems.

HTH,
Karl

von Karl H. (kbuchegg)


Lesenswert?

EGSler schrieb:
> @ Rolf Magnus
> Dann wird wohl eines der beiden der richtige Weg sein, ich lese mir mal
> beides genauer durch und probiere das aus.
>
> @ Karl Heinz
> Sicher habe ich die Hinweise dankend aufgenommen, aber da liegt ja
> gerade nicht mein Problem, diese Ausführungen funktionieren ja.

'funktionieren' bedeutet noch lange nicht, dass es richtig ist.

von Rolf M. (rmagnus)


Lesenswert?

EGSler schrieb:
> @ Rolf Magnus
> Dann wird wohl eines der beiden der richtige Weg sein, ich lese mir mal
> beides genauer durch und probiere das aus.

Um das kurz zu erläutern: Bei clock_nanosleep() kann man im Gegensatz zu 
usleep() auch eine absolute Zeit angeben, also man kann ihm nicht nur 
sagen "warte für x Zeiteinheiten", sondern auch "Warte bis zum Zeitpunkt 
x". Mit usleep() sieht es in Pseudocode ungefähr so aus:
1
schleife
2
{
3
    irgendwas();
4
    warte(100 ms);
5
}

Wenn irgendwas() jetzt 20 ms braucht, dauert der Gesamtzyklus 120 ms, 
wenn es 50 ms braucht, dauert er 150 ms. Mit clock_nanosleep() kann man 
das aber auch so machen:
1
x = aktuelle_zeit();
2
schleife
3
{
4
    irgendwas();
5
    x += 100 ms;
6
    warte_bis_zeitpunkt(x);
7
}

Hier ist die Zykluszeit immer 100 ms, unabhängig davon, ob irgendwas() 
nun 5, 20 oder 50 ms braucht. Erst wenn es mehr als 100 ms braucht, 
kommt es natürlich zu Zykluszeitverletzungen, aber dann ist das System 
einfach überlastet.

von EGSler (Gast)


Lesenswert?

@Karl-Heinz
Da hast du natürlich Recht. Ich war von der Informationsflut kurzeitig 
ein wenig überfordert, ich habe mich wieder berappelt^^
Ja, mit den Kommentaren hast du Recht. Ich dachte ich müsste auf "90" 
abfragen, da meine Variable ja ein int ist.
Man sieht vermutlich alleine schon an meinen Kommentaren, wie viel 
Erfahrung ich mit Software bereits habe...^^ Aber mit Büchern und 
Internet kommt man gut vorwärts =)

@ Rolf
Ahh, das ist natürlich super. So hatte ich das bisher nicht verstanden. 
Dann ist mein Zeit-Problem ja mit dieser Funktion ziehmlich gut zu 
lösen, schätze ich!

Danke für eure Tipps bisher! =)

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.