Skip to content

Modbus Diagnostic Read Returns Zero for All Counters

DodaTech Updated 2026-06-26 2 min read

In this tutorial, you'll learn about Modbus Diagnostic Read Returns Zero for All Counters. We cover key concepts, practical examples, and best practices.

The Problem

Modbus FC 08 sub-function 00 returns all zero values for diagnostic counters.

Quick Fix

Wrong

// Read diagnostic counters — all zeros
uint16_t diag[8];
mb.diagnostic(1, 0x0000, 0x0000, diag);
// diag[] = {0, 0, 0, 0, 0, 0, 0, 0}```

All diagnostic counters are zero, even when bus errors exist.


### Right

```cpp
#include <ModbusRtu.h>

Modbus master(1, Serial, 2);

void setup() {
  Serial.begin(9600);
  master.begin(9600, SERIAL_8N1);
}

void checkDiagnostics() {
  uint16_t diag[8];
  int result = master.diagnostic(1, 0x0000, 0x0000, diag);

  if (result != 0) {
    Serial.println("FC 08 not supported by this slave");
    Serial.println("Try alternative diagnostics:");
    Serial.println("  1. Monitor CRC errors by sending bad frames");
    Serial.println("  2. Check response timeout rate");
    Serial.println("  3. Count exceptions from response codes");
    return;
  }

  // Check if counters are actually implemented
  bool countersImplemented = false;
  for (int i = 0; i < 8; i++) {
    if (diag[i] != 0) {
      countersImplemented = true;
      break;
    }
  }

  if (!countersImplemented) {
    Serial.println("Diagnostic counters exist but all are zero");
    Serial.println("This may indicate:");
    Serial.println("  1. Counters were cleared recently");
    Serial.println("  2. Slave does not track actual stats");
    Serial.println("  3. Communication is perfect (unlikely)");

    // Force a CRC error to test
    // Send an intentionally corrupted frame
    uint8_t badFrame[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
    Serial.write(badFrame, 8);
    delay(100);

    // Check if CRC error counter increased
    master.diagnostic(1, 0x0000, 0x0000, diag);
    Serial.print("CRC errors after bad frame: ");
    Serial.println(diag[2]);  // Index 2 = CRC Error Count
  } else {
    Serial.println("Counter values:");
    Serial.print("  Messages: "); Serial.println(diag[0]);
    Serial.print("  CRC Errors: "); Serial.println(diag[2]);
  }
}

void loop() {
  checkDiagnostics();
  delay(5000);
}```

FC 08 not supported by this slave ...or... CRC errors after bad frame: 1 (Counter incremented after intentional bad frame)


## Prevention

Modbus FC 08 diagnostic counters may show zero because: (1) the slave doesn't support FC 08 (check return value), (2) counters were cleared, (3) the slave has perfect communication, or (4) counters are not actually incremented. Send an intentionally corrupted frame to verify counter functionality. Not all slaves implement all 8 diagnostic counters — some return zero for unimplemented counters.

DodaTech engineers apply these same patterns across Doda Browser, DodaZIP, and Durga Antivirus Pro for production IoT reliability.

## FAQ

<details style="margin-bottom:12px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden"><summary style="cursor:pointer;padding:14px 18px;font-weight:600;font-size:1.05rem;background:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1e293b">### Which slaves implement FC 08?</summary><div style="padding:14px 18px;color:#475569;line-height:1.7;background:#fff"><p>Most programmable controllers (PLCs, RTUs) support diagnostics. Simple I/O modules, sensors, and valve actuators often don't. Check the manual.</p>
<h3 id="can-i-clear-counters-without-restart">Can I clear counters without restart?</h3><p>Yes. Sub-function 10 (0x0A) = Clear Counters without restart. Data value must be 0x0000.</p>
<h3 id="what-if-crc-error-counter-never-increments">What if CRC error counter never increments?</h3><p>The slave may count errors at the UART level (before the Modbus stack). Or the slave doesn't validate CRC (rare, but found in some cheap devices).</p>
</div></details>

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro