Forum: PC-Programmierung VB.net single -> avr float -> VB.net single


von Bassti (Gast)


Lesenswert?

Hallo,

ich versuchs mal möglichst kurz zu machen. Ich hab mich schon über die 
besagte Thematik informiert. Leider gabs keine wirklich guten 
Lösungsansätze dafür...

Also das Versenden des Single Wertes über UART als Binärstring klappt 
super, der erwartete Wert kommt beim AVR so an wie er soll. Nur leider 
klappt das rücklesen nicht. Dort wird ein gesendetes 0,004 zu 
0,0029xxxx...

Das ganze wird erst problematisch bei kleineren Zahlen nach dem Komma...
Da das Versenden problemlos funktioniert, scheint evtl die VB Funktion 
BitConverter.ToSingle() Probleme zu verursachen... Gibts hier 
alternative Funktionen?

Ich weiß das in jedem Prozessor die Gleitkommazahlen anders gehandhabt 
werden können, aber mit einer entsprechend guten Funktion müsste doch 
die AVR Darstellung der float Zahl wieder herstellbar sein. Eine 3 
stellige Genauigkeit würde mir völlig ausreichen, obwohl float/single ja 
eine 7 stellige besitzen sollte...

Schonmal danke

MfG

Basti

von Peter II (Gast)


Lesenswert?

dann finde doch erstmal die genaue ursache.

Las dir das sigle als HEX am PC anzeigen, dann übertrage es zum AVR. 
Lass es dir wieder als Wert und als Hex anzeigen. Wenn du es jetzt 
erneut zum PC überträgst dann sollte es ja noch der gleiche HEX wert 
sein. Wenn du jetzt BitConverter.ToSingle() aufrufst dann muss auch 
wieder das gleiche rauskommen.

von Bassti (Gast)


Lesenswert?

Ja die Ursache liegt zwischen AVR zu PC (VB.net)
Durch LCD am AVR seh ich ja, dass ein sinnvoller float angekommen ist...
Dabei ist mir egal ob aus dem 0,004 -> 0,00398 geworden ist...

Aber wenn ich das ganze zurück an den Rechner sende, verhaut es mir die 
Zahl um ~40%

Achso das Senden in C (AVR) hab ich so veranstaltet:
1
union konverterf
2
{
3
  unsigned char      c[4];   //4 Byte
4
  float       f;     //4 Byte
5
};
6
7
8
void uart_putf(float data)
9
{
10
    union konverterf z;
11
12
  z.f = data;
13
14
  uart_putc(z.c[0]);
15
  uart_putc(z.c[1]);
16
  uart_putc(z.c[2]);
17
  uart_putc(z.c[3]);
18
19
20
}/* uart_putf */


Das einlesen in VB über den besagten BitConverter und dem SerialPort 
Interface + SerialPort.Encoding = Encoding.GetEncoding(28591).

Beide Baugruppen laufen bei mir schon seit nem Jahr "problemfrei"... 
heute hab ich solch kleine Zahlenwerte versenden wollen und da bin ich 
erstmal darauf gestoßen... :-/

MfG

Basti

von Peter II (Gast)


Lesenswert?

Bassti schrieb:
> Aber wenn ich das ganze zurück an den Rechner sende, verhaut es mir die
> Zahl um ~40%

wenn du aber einen Wert zum AVR schickt und diesen gleich wieder zurück 
zum pc müssen bei PC erstmal die gleiche Daten (also diese 4bytes) 
ankommen. Hast du das geprüft?

von Bassti (Gast)


Lesenswert?

So, hab mal nachgeschaut...

Also zuerst was raus geht mit folgendem Hilfsmittel:

MsgBox(BitConverter.ToUInt32(xxx))

Das Ergab in Hex umgerechnet: 3B83126F

Dann das was der Controller Sendet mit HTerm abgefangen: 3B83126F

Und nun was mein Programm draus macht... selbe Funktion wie oben UInt32: 
3B3F126F


kA was das soll :-/ genau in der Mitte stimmt was nicht...

von Peter II (Gast)


Lesenswert?

welche gleitkommazahl soll denn die 3B83126F darstellen?

von Peter II (Gast)


Lesenswert?

das kommt bei mir raus:

byte[] a = new byte[4];
a[0] = 0x3B;
a[1] = 0x83;
a[2] = 0x12;
a[3] = 0x6F;

Single s = BitConverter.ToSingle(a, 0);

//s = 4.534346E+28

a[3] = 0x3B;
a[2] = 0x83;
a[1] = 0x12;
a[0] = 0x6F;

Single s2 = BitConverter.ToSingle(a, 0);
//s2 = 0.004

von Bassti (Gast)


Lesenswert?

dann ist der Fehler evtl bei der Encoding.GetEncoding Zeile zu suchen... 
was stellst du denn für ein Code ein?

Erstmal danke für deine Hilfe...

von Peter II (Gast)


Lesenswert?

Bassti schrieb:
> dann ist der Fehler evtl bei der Encoding.GetEncoding Zeile zu suchen...

der Fehler ist das du überhaupt Enconding verwendest. Wenn du binary 
Daten austauscht dann hat das dort nichts zu suchen!

von Bassti (Gast)


Lesenswert?

Wenn ich die Zeile auskommentiere hab ich aber den selben Fehler im 
float lesen und meine signed short variablen sind alle positiv...
auch nicht viel besser...

Jedenfalls würde ich die Funktion des BitConverters erstmal als 
Funktionsfähig bezeichnen... aber das Serialportinterface braucht noch 
die richte Codierung :-/

von Peter II (Gast)


Lesenswert?

Bassti schrieb:
> aber das Serialportinterface braucht noch
> die richte Codierung

nein braucht es nicht, du darst auf keinen fall ein String lesen, du 
musst ein byte array lesen! Und bytes haben keine codierung.

von Bassti (Gast)


Lesenswert?

Ach verdammt, dafür müsste ich das komplette Programm umstricken :-/

von Peter II (Gast)


Lesenswert?

Bassti schrieb:
> Ach verdammt, dafür müsste ich das komplette Programm umstricken :-/

dann hast du aber kein sauberes design, normalweise sollte senden und 
empfangn zentral an einer stelle sein. von dort geht es dann mit eigenen 
Datentype und stukturen weiter.

Zeig doch mal den code.

von Bassti (Gast)


Lesenswert?

freu habs gerade noch hinbekommen... das erspart mir nen Haufen 
Arbeit...

Also das mein VB Code nicht wirklich sauber ist, dass weiß ich... Ist 
mehr zusammen gegoogelt... bin eher C programmierer... demnächst wird 
das Tool noch auf C# portiert... obwohl das ja auch nicht viel mit C 
aufn AVR am Hut hat...

Achso, hier die Lösung:

Wenn ich dem Serial Port die Encodernummer 28591 zuweise, dann muss ich 
beim decodieren vom String in ein Byte arryer mit 
System.Text.Encoding.GetBytes auch die selbe encoding Nummer 
vorwählen... die stand noch auf default... :-/
peinlich peinlich...

Danke für deine Mühe!!!

MfG

Basti

von Peter II (Gast)


Lesenswert?

Bassti schrieb:
> Achso, hier die Lösung:
> Wenn ich dem Serial Port die Encodernummer 28591 zuweise

das würde ich nicht als Lösung betrachten, mehr als Workaround. Die 
Verwendung von Strings ist hier einfach falsch und kann dir immer wieder 
probleme machen. Du hast keine Strings! du übeträgst einfach DATEN und 
diese speicher man nun mal nicht in strings sondern in byte arrays.

von Bassti (Gast)


Lesenswert?

Mag sein, aber möchte gern die praktische Funktion 
SerialPort.ReadTo(abschlusszeichen) benutzen. (zu faul was selbst zu 
schreiben)

Und wenn ichs hin und her codiere gehts ja auch erstmal, sollte man halt 
nur mit dem selben Encoder machen... =)
Bei nächsten Projekt werd ich dann gleich mit Bytes anfangen...

von Peter II (Gast)


Lesenswert?

Bassti schrieb:
> Mag sein, aber möchte gern die praktische Funktion
> SerialPort.ReadTo(abschlusszeichen) benutzen. (zu faul was selbst zu
> schreiben)


do {
  byte b = SerialPort.ReadByte();
  data.add(b);
} while( b != abschlusszeichen )


> Und wenn ichs hin und her codiere gehts ja auch erstmal, sollte man halt
> nur mit dem selben Encoder machen... =)
und du hast auch alle Steuerzeichen getestet? Du weist also genau wie 
dein codierung auf jedes Zeichen reagiert - dann ist ja gut. Ich würde 
mich nicht darauf verlassen.

von Peter II (Gast)


Lesenswert?

wenn du mit SerialPort.ReadTo(abschlusszeichen) arbeitest wie stellst du 
überhaupt sicher das sich in deinem single sich das Abschlusszeichen 
nicht befindet?

von Bassti (Gast)


Lesenswert?

darüber das der scalierungswert nur von 1 bis 0,001 geändert werden kann 
und das Abschlusszeichen sich nicht in dem Bereich befindet -> z.b. 
exponent

Ich seh ein, dass es nur ne Notlösung ist... aber da es Hobbybereich 
betrifft werd ich nicht mehr alles auf Byte ummünzen... zumal es bald 
eine komplett neue Software gibt...

Wie würde man denn am besten sicher stellen das es wirklich das 
Abschlusszeichen ist, wenn man alle float-varianten drin hat?

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.