Convert LONG value to FLOAT by calculation

I am working on some software project which only output by LONG(4 bytes, actually it's a float value) and no data type available.

How to convert the value from Long to FLOAT correctly?

For example:

Program output: 1121058816 Actual HEX : 0x42D20000 Float: 105

‭Program Oupput: 1061662228‬ Actual HEX: 0x‭3F47AE14‬ Float: 0.78

You can use a union to address the same memory locations using two different types, but be sure that the byte order and encoding is correct for Arduino (it seems to be from this example).

union equiv {
  float x;
  unsigned long l;
} equiv ;

void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
 equiv.l = 0x42D20000;
 Serial.print("float value ");
 Serial.println(equiv.x);  //prints "105.00"
}

void loop() {
  // put your main code here, to run repeatedly:

}

jremington: You can use a union to address the same memory locations using two different types, but be sure that the byte order and encoding is correct for Arduino (it seems to be from this example).

The IDE uses Big Endian, doesn't it?

econjack: The IDE uses Big Endian, doesn't it?

The IDE uses whatever endianess the computer it is running on uses.

Arduinos use litte endian.

Here you can see a dump of two variables which both have the value 105.

The sketch uses a rather flexible dump function that works on the first 64k of RAM, FLASH and EEPROM,
but don’t get distracted by that additional complexity of the code.

float 0204: 00 00 D2 42                                     '..ÒB'
long  0200: 69 00 00 00                                     'i...'
typedef byte (*accessFunction)(const byte *adr);
void dumpGen(const byte* adr, int len, accessFunction accs, const __FlashStringHelper* pfx, bool withAdr = true, int suppHex = -1);
void dumpR(const void* adr, int len, const __FlashStringHelper* pfx = NULL);
void dumpF(const void* adr, int len, const __FlashStringHelper* pfx = NULL);
void dumpE(const void* adr, int len, const __FlashStringHelper* pfx = NULL);

float tfValue = 105;
long tlValue = 105;

void setup() {
  Serial.begin(115200);
  dumpR(&tfValue, sizeof(tfValue), F("float "));
  dumpR(&tlValue, sizeof(tlValue), F("long  "));
}

void loop() {}


byte accRAM(const byte *adr) {
  return *adr;
}

byte accPGM(const byte *adr) {
  return pgm_read_byte_near(adr);
}

byte accEEPROM(const byte *adr) {
  return eeprom_read_byte(adr);
}

void dumpGen(const byte* adr, int len, accessFunction accs, const __FlashStringHelper* pfx, bool withAdr, int suppHex) {
  byte idx;
  byte blanks;
  if (len) {
    for (; len > 0; len -= 16, adr += 16) {
      Serial.print(pfx);
      if (withAdr) {
        phAdr(adr);
      }
      for (idx = 0; idx < 16; idx++) {
        if (idx < len ) {
          byte curr = (*accs)(adr + idx);
          if (suppHex < 0 || suppHex != curr) {
            phByte(curr);
          } else {
            Serial.write('.');
            Serial.write('.');
          }
          blanks = 1;
        } else {
          blanks = 3;
        }
        while (blanks--) {
          Serial.write(' ');
        }
      }
      Serial.write('\'');
      for (idx = 0; (idx < 16) && (idx < len); idx++) {
        byte curr = (*accs)(adr + idx);
        Serial.write(curr < 0x20 || (suppHex >= 0 && curr == suppHex) ? '.' : curr);
      }
      Serial.write('\'');
      Serial.println();
    }
  }
}

void dumpR(const void* adr, int len, const __FlashStringHelper* pfx) {
  dumpGen((const byte*)adr, len, accRAM, pfx);
}

void dumpF(const void* adr, int len, const __FlashStringHelper* pfx) {
  dumpGen((const byte*)adr, len, accPGM, pfx);
}

void dumpE(const void* adr, int len, const __FlashStringHelper* pfx) {
  dumpGen((const byte*)adr, len, accEEPROM, pfx);
}

void phByte(byte value) {
  if (value < 16) {
    Serial.write('0');
  }
  Serial.print(value, HEX);
}

void phAdr(const byte* adr) {
  phByte((byte)(((uint16_t)adr) >> 8));
  phByte((uint16_t)adr);
  Serial.write(':');
  Serial.write(' ');
}

Thansk Jremington, the union works great for me.

jremington: You can use a union to address the same memory locations using two different types, but be sure that the byte order and encoding is correct for Arduino (it seems to be from this example).

union equiv {
  float x;
  unsigned long l;
} equiv ;

void setup() {   // put your setup code here, to run once: Serial.begin(9600); equiv.l = 0x42D20000; Serial.print("float value "); Serial.println(equiv.x);  //prints "105.00" }

void loop() {   // put your main code here, to run repeatedly:

}