%%{init: {'theme': 'base', 'themeVariables': {'primaryColor':'#2C3E50','primaryTextColor':'#fff','primaryBorderColor':'#16A085','lineColor':'#16A085','secondaryColor':'#E67E22'}}}%%
sequenceDiagram
participant S as Sender
participant C as Channel
participant R as Receiver
Note over S: Original Data: "HELLO"
S->>S: Calculate check value<br/>from data bytes
S->>C: Send: Data + Check Value
Note over C: Transmission<br/>(may introduce errors)
C->>R: Receive data
R->>R: Recalculate check value<br/>from received data
alt Check values match
R-->>R: Data accepted as valid
else Check values differ
R-->>S: Request retransmission
end
743 Error Detection: CRC and Checksums
By the end of this section, you will be able to:
- Understand error detection fundamentals: Explain why IoT networks need mechanisms to detect data corruption
- Compare CRC and checksums: Differentiate between simple checksums and CRC for error detection capability
- Calculate CRC values: Understand the polynomial division process behind CRC computation
- Identify error detection limitations: Recognize what types of errors each mechanism can and cannot detect
- Choose appropriate algorithms: Select the right error detection method based on reliability requirements and resource constraints
743.1 Prerequisites
Before diving into this chapter, you should be familiar with:
- Transport Fundamentals: Understanding TCP vs UDP trade-offs and basic acknowledgment concepts provides essential context for error detection
- Reliability Overview: The parent chapter introducing all five pillars of IoT reliability
- Binary and Hexadecimal: Familiarity with bitwise operations is essential for understanding checksum calculations
Wireless channels are inherently noisy. Electromagnetic interference from motors, microwaves, and other devices can flip bits during transmission. Signal fading in multipath environments corrupts data randomly. Without error detection, your temperature sensor might report 125C instead of 25C due to a single bit flip - and your system would have no way to know the data is wrong.
743.2 Error Detection Fundamentals
Error detection identifies when data has been corrupted during transmission. The sender computes a mathematical function over the data and appends the result (checksum or CRC). The receiver performs the same computation - if the results differ, corruption occurred.
743.2.1 The Error Detection Process
743.2.2 Types of Transmission Errors
| Error Type | Description | Example | Detection Difficulty |
|---|---|---|---|
| Single bit | One bit flipped | 0x48 becomes 0x49 | Easy |
| Burst error | Multiple consecutive bits flipped | 0x4845 becomes 0x3912 | Moderate |
| Byte swap | Two bytes exchange positions | 0x1234 becomes 0x3412 | Hard for checksums |
| Insertion | Extra byte added | βABβ becomes βACBβ | Moderate |
| Deletion | Byte removed | βABCβ becomes βACβ | Moderate |
743.3 Simple Checksum Algorithms
The simplest approach is to sum all bytes in the message. Several variants exist with different trade-offs.
743.3.1 Sum-of-Bytes Checksum
uint8_t calculateChecksum(const uint8_t* data, size_t length) {
uint8_t sum = 0;
for (size_t i = 0; i < length; i++) {
sum += data[i];
}
return sum;
}Advantages: - Extremely fast (single addition per byte) - Minimal code size - Works on any processor
Disadvantages: - Cannot detect byte reordering (addition is commutative) - Poor burst error detection - Weak against certain error patterns
743.3.2 Internet Checksum (Oneβs Complement)
Used in IP, TCP, and UDP headers, this algorithm treats data as 16-bit words and performs oneβs complement addition:
uint16_t internetChecksum(const uint16_t* data, size_t wordCount) {
uint32_t sum = 0;
for (size_t i = 0; i < wordCount; i++) {
sum += data[i];
}
// Fold 32-bit sum to 16 bits (add carry bits)
while (sum >> 16) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
return ~sum; // One's complement
}Key property: The checksum of the data plus its checksum equals 0xFFFF (all ones), making verification simple.
Simple checksums cannot detect when bytes are transposed:
Original: 0x12 + 0x34 = 0x46
Swapped: 0x34 + 0x12 = 0x46 (same checksum!)
This is why TCP/IP uses checksums for headers (where errors are unlikely) but CRC for link-layer frames (where bit errors are common).
743.4 Cyclic Redundancy Check (CRC)
CRC provides much stronger error detection by treating the data as a polynomial and dividing by a fixed generator polynomial. The remainder becomes the CRC value.
743.4.1 How CRC Works Conceptually
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor':'#2C3E50','primaryTextColor':'#fff','primaryBorderColor':'#16A085','lineColor':'#16A085','secondaryColor':'#E67E22'}}}%%
flowchart TB
subgraph Input["Data as Polynomial"]
DATA["Message: 11010011<br/>= x^7 + x^6 + x^4 + x + 1"]
end
subgraph Process["Division Process"]
SHIFT["Append n zeros<br/>(n = polynomial degree)"]
DIV["XOR-divide by<br/>generator polynomial"]
REM["Remainder = CRC"]
end
subgraph Poly["Generator Polynomial"]
GEN["CRC-8: x^8 + x^2 + x + 1<br/>= 0x107 (binary: 100000111)"]
end
subgraph Output["Result"]
CRC["CRC value appended<br/>to message"]
end
DATA --> SHIFT
SHIFT --> DIV
GEN --> DIV
DIV --> REM
REM --> CRC
style Input fill:#2C3E50,stroke:#16A085,color:#fff
style Process fill:#16A085,stroke:#2C3E50,color:#fff
style Poly fill:#E67E22,stroke:#2C3E50,color:#fff
style Output fill:#2C3E50,stroke:#16A085,color:#fff
743.4.2 CRC-16 Implementation
#define CRC16_POLYNOMIAL 0x1021 // CRC-CCITT
#define CRC16_INITIAL 0xFFFF
uint16_t calculateCRC16(const uint8_t* data, size_t length) {
uint16_t crc = CRC16_INITIAL;
for (size_t i = 0; i < length; i++) {
crc ^= ((uint16_t)data[i] << 8);
for (int bit = 0; bit < 8; bit++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ CRC16_POLYNOMIAL;
} else {
crc = crc << 1;
}
}
}
return crc;
}743.4.3 Common CRC Polynomials
| CRC Type | Polynomial | Width | Used In |
|---|---|---|---|
| CRC-8 | 0x07 | 8 bits | I2C, SMBus |
| CRC-16-CCITT | 0x1021 | 16 bits | Bluetooth, USB, X.25 |
| CRC-16-IBM | 0x8005 | 16 bits | Modbus, USB |
| CRC-32 | 0x04C11DB7 | 32 bits | Ethernet, ZIP, PNG |
743.5 CRC vs Checksum Comparison
| Feature | Simple Checksum | CRC-16 | CRC-32 |
|---|---|---|---|
| Computation | Sum of bytes | Polynomial division | Polynomial division |
| Size | 1-2 bytes | 2 bytes | 4 bytes |
| Burst Error Detection | Poor | Good (16+ bits) | Excellent (32+ bits) |
| Single Bit Errors | 100% | 100% | 100% |
| Two Bit Errors | ~50% | 100% | 100% |
| Byte Swap Detection | 0% | 100% | 100% |
| CPU Cycles (8-bit MCU) | ~2 per byte | ~40 per byte | ~80 per byte |
| Code Size | ~20 bytes | ~100 bytes | ~200 bytes |
743.5.1 When to Use Each
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor':'#2C3E50','primaryTextColor':'#fff','primaryBorderColor':'#16A085','lineColor':'#16A085','secondaryColor':'#E67E22'}}}%%
flowchart TD
START["Need Error Detection"] --> Q1{"Critical data?<br/>(safety, financial)"}
Q1 -->|Yes| CRC32["Use CRC-32"]
Q1 -->|No| Q2{"Noisy channel?<br/>(wireless, long cables)"}
Q2 -->|Yes| CRC16["Use CRC-16"]
Q2 -->|No| Q3{"Resource constrained?<br/>(tiny MCU, battery)"}
Q3 -->|Yes| CHECKSUM["Use Simple Checksum"]
Q3 -->|No| CRC16B["Use CRC-16"]
style CRC32 fill:#E67E22,stroke:#2C3E50,color:#fff
style CRC16 fill:#16A085,stroke:#2C3E50,color:#fff
style CRC16B fill:#16A085,stroke:#2C3E50,color:#fff
style CHECKSUM fill:#7F8C8D,stroke:#2C3E50,color:#fff
743.6 CRC Error Detection Capabilities
743.6.1 What CRC Detects
CRC is guaranteed to detect:
- All single-bit errors - Any single bit flip is caught
- All double-bit errors - Any two bit flips anywhere in the message
- All odd-number bit errors - 1, 3, 5, β¦ bit flips
- All burst errors shorter than CRC width - CRC-16 catches all bursts up to 16 bits
743.6.2 Undetectable Errors
No error detection is perfect. CRC may miss:
- Burst errors longer than CRC width - Detection probability is 1 - 2^(-n) for n-bit CRC
- Specific polynomial multiples - Errors that produce valid remainders
For CRC-32 with random errors: - Probability of undetected error = 2^(-32) = 0.00000000023% - For 1 billion messages, expect ~0.2 undetected corruptions
This is why CRC is combined with other mechanisms (sequence numbers, ACKs) for critical applications.
743.7 Hardware CRC Acceleration
Many IoT microcontrollers include hardware CRC units that compute CRC in a single clock cycle per byte:
// ESP32 hardware CRC example
#include "esp_rom_crc.h"
uint32_t fastCRC32(const uint8_t* data, size_t length) {
// Hardware-accelerated CRC-32
return esp_rom_crc32_le(0, data, length);
}
uint16_t fastCRC16(const uint8_t* data, size_t length) {
// Hardware-accelerated CRC-16/CCITT
return esp_rom_crc16_le(0, data, length);
}743.7.1 Performance Comparison
| Method | Cycles per Byte | 100-byte Message |
|---|---|---|
| Software CRC-32 | ~80 | 8000 cycles |
| Hardware CRC-32 | ~1 | 100 cycles |
| Software CRC-16 | ~40 | 4000 cycles |
| Hardware CRC-16 | ~1 | 100 cycles |
Before implementing software CRC, check if your microcontroller has hardware support: - ESP32: Yes (ROM functions) - STM32: Yes (CRC peripheral) - nRF52: Yes (CRC peripheral) - ATmega328: No (software only)
743.8 Knowledge Check
Question: A simple sum-of-bytes checksum will FAIL to detect which type of error?
- Single bit flip in one byte
- Two bytes swapping positions
- All bits in one byte flipped
- Addition of an extra zero byte
Click for answer
Answer: B) Two bytes swapping positions
When two bytes swap positions (e.g., 0x12 0x34 becomes 0x34 0x12), the sum remains identical because addition is commutative. CRC detects this because polynomial division considers bit positions, not just values.Question: CRC-16 is GUARANTEED to detect:
- All errors up to 16 bits anywhere in the message
- All burst errors up to 16 consecutive bits
- 50% of all possible error patterns
- Only single-bit errors
Click for answer
Answer: B) All burst errors up to 16 consecutive bits
CRC-n is guaranteed to detect all burst errors of n bits or fewer. For longer bursts, detection probability is very high but not 100%. CRC also detects all single-bit, double-bit, and odd-number bit errors.Question: For a battery-powered sensor sending temperature readings over a noisy 433 MHz radio link, which error detection is most appropriate?
- No error detection (saves power)
- Simple 8-bit checksum
- CRC-16
- CRC-32
Click for answer
Answer: C) CRC-16
Noisy wireless channels require strong error detection (rules out A and B). CRC-16 provides excellent burst error detection suitable for radio links. CRC-32 is overkill for sensor data and wastes power - the 2 extra bytes per message add up over thousands of transmissions.743.9 Summary
This chapter covered error detection mechanisms for IoT networks:
Key Concepts:
- Checksums provide basic error detection with minimal overhead
- CRC uses polynomial division for much stronger error detection
- Burst errors are common in wireless channels - CRC handles them well
- Hardware acceleration makes CRC nearly free on modern MCUs
Trade-offs:
| Mechanism | Overhead | Detection | Best For |
|---|---|---|---|
| 8-bit checksum | 1 byte | Weak | Resource-constrained, reliable channels |
| CRC-16 | 2 bytes | Strong | Typical IoT wireless |
| CRC-32 | 4 bytes | Excellent | Critical data, Ethernet |
What is Next: The Retry Mechanisms and Sequence Numbers chapter covers how to recover from errors once detected.
- Reliability Overview: Parent chapter with all five reliability pillars
- Retry and Sequencing: Recovery after error detection
- Connection State Lab: Hands-on implementation of all concepts
- Transport Fundamentals: TCP/UDP error handling approaches