unsigned char array elemente verbinden

Hallo allerseits,

bevor ich zu meinem Problem komme, erstmal was zum Projekt.

Mit dem CAN BUS Shield sende ich eine Anfrage an ein Messmodul welches mir Daten zurück sendet.
Diese Daten sind in einem Array[8] von denen ich aber nur Array[2]-Array[5] benötige. Das Problem nun ist aber das die Daten ein Messwert in float sind und im Array gesplittet werden. Also aus 187197169101 wird dann {101,169,197,187}. Muss also die Daten zusammensetzen und dann in float umwandeln. In meinem Code soll das ganze zurzeit noch über Serial.print() ausgegeben werden, wird aber später über ein LCD Display ausgegeben.

Also konkret, wie kann ich die einzelnen Elemente des Arrays wieder zu einer Zahl zusammen setzten?

Ich hab schon einige Lösungsansätze gefunden, allerdings behandeln diese nicht unsigned char sondern nur char.

Könnt ihr mir da irgendwie weiter helfen? Sollten die Lösungen für char auch für unsigned char klappen?

Hab es z.B. mit der Methode versucht: Variablen verketten
hat aber leider nicht zum Erfolg geführt.

Stehe im Moment ziemlich auf dem Schlauch und hoffe einer da draussen kann mir weiter helfen. Vielleicht ist die Lösung ja einfacher als gedacht und ich seh den Wald vor lauter Bäumen nicht mehr.

// demo: CAN-BUS Shield, receive data with check mode
// send data coming to fast, such as less than 10ms, you can use this way
// loovee, 2014-6-13

#include <SPI.h>
#include "mcp_can.h"


// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 10;
const int LED        = 8;
boolean ledON        = 1;

MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

void setup()
{
    Serial.begin(115200);
    pinMode(LED,OUTPUT);

    while (CAN_OK != CAN.begin(CAN_250KBPS))              // init can bus : baudrate = 250k
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println("Init CAN BUS Shield again");
        delay(100);
    }
    Serial.println("CAN BUS Shield init ok!");

}

unsigned char stmp[8] = {0x0F,0x00,0x00,0x00,0x00,0x00,0x55,0x30};


void loop()
{
  unsigned char len = 0;
  unsigned char buf[9];
  unsigned char newbuf[5];
  newbuf[0] = buf[2];
  newbuf[1] = buf[3];
  newbuf[2] = buf[4];
  newbuf[3] = buf[5];
 

    if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
    {
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

        unsigned char canId = CAN.getCanId();
        
        Serial.println("-----------------------------");
        Serial.println("get data from ID: ");
        Serial.println(canId);
        for(int i = 0; i<len; i++)    // print the data
        {
            Serial.print(buf[i]);
            Serial.print("\t");
            if(ledON && i==0)
            {

               digitalWrite(LED, buf[i]);
               ledON = 0;
               delay(500);
            }
            else if((!(ledON)) && i==4)
            {

               digitalWrite(LED, buf[i]);
               ledON = 1;
            }
        }

        Serial.println();
    }

  CAN.sendMsgBuf(0x300,0,8,stmp);
  delay(100);
  

}

Hab meine Sache zurzeit im Labor, kann es also nicht direkt Testen aber erstmal danke für den Tip.
Was findest du eigenartig daran?

Allerdings ändern sich die Werte auch ständig. Hatte auch schon Daten von 61.20.2.207 - {207,2,20,61}, dann würde deine Formel nicht mehr passen. Aber trotzdem danke für den Hinweis

Wenn es sich um eine float Zahl im Binärformat handelt, dann liefert ein Typecast (float)buf[2] o.ä. auf das erste Byte den Wert als float. Das aber nur, wenn die Codierung von float bei Sender und Empfänger übereinstimmt, und auch die Bytes in der richtigen Reihenfolge (byte order) gesendet werden.

@DrDiettrich hast du ein Beispiel dafür, kann es mir noch nicht so recht vorstellen.

@noiasca tut mir leid aber mein Taschenrechner scheint dann anders zu funktionieren aber ich komm sowohl Handschriftlich als auch mit meinem Rechner nicht auf das Ergebnis.

        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
       float val = *(float*)(&buf[2]);

So etwa :wink:

noiasca:
also wenn das wirklich so ist

187197169101 wird dann {101,169,197,187}.

und du hast das Array,

dann ist das x[0]+x[1]*100+x[2]*10000+x[3]*1000000

finde ich aber eigenartig.

Das was Du rechnest ist eine 4 Sstellen lange Dezimalzahl und keine 4 Byte Zahl (101,169,197,187) da ist die Zahlenbasis 256 also wennschon
x[0]+x[1]246+x[2]256256+x[3]256256256
Aber der TO hat eine Fließkommazahl. Bei Arduino ist das eine 32 Bit Fließkommazahl.
siehe Einfache Genauigkeit – Wikipedia
die 32 Bit setzen sich zusammen aus 1 Bit Vorzeichen, 8 bit Exponent und 23 bit Mantisse
also anders gesagt
(-1+2*Bit 31) *(Bit0 bis Bit22) *2^(Bit23 bis bit30)

Grüße Uwe

noiasca:
61.20.2.207 - {207,2,20,61}
also

61000000+
200000+
2000+
207

Das ist wohl nur zur Verwirrung.

tobbe_tobsen:
Also aus 187197169101 wird dann {101,169,197,187}

.
Das ist auch verwirrend, wenn 187197169101 eine einzelne Zahl sein soll. Aber ich gehe mal davon aus, dass es die Ausgabe von

        for(int i = 0; i<len; i++)    // print the data
               Serial.print(buf[i]);

ist.
buf[0] wäre dann 187 und

byte buf[4] = {187,197,169,101};
float f = * (float*) buf; // 0x65a9c5bb = 1.0021593*10^23 eher seltsam.

Bei umgekehrter Reihenfolge {101,169,197,187}
ergäbe sich 0xbbc5a965 =  -0.0060321563, auch nicht wirklich überzeugend.

Sicher, dass du da eine IEEE-754 float32 Zahl in deinem CAN-Bus Protokoll hast?

Mein Lieblings-Spielzeug ist übrigens www.h-schmidt.net/FloatConverter/IEEE754de.html

michael_x:
Mein Lieblings-Spielzeug ist übrigens www.h-schmidt.net/FloatConverter/IEEE754de.html

Oh, das ist ja ein sehr nettes Tool. Das kommt gleich auf meine Linkliste!

@michael_x danke für die Antwort, hat mein Problem gelöst. Die Werte stimmen soweit, es geht um eine Gasmessung bei der sich der Wert um die Null herum bewegt. Vielen Dank nochmal.