📱 Level 5 – App Communication

Project 5.9: "Early Warning System"

What you’ll learn

  • ✅ Detect rain, soil moisture, and temperature: Read three sensors to monitor conditions.
  • ✅ Create early warnings: Print app-friendly alerts like “ALERT:FLOOD_RISK” and “ALERT:DROUGHT”.
  • ✅ Push-style notifications: Format messages for app to pop up warnings clearly.
  • ✅ Protection actions: Print commands to cover/protect equipment when alerts trigger.
  • ✅ Reliable thresholds: Prevent false alarms with confirmation windows.

Key ideas

  • Short definition: Early warnings are fast messages sent when sensor values cross safety lines.
  • Real-world link: Weather stations and smart farms warn about rain, floods, and droughts so we act in time.

Blocks glossary (used in this project)

  • DHT11 temperature: Reads air temperature in Celsius from Pin 26.
  • Analog input (ADC): Reads soil moisture as a raw number (0–4095) from Pin 32.
  • Digital input (Pin): Reads raindrop sensor (1 = wet trigger, 0 = dry) from Pin 35.
  • If / else: Decides when to trigger alerts.
  • Serial println: Sends “KEY:VALUE” and “ALERT:…” messages to the app.
  • Timing windows: Confirms events over short periods to avoid false alerts.

What you need

Part How many? Pin connection
D1 R32 1 USB cable (30 cm)
DHT11 1 Signal → Pin 26, VCC, GND
Soil humidity sensor 1 Signal → Pin 32 (ADC), VCC, GND
Raindrop detection sensor 1 DO → Pin 35 (digital input), VCC, GND

🔌 Wiring tip: Use Pin 35 for raindrop (input-only pins 34–39 are ideal), Pin 32 for soil (ADC), and Pin 26 for DHT11. Keep wires short to reduce noise.
📍 Pin map snapshot: Using 26 (DHT), 32 (soil ADC), 35 (rain DO). Others stay free for future actuators.


Before you start

  • USB cable is plugged in
  • Serial monitor is open
  • Test print shows:
print("Ready!")  # Confirm serial is working

Microprojects (5 mini missions)

Microproject 5.9.1 – Sensor triad: rain, soil, temperature

Goal: Read all three sensors and print clean values.
Blocks used:

  • DHT11 temperature: Get temp in °C.
  • Analog input (ADC): Read soil raw, map to percent.
  • Digital input: Read rain state (1/0).

Block sequence:

  1. Setup DHT11 on Pin 26.
  2. Setup ADC on Pin 32 (12-bit).
  3. Setup raindrop input on Pin 35.
  4. Read and print values.

MicroPython code:

import dhtx  # Import DHT11 library for temperature
import machine  # Import machine for ADC and Pin control

sensor = dhtx.DHT11(26)  # Create DHT11 on Pin 26
print("Microproject 5.9.1: DHT11 ready on Pin 26")  # Status message

adc32 = machine.ADC(machine.Pin(32))  # Create ADC on Pin 32 for soil sensor
adc32.atten(machine.ADC.ATTN_11DB)  # Set ADC attenuation for full-scale reading
adc32.width(machine.ADC.WIDTH_12BIT)  # Use 12-bit resolution (0–4095)
print("ADC ready on Pin 32 (soil)")  # Status message

rain = machine.Pin(35, machine.Pin.IN)  # Digital input for raindrop on Pin 35
print("Raindrop input ready on Pin 35")  # Status message

temp_c = sensor.temperature()  # Read temperature in Celsius
print("TEMP:", temp_c)  # App-friendly temperature print

raw = adc32.read()  # Read raw soil moisture value
print("SOIL_RAW:", raw)  # Show raw number for calibration

soil_pct = int((4095 - raw) * 100 / 4095)  # Convert raw to % (higher=wet)
print("SOIL:", soil_pct)  # App-friendly soil percent

rain_state = rain.value()  # Read raindrop: 1=wet trigger, 0=dry
print("RAIN:", rain_state)  # App-friendly rain state

Reflection: Now you can “feel” sky, ground, and air—perfect for early warnings.
Challenge:

  • Easy: Print “PLACE:GARDEN” after the readings.
  • Harder: Average soil from 3 samples before mapping.

Microproject 5.9.2 – Thresholds and base alerts

Goal: Define thresholds and print heat/dry/rain alerts.
Blocks used:

  • Variables: temp_high, soil_low.
  • If / else: Trigger alerts on crossing.

Block sequence:

  1. Set temp_high = 32°C, soil_low = 30%.
  2. If temp ≥ temp_high → ALERT:HEAT.
  3. If soil < soil_low → ALERT:DROUGHT.
  4. If rain_state == 1 → ALERT:RAIN.

MicroPython code:

temp_c = 31  # Example temperature for testing (replace with sensor)
soil_pct = 25  # Example soil moisture percent (replace with sensor)
rain_state = 1  # Example rain state (1=wet trigger)

temp_high = 32  # Temperature threshold in Celsius
soil_low = 30  # Soil dryness threshold in percent
print("Microproject 5.9.2: Thresholds ->", "TEMP_HIGH:", temp_high, "SOIL_LOW:", soil_low)  # Show thresholds

if temp_c >= temp_high:  # Check temperature threshold
    print("ALERT:HEAT")  # Alert for heat

if soil_pct < soil_low:  # Check soil dryness threshold
    print("ALERT:DROUGHT")  # Alert for drought risk

if rain_state == 1:  # Check rain detection
    print("ALERT:RAIN")  # Alert for rain

Reflection: Clear thresholds = clear alerts—set numbers that match your environment.
Challenge:

  • Easy: Add ALERT:COLD when temp_c < 15.
  • Harder: Add ALERT:WIND later if you add a wind sensor.

Microproject 5.9.3 – Flood and drought combined logic

Goal: Print stronger warnings when multiple conditions are met.
Blocks used:

  • If / and: Combine conditions for risk levels.
  • Serial println: Print “ALERT:FLOOD_RISK” or “ALERT:SEVERE_DROUGHT”.

Block sequence:

  1. If rain_state == 1 and soil_pct > 80 → FLOOD_RISK.
  2. If rain_state == 0 and soil_pct < 20 → SEVERE_DROUGHT.
  3. Else print STATUS:OK.

MicroPython code:

temp_c = 28  # Example temp (replace with sensor)
soil_pct = 85  # Example soil percent (replace with sensor)
rain_state = 1  # Example rain (1=wet trigger)

print("Microproject 5.9.3: Combined risk checks")  # Status message

if (rain_state == 1) and (soil_pct > 80):  # Rain and very wet soil
    print("ALERT:FLOOD_RISK")  # Strong flood warning
elif (rain_state == 0) and (soil_pct < 20):  # No rain and very dry soil
    print("ALERT:SEVERE_DROUGHT")  # Strong drought warning
else:  # Neither severe case
    print("STATUS:OK")  # Normal status

Reflection: Combining signals gives smarter warnings—context matters.
Challenge:

  • Easy: Add ALERT:MUD if soil_pct > 90.
  • Harder: Add multi-level severity (LOW/MID/HIGH) as separate prints.

Microproject 5.9.4 – Push-style notifications for the app

Goal: Format messages that the app can show as notifications.
Blocks used:

  • Serial println: Print “NOTIFY:…” messages.
  • Variables: Compose readable text.

Block sequence:

  1. Build text like “NOTIFY:RAIN_DETECTED”.
  2. Include “DETAIL:” lines with values.
  3. Print both.

MicroPython code:

temp_c = 30  # Example temp for message (replace with sensor)
soil_pct = 40  # Example soil percent (replace with sensor)
rain_state = 1  # Example rain state (replace with sensor)

notify = "NOTIFY:RAIN_DETECTED"  # Short notification tag
print(notify)  # Send notification tag to app

detail = "DETAIL:TEMP=" + str(temp_c) + ",SOIL=" + str(soil_pct) + ",RAIN=" + str(rain_state)  # Compose details
print(detail)  # Send details to app

Reflection: Short tag + details make notifications easy to pop and read.
Challenge:

  • Easy: Change to NOTIFY:DRY_SOIL.
  • Harder: Add “PLACE:GARDEN_A” and a timestamp.

Microproject 5.9.5 – Protection systems activation

Goal: Print protection commands when risks are high.
Blocks used:

  • If / else: Decide protection.
  • Serial println: Print “PROTECT:…” lines.

Block sequence:

  1. If FLOOD_RISK → PROTECT:COVER_ON.
  2. If SEVERE_DROUGHT → PROTECT:SHADE_ON.
  3. Else → PROTECT:OFF.

MicroPython code:

soil_pct = 18  # Example soil percent (replace with sensor)
rain_state = 0  # Example rain state (replace with sensor)

print("Microproject 5.9.5: Protection action planner")  # Status message

if (rain_state == 1) and (soil_pct > 80):  # Flood risk condition
    print("PROTECT:COVER_ON")  # Command to deploy covers (simulated)
elif (rain_state == 0) and (soil_pct < 20):  # Severe drought condition
    print("PROTECT:SHADE_ON")  # Command to add shade or reduce evaporation (simulated)
else:  # No strong risk
    print("PROTECT:OFF")  # No protection needed

Reflection: Protection commands are like safety switches—turn them on only when truly needed.
Challenge:

  • Easy: Add PROTECT:ALERT_ONLY to notify without action.
  • Harder: Add a cooldown (60 s) before changing protection state again.

Main project – Early warning system

Blocks steps (with glossary)

  • DHT11 + soil + rain: Read all sensors and map soil to percent.
  • Base alerts: Heat/drought/rain using thresholds.
  • Combined risk: Flood or severe drought using multi-signal checks.
  • Notifications: Print NOTIFY + DETAIL messages.
  • Protection: Print PROTECT commands to simulate safety actions.

Block sequence:

  1. Setup sensors on 26, 32, 35.
  2. Read TEMP, SOIL(%), RAIN and print them.
  3. Trigger base alerts on thresholds.
  4. Trigger combined risk alerts.
  5. Print NOTIFY and PROTECT messages for the app.

MicroPython code (mirroring blocks)

# Project 5.9 – Early Warning System

import dhtx  # Read DHT11 temperature sensor
import machine  # Read ADC and digital inputs
import time  # Add timing utilities for confirmation windows

sensor = dhtx.DHT11(26)  # DHT11 on Pin 26
print("DHT11 ready on Pin 26")  # Confirm sensor setup

adc32 = machine.ADC(machine.Pin(32))  # Soil sensor ADC on Pin 32
adc32.atten(machine.ADC.ATTN_11DB)  # Configure ADC attenuation for full scale
adc32.width(machine.ADC.WIDTH_12BIT)  # Use 12-bit resolution (0–4095)
print("ADC ready on Pin 32 (soil)")  # Confirm ADC setup

rain = machine.Pin(35, machine.Pin.IN)  # Raindrop DO input on Pin 35
print("Raindrop input ready on Pin 35")  # Confirm raindrop input

temp_high = 32  # Temperature alert threshold (C)
soil_low = 30  # Soil dryness threshold (%)
print("Thresholds -> TEMP_HIGH:", temp_high, "SOIL_LOW:", soil_low)  # Show thresholds

while True:  # Continuous monitoring loop
    temp_c = sensor.temperature()  # Read temperature from DHT11
    print("TEMP:", temp_c)  # App-friendly temperature output

    raw = adc32.read()  # Read raw soil value
    print("SOIL_RAW:", raw)  # Print raw for calibration

    soil_pct = int((4095 - raw) * 100 / 4095)  # Map raw to percent (higher=wet)
    print("SOIL:", soil_pct)  # App-friendly soil percent

    # Confirm rain using a short 200 ms window to reduce false alerts
    confirm_hits = 0  # Start confirmation counter
    start = time.ticks_ms()  # Record window start time
    while time.ticks_diff(time.ticks_ms(), start) < 200:  # Sample for 200 ms
        confirm_hits += rain.value()  # Add 1 whenever sensor is HIGH
        time.sleep(0.01)  # Sample every 10 ms
    rain_state = 1 if confirm_hits > 5 else 0  # Confirm rain if several highs
    print("RAIN:", rain_state, "CONFIRM_HITS:", confirm_hits)  # App-friendly rain state

    # Base alerts
    if temp_c >= temp_high:  # Heat threshold
        print("ALERT:HEAT")  # Heat alert
    if soil_pct < soil_low:  # Dry soil threshold
        print("ALERT:DROUGHT")  # Drought alert
    if rain_state == 1:  # Rain detection
        print("ALERT:RAIN")  # Rain alert

    # Combined risk alerts
    if (rain_state == 1) and (soil_pct > 80):  # Rain + very wet soil
        print("ALERT:FLOOD_RISK")  # Strong flood warning
        print("NOTIFY:FLOOD_RISK")  # Notification tag
        print("DETAIL:TEMP=" + str(temp_c) + ",SOIL=" + str(soil_pct) + ",RAIN=" + str(rain_state))  # Details
        print("PROTECT:COVER_ON")  # Simulated protection action
    elif (rain_state == 0) and (soil_pct < 20):  # No rain + very dry soil
        print("ALERT:SEVERE_DROUGHT")  # Strong drought warning
        print("NOTIFY:SEVERE_DROUGHT")  # Notification tag
        print("DETAIL:TEMP=" + str(temp_c) + ",SOIL=" + str(soil_pct) + ",RAIN=" + str(rain_state))  # Details
        print("PROTECT:SHADE_ON")  # Simulated protection action
    else:  # Normal status path
        print("STATUS:OK")  # Normal status
        print("PROTECT:OFF")  # No protection needed

    time.sleep(2)  # Wait 2 seconds before next cycle for readability

External explanation

  • What it teaches: You built a real early warning flow: read sensors, decide risks, send notifications, and propose protective actions.
  • Why it works: Temperature and soil map to human-friendly values; rain is confirmed in a short window to avoid false triggers; combined conditions produce stronger alerts; “NOTIFY” and “DETAIL” messages help the app display clear warnings.
  • Key concept: “Sense → confirm → alert → notify → protect.”

Story time

Your robot is now a weather guardian. It spots rain, checks the ground, feels the air, and warns you with quick, clear messages—before trouble hits.


Debugging (2)

Debugging 5.9.A – Early warnings are not activated

Problem: Conditions hit thresholds but no alert appears.
Clues: Serial shows TEMP/SOIL/RAIN, but no “ALERT:…” lines.
Broken code:

if temp_c > temp_high:  # Excludes equal
    print("ALERT:HEAT")  # Heat alert (may miss exact threshold)

Fixed code:

if temp_c >= temp_high:  # Include equal case
    print("ALERT:HEAT")  # Heat alert fires reliably

Why it works: Including equality prevents missing the exact threshold value.
Avoid next time: Decide clearly whether equality should trigger alerts and code it.

Debugging 5.9.B – False alerts

Problem: Random rain spikes or noisy soil readings cause alerts.
Clues: Rain briefly prints 1, then 0; alerts flicker.
Broken code:

rain_state = rain.value()  # Single read is too sensitive to spikes
print("RAIN:", rain_state)  # May fluctuate

Fixed code:

confirm_hits = 0  # Count highs in a short window
start = time.ticks_ms()  # Start timing
while time.ticks_diff(time.ticks_ms(), start) < 200:  # 200 ms window
    confirm_hits += rain.value()  # Add HIGHs
    time.sleep(0.01)  # Small sampling interval
rain_state = 1 if confirm_hits > 5 else 0  # Confirm only if many highs
print("RAIN:", rain_state, "CONFIRM_HITS:", confirm_hits)  # Explain confirmation

Why it works: A confirmation window smooths noise and reduces false positives.
Avoid next time: Sample over short windows and choose sensible confirmation thresholds.


Final checklist

  • TEMP, SOIL(%), and RAIN printed clearly
  • Base alerts fired at thresholds
  • Combined risk alerts printed (FLOOD_RISK or SEVERE_DROUGHT)
  • NOTIFY and DETAIL messages appeared for the app
  • PROTECT commands printed when risks were high

Extras

  • 🧠 Student tip: Add “ALERT:LOW_BAT” if you track battery later; keep formats short.
  • 🧑‍🏫 Instructor tip: Have students test real wet/dry soil values to set practical thresholds.
  • 📖 Glossary:
    • Confirmation window: Short sampling period to verify an event before alerting.
    • Combined risk: Alert triggered by multiple conditions together.
    • Protection command: Printed action telling actuators what to do (simulated).
  • 💡 Mini tips:
    • Pace prints with small delays so the app doesn’t miss messages.
    • Keep wiring steady—sensor noise creates false alerts.
    • Label your station with PLACE to distinguish multiple setups.
On this page