The Tank Sensor Fault Detector

JSS 3 MakeCode micro:bit Simulation first Range & Parity Check
Simulation lab
Board: BBC micro:bit
Open MakeCode ↗
Simulator preview
☀️ 80

Change the slider level and observe the 5x5 LED display.

📁 Tools ▴
  • Web browser (Chrome, Edge, Firefox)
  • Internet connection
  • MakeCode (micro:bit) online editor

🔧 Build Your Defensive Telemetry Validator

1 Sample an analog tank level transducer on pin A0 (0–1023 ADC range).
2 Perform hardware sanity bounds checking: readings < 50 indicate disconnected cables; readings > 980 indicate VCC short-circuits.
3 Calculate single-bit even parity across the 7-bit data byte.
4 Sound an emergency fault buzzer whenever out-of-bounds voltages or parity failures are detected!
🧩 Block plan / Starter code ▴
const int SENSOR_PIN = A0;
const int FAULT_ALARM = 12;

bool checkParity(byte val, byte parityBit) {
  byte ones = 0;
  for (int i = 0; i < 7; i++) {
    if ((val >> i) & 1) ones++;
  }
  return ((ones % 2) == parityBit);
}

void setup() {
  pinMode(FAULT_ALARM, OUTPUT);
  Serial.begin(9600);
  Serial.println("Defensive Sensor Validator Ready.");
}

void loop() {
  int rawADC = analogRead(SENSOR_PIN);

  // Hardware Boundary Diagnostics
  if (rawADC < 50) {
    digitalWrite(FAULT_ALARM, HIGH);
    Serial.println("CRITICAL FAULT: Broken Wire / Sensor Disconnected!");
  } else if (rawADC > 980) {
    digitalWrite(FAULT_ALARM, HIGH);
    Serial.println("CRITICAL FAULT: Short Circuit to 5V Rail!");
  } else {
    digitalWrite(FAULT_ALARM, LOW);
    byte levelPercent = map(rawADC, 50, 980, 0, 100);
    Serial.print("Sensor Healthy: Level = ");
    Serial.print(levelPercent);
    Serial.println("%");
  }
  delay(500);
}

Physical boundary validation separates valid operational readings from electrical hardware failure states.

⚗️ Test your model

Test Condition / ActionExpected Result
Normal Operational Voltage (raw 512)Alarm LOW; outputs 'Sensor Healthy: Level = 50%'
Unplug Sensor Wire (raw 0)Alarm HIGH; outputs 'Broken Wire / Sensor Disconnected!'
Short Wire to 5V (raw 1023)Alarm HIGH; outputs 'Short Circuit to 5V Rail!'
⚑ Try a challenge

Implement an automated watchdog timer that triggers an alarm if the sensor reading stays frozen at the exact same float value for 10 minutes!

❓ Quick check
What is the primary danger of accepting telemetry sensor data blindly without range and checksum validation?

📖 Our Story & Concepts

In community water towers, outdoor wiring is exposed to rain, rodents, and corrosion. If a sensor wire snaps, the analog pin floats to 0 volts. A naive program looks at 0V and concludes: "The tank is completely empty! Turn on the main borehole pump at maximum power!" Meanwhile, the tank was actually full, causing massive flooding and wasting precious water!

Defensive computing assumes hardware can fail. By utilizing 4–20mA current loop standards or 0.5V–4.5V ratiometric voltage spans, zero volts is explicitly reserved as a Hardware Cable Fault rather than zero level.

</> Full Annotated Code Walkthrough

// Complete Industrial Parity & Boundary Validator
const int SENSOR_PIN = A0;
const int RED_FAULT_LED = 12;
const int GREEN_OK_LED = 13;

struct TelemetryPacket {
  byte dataByte;
  byte parityBit;
};

TelemetryPacket encodePacket(byte rawVal) {
  TelemetryPacket p;
  p.dataByte = rawVal & 0x7F; // 7-bit payload
  byte ones = 0;
  for (int i = 0; i < 7; i++) {
    if ((p.dataByte >> i) & 1) ones++;
  }
  p.parityBit = ones % 2; // Even parity
  return p;
}

void setup() {
  pinMode(RED_FAULT_LED, OUTPUT);
  pinMode(GREEN_OK_LED, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  int raw = analogRead(SENSOR_PIN);
  if (raw < 45 || raw > 980) {
    digitalWrite(RED_FAULT_LED, HIGH);
    digitalWrite(GREEN_OK_LED, LOW);
    Serial.println("FAULT: Signal Out-of-Bounds!");
  } else {
    digitalWrite(RED_FAULT_LED, LOW);
    digitalWrite(GREEN_OK_LED, HIGH);
    byte val = map(raw, 45, 980, 0, 100);
    TelemetryPacket pkt = encodePacket(val);
    Serial.print("Telemetry Valid: "); Serial.print(pkt.dataByte);
    Serial.print(" | Parity: "); Serial.println(pkt.parityBit);
  }
  delay(400);
}

Physical boundary validation separates valid operational readings from electrical hardware failure states.

▷ Expected Results & Troubleshooting

Test Condition / ActionExpected Result
Normal Operational Voltage (raw 512)Alarm LOW; outputs 'Sensor Healthy: Level = 50%'
Unplug Sensor Wire (raw 0)Alarm HIGH; outputs 'Broken Wire / Sensor Disconnected!'
Short Wire to 5V (raw 1023)Alarm HIGH; outputs 'Short Circuit to 5V Rail!'

⚑ Extension Challenges & Blueprints

⚑ Extension Challenges
  • Level 1: Add a 2-bit cyclic redundancy check (CRC) algorithm.
  • Level 2: Trigger a safety lockout that shuts down water intake pumps during fault states.
  • Level 3: Store fault occurrence timestamps into non-volatile EEPROM memory for field audits.

❓ Check Your Understanding

Question 1: What is the primary danger of accepting telemetry sensor data blindly without range and checksum validation?

Question 2: If an ultrasonic tank sensor measures distance in a 200cm tank, why is a reading of 999cm classified as an immediate hardware fault?

Question 3: In a checksum scheme where Checksum = (Reading + Sequence) % 10, what is the valid checksum for Reading = 45 and Sequence = 3?

Question 4: What state should a safety-critical water monitor enter when consecutive telemetry packets fail validation?

Feedback appears after you check your answer.