Hallo,
ich hänge immernoch an meiner GPS- Geschwindigkeitsanzeige. Inzwischen
klappt die Kommunikation über UART tadellos, aber die Auswertung des
Strings noch nicht ganz.
Und zwar empfange ich vom GPS- Empfänger die Geschwindigkeit in Knoten,
und speichere sie, in der als char initialisierten Variable, empfangen
ab.
Anschliessend will ich die Variable nach int konvertieren, damit ich sie
zum Umrechnen in km/h mit 1,85 multiplizieren kann.
Wenn das geschehen ist, muss sie jedoch wieder nach char konvertiert
werden, da sie mit der Funktion lcd_string(string) auf einem LCD
ausgegeben werden soll. Bei dem ganzen Vorgang sollen die beiden
Nachkommastellen erhalten bleiben, und es soll möglichst schnell
geschehen, weshalb ich auf Bibliotheksfunktionen verzichtet habe, und
versucht habe, die Konvertierung von Hand zu machen. Allerdings klappt
das nicht so ganz wie erwünscht, wenn der Empfänger 0.00 Knoten schnell
ist, und auch 0.00 sendet (was der Mega8 auch empfängt), dann zeigt das
LCD das an, was auf dem Bild zu sehen ist.
Also die Formatierung stimmt, die Werte jedoch nicht.....
Hier mal mein Code zum Konvertieren und Rechnen:
1
empfangen[0]=uart_getchar();//Per UART die Daten com GPS- Empfaenger
2
empfangen[1]=uart_getchar();//empfangen
3
empfangen[2]=uart_getchar();
4
empfangen[3]=uart_getchar();
5
....
6
//Wenn empfangen[1] ein Komma ist (was ja
7
if(empfangen[1]=='.')//bei einer einstelligen Geschwindigkeit
8
{//der Fall ist)
9
empfangen[1]=empfangen[2];//Das Komma "rausmachen"
10
empfangen[2]=empfangen[3];
11
knoten=empfangen[0]*1000+empfangen[1]*100+empfangen[2]*10+empfangen[3];//Die char- Werte in einer int speichern
12
mh=knoten*185;//Von Knoten nach mh umrechnen
13
ausgabearry[0]=mh/100000+'0';//Die ints wieder in char speichern
Beim Auswerten der empfangenen Zeichen die '0' abziehen, die du vor der
Ausgabe wieder draufaddierst:
knoten = (empfangen[0]-'0') * 1000 + ......
Und was hat knoten für einen Datentyp? Müsste schon long sein, sonst
gibts einen Überlauf nach der Multiplikation mit 185000.
knoten = empfangen[0]*1000 + empfangen[1]*100 + empfangen[2]*10 +
empfangen[3];
Ich glaube, das geht so nicht, weils eigentlich chars sind. Wenn in
empfangen[1] zB ne 8 steht, kommt bei *100 800 raus... char ist 8Bit und
geht damit nur bis 256. Du baust damit Überläufe, du kaum kontrollierbar
sind.
Versuchs ma mit "Atoi", aka Ascii to Integer. Damit geht das (benutz ich
auch um werte ausm string rauszuziehen).
Ich hab mh und knoten als unsigned int initialisiert.
Die von die genannten Veränderungen hab ich nun mal durchgeführt, nun
dieht die betreffende Zeile so aus:
Allerdings kommt auf dem LCD nun 0.PP, wenn der gesendete String 0.00
ist, und bei irgendeiner Geschwindigkeit kommt immer 0.XX (X sind
irgendwelche großen Buchstaben). Ich will da ja aber Zahlen haben.....
@Matthias: Wenn ich mit atoi konvertiere, bleiben dann die
Nachkommastellen erhalten? Also ich konvertier dann empfangen in knoten,
und der Rest bleibt so, wie er ist, oder?
Gruß, Steffen
holger wrote:
>>@Matthias: Wenn ich mit atoi konvertiere, bleiben dann die>>Nachkommastellen erhalten?>> Ein int hat keine Nachkommastellen.
Stimmt, natürlich....
Also kann ich atoi nicht verwenden, da ich ja Nachkommastellen benötige.
Oder geht atoi auch mit double oder so? Aber wenn ich eben double
verwende, wird das Programm wieder großer und langsamer, deswegen will
ich nach Möglichkeit int verwenden....
Gruß, Steffen
>geht atoi auch mit double oder so?
Heißt 'atod' und 'dtoa', steht alles in der libc vom WINAVR.
Ich benutze bei Messwerten ausschließlich double-Variablen, hatte bisher
noch keine Timing- oder Geschwindigkeitsprobleme.
Hmmm, wenn ich die libc.a, einbinde, und atod folgendermaßen verwende:
1
knoten=dtoa(empfangen);
dann kommt folgender Fehler:
161: undefined reference to `dtoa'
Hab ich irgendwas übersehen? knoten ist eine double- Variable und
empfangen eine char.
Gruß, Steffen
Das atoi machst du fuer jede stelle des char-arrays einzeln... Atoi
überprüft EIN ascii zeichen darauf, welchen Zahlenwert es hat und
konvertiert diesen dann (ascii zeichen sind chars, also wieder 8bit).
also in etwa: knoten = atoi(empfangen[1]) + atoi(empfangen[2])+...
Wenn du auf nummer sicher gehen willst, dann machst du das ganze schritt
fuer schritt, also so:
var1 = atoi(empfangen[1])
var2 = atoi(empfangen[2])
var3 = atoi(empfangen[3])
knoten = var1 + var2 + var3;
so kannst du mit dem debugger oder einer geeigenten Ausgabe gucken, ob
die konvertierung funktioniert.
Wenn ich mich recht erinnere, geht das ganze auch mit fprintf (oder wars
sprintf??) damit kann man strings auch in integerwerte umfummeln, hab
aber die syntax nicht im kopf und das c-buch liegt natürlich auffe
arbeit... Google mal printf-familie, da muesste was schlaues
beirumkommen...
Matthias wrote:
> also in etwa: knoten = atoi(empfangen[1]) + atoi(empfangen[2])+...
Ich habs jetzt mal so gemacht aber auf dem LCD kamen wieder nur
Buchstaben....
> Wenn du auf nummer sicher gehen willst, dann machst du das ganze schritt> fuer schritt, also so:>> var1 = atoi(empfangen[1])> var2 = atoi(empfangen[2])> var3 = atoi(empfangen[3])>> knoten = var1 + var2 + var3;
So werde ich es dann noch versuchen, vielleicht klappt das ja....
Zu printf: Mit sprintf habe ich es bereits versucht bin jedoch daran
gescheitert.... Kann man mit sprintf auch immer nur ein Zeichen
konvertieren?
Gruß, Steffen
@Steffen O.
Sorry, aber dein Code ist ziemlicher Murks. Du ignorierst die Kodierung
(ASCII) rechnest empfangen[3] gleich zweimal mit ein und gehst davon
aus, dass ein einstelliger mph-Wert auch einen einstelligen kmh-Wert
ergibt. Das muss ja schiefgehen.
Das einfachste wäre wohl, mit den schon genannten Bibliotheksfunktionen
und Fließkommazahlen zu rechnen. Wenn es wirklich auf Geschwindigkeit
ankommt, musst du dich noch einmal hinsetzen und den Algorithmus
ordentlich ausarbeiten und nicht gleich mit dem Koden anfangen.
Divisionen sollte man da zudem möglichst vermeiden.
Sorry, aber bei diesem Code weiss ich ja gar nicht, wo ich anfangen
soll... Du hast offensichtlich keine Ahnung von Datentypen im
allgemeinen noch von denen von C im Besonderen. Und dir zu helfen bringt
auch nix, schliesslich ist es offensichtlich, dass du nicht mal ein
C-Buch gelesen hast, so zur Vorbereitung. Und deswegen ist es sinnlos
dir jetzt den richtigen Code zu geben, damit lernst du es dann ja doch
nicht.
Wieso nimmst du nicht einfach Basic? Und lass bitte das Argument der
Geschwindigkeit weg, wie oft pro Sekunde soll sich der Wert denn bitte
ändern?!?
@vbchaos: Ja, das Array empfangen enthält nur die Zeichen, und eben den
Punkt.
@Matthias: Danke für den Tip, werde ich dann gleich mal testen.
@Detlev T.: Ja, stimmt, ich rechne empfangen[3] noch mit ein, obwohl es
das ja gar nicht mehr gibt - der Wert von empfangen[3] steht ja in
empfangen[2]...
Ich hab eben ein bisschen rumprobiert, und das hab ich das dann einfach
übersehen....
@Jörg Stegemann: Wieso denkst du, ich habe keine Ahnung von Datentypen?
Ich habe sehr wohl ein C- Buch gelesen, und mir ist eigentlich auch
alles klar, was darin behandelt wurde.
Wieso sollte ich auf Basic umsteigen? Ich hab jetzt mit C angefangen,
und will auch dabei bleiben. Ich lerne eben noch und da kann man doch
auch Fehler machen, oder?
Und wenn mir nun jemand den richtigen Code gibt, dann werde ich den
nicht nur einfach reinkopieren, sondern ich schaue mir den dann genau
an, und versuche zu verstehen, wie das funktioniert....
Gruß, Steffen
Es ist offensichtlich, dass du den Unterschied zwischen char und byte
nicht kennst. Sonst wärst du nicht auf die Idee gekommen mit den ASCII
Werten zu rechnen, oder? Dann hast du anscheinend auch keine Ahnung von
den Wertelimits der verschiedenen Datentypen, denn die meisten deiner
Rechnungen dürften für Overflows sorgen.
Und die Idee mit Basic ist einfach: In den meisten Basicvarianten kommt
es auf den genauen Typ nicht an, die machen "automatisch" das Richtige.
Und mir scheint das ist genau das, was du brauchst.
BTW: Ist dir z.B. klar dass du beim Setzen von "knoten" den letzten Teil
(" + empfangen[3]") weglassen musst?
Jörg Stegemann wrote:
> Es ist offensichtlich, dass du den Unterschied zwischen char und byte> nicht kennst. Sonst wärst du nicht auf die Idee gekommen mit den ASCII> Werten zu rechnen, oder? Dann hast du anscheinend auch keine Ahnung von> den Wertelimits der verschiedenen Datentypen, denn die meisten deiner> Rechnungen dürften für Overflows sorgen.
Hmmm, laut meinem C- Buch kann selbst eine, als unsigned int deklarierte
Variable eine Zahl bis 4294967295 aufnehmen und die größte Zahl die bei
meinen Rechungen rauskommen wird, ist eigentlich nicht größer....Ich hab
ja auch noch double verwendet, da ist der Zahlenbereich noch größer!
> Und die Idee mit Basic ist einfach: In den meisten Basicvarianten kommt> es auf den genauen Typ nicht an, die machen "automatisch" das Richtige.> Und mir scheint das ist genau das, was du brauchst.
Ja, stimmt schon, aber ich will jetzt nicht plötzlich wegen sowas
umsteigen. Und es ist ja nicht so, dass das unmöglich ist zu lernen,
wenn ich noch ein bisschen Übung habe, klappt das bestimmt, da ist doch
ein Umstieg völlig unnörig.
> BTW: Ist dir z.B. klar dass du beim Setzen von "knoten" den letzten Teil> (" + empfangen[3]") weglassen musst?
Ja, hab ich im meinem vorherigen Post ja geschrieben, ist verbessert...
Naja, ich will hier jetzt auch nicht wegen so was rumdiskutieren, es
stimmt, ich bin eben noch Anfänger, und habe so etwas noch nie
gemacht....
Gruß, Steffen
Steffen O. wrote:
> Hmmm, laut meinem C- Buch kann selbst eine, als unsigned int deklarierte> Variable eine Zahl bis 4294967295 aufnehmen
Dann hast Du ein C-Buch für ein 32-Bit-System! Kleineren Systemen ist
(unsigned) int i.d.R. 16 Bit breit, dementsprechend sind nur 65536
unterschiedliche Werte möglich. Ein long int hätte auf der
AVR-Plattform 32 Bit.
> ....Ich hab ja auch noch double verwendet,
double ist ein Gleitkommaformat! Das ist was ganz anderes.
> da ist der Zahlenbereich noch größer!
Auf einem AVR hat double 32 Bit, genauso viel wie ein long int.
Johannes M. wrote:
> Steffen O. wrote:>> Hmmm, laut meinem C- Buch kann selbst eine, als unsigned int deklarierte>> Variable eine Zahl bis 4294967295 aufnehmen> Dann hast Du ein C-Buch für ein 32-Bit-System!
Ja, das könnte sehr gut sein, mein Buch beschäftigt sich mit dem
Programmieren von PCs....
> Kleineren Systemen ist> (unsigned) int i.d.R. 16 Bit breit, dementsprechend sind nur 65536> unterschiedliche Werte möglich.
Aber selbst da müsste ich 350 Knoten schnell sein, damit in der Zeile:
1
mh=knoten*185;
ein int nicht mehr reicht.
> Ein long int hätte auf der> AVR-Plattform 32 Bit.>>> ....Ich hab ja auch noch double verwendet,> double ist ein Gleitkommaformat! Das ist was ganz anderes.>> da ist der Zahlenbereich noch größer!> Auf einem AVR hat double 32 Bit, genauso viel wie ein long int.
Ah, ok...
Also muss ich es als double initialisieren, da ich ja Nachkommastellen
benötige (bei der Umwandlung mit Bibliotheksfunktionen).
Gruß, Steffen
@Steffen O.
Vorschlag für einen Algorithmus:
String vom GPS einlesen.
Schleife, die den String Zeichen für Zeichen in unsigned long umwandelt:
Test auf Dezimalpunkt: Falls nein: variable *10 + <Zeichen> - '0';
Falls ja: darauffolgendes Zeichen umwandeln und
Schleife abbrechen. (Oder noch zwei Zeichen) z.B. so:
1
unsignedlongkmh=0;
2
char*p=empfangen;
3
unsignedintcnt=10;/* maximale Stellenzahl */
4
5
while(cnt--)
6
{
7
if((*p)=='.')cnt=2;/* noch zwei Stellen und Schluss */
8
elsekmh=kmh*10+(*p)-'0';
9
p++;
10
}
(Ein Dezimalpunkt mit einer entsprechenden Anzahl Nachkommastellen muss
garantiert vorhanden sein!)
In der Variablen kmh hast du jetzt hunderstel Knoten.
Multiplizieren mit 185. In der Variablen sind jetzt zehntausendstel
km/h.
Durch hundert teilen. In der Variablen sind jetzt hunderstel km/h
ltoa verwenden, um die Zahl wieder in einen String zu verwandeln.
Vor den letzten beiden Stellen (strlen) einen Dezimalpunkt einfügen.
Ausgeben.
Ok, dank dir für deine Hilfe!
Ich wusste jetzt nicht, ob man mit itoa immer nur ein Zeichen
konvertieren kann, oder nicht, und deshalb siehts jetzt mal so aus:
1
unsignedcharempfangen[5],ausgabearry[10];
2
unsignedlongkmh=0;
3
char*p=empfangen;
4
unsignedintcnt=10;/* muss ich hier die genau maximale Stellenzahl angeben, oder kann das auch ein Wert sein, der dann noch ein wenig Reserve hat? */
5
....
6
empfangen[0]=uart_getchar();
7
empfangen[1]=uart_getchar();
8
empfangen[2]=uart_getchar();
9
empfangen[3]=uart_getchar();
10
11
empfangen[1]=empfangen[2];
12
empfangen[2]=empfangen[3];
13
14
while(cnt--)
15
{
16
if((*p)=='.')cnt=2;/* noch zwei Stellen und Schluss */
17
elsekmh=kmh*10+(*p)-'0';
18
p++;
19
}
20
21
kmh=kmh*185;
22
kmh=kmh/100;
23
itoa(kmh,ausgabearry,10);
24
lcd_string(ausgabearry);
Bis jetzt hab ich noch keinen Dezimalpunkt, das kommt noch, ist aber zum
Überprüfen jetzt nicht notwendig.....
Ich hab dann alles so umgeschrieben, und den Mega8 geflasht. Auf dem Lcd
kommen nun immer irgendwelche Nachkommastellenlose Werte (ist ja auch
klar, der Punkt fehlt ja noch), die aber immer irgendwie hin- und
herschwanken, mal im negativen Bereich, mal im positiven. Und das,
obwohl sich mein Empfänger mit 0.00 Knoten bewegt und dies der µC auch
empfängt! (Habe schonmal empfangen ausgegeben, und da kann dann immer
0.00)
Woran liegt das nun?
Vielen Dank schon einmal im Voraus.
Gruß, Steffen
Damit überschreibst du den Dezimalpunkt. Daher werden insgesamt 10
Zeichen gewandelt, obwohl das array nur fünf Zeichen lang ist. Was immer
auch dahinter im Speicher steht, wird mitgewandelt. Setze cnt am Anfang
auf die Gesamtzahl der Stellen ohne Dezimalpunkt (in diesem Fall 3)
Zudem liest das Programm nur vier Zeichen ein, was für je zwei Vor- und
Nachkommastellen plus Dezimalpunkt ist das zuwenig. Sendet der
GPS-Empfänger kein Zeilenende (CR oder so?)
@Detlef
Deine maximale Stellenzahl ist 11 und dafür ist 2^32 etwas knapp.
@Steffen
Das stimmt nur, wenn der Compiler vorher alles richtig macht. Zum
Beispiel ist es ein reiner Glücksspiel, ob bei "empfangen[0]*1000" das
Richtige heraus kommt oder nicht.
BTW:
for( int Index = 0; Index < sizeof( empfangen); Index++)
{
if( empfangen[ Index] == '.')
continue;
kmh = kmh * 10 + empfangen[ Index] - '0';
}
Das basiert auf meinem Verständnis von dem, was du erreichen willst. Ich
habe keine Ahnung, was das Inputformat wirklich ist, deswegen kann es
sein, dass der Code nicht immer funktioniert.
> Damit überschreibst du den Dezimalpunkt. Daher werden insgesamt 10> Zeichen gewandelt, obwohl das array nur fünf Zeichen lang ist. Was immer> auch dahinter im Speicher steht, wird mitgewandelt. Setze cnt am Anfang> auf die Gesamtzahl der Stellen ohne Dezimalpunkt (in diesem Fall 3)
Ok, hab ich nicht mitgedacht, bei meiner vorherigen Auswertung hab ich
den Deziamlpunkt nicht gebraucht, aber bei deiner Version benötige ich
ihn ja...
> Zudem liest das Programm nur vier Zeichen ein, was für je zwei Vor- und> Nachkommastellen plus Dezimalpunkt ist das zuwenig. Sendet der> GPS-Empfänger kein Zeilenende (CR oder so?)
Diese vier Zeichen sind Teil einer großen Strings, den der Empfänger
sendet. Vor der geschwindigkeit steht ein E und ein , und wenn diese
beiden Zeichen kamen, empfängt mein Programm die nächsten vier Zeichen,
und schreibt sie in empfangen. Wenn ich eben weniger wie 10 km/h fahre,
hat der String nur 3 Zeichen, fahre ich jedoch weniger als 100, aber
mehr wie 9.99, hat der String 4 Zeichen, usw. Das wird aber an anderer
Stelle schon ausgewertet, dann muss ich eben immer vor Schleife den Wert
von cnt anpassen.
Gruß, Steffen
Jörg Stegemann wrote:
> Deine maximale Stellenzahl ist 11 und dafür ist 2^32 etwas knapp.
Hat ein Moment gedauert, bis ich verstanden habe, was du meinst. cnt=10
war nur ein Beispiel. Genau wie du kenne ich nicht das Format, das der
GPS-Empfänger ausgibt. Allerdings bricht meine Schleife ja zusätzlich
nach zwei Nachkommastellen ab. Bei Geschwindigkeiten unter Mach 300 gibt
es also noch keinen Überlauf. Das sollte reichen :)
@Steffen O.
Auf deutsch: Du hast immer genau zwei Nachkommastellen, aber eine
wechselnde Anzahl Stellen vor dem Komma? Prima, dann umgehe doch einfach
dieses "empfangen" und mache es doch einfach so:
1
unsignedlongkmh=0;
2
charc;
3
charcnt=6;/* maximal 999 Knoten, aber eigentlich unwichtig */
4
5
while(cnt--)
6
{
7
c=uart_getchar();
8
if(c=='.')cnt=2;/* noch zwei Stellen und Schluss */
Ok, ich habe nun die besagten zwei Zeilen rausgenommen, die den
Dezimalpunkt überschrieben haben, und cnt auf 3 gesetzt. Wenn ich den µC
dann neu flashe, erscheint für kurze Zeit wirklich eine 0, dann jedoch
kommen wieder irgendwelche Zahlen. Woran liegt das nun schon wieder?
Der Empfänger gibt die Geschwindigkeit (in Knoten) in folgendem Format
aus: X.XX (bei einer Geschw. unter 10), XX.XX (bei einer Geschw. unter
100, über 9.99) und XXX.XX (bei einer Geschw. über 99.9, aber unter
500).
Bei ca. 500km/h hat der Empfänger keinen Empfang mehr, aber das benötige
ich eh nicht, so bis 200km/h sollte allemal ausreichen.
@Jörg Stegemann: Dein Beispiel sieht auch nicht schlecht aus, werde ich
auch mal testen....
Gruß, Steffen
Steffen O. wrote:
> Ok, ich habe nun die besagten zwei Zeilen rausgenommen, die den> Dezimalpunkt überschrieben haben, und cnt auf 3 gesetzt. Wenn ich den µC> dann neu flashe, erscheint für kurze Zeit wirklich eine 0, dann jedoch> kommen wieder irgendwelche Zahlen. Woran liegt das nun schon wieder?
Wird kmh vor jedem neuen Einlesen(!) wieder auf 0 gesetzt?
cnt=3 ist zudem falsch, wie mir gerade auffällt. Den Dezimalpunkt muss
man doch mitzählen.
cnt muss natürlich auch vor jeder Wandlung auf den entsprechenden Wert
gesetzt werden.
itoa hat doch vorher funktioniert. (Sollte dass nicht ltoa sein?) Da
hängt wohl was. Wie ist den uart_getchar() realisiert? Möglicherweise
dauert die Berechnung dafür zu lange. Dann musst du die Werte doch erst
einmal in ein Array einlesen und dann erst rechnen.
Hmmm, ja, stimmt itoa hat vorhin funktioniert....
Itoa wandelt eine als int deklarierte Variable in einen String um, ob
das eben auch bei long funktioniert?
Also ltoa wird auch ohne Murren compiliert, also werde ich es damit mal
versuchen.
cnt wird nun auch vor jeder Wandlung auf 4 gesetzt, also das passt.
uart_getchar() ist aus der Fleury lib, also uart_getchar() wartet bis
Zeichen da sind, dann werden auch noch Sachen wie Buffer Overflow, Frame
Error, usw. ausgewertet. Wenn ich es nur mit uart_getc() mache, dann
wartet er nicht, bis ein Zeichen da ist. Also eigentlich müsste das
passen, hat ja auch schon davor so funktioniert.
Ich kann die Änderungen leider erst in 15min testen.....
Gruß, Steffen
Also, bei der Lösung, bei der das Empfangene in c gespeichert wird,
kommt auf dem LCD nichts an. Ich werde jetzt nochmal die alter Routine
testen, bei der ganz normal alles empfangene in empfangen gespeichert
wird, und dann diese Variable ausgewertet wird.
Gruß, Steffen
Steffen O. wrote:
> ....> kmh = 0;> while(cnt--)> {> c = uart_getchar();> if(c == '.'){ cnt = 2; }/* noch zwei Stellen und Schluss */> else {kmh = kmh * 10 + c - '0';}> }>
Täusche ich mich, oder passiert mit den Nachkommastellen nichts?
Wenn Du den Punkt findest, sagst Du "noch zwei Stellen addieren".
Deren erste muss dann aber durch 10 geteilt werden, die zweite durch 100
etc!
1
kmh=0;
2
nachKomma=false;
3
teiler=1;
4
while(cnt--){
5
c=uart_getchar();
6
if(c=='.'){
7
cnt=2;/* noch zwei Stellen und Schluss */
8
nachkomma=true;
9
}
10
else{
11
kmh=kmh*10+(c-'0')/10^(teiler++);
12
}
13
}
Und mit welchem cnt-Wert gehst Du in die while.loop?
Und wenn kein dezimal-Punkt kommt?
Gruß Hanns
Hallo,
wenn die Geschwindigkeit in Knoten 4 Stellen mit Dezimalpunkt hat
(X.XX), dann gehe ich mit cnt = 4 in die Schleife. Wenn sie 5 Stellen
hat (XX.XX), dann eben mit cnt = 5.
Ein Dezimalpunkt kommt immer, da der Empfänger die Geschwingigkeit immer
mit zwei Nachkommastellen ausgibt.
Du könntest Recht haben mit dem Teilen, ich werde das mal testen - Danke
für den Tip!
Gruß, Steffen
Steffen O. wrote:
> Hallo,> wenn die Geschwindigkeit in Knoten 4 Stellen mit Dezimalpunkt hat> (X.XX), dann gehe ich mit cnt = 4 in die Schleife. Wenn sie 5 Stellen> hat (XX.XX), dann eben mit cnt = 5.
Das bedeutet aber, daß den Wert als String bereits kennst, bevor Du
einzelne
char umwandelst! DAnn kannst Du das ganze doch von hinten aufrollen:
Ganz rechts stehen die Hunderstel, davor die 10tel, dann komma, dann
mindestens ein Einer, und manchmal ein Zehner! Oder?
> Ein Dezimalpunkt kommt immer, da der Empfänger die Geschwingigkeit immer> mit zwei Nachkommastellen ausgibt.> Du könntest Recht haben mit dem Teilen, ich werde das mal testen - Danke> für den Tip!
Idh denke, damit habe ich Recht, denn nach dem Komma kommen immer die
10tel, dann 100tel i.e. n / (10 hoch PositionNachDemKomma )
> Gruß, Steffen
Ebenso Hanns
Hanns Weil wrote:
> Steffen O. wrote:>> Hallo,>> wenn die Geschwindigkeit in Knoten 4 Stellen mit Dezimalpunkt hat>> (X.XX), dann gehe ich mit cnt = 4 in die Schleife. Wenn sie 5 Stellen>> hat (XX.XX), dann eben mit cnt = 5.>> Das bedeutet aber, daß den Wert als String bereits kennst, bevor Du> einzelne> char umwandelst! DAnn kannst Du das ganze doch von hinten aufrollen:> Ganz rechts stehen die Hunderstel, davor die 10tel, dann komma, dann> mindestens ein Einer, und manchmal ein Zehner! Oder?
Ja, genau so ist es: Hundertstel, Zehntel, Dezimalpunkt, mindestens ein
Einer, machmal noch ein Zehner, und manchmal auch ein Hunderter. Ich
weiß davor, wie viel Stellen der String hat....
>> Ein Dezimalpunkt kommt immer, da der Empfänger die Geschwingigkeit immer>> mit zwei Nachkommastellen ausgibt.>> Du könntest Recht haben mit dem Teilen, ich werde das mal testen - Danke>> für den Tip!> Idh denke, damit habe ich Recht, denn nach dem Komma kommen immer die> 10tel, dann 100tel i.e. n / (10 hoch PositionNachDemKomma )
Ja, das müsste eigentlich stimmen....
Eine Potenz schreibe ich in c doch so: Grundzahl^Hochzahl
Gruß, Steffen
Matthias Lipinsky wrote:
>>Eine Potenz schreibe ich in c doch so: Grundzahl^Hochzahl>> NEin.>> Das ^ bedeutet in C xor.
Ah, ok. Wie schreibe ich es dann?
Steffen O. wrote:
> Hmmm, dann schreibe ich eben zur Übung eine kleine Potenzfunktion ;-)
Ich würde mir meine Function nochmals überlegen:
- Ich hab die "Zahl" als String
- den will ich wandeln
- das mach ich in einer subroutine
- dort lese ich mit uart_getch() nochmals Zeichen ein, die ich alle
schon habe?!
- Warum übergebe ich dann der Function nicht den bereits vorhanden
string, und arbeite den ab?
- Da kannst DU dann von vorn oder hinten beginnen, den String zu
verarbeiten.
-beginne ich von hinten, weiß ich VOR dem Komma IMMER, mit welchen
FActor die einzelnen Zahl zu multiplizieren ist.
in etwas so. Wobei ich mal davon ausgehe, es handelt sich tatsächlich
umne funktion )
Das kann nicht stimmen. Warum das eine mit 10 multiplizieren UND das
andere noch dividieren? Bei dem zweiten Term kommt übrigens immer null
heraus, da c-'0' eine Zahl zwischen 0 und 9 sein soll.
Meine Idee war es die long int Variable kmh als hunderstel(!) mph zu
interpretieren und entsprechend damit zu rechnen, also faktisch als
Fixkomma Zahl, die es nativ in C aber nicht gibt. Alternativ könnte man
mit Fließkommazahlen arbeiten, was allerdings dem Wunsch von Steffen
nach einer schnellen Verarbeitung entgegenläuft. Dann braucht man aber
keine eigene Wandelroutine, sondern kann gleich die
Bibliotheksfunktionen (atof, strtof) nehmen.
Vielen Dank erstmal an alle für eure Unterstützung!!!!
Hanns Weil wrote:
> Steffen O. wrote:>> Hmmm, dann schreibe ich eben zur Übung eine kleine Potenzfunktion ;-)>> Ich würde mir meine Function nochmals überlegen:>> - Ich hab die "Zahl" als String> - den will ich wandeln> - das mach ich in einer subroutine> - dort lese ich mit uart_getch() nochmals Zeichen ein, die ich alle> schon habe?!
Ich lese keine Zeichen nochmal ein. Die Geschwindigkeit in Knoten wird
vom GPS- Empfänger per UART empfangen, und anschliessend als String
gespeichert. Und nun muss diese Zahl im String umgewandelt werden.
> - Warum übergebe ich dann der Function nicht den bereits vorhanden> string, und arbeite den ab?
So will ich es doch machen.....
> - Da kannst DU dann von vorn oder hinten beginnen, den String zu> verarbeiten.
Ja, genau.
> -beginne ich von hinten, weiß ich VOR dem Komma IMMER, mit welchen> FActor die einzelnen Zahl zu multiplizieren ist.> in etwas so. Wobei ich mal davon ausgehe, es handelt sich tatsächlich> umne funktion )
Es ist doch eigentlich egal, ob ich von vorne, oder von hinten beginne,
da ich ja schon davor weiß, wie viel Zeichen vor_ und wie viele _nach
dem Dezimalpunkt sind.
>
1
>
2
>doublewandle_String_in_Double(stringtheString){
3
>
4
>doubletheReturn;
5
>intlen;
6
>booleannachkomma;
7
>intnPow;// Exponent zu 10
8
>
9
>theReturn=0.00;
10
>len=Laenge(theString)
11
>nachkomma=true;
12
>nPow=2;// beginne mit zweiter NAchkommastelle
13
>
14
>while(nLaenge--){
15
>wenn(DezimalPunkt){
16
>nachkomma=false;
17
>nPow=1;// vorbereiten für Multiplikation
18
>continue;// weiß, dass das nichtbeliebt ist
19
>}
20
>wandledenBuchstabenanPosleninInt;
21
>wennnachkomma,{
22
>teiledurch10HochnPow;
23
>nPow--;
24
>}else{//Vorkommastellen
25
>multiplizieremit10hochnPow;
26
>nPow++;
27
>}
28
>addierzutheReturn
29
>}
30
>
31
>returntheReturn;
32
>}
33
>
Ja, das sieht schon nicht schlecht aus!
Ich werde es dann heute oder morgen mal coden, muss eben schauen, wann
ich mal ein wenig Zeit finde.
Die Funktion zum Potenzieren hab ich übrigends spaßeshalber mal
geschrieben, klappt wunderbar....
Gruß, Steffen
@Steffen O.
Wenn du dich also jetzt entschlossen hast, doch Fließkommazahlen zu
verwenden, warum benutzt du nicht einfach die Funktion strtod? Oder
erfindest du gern das Rad neu?
Detlev T. wrote:
> @Steffen O.> Wenn du dich also jetzt entschlossen hast, doch Fließkommazahlen zu> verwenden, warum benutzt du nicht einfach die Funktion strtod? Oder> erfindest du gern das Rad neu?
Nein, ich wollte eigentlich nicht mit Fließkommazahlen arbeiten. Mit dem
"Das sieht doch gut aus" meinte ich nicht den kompletten Ausschnitt,
sondern Teile daraus, die ich so übernehmen kann....
Sorry, für die Missverständnisse.
Gruß, Steffen