Wire.read -> (un)signed char/short/int/long/longLong/float/double ->Wire.write

Hallo,
ich nutzte IDE 1.8.5 und Wire.h und tausche über I2C Daten mit einem Python-Programm auf einem Raspi aus.

In Python gibt es ein Anweisungspärchen pack/unpack mit dem Daten einfach und flexibel aus/in unterschiedliche Formate umgesetzt werden können. 7.3. struct — Interpret strings as packed binary data — Python 2.7.18 documentation
Ich suche etwas vergleichbares für c++.

Ich möchte char* aus dem read möglichst mit einer variablen Anweisung in das jeweils gewünschte Format (Kennzeichen wird passend zu den Bytes ebenfalls als Variable mitgegeben) umsetzen und umgekehrt für den Rückweg.

Jetzt mache ich das über (byte*)&intVar; (byte*)&longVar; usw. bzw. memcpy (&longVar, chrBuf, sizeof (long)); usw.

Zum einen individuell pro Format, zum anderen kein so schönes Anweisungspärchen

Da in c++ (anders als in Python) eine Variable einem festen Type zugeordnet ist , wird es vermutlich zumindest für float eine Ausnahme erfordern. Alle anderen Type unterscheiden sich ja nur in der Anzahl Bytes.

Gibt es etwas ähnlich schönes für c++?

Für die Übertragung ist ein Float auch nur eine Folge von 4 Bytes. Struct gibt es auch.
Wo Du evtl. Probleme bekommen könntest, ist die unterschiedliche Länge der Variablen in beiden Systemen und die Ausrichtung im struct.

Gruß Tommy

Beliebige Datentypen per I2C geht einfach mit einer Union aus dem Datentyp (oder einem anonymen struct) und einem Byte Array.

z.B.:

union Data
{
  float value;
  byte asBytes[sizeof(float)];
};

Oder für mehrere Variablen:

union Data
{
  struct
  {  
     float value1;
     float value2;
  };
  byte asBytes[sizeof(float) * 2];
};

In einer Union teilen sich alle Elemente den gleichen Speicherplatz. Wenn man also Byte-weise per read() ausliest und in das Array schreibt, hat man direkt die Variablen. Und ein Array kann man in einem Rutsch auch mit write() senden (was auch im Request Event Handler so nötig ist!)

Bei der Übertragung auf einen 32/64 Bit Computer musst du auch auf die unterschiedliche Größe der Datentypen achten. Auf einem AVR Arduino mit 8 Bit hat int nur 2 Bytes. Auf einem PC hat int 4 Bytes. Double hat auf einem AVR 4 Bytes. Auf dem PC 8.

Dein Link ist super. Kurz oberhalb (7.3.2.1. Byte Order, Size, and Alignment) steht noch mehr sinnvolles.

the packed representation uses the IEEE 754 binary32 (for ‘f’)

Arduino verwendet auch IEEE 754 und ist Little-Endian, (Raspbi weiss ich nicht)

Use sys.byteorder to check the endianness of your system.