float in byte ? "Verlust" erlaubt

Hallo in die Runde,

in mein Netzwerk soll ein Temperatursensor (Dallas 18B20) integriert werden. Es ist keine besonders hohe Genauigkeit gefordert- letztendlich ist die gewünschte Kernfunktion ein Frostwarner. Also auf die Nachkommastellen kann ich verzichten, wenn es mit nicht geht…

Im meinem Netzwerk habe ich alle Daten die per nrf24 gefunkt werden auf “byte”, möchte jetzt also nicht anfangen zu mischen- somit muss ich die Temperatur in byte wandeln- so weit kein Problem… die Frage ist was mit Temperaturen unter 0 passiert… ich hab mir da jetzt auch schon etwas beholfen…

Hat jemand eine Idee für eine inteligentere Lösung? Es können 3 Stelle (byte) im Array belegt werden…

#include <SPI.h>
#include "RF24.h"
#include "Time.h"
#include <OneWire.h>
#include <DallasTemperature.h>

byte RaumID = 23;
#define ONE_WIRE_BUS 5
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

RF24 radio(9, 10);

float Temperatur;

long letzteMeldung = 0;
long meldungsAbstand = 6000;

byte Sensoralt[9];
byte Sensor[9];

void setup()
{
  Sensor[0] = RaumID; // muss man nur einmal setzen
  
  sensors.begin();
  Serial.begin(115200);

  radio.begin();
  radio.openWritingPipe((byte*)"2Node");
  radio.setRetries(15,15); 
  radio.setPALevel(RF24_PA_HIGH);       
  radio.setDataRate(RF24_1MBPS); 
  radio.startListening();
}

void loop()
{
  unsigned long aktuelleMeldung = millis();
  sensors.requestTemperatures(); 
  
  Temperatur = (sensors.getTempCByIndex(0));
  if (Temperatur >= 0)
  {Sensor[3] = byte(Temperatur);}
  else
  {Sensor[4] = (byte(Temperatur))*-1;}
  Sensor[1] = 0;
  Sensor[2] = 0;
  Sensor[5] = 0;
  Sensor[6] = 0;
  Sensor[7] = 0;
  Sensor[8] = 0;
 //if (Sensor[1] != Sensoralt[1])
  if (aktuelleMeldung - letzteMeldung > meldungsAbstand) 
    {
    letzteMeldung = aktuelleMeldung;
    printSensorArray();
    radio.stopListening();
    radio.write(Sensor, sizeof(Sensor));
    radio.startListening();
    } 
  Sensoralt[3] = Sensor[3];
}

void printSensorArray() 
{
  Serial.println(F("sende "));
  Serial.print(F(" Raum ID:      " ));
  Serial.println(Sensor[0]);
  Serial.print(F(" Temperatur : "));
  Serial.println(Temperatur);
  Serial.print(Sensor[3]);
  Serial.print(F(","));
  Serial.println(Sensor[4]);
  Serial.println(F("  "));
}

Es gibt doch auch "signed char" als 8Bit Datentyp, Wertebereich -128 bis 127.

Gruß Peter

Du solltest RaumID als const byte oder direkt #define angeben.

Wie sieht die Auswertung vom Dallas aus, kannst du diesen als Negativ erhalten? Byte kann nicht negativ sein. Also würde es sich anbieten, das ganze mit einem Offset abzuhandeln der auf der Gegenstelle wieder umgeschrieben werden muss.

Das ganze könnte man mit dem Map befehl erschlagen. Ggf vorher bereits die Kommastellen geschickt auf und abbrunden, bzw. einfach nur abschneiden.

map(val, minValFloat, maxValFloat, 0, 255);

hi,

Du könntest die grade von -20 bis +42 in den ersten sechs bit unterbringen und viertelgrade in den restlichen zwei.

gruß stefan

das klingt gut... wie bekomme ich denn die Nachkommastellen isoliert?

hi,

wenn Du 20 zum temperatur (float) - wert dazuzählst, bist Du mal im richtigen bereich.

dann die nachkommastellen mit round abschneiden.

wenn Du das ergebnis von der ursprunglichen zahl abziehst, haste die kommastellen.

gruß stefan

wenn du den 18b20 direkt ausliest, erhälst du 2 byte für die Temperatur, die überträgst du und errechnest die Temperatur im Empfänger.

Das klingt gut und logisch... und die negativen mache ich so wie schon unten gezeigt.... :-) danke für den Tipp!

Man kann auch die vier Bytes eines Floats direkt als Bytes übertragen

Version 1:

void setup() 
{
  Serial.begin(9600);

  float f1 = 25.10;
  byte* b = (byte*)&f1;

  for (unsigned int i = 0; i < 4; i++)
    Serial.println(b[i], HEX);

  float f2 = *((float*)b);
  Serial.println(f2);
}

void loop() 
{
}

Dann noch merken dass Array-Variablen Zeiger auf das erste Element sind und man kann ein Byte Array direkt als Float ansprechen und umgekehrt. Einfach indem man die Adressen castet

Version 2 (und etwas sauberer und einfacherer):

union temperature
{
  byte asByte[4];
  float asFloat;
};

void setup() 
{
  Serial.begin(9600);

  temperature temp;
  temp.asFloat = 25.10;

  for (unsigned int i = 0; i < 4; i++)
    Serial.println(temp.asByte[i], HEX);
}

void loop() 
{
}

Anders herum einfach die Daten nach temp.asByte einlesen und man hat den Wert sofort in temp.asFloat

hi,

neugier:

wie machst es denn nun? 1 byte? 2? 4?

gruß stefan

Für die Stellen vor dem Komma lasse ich es wie unten gezeigt, nutze also im array eine Stelle mit 1byte für die positiven Werte, eine andere Stelle für die negativen. Die entsprechende Umsetzung funktioniert auch beim Empfänger... Für die Nachkommastellen werde ich dann einen 3. Platz in meinem Array belegen- das mach ich mal bei Gelegenheit... ;-)

ups!

hab' Deinen ersten beitrag nicht richtig gelesen, aufgrund der überschrift dachte ich, Du willst die float in EIN byte.

gruß stefan