Hallo zusammen,
im Rahmen meines Projektes bin ich gerade auf ein neues Problem
gestoßen. Mein MSP430 hört auf dem CAN-Bus mit, was alles so gesendet
wird. Dabei achtet er auf ungefähr eine handvoll CAN-Botschaften
identifiziert durch die entsprechende ID. Die IDs werden dabei von einer
SD Karte gelesen und sind im aktuellen Fall Fünf an der Anzahl.
Der Controller soll nun den Bus abhören und Alarm schlagen, sobald eine
ID innerhalb einer Sekunde nicht empfangen worden ist (fast alle
Botschaften werden dabei alle 40ms gesendet).
Gerade wollte ich eine Ausgabe implementieren, welche einige Messwerte
per UART über USB an den Computer sendet (Das Board wird als USB Serial
Converter am PC erkannt).
Gesagt, getan und es funktioniert. Allerdings wird das Board dadurch
scheinbar so stark belastet, dass meine Menüführung quasi gar nicht mehr
möglich ist (Software-Debouncing in while-Schleife in der main).
Kann das sein? Ist das Senden via UART so anspruchsvoll? Oder sind es
eher meine String-Operationen (1x strcpy, 8x strcat, 1x itoh, 1xitoa, 2x
ftoa, Routinen aus numtostr-Paket hier aus dem Forum:
Beitrag "C-Umwandlungsfunktionen für double/int/long nach String"), die zuviel Rechenzeit
benötigen?
Eine Nachricht sieht zum Beispiel so aus:
"Fehlende CAN-Nachricht: ID: 0x123; Temp: 12.123; Hum: 12.123, Spannung:
0\r\n"
Im Moment ist der CAN-Bus abgeklemmt und das Board soll auf 5
Nachrichten reagieren. Demnach wird die obige Nachricht 5mal pro Sekunde
(mit unterschiedlichen IDs) gesendet.
Was meint ihr? Woran wird es am wahrscheinlichsten liegen?
@ Roland M. (eroli)
>Gesagt, getan und es funktioniert. Allerdings wird das Board dadurch>scheinbar so stark belastet, dass meine Menüführung quasi gar nicht mehr>möglich ist (Software-Debouncing in while-Schleife in der main).
Aua! Das macht man mit einem TIMER! Siehe Entprellung>Kann das sein? Ist das Senden via UART so anspruchsvoll? Oder sind es
Nein.
>Was meint ihr? Woran wird es am wahrscheinlichsten liegen?
An deiner unpassenden Programmierung.
Sorry für den Doppelpost, aber ich habe gerade mal probiert alle
Umwandlungen (itoh, itoa und ftoa) auszukommentieren und dann
funktioniert es wunderbar. Auch mit itoh und itoa läuft es gut.
Scheinbar braucht die ftoa-Funktion sehr viel Rechenzeit. Diese sieht
bei mir so aus
Gibt es da vielleicht effizientere Wege?
@ Falk Brunner: Sicher ist das per Timer eleganter, aber das ist hier an
dieser Stelle nicht das Problem. Dennoch werde ich das wohl auf einen
neuen Timer umstellen. Danke für den Hinweis.
Roland M. schrieb:> eher meine String-Operationen (1x strcpy, 8x strcat, 1x itoh, 1xitoa, 2x> ftoa,
Da kommt allerdings dann schon einiges zusammen.
> "Fehlende CAN-Nachricht: ID: 0x123; Temp: 12.123; Hum: 12.123, Spannung:> 0\r\n"
Muss das wirklich so geschwätzig sein?
Je nach Baudrate, dauert eine Übertragung dann schon seine Zeit. Und
auch (speziell bei Floating Point) die Aufbereitung von Werten in eine
ASCII Repräsentierung kriegt man nicht gratis.
Klar ist mir zb nicht, wozu du die ganzen strcpy und strcat brauchst.
Am Terminal kannst du sowieso nicht unterscheiden, ob das Programm
zuerst ala
1
strcpy(buffer,"Hallo ");
2
strcat(buffer,"World!\n");
3
4
uart_string(buffer);
den Text zuerst in einen String zusammengebaut hat, oder ob du mittels
1
uart_string("Hallo ");
2
uart_string("World!\n");
2 String-Übertragungen hattest. Der einzige Unterschied: du belastest
deinen µC mit einem zusätzlichen Buffer, in dem erst mal alles 20 mal
umkopiert werden muss, ehe es dann tatsächlich per UART auf die Reise
geht.
Hallo Karl Heinz,
du hast natürlich Recht... Da habe ich gar nicht drüber nachgedacht. Ich
habe es nun wie du vorgeschlagen hast abgeändert und die einzelnen
Konvertierungsergebnisse direkt an den UART zum Senden übergeben. Es ist
ein wenig besser, aber es braucht immer noch tierisch lange.
Ich denke das wesentliche Problem hierbei ist die ftoa-Geschichte...
Baudrate ist übrigens 38400. Zuerst war ich bei 9600 und dachte das
Problem mit einer Erhöhung entschärfen zu können. Hat aber zu keiner
merklichen Verbesserung beigetragen...
@ Roland M. (eroli)
>Umwandlungen (itoh, itoa und ftoa) auszukommentieren und dann>funktioniert es wunderbar. Auch mit itoh und itoa läuft es gut.
Das ist ja schon mal ein wichtiger Hinweis.
>Scheinbar braucht die ftoa-Funktion sehr viel Rechenzeit. Diese sieht>bei mir so aus
Wozu postest du denn Quelltext? Das sind doch normalerweise Funktionen,
die in deiner Compilerbilbiothek mit drinstecken. Wahrscheinlich auch
deutlich besser optimiert. Möglicherweise musst du die (optimierte)
Bibliothek zu deinem Code linken, damit die (langsamen)
Standardfunktionen ersetzt werden. Beim avr gcc ist das jedenfalls so.
Roland M. schrieb:> Ich denke das wesentliche Problem hierbei ist die ftoa-Geschichte...
Flaoating Point ist für einen µC ohne FPU schon recht aufwändig.
Brauchst du wirklich die Temperatur auf 2 Nachkommastellen. Und: wenn
ja, brauchst du sie wirklich in der Form 89.50 oder reicht dir zum
Debuggen nicht auch ein 8950 und du weißt ganz einfach, dass zwischen
Zeher und Hunderter ein Dezimalpunkt rein muss.
Das könnte zb auch ein Programm mit viel weniger Aufwand erledigen.
Funktionen werden meistens umfangreicher und aufwändiger, wenn sie so
allgemein wie möglich sein müssen. Braucht man diese Allgemeingültigkeit
nichtm, dann vereinfacht sich vieles.
Eine Ausgabe, die einen 16 Bit int immer in ein Feld der Größe 7 Zeichen
(inkl. abschliessendes 0-Byte) reinschreibt und zwar immer mit führenden
0-en, ist ein trivial und wird kaum länger als ein paar Zeilen.
Verglichen mit deinem Monster für ltoa ist das schon recht heftig.
Nicht aus den Augen lassen, solltest du aber die Baudrate. Bei zb 9600
Baud, kriegst du gerade mal ca. 1000 Zeichen pro Sekunde rüber. D.h. pro
Zeichen dauert die Übertragung 1ms. Der Unterschied zwischen
"Fehlende CAN-Nachricht: ID: 0x123; Temp: 12.123; Hum: 12.123, Spannung:
0\r\n"
und
"miss ID 123; T 12 H 12 V 0\r\"
siond alleine aus dem Grund schon mal 46ms bei 9600 Baud. Und das nur
dadurch, dass dein Programm nicht so geschwätzig ist.
Hallo zusammen,
da ich wirklich nicht gedacht hätte, dass die Konvertierung einer
float-Variablen in einen String so anspruchsvoll ist, habe ich mich dazu
entschieden die Variable auf einen int zu casten und dann mittels itoa
zu konvertieren.
Die vielen strcat-Funktionen habe ich quasi durch meine
UART_Transmit-Funktion ersetzt, sodass auch der große Buffer wegfällt.
Jetzt läuft es für mich akzeptabel schnell.
Vielen Dank für eure Erfahrungen ;-)
EDIT: Übrigens gibt es in der stdlib vom MSPGCC keine ftoa-Funktionen
und dergleichen ;-) Daher hatte ich weiter oben das Quelltext-Monster
gepostet ;-)