📱 Level 5 – App Communication

Project 5.4: "Fan Control by Temperature"

What you’ll learn

  • ✅ Read temperature: Use DHT11 to get temperature in degrees Celsius.
  • ✅ Control a fan: Turn the L9110 fan ON/OFF when it’s too hot.
  • ✅ Speed by temperature: Adjust fan speed with PWM based on the temperature.
  • ✅ Modes: Switch between automatic and manual control.
  • ✅ App-ready: Print clean status messages for easy app monitoring.

Key ideas

  • Short definition: A sensor gives numbers; we use those numbers to decide and act.
  • Real-world link: Thermostats turn fans on when rooms get warm to stay comfortable.

Blocks glossary (used in this project)

  • DHT11 temperature: Reads the current temperature from the sensor.
  • Digital output (Pin): Turns the fan ON/OFF.
  • PWM (fan speed): Sets how fast the fan spins by changing duty.
  • if / else: Decides actions based on a threshold.
  • Variable: Stores mode, threshold, and speed.
  • Serial println: Shows what the robot is doing (for debugging and apps).

What you need

PartHow many?Pin connection
D1 R321USB cable (30 cm)
DHT11 sensor1Signal → Pin 26, VCC, GND
L9110 fan module1IN1 → Pin 23 (fan control), VCC, GND

🔌 Wiring tip: Keep DHT11 data wire short and stable. Connect DHT11 signal to Pin 26. Connect L9110 IN1 to Pin 23 for ON/OFF or PWM control.
📍 Pin map snapshot: Using pins 26 (DHT11) and 23 (fan). Others remain free for displays/apps.


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.4.1 – Temperature reading

Goal: Read and print the temperature from DHT11.
Blocks used:

  • DHT11 temperature: Get degrees Celsius.
  • Serial println: Show the value.

Block sequence:

  1. Initialize DHT11 on Pin 26.
  2. Read temperature.
  3. Print it.

MicroPython code:

import dhtx  # Import DHT library for temperature
sensor = dhtx.DHT11(26)  # Create DHT11 sensor on Pin 26
temp_c = sensor.temperature()  # Read temperature in Celsius
print("Microproject 5.4.1: Temperature (C) =", temp_c)  # Show the reading

Reflection: Start by trusting the numbers—this is your thermometer.
Challenge:

  • Easy: Read twice and print the average.
  • Harder: Label “HOT” if temp ≥ 30, else “OK”.

Microproject 5.4.2 – Fan activation by temperature

Goal: Turn the fan ON if temperature is above a threshold.
Blocks used:

  • Digital output: Control Pin 23.
  • if / else: Compare temp to threshold.

Block sequence:

  1. Set threshold = 28°C.
  2. Read temperature.
  3. If temp ≥ threshold → fan ON; else OFF.
  4. Print status.

MicroPython code:

import dhtx  # Import DHT library
import machine  # Import machine for Pin control

sensor = dhtx.DHT11(26)  # DHT11 on Pin 26
fan = machine.Pin(23, machine.Pin.OUT)  # Fan control pin on 23

threshold_c = 28  # Temperature threshold in Celsius
print("Microproject 5.4.2: Threshold (C) =", threshold_c)  # Show chosen threshold

temp_c = sensor.temperature()  # Read current temperature
print("Temperature (C) =", temp_c)  # Show temp

if temp_c >= threshold_c:  # Decide based on threshold
    fan.value(1)  # Turn fan ON
    print("Fan: ON (too warm)")  # Explain action
else:
    fan.value(0)  # Turn fan OFF
    print("Fan: OFF (comfortable)")  # Explain action

Reflection: Thresholds are simple rules—above means “act,” below means “wait.”
Challenge:

  • Easy: Change threshold to 26°C.
  • Harder: Print “ALERT:HEAT” when temp ≥ 32°C.

Microproject 5.4.3 – Temperature-controlled speed (PWM)

Goal: Use PWM to set fan speed from 0–100% based on temperature.
Blocks used:

  • PWM duty: Change speed smoothly.
  • Math map: Convert temperature to a duty value.

Block sequence:

  1. Create PWM on Pin 23, freq=2000 Hz.
  2. Map temp range to duty (0–1023).
  3. Apply duty and print speed %.

MicroPython code:

import dhtx  # Import DHT library
import machine  # Import machine for PWM
sensor = dhtx.DHT11(26)  # DHT11 on Pin 26

pwm = machine.PWM(machine.Pin(23))  # Create PWM on Pin 23
pwm.freq(2000)  # Set PWM frequency to 2000 Hz
print("Microproject 5.4.3: PWM initialized at 2000 Hz")  # Confirm PWM setup

temp_c = sensor.temperature()  # Read temperature
print("Temperature (C) =", temp_c)  # Show temp

temp_min = 20  # Start of fan ramp (no spin below this)
temp_max = 32  # Full speed at this temperature
print("Ramp range (C):", temp_min, "to", temp_max)  # Explain ramp

# Constrain temperature to the ramp range
if temp_c < temp_min:  # Below ramp start
    temp_c = temp_min  # Clamp to minimum
    print("Clamped to temp_min:", temp_c)  # Explain clamp
if temp_c > temp_max:  # Above ramp end
    temp_c = temp_max  # Clamp to maximum
    print("Clamped to temp_max:", temp_c)  # Explain clamp

# Map temperature to duty (0–1023)
duty = int((temp_c - temp_min) * 1023 / (temp_max - temp_min))  # Linear map to duty
print("PWM duty (0-1023) =", duty)  # Show duty

pwm.duty(duty)  # Apply duty to control speed
speed_pct = int(duty * 100 / 1023)  # Convert duty to percent
print("Fan speed % =", speed_pct)  # Show speed percent

Reflection: PWM lets the fan spin gently or fast—smooth control feels smart.
Challenge:

  • Easy: Change temp_max to 30°C for quicker full speed.
  • Harder: Add a minimum duty (e.g., 200) so the fan starts reliably.

Microproject 5.4.4 – Automatic and manual mode

Goal: Switch between AUTO (sensor decides) and MANUAL (you decide).
Blocks used:

  • Variable mode: Store “AUTO” or “MANUAL”.
  • if / else: Choose behavior.
  • PWM/digital: Set speed or ON/OFF based on mode.

Block sequence:

  1. mode = “AUTO”.
  2. If AUTO → use temperature ramp.
  3. If MANUAL → set fixed speed or ON/OFF.
  4. Print mode and action.

MicroPython code:

import dhtx  # Import DHT library
import machine  # Import machine for PWM
sensor = dhtx.DHT11(26)  # DHT11 on Pin 26
pwm = machine.PWM(machine.Pin(23))  # PWM on Pin 23
pwm.freq(2000)  # Set PWM frequency
print("Microproject 5.4.4: PWM ready (2000 Hz)")  # Confirm PWM

mode = "AUTO"  # Choose mode: "AUTO" or "MANUAL"
print("Mode =", mode)  # Show current mode

if mode == "AUTO":  # Automatic control by temperature
    temp_c = sensor.temperature()  # Read temperature
    print("Temperature (C) =", temp_c)  # Show temp
    temp_min, temp_max = 20, 32  # Ramp range
    print("Ramp:", temp_min, "to", temp_max)  # Explain range
    if temp_c < temp_min:  # Clamp low
        temp_c = temp_min  # Clamp
        print("Clamped low to", temp_c)  # Explain
    if temp_c > temp_max:  # Clamp high
        temp_c = temp_max  # Clamp
        print("Clamped high to", temp_c)  # Explain
    duty = int((temp_c - temp_min) * 1023 / (temp_max - temp_min))  # Map temp to duty
    print("Duty =", duty)  # Show duty
    pwm.duty(duty)  # Apply duty
    print("Fan: AUTO speed applied")  # Confirm
else:  # Manual control
    duty = 700  # Fixed duty in manual mode
    print("Manual duty =", duty)  # Show chosen duty
    pwm.duty(duty)  # Apply duty
    print("Fan: MANUAL speed applied")  # Confirm

Reflection: Modes give you flexibility—sometimes you want full control, sometimes you want automation.
Challenge:

  • Easy: Set MANUAL duty to 400.
  • Harder: Add a manual ON/OFF toggle variable.

Microproject 5.4.5 – Integration with monitoring app

Goal: Print clean strings your app can display.
Blocks used:

  • Serial println: Output “TEMP”, “FAN”, and “MODE” data.
  • Variable: Store current duty and state.

Block sequence:

  1. Read temp.
  2. Compute duty and speed %.
  3. Print strings: TEMP:xx, FAN:ON/OFF or FAN:SPEED:xx, MODE:xxx.

MicroPython code:

import dhtx  # Import DHT library
import machine  # Import machine for PWM
sensor = dhtx.DHT11(26)  # DHT11 on Pin 26
pwm = machine.PWM(machine.Pin(23))  # PWM on Pin 23
pwm.freq(2000)  # Set PWM frequency
mode = "AUTO"  # Choose current mode
print("Microproject 5.4.5: Mode =", mode)  # Show mode

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

# Compute duty based on AUTO mode ramp (or fixed in MANUAL)
if mode == "AUTO":  # Automatic mapping
    temp_min, temp_max = 20, 32  # Ramp range
    if temp_c < temp_min:  # Clamp low
        temp_c = temp_min  # Clamp
    if temp_c > temp_max:  # Clamp high
        temp_c = temp_max  # Clamp
    duty = int((temp_c - temp_min) * 1023 / (temp_max - temp_min))  # Map temp to duty
else:  # Manual fixed duty
    duty = 700  # Fixed manual speed

pwm.duty(duty)  # Apply duty
speed_pct = int(duty * 100 / 1023)  # Duty to percent
print("FAN:SPEED:", speed_pct)  # App-friendly fan speed percent
print("MODE:", mode)  # App-friendly mode string

Reflection: Clean “KEY:VALUE” strings make apps simple and reliable.
Challenge:

  • Easy: Add “ALERT:HEAT” when temp ≥ 32°C.
  • Harder: Print “TARGET:xx” when in MANUAL to show desired speed.

Main project – Fan control by temperature

Blocks steps (with glossary)

  • DHT11 temperature: Read temp from Pin 26.
  • Decision (if): Compare to threshold for ON/OFF.
  • PWM duty: Adjust speed based on temp ramp.
  • Modes: AUTO uses sensor; MANUAL uses fixed duty.
  • Serial prints: Output TEMP, FAN, MODE for app monitoring.

Block sequence:

  1. Setup DHT11 (Pin 26), PWM (Pin 23, 2000 Hz).
  2. Read temperature and print it.
  3. If AUTO → map temp to duty and set speed.
  4. If MANUAL → set fixed duty.
  5. Print TEMP, FAN:SPEED, MODE for app.

MicroPython code (mirroring blocks)

# Project 5.4 – Fan Control by Temperature

import dhtx  # Read DHT11 temperature sensor
import machine  # Control PWM for the fan
import time  # Add small delays to stabilize readings

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

pwm = machine.PWM(machine.Pin(23))  # PWM channel on Pin 23 (fan control)
pwm.freq(2000)  # Set frequency to 2000 Hz for smooth fan control
print("PWM ready on Pin 23 (2000 Hz)")  # Confirm PWM setup

mode = "AUTO"  # Choose control mode: "AUTO" or "MANUAL"
print("Mode =", mode)  # Show current mode

temp_min, temp_max = 20, 32  # Temperature ramp range for AUTO mode
print("AUTO ramp (C):", temp_min, "to", temp_max)  # Explain ramp

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

    if mode == "AUTO":  # Sensor-based speed control
        t = temp_c  # Work on a local copy for clamping
        if t < temp_min:  # Clamp temperature to lower bound
            t = temp_min  # Clamp low
            print("Clamped low to", t)  # Explain clamp
        if t > temp_max:  # Clamp to upper bound
            t = temp_max  # Clamp high
            print("Clamped high to", t)  # Explain clamp
        duty = int((t - temp_min) * 1023 / (temp_max - temp_min))  # Map temp to duty
        print("Duty (0-1023) =", duty)  # Show duty
        pwm.duty(duty)  # Apply duty to fan
        speed_pct = int(duty * 100 / 1023)  # Convert duty to percent
        print("FAN:SPEED:", speed_pct)  # App-friendly speed string
        print("MODE:", mode)  # App-friendly mode string
    else:  # Manual fixed speed
        duty = 700  # Choose a fixed duty for manual mode
        print("Manual duty =", duty)  # Show manual setting
        pwm.duty(duty)  # Apply duty to fan
        speed_pct = int(duty * 100 / 1023)  # Convert duty to percent
        print("FAN:SPEED:", speed_pct)  # App-friendly speed
        print("MODE:", mode)  # App-friendly mode

    time.sleep(1)  # Wait 1 second between updates for stability

External explanation

  • What it teaches: Your robot reads temperature, decides if the fan should run, and sets speed based on how hot it is.
  • Why it works: The DHT11 gives a temperature; we compare it to a threshold or map it to a PWM duty; PWM changes the power to the fan, so it spins faster when hotter.
  • Key concept: “Sense → decide → control.”

Story time

You just built climate control. Your robot keeps its cool—literally—speeding up the fan when things heat up.


Debugging (2)

Debugging 5.4.A – Fan does not activate at the threshold

Problem: Temperature is above the threshold, but the fan stays OFF.
Clues: Serial shows “TEMP: 30” and “Threshold: 28,” but no change.
Broken code:

if temp_c > threshold_c:  # Strictly greater than
    fan.value(1)  # Turn on

Fixed code:

if temp_c >= threshold_c:  # Greater than or equal includes exact threshold
    fan.value(1)  # Turn fan ON
    print("Fan: ON at threshold")  # Confirm behavior

Why it works: Using >= triggers the fan exactly at the threshold instead of skipping that value.
Avoid next time: Decide whether equality should count as “ON” and code it clearly.

Debugging 5.4.B – Irregular speed control (fan stuttering)

Problem: Fan speed jumps or stutters when temperature fluctuates.
Clues: Duty changes too quickly; speed feels choppy.
Broken code:

duty = int((temp_c - temp_min) * 1023 / (temp_max - temp_min))  # No clamp, noisy input
pwm.duty(duty)  # Apply directly

Fixed code:

# Clamp first, then map
t = temp_c  # Local temp for processing
if t < temp_min:  # Clamp lower
    t = temp_min  # Clamp
if t > temp_max:  # Clamp upper
    t = temp_max  # Clamp
duty = int((t - temp_min) * 1023 / (temp_max - temp_min))  # Stable mapping
pwm.duty(duty)  # Apply duty
print("Smoothed duty =", duty)  # Explain stabilizing

Why it works: Clamping and mapping reduce sudden duty jumps, stabilizing speed.
Avoid next time: Add small delays (500–1000 ms) and avoid recalculating too fast.


Final checklist

  • I saw the temperature value in serial
  • The fan turned ON at or above the threshold
  • The fan speed changed smoothly with temperature

Extras

  • 🧠 Student tip: Add “MODE:MANUAL” and a variable duty to pick your own speed.
  • 🧑‍🏫 Instructor tip: Have students record temp vs duty to see the linear mapping.
  • 📖 Glossary:
    • DHT11: A simple sensor that reads temperature and humidity.
    • PWM (Pulse Width Modulation): A way to control speed/power by changing duty.
    • Threshold: The decision line where behavior changes.
  • 💡 Mini tips:
    • Read every 1–2 seconds to avoid jitter.
    • Use a minimum duty (e.g., 200) so the fan starts reliably.
    • Keep serial messages short for easy app parsing.
On this page