Transmissió d'un número real de tipus IEEE-754 (4 bytes) i llur recuperació a NodeRED
Contingut
Transmissió d'un nombre real en format IEEE-754
Representació d'un nombre real (tipus float en C de 4 bytes) en format IEEE-754
IEEE Standard 754 Floating Point Numbers
Enllaç a un codificador / descodificador de nombres reals IEEE-754 (Codi a GitHub d'en Ray Toal)
Exemple de conversió d'un nombre real a 4 bytes
Codi en C de l'IDE d'Arduino
#define N_DATA_BYTES 4
union uFloat{
float f;
unsigned char uc[4];
};
static uint8_t mydata[N_DATA_BYTES];
void vVisualitzacioFloatEnBytes(float fNum){
union uFloat ufA;
int i,k;
ufA.f = fNum;
Serial.print("Vector de bytes: ");
for(i = N_DATA_BYTES - 1 , k = 0 ; i >= 0 ; i-- , k++ ){
mydata[k] = ufA.uc[i];
Serial.print(mydata[k],DEC);Serial.print(" ");
}
Serial.println();
}
Exemple fent-ne ús: IoT-02-22_ttn-otaa_dam_02_float.ino
Per si us cal repassar la diferència entre una unió i una estructura en C (Cerqueu la imatge que clarifica la diferència)
Codi en Python
- float de 32 bits a 4 bytes:
import struct
def float_a_bytes():
try:
# Demanem el número a l'usuari
entrada = input("Introduïu un número decimal (ex: -12.3): ")
numero = float(entrada)
# 'f' indica un float de 32 bits (4 bytes)
# '>' indica format "big-endian" (el byte més significatiu primer)
bytes_codificats = struct.pack('>f', numero)
# Convertim l'objecte de bytes en una llista d'enters (0-255)
llista_decimal = list(bytes_codificats)
print(f"La codificació IEEE-754 de {numero} en 4 bytes és:")
print(llista_decimal)
# Convertim cada byte a binari de 8 bits i els unim tots
cadena_binaria = "".join(f"{b:08b}" for b in bytes_codificats)
print(f"La codificació IEEE-754 de {numero} en cadena de 32 zeros i uns és {cadena_binaria}")
except ValueError:
print("Error: Si us plau, introduïu un número vàlid.")
if __name__ == "__main__":
float_a_bytes()
- 4 bytes a float de 32 bits:
import struct
def bytes_a_float():
try:
# Demanem els 4 números
entrada = input("Introduïu 4 números decimals en 'big-endian' (ex: 193,68,204,205): ")
# Convertim l'entrada en una llista d'enters
# Això separa per comes i elimina espais en blanc
valors = [int(n.strip()) for n in entrada.split(',')]
if len(valors) != 4:
print("Error: Heu d'introduir exactament 4 números separats per comes.")
return
# Convertim la llista d'enters en un objecte de bytes
# El mètode bytes() espera valors entre 0 i 255
objecte_bytes = bytes(valors)
# 'struct.unpack' retorna una tupla, per això agafem l'índex [0]
# '>f' indica Big-Endian i Float de 32 bits
numero = struct.unpack('>f', objecte_bytes)[0]
print(f"El número decimal representat per {valors} és: {numero}")
except ValueError:
print("Error: Assegureu-vos d'introduir números enters vàlids (0-255).")
except Exception as e:
print(f"S'ha produït un error inesperat: {e}")
if __name__ == "__main__":
bytes_a_float()
Recuperació d'un nombre real a NodeRED
Instal·lació del node node-red-contrib-float
Node node-red-contrib-float de NodeRED per a convertir números reals en format IEEE-754 apartir d'una cadena de zeros i uns. Instal·leu-ho anant a Menú / Settings / Palette / Install cercant IEEE-754.
Exemple d'ús al NodeRED emprant el node node-red-contrib-float
El flux de NodeRED superior el podeu descarregar aquí: Arxiu exempleDescodificantIEEE754.json amb un flux importable a NodeRED com a exemple de descodificació IEEE-754
Node d'injecció -12.3 en cadena de 32 zeros i uns
Funció n -> 2 decimals
Per a assegurar que tan sols es visualitzin dos decimals (es multiplica i es divideix per 100):
msg.payload = parseFloat(parseInt(msg.payload * 100))/100; return msg;
Funció Injecció de -12.35 --> [193,69,153,154]
Pas dels 4 bytes en base 10 que representen el número real -12.35:
msg.payload = [193,69,153,154]; return msg;
Funció Vector 4 números -> Cad 0 i 1
Funció que converteix els quatre bytes del nombre real a una cadena de 32 zeros i uns:
var vector = msg.payload;
var zerosUns = "";
var currentBits = "";
for(var i = 0; i < 4; i++){
currentBits = vector[i].toString(2);
while(currentBits.length < 8)
currentBits = "0" + currentBits;
zerosUns += currentBits;
}
return [msg,{"payload":zerosUns}];
Transmissió de tres nombres reals en format IEEE-754
Exemple de conversió de tres nombres reals a 12 bytes (3 x 4 bytes)
#define N_DATA_BYTES 12
#define NUM_FLOAT_A -12.35f
#define NUM_FLOAT_B 12.35f
#define NUM_FLOAT_C -12.30f
union uFloat {
float f;
unsigned char uc[4];
};
static uint8_t mydata[N_DATA_BYTES];
void vSetFloatAtFrame(float fValue, unsigned char* ucFrame, int nPos) {
union uFloat ufA;
int i, k;
ufA.f = fValue;
Serial.print("Vector de bytes: ");
for (i = 3 , k = 0 ; i >= 0 ; i-- , k++ ) {
ucFrame[k+nPos] = ufA.uc[i];
Serial.print(ucFrame[k+nPos], DEC); Serial.print(" ");
}
Serial.println();
}
void do_send(osjob_t* j) {
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
vSetFloatAtFrame(NUM_FLOAT_A,mydata,0);
vSetFloatAtFrame(NUM_FLOAT_B,mydata,4);
vSetFloatAtFrame(NUM_FLOAT_C,mydata,8);
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, mydata, N_DATA_BYTES, 0);
Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
Exemple fent-ne ús: IoT-02-22_ttn-otaa_dam_03_floats.ino
Recuperació de tres nombres reals a NodeRED
El flux de NodeRED superior el podeu descarregar aquí: Arxiu exempleDescodificantIEEE754_3reals.json amb un flux importable a NodeRED com a exemple de descodificació de tre nombres reals en format IEEE-754
Funció Rebent 3 floats (12 bytes)
var vector = msg.payload;
var currentBits = "";
var zerosUns = ["","",""];
if(vector.length == 12){
for(var k = 0; k < 3; k++){
for(var i = 0; i < 4; i++){
currentBits = vector[i+4*k].toString(2);
while(currentBits.length < 8)
currentBits = "0" + currentBits;
zerosUns[k] += currentBits;
}
}
return [{"payload":zerosUns[0]},
{"payload":zerosUns[1]},
{"payload":zerosUns[2]}];
}
Funció --> payload
msg.payload = msg.payload.uplink_message.frm_payload; return msg;



