imud-arduino

Troubleshooting

Organized by what you’re seeing, since that’s what you know when you get stuck. New to the library? Work through GETTING-STARTED.md first — most problems below are a step from that guide that got skipped.


Nothing at all in the Serial Monitor

Most likely: the Serial Monitor was opened before the board finished booting, or the board hasn’t been reset since upload.

  1. Check the baud dropdown reads 115200.
  2. Press the RST/EN button on the board — the sketch restarts and prints its opening lines again.
  3. Confirm the upload actually succeeded (“Done uploading” / “SUCCESS”).
  4. On some ESP32 boards the USB serial link takes a moment; the examples already delay(200) after Serial.begin() for this reason.

Garbage characters instead of text

Output like ����@�x�� means exactly one thing: the baud rate doesn’t match. Set the Serial Monitor to 115200, the same number as Serial.begin(115200) in the sketch. Nothing else causes this specific symptom, so don’t go looking further.

No serial port to select

  1. Try a different USB cable. Many cheap cables carry power only, and this is the single most common cause.
  2. Some boards (especially ESP32 clones with CP210x or CH340 chips) need a USB-serial driver installed on your computer. Search for your board’s chip name plus “driver”.
  3. Try a different USB port, ideally directly on the computer rather than through a hub.

Stuck on “Connecting to WiFi”

The sketch prints one dot per attempt, so an endless row of dots (Connecting to WiFi "home"........) means the join is failing.

WiFi connects, but no packets ever arrive

You see the board’s own IP printed, then waiting for the first packet... repeating. The network stack is fine; the board can’t reach the daemon.

Work down this list in order:

  1. Is IMUD_HOST the right address? It must be the IP of the machine running imud or fake_daemon.pynot the board’s own IP (which the sketch prints, and which is a different number), and never 127.0.0.1 or localhost.
  2. Is the server actually running? The fake_daemon.py terminal should still be showing TCP listener on 0.0.0.0:10112. It also prints client (…) connected when your board reaches it — if that line never appears, nothing is getting through.
  3. Same network? A “guest” WiFi network is usually isolated from the main one on purpose. Client isolation / “AP isolation” on the router does the same thing.
  4. Firewall. macOS and Windows firewalls commonly block incoming connections to Python. Allow it, or test by temporarily disabling the firewall. On Linux, check ufw/firewalld for port 10112.
  5. Right port? 10112 for TCP, 10111 for UDP. If you changed [stream] tcp_port in the daemon config, match it here.
  6. Real daemon only: confirm [stream] tcp_enabled = true in /etc/imud/imud.conf, and that the daemon is running.

A quick way to isolate the board from the equation: from another computer on the same network, run telnet <host> 10112 or nc <host> 10112. If that also hangs, the problem is the server or the network, not your sketch.

Everything reads 0.0 forever

heading, pitch and roll all sit at exactly 0.0 and never move.

If no packet has ever arrived, this is a display artifact: packet() is zero-filled until the first valid packet lands. HelloAttitude and UdpListen guard against this, but a sketch of your own might not. Check imud.packetsReceived() > 0 before trusting any field, then work through no packets ever arrive.

If packets are arriving (pkts= is climbing), then the daemon really is reporting zeros — look at the daemon end, not the client.

true_hdg reads n/a forever

Working as designed. True heading needs the local magnetic declination, and the library refuses to guess: imud_true_heading() returns -1.0f whenever IMUD_FLAG_DECLINATION_VALID is clear, rather than silently handing you a wrong bearing. See GLOSSARY.md.

Set the declination in the daemon’s configuration. Note that fake_daemon.py does set it (to 11.25°), so with the test server you should see a real number — true_hdg exactly 11.25 higher than hdg.

converged=no

The attitude filter hasn’t settled yet. Give it 10–30 seconds after the daemon starts. Don’t trust attitude while this reads no.

If it never converges on real hardware, the daemon end needs attention — typically magnetometer calibration or a sensor mounted near something magnetic.

crc_err is climbing

Each count is a packet that failed validation and was discarded.

resyncs is climbing

The parser lost frame alignment and had to hunt for the next packet boundary. This essentially always rises alongside crc_err and for the same reasons — treat it as a symptom, not a separate fault. On a healthy TCP link both stay at 0.

resyncs rising while crc_err stays flat would be unusual and worth reporting as a bug.

UDP: rate stays 0.0 Hz

Almost always multicast being dropped by your network. Many consumer access points silently discard or heavily rate-limit multicast traffic, and some drop it entirely when a client is in power-save mode.

To confirm it’s the network and not your sketch, bypass multicast entirely and send UDP straight to the board’s own IP (the one it prints at startup):

python3 tools/fake_daemon.py --udp 192.168.1.87:10111 --rate 100

If unicast works and multicast doesn’t, it’s the access point. Options: use the TCP path instead (TcpBasic), use unicast UDP, or enable IGMP snooping/multicast forwarding on the router if it offers it.

Also worth checking: [highrate] enabled = true in the daemon config, and that the group and port match on both ends.

The connection drops after a while

Compile error: “needs a WiFi-capable core”

#error "This example needs a WiFi-capable core (ESP32, ESP8266, or RP2040 W)"

The examples need a board with networking. An Arduino Uno, Nano, or Mega won’t work. Select an ESP32, ESP8266, or Pico W board under Tools → Board.

If you’re using an Ethernet shield rather than WiFi, the library supports that fine — it works with any Client/UDP implementation — but the examples are written for WiFi. Swap WiFiClient for EthernetClient and drop the WiFi-join code.

Compile error: no member named flags_ext

You’re compiling an example from this version against an older copy of ImudClient.h. The Arduino IDE keeps libraries in your sketchbook libraries/ folder — an old ImudClient there will shadow the one you think you installed. Delete the old copy and re-install.

The related runtime trap: this library version speaks wire v18 and requires imud ≥ 1.10. Against an older daemon it receives nothing at all — no error, no packets, just silence — because every packet fails the version check. If you’re on an older daemon, install the ImudClient line that matches it instead:

Daemon Wire ImudClient
imud 1.4–1.6 v14 1.0.x
imud 1.7–1.9 v17 1.1.x
imud ≥ 1.10 v18 1.2.x

See the wire-sync warning.


Still stuck?

Open an issue — see Reporting bugs for what to include. A copy of your Serial Monitor output, your board type, and your imud version make this much faster to diagnose.