Serial.write() Problem

Hallo Zusammen,

ich möchte über die Funktion Serial.write(); Daten an PC (LabView) schicken. Ich habe boolean, int, float Datentypen. (Bei boolean und int bis 255 klappt es, da nur ein Byte benötigt wird.) Laut arudino.cc gibt Serial.write(val) ,Serial.write(str) und Serial.write(buf, len) zur Auswahl.

Ich habe festgestellt, dass ich z.B. bei Serial.write(analogRead(A0)); nur ein Byte erhalte. Danach habe ich über die Funktion String(analogRead(A0)); versucht ein String zu machen und zu übertragen. Leider kam eine Fehlermeldung. Strings können nur über Serial.print(); versendet werden (laut einem thread).
In einem Forum kam ich auf die union Funktion:

union memory
{
float fl;
byte bytes[4];
}
union memory value;
value 12.2;
Serial.write(value.bystes,4);

Nun kommt eine Fehler:
“Communicate.ino: In function 'void loop()':
Communicate:34: error: no match for 'operator=' in 'value = 1.219999980926513671875e+1'
Communicate.ino:27: note: candidates are: loop()::memory& loop()::memory::operator=(const loop()::memory&)”

Wie kann ich am besten int, float über serial.write(); verschicken?
z.B.:
int x;
x=1200;

float y;
y=12.24;

Ich Danke im Voraus für eure Hilfe.

Beste Grüße Kalle

Warum nicht Serial.print nutzten? Wegen den float Zahlen, da müsstest du mal eben bei Google schauen. Irgendwo gibt es die Möglichkeit, die Serial Klasse dafür auszubohren. Sinnvoller ist es aber, Daten mit Festkommaarithmetik zu übertragen.

Serial.print habe ich probiert. Leider kommt nicht das gewünschte Ergebnis, wenn ich aus Serial.write ein Serial.print mache.

Serial.write("AA"); //Adresse für die case-Fkt.
Serial.write(digitalRead(SWITCH));
delay(50);
Serial.write("AB");//Adresse für die case-Fkt.
Serial.write(1200);
delay(50);
Serial.write("AC");//Adresse für die case-Fkt.
Serial.write(44);
delay(50);
Serial.write("AD");//Adresse für die case-Fkt.
Serial.write(10);
delay(50);

Hast du eine Idee wie ich aus int Wert 2 bytes mache? Dann könnte ich byteweise die Werte senden und in LabView wieder zusammenbringen.

beste grüße

Hab ein weg gefunden aus einem integerWert ein byte array zu erhalten.
Jetzt fehlt nur noch der float Wert.

Beste Grüße

Kalle

Ps.: hier ein minimalbsp.

long bytesToInteger(byte b[4]) {
long val = 0;
val = b[0] << 24;
val |= b[1] << 16;
val |= b[2] << 8;
val |= b[3];
return val;
}

void setup() {
// initialize serial:
Serial.begin(115200);

...

}

void loop() {}

byte b[4];
integerToBytes(1056964608, b);
for (int i=0; i<4; ++i) {
Serial.write((int )b*);*

  • }*
int x = 1200; // 00000100|10110000
uint8_t x1 = x & 0xFF; // 10110000 HighByte
uint8_t x2 = (x >> 8) & 0xFF; // 00000100 LowByte

Auf der Gegenseite einfach wieder so zusammensetzen.

int y = (x2<<8)+x1;

Edit: Sehe schon, die Idee hat ein paar Funktionen dafür parat :wink:

Floatzahlen kannst du nach der Festkommarithmetik, wie oben geschrieben verarbeiten.

float value = 10.123;
int x = value*1000;
uint8_t x1 = x & 0xFF;
uint8_t x2 = (x>>8) & 0xFF;

Vielen Dank für den zusätzlichen Tipp.

Beste Grüße ins Münsterland.

Am einfachsten ist es immer man macht einen Cast der Adresse auf ein Byte Array. Das ist in C simpel, da Arrays nicht viel mehr als Zeiger auf das erste Byte sind:

float f = 12.3456;
byte* b = (byte*)&f;

Dann kann man das als Array betrachten:

Serial.write(b, 4);

Und muss man gar nichts Schieben und ausmaskieren.

Anders herum dereferenziert man einfach den Zeiger nach dem Cast:

float f2 = *(float*)b;

Funktioniert genauso mit int oder long.