Datentypen konvertieren in Byte

Hallo zusammen, ich muss ein int, oder Long, oder float in ein Byte Datentyp konvertieren.

Der Wert ist zum Beispiel int Drehzahl = 1500 . Wenn ich nun das via I2C an einen anderen Mega sende, kommt nur die Aufteilung 0 bis 255 als Wert an.

Im Web gibt's ein paar Sachen über I2C und Übertragung von Datentypen, was nicht so richtig bei mir funktionierte. Die Übertragung funktionierte dann nicht mehr. Ich würde also gerne vorher den richtigen Datentyp Byte auf die Reise schicken.

Hat jemand eine Idee wie ich Datentypen umrechnen/konvertieren kann?

Ich danke euch.

LG Christian (Anfänger)

für int z.B. könntest du itoa nehmen

Es gibt nur zwei Wege, größere Zahlen byteweise zu übertragen:

a) Aufteilen in so viele Bytes, wie für den zu transportierenden Datentyp notwendig - also z.B. für ein einfaches Int auf zwei Bytes im Prinzip:

b1 = x mod 255 , b2 = x div 255 dann übertragen und nach dem Empfang: x=b2*255 + b1

b) du skalierst den Wert mittells Division herunter, bis er in ein Byte passt und nach dem Empfang per Multiplikation wieder hoch. Dabei verlierst du nat. "Auflösung" (Anzahl der Stufen).

@ ardubu:

öhhh itoa sagt mir jetzt nichts, bedenke ich programmiere erst seit 4 Wochen :-)

Kannst du weiter ausführen?

@ qualiat:

Danke ist ja doch recht komplex aber jetzt hab ich den Hintergrund verstanden. Danke. Ich schau mal was bei der Division rauskommt. Die Zieldrehzahl 1500 werde ich eh mit dem Diesel nur umkreisen können. Da gibt es ein bisschen Luft na oben und unten. (BHKW)

Danke und Grüße Christian

schau einmal hier: itoa

Musst zwischen byte und byte Array unterscheiden. Ein int besteht ( beim Arduino) aus 2 byte, ein long und ein float aus 4 byte. Mit itoa kannst du ein int in Text umwandeln, der besteht aus mehreren Buchstaben, die je ein byte groß sind(+ Endekennung) Für den Text "1500" brauchst du also min. 5 byte.

Man kann per I2C mehrere Byte übertragen, dazu hilft dir vielleicht die c - union, mit der man den gleichen Speicherbereich auf verschiedene Arten behandeln kann. Siehe z.B. hier http://forum.arduino.cc/index.php?topic=288713.0


Einfacher ( bei vermutlich ausreichender Genauigkeit ) ist natürlich die Skalierung auf ein einzelnes Byte

   byte compressed_data = analogRead(A0) / 4; // ( 0 .. 255 )

itoa() ist Blödsinn. Er will keine Strings versenden!

Union ist ein sehr schöne Option. Das geht vor allem mit allen Datentypen

Bei Integern kann man auch einfach nach rechts schieben:

int value = 1500;
byte low = value;   //wird automatisch gekürzt
byte high = value >> 8;    //oberes Byte

Das geht genauso mit long wenn man nochmal >> 16 und >> 24 macht. Bytes wieder in int wandeln geht dann mit links schieben und verodern.

Für int gibt es in der IDE auch fertige Makros: https://www.arduino.cc/en/Reference/LowByte https://www.arduino.cc/en/Reference/HighByte

Und wieder nach int hiermit: https://www.arduino.cc/en/Reference/WordCast

Union ist ein sehr schöne Option. Das geht vor allem mit allen Datentypen

Da kann es durchaus derbe Unterschiede zwischen Prozessoren und Compilern geben. Im Einzelfall möglich, aber nicht portabel.

nicht portabel.

I2C Datenübertragung ist relativ hardwarenah. Da würde ich mir um Portabilität Gedanken machen, wenn es soweit ist ;)

Christian, erzähl doch mal, wohin und warum du die Drehzahl (egal ob 1500, (byte)150, (byte) 1500*256L/6000 oder "1500" oder was auch immer) senden willst.

Da kann es durchaus derbe Unterschiede zwischen Prozessoren und Compilern geben.

Wenn man komplett verschiedene Systeme hat. Hier geht es um Mega zu Mega. Da ist das kein Problem. Außerdem will er auch long und floats verschicken. Da braucht man was anderes.

Eine andere Option sind Templates, Zeiger und Casts:

#include <Arduino.h>
#include <Wire.h>

const byte DEVICE_ADR = 0x50;

template<typename T>
void send(T value)
{
  Wire.beginTransmission(DEVICE_ADR);
 
  byte* b = (byte*)&value;
  for (byte i = 0; i < sizeof(T); i++)
    Wire.write(*(b++));

  Wire.endTransmission();
}

Das muss in einen Header den man dann im Sketch inkludiert.

Damit erschlägt man alle möglichen Datentypen auf einmal. Geht sogar mit structs.

Aber Achtung:
Das geht nicht im onRequest() Event Handler da man da nur ein einziges mal write() machen kann. Wenn das mit einem Event Handler laufen soll ist die Union das einfachste, da man ein Array in einem einzigen write() verschicken kann.

Super vielen Dank für Eure Unterstützung. Es funktioniert.

Ich habe mich durch ein teilen und malnehmen durch 10 entschieden, da dieses für mich ausreichend genau ist.

Wenn ich jetzt noch wüsste warum mein I2C Display ab und zu abstürzt....

Ich überlege gerade ob es Sinn macht einen extra Post aufzumachen. Aber kurz zu diesen Fall da dieser mit dem zu tun hat:

Über millis 3 Sekunden wird das I2C Display neu beschrieben LCM1602 . Am Bus hängt ein zweiter Mega der das Messen der Drehzahl und senden übernimmt. Der zweite ist der Master. Der Slave schreibt das Display. Es kann sein das nach 3 Minuten oder nach 10 h das Display Zeichenmüll anzeigt. Es stürzt nie ab wenn der Zweite Mega nicht am Bus ist. Master/Slave Rolle habe ich schon mal getauscht. Der Fehler ritt häufiger auf wenn tatsächlich gemessen wird , da liegen wir dann bei 2 Minuten mit zum Reset. Übrigens die Programme laufen weiter, nur das Display stirbt. Auch Millis auf 10 Sekunden zu erhöhen bringt nichts. Millis kleiner gleich 2 Sekunden bringt es sofort zum Absturz.

Ich habe mir auch ein Neues gekauft, selber Effekt. Display alleine am Bus läuft durch. Strom: Über Netzteil ein Mega versorgt das Display und auch den zweiten (Master) Mega. Im I2C habe ich auch 2 Wiederstände auf SCL und SDA zu 5V gelegt. jeweils 10k. Brachte aber nichts.

Jemand eine Idee?

Danke und Grüße Christian

@ michael_x

Ich habe nur deshalb einen zweiten Mega (es hätte auch ein Nano getan), weil am ersten Mega ein Servo angeschlossen ist, der mir beim Interrupt fall (Einlesen Pulse für Hall Messung) mir Pulse reinmogelt und mir die Messung versaut. Durch Trennung der Boards bin ich in der Not aufs diese "Lösung" gekommen.

Dazu gibt's es ein Post: https://forum.arduino.cc/index.php?topic=368997.0

LG Christian

Eifelchris: Der Slave schreibt das Display.

Wenn ich den Aufbau und I2C richtig verstanden habe, geht das nicht. Der eine Mega ist Slave und das Display ist auch Slave. Eine Kommunikation Slave-Slave ist nicht vorgesehen.

Versuch: Nur der Master-Mega beschreibt das Display mit irgendeinem Text, ob der Absturz dann auch stattfindet.

Das ist meine Idee.

Hi, ok guter Tipp, aber da tun sich neue Probleme auf.

Ich habe es so verstanden das sich der Master dadurch definiert, dass bei wire.begin() nichts in der Klammer steht. Der Slave bekommt eine Adresse wire.beginn(5).

Es folgt zum senden dann: Wire.beginTransmission(5); //also an 5 senden Wire.write(sendedrehzahl2); Wire.endTransmission();

Wenn ich das nun drehe, so muss er ja an den Master senden welcher ja nichts definiert hat bei wire.beginn() in seiner Klammer. Der Compiler lässt ein leeres Argument auch schon nicht zu.

Was sogar funktioniert ist, wenn beide die selbe Adresse haben, also slave slave :) Ich habe es jetzt so, dass einer 5 ist und der andere 6. Nur wer ist jetzt Master?

LG Christian

Wire.begin(); // macht den AVR zum Master, kein Slave Betrieb möglich

Wire.begin(5); // macht den AVR zum Slave, Masterbetrieb jederzeit möglich.

Wire.beginTransmission(5); // macht den AVR zum Master, ob Slave Betrieb möglich ist, wird von Wire.begin() entschieden.

I2C kann Multimaster Betrieb, das kann aber bei zahlreichen AVRs auf dem Bus zu Raceconditions führen.

Hallo combie,

vielen Dank. Also wenn einer 5 ist und der andere 6 ist erstmal dann nichts falsches? bzw kann das dann nicht die Ursache für das abstürzen des Displays sein?

Wenn ich nicht messe also 0 Umdrehungen gesendet werden ( Jede Sekunde) dann bleibt das Display länger online. Wir reden hier dann von 30 min bis Stunden. Sobald ich aber anfange zu messen, ist nach ca 1 Minute Schluss.

LG Christian

Also.... meine Glaskugel sagt: Dein Display ist völlig in Ordnung.

Die Glaskugel sagt weiterhin: Du schickst Schrottdaten zum Display, und wunderst dich dann über eine Fehlfunktion.

Die Ursache für die Schrottdaten ist sicherlich in deinem Code verborgen. Oder vielleicht auch in der Verkabelung mit ihren Pullups ...