Perché un float Modbus legge 1.5E+35
Ti aspetti 123.456 e a schermo compare 1.5184998E+35. Il dispositivo funziona, il cablaggio pure: i quattro byte sono giusti, vengono solo letti nell'ordine sbagliato.
Il sintomo
Un dispositivo invia un float a 32 bit in due registri. Per 123.456 i registri contengono
42F6 e E979. Letti nell'ordine giusto, i quattro byte 42 F6 E9 79
danno 123.456. Letti in un altro ordine, gli stessi byte danno qualcosa che sembra rumore:
| Ordine dei byte | Byte | Float |
|---|---|---|
| ABCD | 42 F6 E9 79 | 123.456 |
| CDAB | E9 79 42 F6 | -1.8833671E+25 |
| BADC | F6 42 79 E9 | -9.8611155E+32 |
| DCBA | 79 E9 F6 42 | 1.5184998E+35 |
L'indizio è la grandezza del numero. Le grandezze fisiche raramente richiedono esponenti oltre ±10: un valore intorno a E+25, E+35 o E-38 quasi mai è una misura reale. È un valore corretto con i byte rimescolati.
Perché succede
Modbus trasmette ogni registro a 16 bit con il byte alto per primo, ma non dice nulla su come dividere un valore a 32 bit tra due registri. Lo sceglie il costruttore, e il master deve fare la stessa scelta.
La seconda causa spesso è nel nostro codice. Il processore di un PC è little-endian, quindi la riga di C# più naturale legge i quattro byte al contrario:
// bytes = 42 F6 E9 79, nell'ordine in cui sono arrivati
float value = BitConverter.ToSingle(bytes, 0); // 1.5184998E+35 su un PC
È esattamente il numero del titolo, da byte perfettamente corretti.
Come correggerlo
In C#, dichiara esplicitamente l'ordine che ti aspetti:
using System.Buffers.Binary;
float value = BinaryPrimitives.ReadSingleBigEndian(bytes); // 123.456
Se il dispositivo usa le word scambiate (CDAB), inverti i due registri prima di decodificare. In uno SCADA o in un master commerciale cerca un'opzione chiamata byte order, word swap o swap registers: il nome cambia da prodotto a prodotto.
Trovare l'ordine in un passaggio
Quando il manuale non lo dice, leggi un valore che conosci all'incirca, come un setpoint che hai impostato o la tensione di rete, e incolla i registri grezzi nel decoder registri insieme al valore atteso. Lo strumento mostra i quattro ordini ed evidenzia quello che corrisponde. Una volta trovato, di solito vale per tutti i valori di quel dispositivo.