Nouveau : le pare-feu IA surveille toute la plateforme et explique chaque incident en termes simples. Découvrez comment ça marche

Floats come out as garbage when my Uno reads a Nano over I2C

Floats come out as garbage when my Uno reads a Nano over I2C

Résolu 6 5

Greenhouse controller, two boards: a Nano reads soil probes and a DS18B20 and acts as I2C slave at 0x08; an Uno is master, collects from the Nano and passes everything over serial to an ESP32 that publishes to Hermetry. The ints (moisture raw, 0-1023) come through fine. The temperature float arrives as nonsense like -2.3e-38 or nan, and Hermetry refuses the key whenever it’s NaN, so the chart has holes.

Slave side:

void onRequest() {
  Wire.write(moisture1 >> 8); Wire.write(moisture1 & 0xFF);
  Wire.write(moisture2 >> 8); Wire.write(moisture2 & 0xFF);
  Wire.write((byte)tempC);     // tried this first, lost decimals
  Wire.write((byte*)&tempC, 4);
}

Master does Wire.requestFrom(8, 9) and reads bytes back into the same variables.

Timestamps in UTC or it didn't happen.
♥ 0

Could you send it as a string and parse it on the other end? That’s what I did for serial.

Still waiting for the gateway to reconnect.
♥ 0

Strings over I2C waste bytes and you only get 32 per transfer. Show the master side, I bet that’s where it breaks.

Measure twice, poll once.
♥ 2

master side, sorry, should have included it:

Wire.requestFrom(8, 9);
m1 = (Wire.read() << 8) | Wire.read();
m2 = (Wire.read() << 8) | Wire.read();
Wire.read();                       // the old byte
for (int i = 0; i < 4; i++) ((byte*)&t)[i] = Wire.read();
Timestamps in UTC or it didn't happen.
♥ 1

Following, I have a similar setup planned for our hotel greenhouse.

♥ 0

Two bugs, and a third waiting to happen. I did nearly this exact thing on a test rig years ago.

1. On the slave, each Wire.write() inside onRequest on AVR replaces the buffer instead of adding to it in some library versions, and the order of evaluation in (Wire.read() << 8) | Wire.read() on the master isn’t defined in C++, so the bytes can come out swapped.

2. The stray single byte shifts everything if the counts ever disagree.

Do it with one struct on both sides and one write:

struct __attribute__((packed)) Packet {
  uint16_t m1, m2;
  int16_t  t_x100;      // 23.47 C -> 2347, no float on the wire
  uint8_t  seq;
};
// slave
void onRequest() { Wire.write((uint8_t*)&pkt, sizeof(pkt)); }
// master
Packet p;
if (Wire.requestFrom(8, sizeof(p)) == sizeof(p))
  Wire.readBytes((uint8_t*)&p, sizeof(p));
float t = p.t_x100 / 100.0;

Scaled integers avoid any float layout question if the slave ever becomes an ESP or an STM32. The seq byte tells you if you’re reading a stale packet. And on the ESP32 side, skip the key entirely if a reading is invalid instead of sending NaN, NaN isn’t valid JSON anyway.

Ground loops are my cardio.
Solution acceptée♥ 4

Struct with scaled int fixed it. Temperature has been clean since yesterday afternoon, no gaps on the chart. The evaluation order thing was news to me.

Timestamps in UTC or it didn't happen.
♥ 0
7 sujets de 1 à 7 (sur un total de 7)
  • Vous devez être connecté pour répondre à ce sujet.

Rejoignez la discussion

Connectez-vous pour poser et répondre à des questions, aimer les messages utiles et marquer la réponse qui a résolu votre problème. Chaque contribution rapporte des points et des niveaux.

Partager