Module 11: Arduino Nano & Compact Builds

Level: ๐ŸŸก Intermediate
Board: Arduino Nano
Prerequisites: Module 8
Estimated time: 60โ€“80 minutes
Goal: Build compact, portable projects and understand board selection.


What You'll Learn

The Arduino Uno is great for learning, but it's too bulky for most finished projects. The Arduino Nano is pin-compatible with the Uno, fits directly on a breadboard, and costs less. In this module you'll learn the Nano's differences, deal with USB drivers, solder headers, choose portable power, plan compact builds for enclosures, and put it all together with a battery-powered portable air quality monitor.


11.1 Nano vs. Uno: What's Different and What's the Same

Hardware Comparison

Spec Arduino Uno Arduino Nano
Microcontroller ATmega328P ATmega328P
Digital pins 14 14 (same)
Analog pins 6 (A0โ€“A5) 8 (A0โ€“A7, two extras)
PWM pins 6 6 (same: 3, 5, 6, 9, 10, 11)
Flash memory 32 KB 32 KB
RAM 2 KB 2 KB
Clock speed 16 MHz 16 MHz
Operating voltage 5V 5V
USB connector USB-B (large) Mini-USB or Micro-USB
Size 68.6 ร— 53.4 mm 45 ร— 18 mm
Breadboard-friendly No (needs jumper wires) Yes (plugs directly in)
Price (clone) ~$3โ€“5 ~$2โ€“4

Pin Mapping: What Moves

The pin functions are identical, but the physical locations change:

Key point: Any Uno sketch runs on a Nano without code changes. The pins are numbered the same. Only the physical wiring layout changes.

Power Differences

Feature Uno Nano
Barrel jack Yes (7โ€“12V DC) No
VIN pin Yes Yes (6.5โ€“12V recommended)
USB power USB-B (500 mA) Mini/Micro-USB (500 mA)
Total 5V output current ~800 mA (barrel) / ~500 mA (USB) ~500 mA (USB)
Onboard regulator AMS1117 (1A capable) AMS1117 variant (varies by clone)

The Nano has no barrel jack. For external power, use the VIN pin (accepts 6.5โ€“12V, regulated down to 5V) or feed regulated 5V directly to the 5V pin.


11.2 USB Drivers: CH340 vs. FTDI

The Driver Problem

Official Arduino Nanos use the FTDI FT232RL USB-to-serial chip. Most affordable clones use the CH340G chip instead. The CH340G requires a separate driver installation on some operating systems.

How to Know Which You Have

Look at the small IC near the USB connector:

Installing CH340 Drivers

Windows: Usually auto-installs via Windows Update. If not, download from the CH340 manufacturer's website.

macOS: Older macOS versions need a manual driver. macOS 12+ typically includes it. If your Nano isn't recognized, search "CH340 macOS driver" for the current installer.

Linux: CH340 support is built into the kernel since around 2014. Should work automatically.

Troubleshooting USB Connection

Symptom Try This
No port appears in IDE Install CH340 driver, try a different cable (data-capable!)
Port appears then disappears Defective clone, try pressing reset during upload
Upload fails with sync error Select "ATmega328P (Old Bootloader)" in Tools โ†’ Processor
Upload works but no serial output Baud rate mismatch, or TX/RX pins used for other purposes

The Old Bootloader trick: Many Nano clones use an older bootloader. If upload fails with "not in sync," go to Tools โ†’ Processor and select "ATmega328P (Old Bootloader)". This is the single most common Nano issue.


11.3 Soldering Headers

Many Nano boards arrive without headers soldered. You'll need to solder them yourself to use the board with a breadboard.

Tools Needed

Tool Purpose
Soldering iron (25โ€“40W) Melting solder
Solder (0.8mm, rosin core, lead-free) Joining metal
Helping hands or PCB holder Holding the board still
Solder wick or solder sucker Fixing mistakes
Flux pen (optional) Improves solder flow

Step-by-Step Header Soldering

1. Prepare:

2. Tack corners first:

3. Solder remaining pins:

4. Inspect:

Common Soldering Mistakes

Mistake Looks Like Fix
Cold joint Dull, grainy blob Reheat and add a tiny bit of fresh solder
Too much solder Large ball covering pad Use solder wick to remove excess
Solder bridge Two adjacent pins connected Use solder wick between them
Lifted pad Copper pad separated from PCB Damaged; use a jumper wire to restore connection

Safety


11.4 Portable Power Options

Battery Options for Nano Projects

Source Voltage Capacity Connect To Notes
USB power bank 5V 5000โ€“20000 mAh USB port Easiest, but may auto-shutoff at low current
3ร—AA (alkaline) 4.5V ~2500 mAh 5V pin directly Marginal: works when fresh, fails as voltage drops
4ร—AA (alkaline) 6V ~2500 mAh VIN pin Good option, runs through regulator
9V battery 9V ~500 mAh VIN pin Short runtime; emergency/demo only
18650 Li-ion (with boost converter) 3.7V โ†’ 5V 2000โ€“3500 mAh 5V pin Great capacity, needs boost circuit
LiPo + TP4056 charger 3.7V โ†’ 5V (boosted) varies 5V pin Rechargeable, compact
2ร—18650 7.4V 2000โ€“3500 mAh VIN pin Through regulator, good runtime
CR2032 coin cell 3V ~220 mAh Not recommended for Nano Too low voltage and current for ATmega328P at 16 MHz

Power Bank Auto-Shutoff Problem

Many USB power banks detect low current draw and turn off, thinking the device is fully charged. A basic Arduino Nano draws only ~20 mA, below the detection threshold of many power banks.

Solutions:

Calculating Battery Runtime

Runtime (hours) = Battery capacity (mAh) / Current draw (mA)

Example: Nano (20 mA) + OLED (20 mA) + MQ-135 sensor (150 mA) = 190 mA total

With 4ร—AA batteries (2500 mAh): 2500 / 190 โ‰ˆ 13 hours

With a 2000 mAh 18650 + boost converter (85% efficient): (2000 ร— 0.85) / 190 โ‰ˆ 9 hours

Always measure actual current draw with a multimeter rather than relying on datasheet values. Actual consumption often differs from specifications.


11.5 Designing for Enclosures

Planning Before Building

Before you build the circuit, plan the enclosure:

1. Measure everything:

2. Sketch the layout:

3. Access considerations:

Enclosure Options

Type Skill Required Cost Best For
Cardboard box Minimal Free Quick prototypes
Plastic project box Low (drill holes) $2โ€“5 Durable prototypes
3D printed Medium (CAD skills) $1โ€“3 filament Custom fit, professional look
Laser-cut acrylic Medium (vector design) $5โ€“10 Clean look, precise dimensions
Altoids tin Low $3 Classic hack, metal = shielding

Wire Management


Module Project: Portable Air Quality Monitor

Objective

Build a battery-powered portable monitor using the Arduino Nano, MQ-135 gas sensor, DHT22 for temperature/humidity, and SSD1306 OLED display. The finished project should be compact enough to fit in a small enclosure.

Components Needed

Component Quantity Notes
Arduino Nano 1 With soldered headers
Mini/Micro USB cable 1 For programming
Breadboard (half-size) 1 Or perfboard for permanent build
MQ-135 Air Quality Sensor module 1 Detects NH3, NOx, alcohol, benzene, smoke, CO2
DHT22 sensor 1
SSD1306 OLED (128ร—64, I2C) 1
10kฮฉ Resistor 1 DHT22 pull-up
4ร—AA battery holder 1 Connect to VIN and GND
AA batteries 4
Slide switch (SPST) 1 Power on/off
Jumper wires 8+ Short ones

Important: MQ-135 Considerations

The MQ-135 contains a heater element that must warm up for accurate readings:

Calibration note: The MQ-135 is not a precision instrument. It gives a relative reading ("better" or "worse" air quality), not exact PPM values. For this project, we'll create a relative scale and track changes over time.

Wiring

Connection Details
Nano A0 MQ-135 AOUT (analog output)
Nano D2 DHT22 DATA (+ 10kฮฉ pull-up to 5V)
Nano A4 OLED SDA
Nano A5 OLED SCL
Nano 5V DHT22 VCC, OLED VCC
Nano VIN Battery + (through slide switch)
Nano GND All component GNDs, battery โˆ’
MQ-135 VCC Battery + (through slide switch) directly, or Nano 5V

Power routing: The MQ-135 draws 150 mA, which is significant. On battery power via VIN, the Nano's regulator handles everything. On USB power, ensure total current stays within USB limits.

The Code

/*
 * Module 11 Project: Portable Air Quality Monitor
 *
 * Arduino Nano with:
 * - MQ-135 gas sensor โ†’ A0
 * - DHT22 โ†’ D2 (10kฮฉ pull-up)
 * - SSD1306 OLED โ†’ A4 (SDA), A5 (SCL)
 * - Battery powered via VIN (4ร—AA through switch)
 *
 * Libraries: Adafruit SSD1306, Adafruit GFX, DHT
 * Board: Arduino Nano (ATmega328P or Old Bootloader)
 */

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

// --- Pins ---
const int MQ135_PIN = A0;
const int DHT_PIN = 2;

// --- Sensors ---
DHT dht(DHT_PIN, DHT22);

// --- OLED ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// --- Air quality baseline ---
// After warm-up, read the sensor in clean air to set baseline
int airBaseline = 0;
bool baselineSet = false;
const unsigned long WARMUP_TIME = 120000;  // 2 minutes (minimum for approximate readings)

// --- Smoothing ---
float smoothedAir = 0;
float smoothedTemp = 0;
float smoothedHumidity = 0;
const float ALPHA = 0.15;
bool firstReading = true;

// --- Timing ---
unsigned long lastSensorRead = 0;
const unsigned long SENSOR_INTERVAL = 2000;
unsigned long lastDisplayUpdate = 0;
const unsigned long DISPLAY_INTERVAL = 500;

// --- History (last 64 readings for graph) ---
int airHistory[64];
int historyIndex = 0;
bool historyFull = false;

// --- Battery voltage monitoring ---
// Read VIN through the voltage divider on the Nano (A7 on some clones)
// This is approximate โ€” varies by board

void drawProgressBar(int x, int y, int w, int h, int percent, bool invert) {
  percent = constrain(percent, 0, 100);
  display.drawRect(x, y, w, h, SSD1306_WHITE);
  int fillW = (w - 2) * percent / 100;
  if (invert) fillW = (w - 2) - fillW;
  display.fillRect(x + 1, y + 1, fillW, h - 2, SSD1306_WHITE);
}

String getAirQualityLabel(int reading) {
  if (!baselineSet) return "Warming up...";

  int diff = reading - airBaseline;

  if (diff < 20) return "Good";
  else if (diff < 80) return "Moderate";
  else if (diff < 150) return "Poor";
  else return "Unhealthy";
}

int getAirQualityPercent(int reading) {
  if (!baselineSet) return 0;
  int diff = reading - airBaseline;
  return constrain(map(diff, 0, 300, 100, 0), 0, 100);
}

void drawMiniGraph(int x, int y, int w, int h) {
  display.drawRect(x, y, w, h, SSD1306_WHITE);

  int count = historyFull ? 64 : historyIndex;
  if (count < 2) return;

  // Find min/max for scaling
  int minVal = 1023, maxVal = 0;
  for (int i = 0; i < count; i++) {
    if (airHistory[i] < minVal) minVal = airHistory[i];
    if (airHistory[i] > maxVal) maxVal = airHistory[i];
  }
  if (maxVal == minVal) maxVal = minVal + 1;

  // Draw points
  for (int i = 0; i < count && i < w - 2; i++) {
    int idx = historyFull ? (historyIndex + i) % 64 : i;
    int py = map(airHistory[idx], minVal, maxVal, y + h - 2, y + 1);
    display.drawPixel(x + 1 + i, py, SSD1306_WHITE);
  }
}

void updateDisplay() {
  display.clearDisplay();
  unsigned long now = millis();

  // --- Header ---
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.print("Air Monitor");

  // Warm-up indicator
  if (!baselineSet) {
    int warmPercent = constrain(now * 100 / WARMUP_TIME, 0, 100);
    display.setCursor(75, 0);
    display.print("W:");
    display.print(warmPercent);
    display.print("%");
  }

  display.drawLine(0, 9, 127, 9, SSD1306_WHITE);

  // --- Air quality ---
  display.setTextSize(1);
  display.setCursor(0, 12);
  display.print("Air: ");

  String label = getAirQualityLabel((int)smoothedAir);
  display.print(label);

  int aqPercent = getAirQualityPercent((int)smoothedAir);
  drawProgressBar(0, 22, 80, 7, aqPercent, false);

  display.setCursor(84, 22);
  display.print((int)smoothedAir);

  // --- Temperature & Humidity ---
  display.setCursor(0, 33);
  display.print("T:");
  display.print(smoothedTemp, 1);
  display.print("C");

  display.setCursor(64, 33);
  display.print("H:");
  display.print(smoothedHumidity, 0);
  display.print("%");

  // --- Mini history graph ---
  drawMiniGraph(0, 43, 64, 20);

  // --- Uptime ---
  display.setCursor(70, 55);
  unsigned long secs = now / 1000;
  char timeStr[10];
  sprintf(timeStr, "%02lu:%02lu:%02lu", secs / 3600, (secs % 3600) / 60, secs % 60);
  display.print(timeStr);

  display.display();
}

void setup() {
  Serial.begin(9600);
  dht.begin();

  // Initialize history
  for (int i = 0; i < 64; i++) airHistory[i] = 0;

  // OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED not found");
    while (1);
  }

  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(5, 10);
  display.println("Portable Air");
  display.println("  Quality Monitor");
  display.println();
  display.println("  Warming up sensor");
  display.println("  Please wait 2 min");
  display.display();

  Serial.println("Air Quality Monitor โ€” Module 11");
  Serial.println("MQ-135 warming up...");
}

void loop() {
  unsigned long now = millis();

  // --- Read sensors ---
  if (now - lastSensorRead >= SENSOR_INTERVAL) {
    lastSensorRead = now;

    // Air quality
    int airRaw = analogRead(MQ135_PIN);

    // DHT22
    float t = dht.readTemperature();
    float h = dht.readHumidity();

    // Smooth
    if (firstReading) {
      smoothedAir = airRaw;
      if (!isnan(t)) smoothedTemp = t;
      if (!isnan(h)) smoothedHumidity = h;
      firstReading = false;
    } else {
      smoothedAir = (ALPHA * airRaw) + ((1 - ALPHA) * smoothedAir);
      if (!isnan(t)) smoothedTemp = (ALPHA * t) + ((1 - ALPHA) * smoothedTemp);
      if (!isnan(h)) smoothedHumidity = (ALPHA * h) + ((1 - ALPHA) * smoothedHumidity);
    }

    // Set baseline after warm-up
    if (!baselineSet && now >= WARMUP_TIME) {
      airBaseline = (int)smoothedAir;
      baselineSet = true;
      Serial.print("Baseline set: ");
      Serial.println(airBaseline);
    }

    // Record history
    airHistory[historyIndex] = (int)smoothedAir;
    historyIndex = (historyIndex + 1) % 64;
    if (historyIndex == 0) historyFull = true;

    // Serial CSV output
    Serial.print(now / 1000);
    Serial.print(",");
    Serial.print(airRaw);
    Serial.print(",");
    Serial.print(smoothedTemp, 1);
    Serial.print(",");
    Serial.println(smoothedHumidity, 1);
  }

  // --- Update display ---
  if (now - lastDisplayUpdate >= DISPLAY_INTERVAL) {
    lastDisplayUpdate = now;
    updateDisplay();
  }
}

Circuit Diagram (SVG)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 420" font-family="monospace" font-size="11">
  <!-- Nano (small form factor) -->
  <rect x="50" y="120" width="100" height="220" fill="#1a6a7a" stroke="#333" stroke-width="2" rx="6"/>
  <text x="100" y="148" text-anchor="middle" fill="white" font-size="13" font-weight="bold">Arduino</text>
  <text x="100" y="165" text-anchor="middle" fill="white" font-size="12">Nano</text>

  <!-- USB -->
  <rect x="78" y="110" width="44" height="16" fill="#888" stroke="#333" stroke-width="1.5" rx="3"/>
  <text x="100" y="122" text-anchor="middle" font-size="7" fill="white">ยตUSB</text>

  <!-- Pins -->
  <rect x="150" y="155" width="22" height="12" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
  <text x="161" y="164" text-anchor="middle" fill="white" font-size="7">VIN</text>
  <rect x="150" y="173" width="22" height="12" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
  <text x="161" y="182" text-anchor="middle" fill="white" font-size="7">GND</text>
  <rect x="150" y="195" width="22" height="12" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
  <text x="161" y="204" text-anchor="middle" fill="white" font-size="7">5V</text>
  <rect x="150" y="225" width="22" height="12" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
  <text x="161" y="234" text-anchor="middle" fill="white" font-size="7">A0</text>
  <rect x="150" y="250" width="22" height="12" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
  <text x="161" y="259" text-anchor="middle" fill="white" font-size="7">D2</text>
  <rect x="150" y="280" width="22" height="12" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
  <text x="161" y="289" text-anchor="middle" fill="white" font-size="7">A4</text>
  <rect x="150" y="300" width="22" height="12" fill="#2a8a9a" stroke="white" stroke-width="1" rx="2"/>
  <text x="161" y="309" text-anchor="middle" fill="white" font-size="7">A5</text>

  <!-- Battery + Switch -->
  <rect x="250" y="120" width="90" height="55" fill="#dd9933" stroke="#333" stroke-width="2" rx="6"/>
  <text x="295" y="142" text-anchor="middle" fill="white" font-size="10" font-weight="bold">4ร—AA</text>
  <text x="295" y="158" text-anchor="middle" fill="white" font-size="9">6V</text>

  <rect x="355" y="132" width="50" height="22" fill="#999" stroke="#333" stroke-width="1.5" rx="4"/>
  <text x="380" y="147" text-anchor="middle" font-size="8" fill="white">Switch</text>

  <line x1="340" y1="140" x2="355" y2="140" stroke="red" stroke-width="2"/>
  <line x1="405" y1="140" x2="440" y2="140" stroke="red" stroke-width="2"/>
  <line x1="440" y1="140" x2="440" y2="161" stroke="red" stroke-width="2"/>
  <line x1="440" y1="161" x2="172" y2="161" stroke="red" stroke-width="2"/>
  <text x="300" y="100" font-size="9" fill="red">Battery + โ†’ Switch โ†’ VIN</text>

  <line x1="250" y1="165" x2="250" y2="179" stroke="blue" stroke-width="2"/>
  <line x1="250" y1="179" x2="172" y2="179" stroke="blue" stroke-width="2"/>

  <!-- MQ-135 -->
  <rect x="350" y="210" width="100" height="55" fill="#cc6633" stroke="#333" stroke-width="2" rx="6"/>
  <text x="400" y="232" text-anchor="middle" fill="white" font-size="11" font-weight="bold">MQ-135</text>
  <text x="400" y="250" text-anchor="middle" fill="white" font-size="8">Air Quality</text>
  <text x="400" y="260" text-anchor="middle" fill="#ffaa88" font-size="7">~150 mA!</text>

  <line x1="172" y1="231" x2="350" y2="231" stroke="green" stroke-width="1.5"/>
  <text x="260" y="226" font-size="8" fill="green">AOUT (A0)</text>

  <line x1="172" y1="201" x2="350" y2="220" stroke="red" stroke-width="1"/>
  <line x1="172" y1="179" x2="350" y2="255" stroke="blue" stroke-width="1"/>

  <!-- DHT22 -->
  <rect x="350" y="290" width="100" height="45" fill="#4488aa" stroke="#333" stroke-width="2" rx="6"/>
  <text x="400" y="312" text-anchor="middle" fill="white" font-size="10" font-weight="bold">DHT22</text>
  <text x="400" y="328" text-anchor="middle" fill="white" font-size="8">Temp+Humidity</text>

  <line x1="172" y1="256" x2="350" y2="308" stroke="green" stroke-width="1.5"/>
  <text x="260" y="280" font-size="8" fill="green">DATA (D2)</text>

  <rect x="280" y="295" width="35" height="12" fill="none" stroke="#333" stroke-width="1" rx="2"/>
  <text x="298" y="304" text-anchor="middle" font-size="7">10kฮฉโ†‘</text>

  <!-- OLED -->
  <rect x="530" y="180" width="130" height="85" fill="#222" stroke="#333" stroke-width="2" rx="6"/>
  <rect x="543" y="190" width="104" height="50" fill="#000" stroke="#555" stroke-width="1" rx="3"/>
  <text x="595" y="210" text-anchor="middle" fill="#00ccff" font-size="10">Air: Good</text>
  <text x="595" y="222" text-anchor="middle" fill="#00ccff" font-size="8">โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–‘โ–‘ 78%</text>
  <text x="595" y="234" text-anchor="middle" fill="#00ccff" font-size="8">T:23.5 H:52%</text>
  <text x="595" y="258" text-anchor="middle" fill="white" font-size="9">SSD1306 OLED</text>

  <line x1="172" y1="286" x2="530" y2="220" stroke="#cc8800" stroke-width="1.5"/>
  <text x="350" y="252" font-size="8" fill="#cc8800">SDA (A4)</text>
  <line x1="172" y1="306" x2="530" y2="240" stroke="#008800" stroke-width="1.5"/>
  <text x="350" y="280" font-size="8" fill="#008800">SCL (A5)</text>

  <!-- Size comparison -->
  <rect x="550" y="310" width="170" height="60" fill="#f8f8f8" stroke="#ccc" stroke-width="1" rx="4"/>
  <text x="635" y="330" text-anchor="middle" font-size="10" font-weight="bold">Form Factor</text>
  <text x="560" y="348" font-size="8">Nano: 45ร—18mm</text>
  <text x="560" y="362" font-size="8">Fits half-size breadboard</text>
</svg>

Circuit Schema (JSON)

{
  "module": 11,
  "project": "Portable Air Quality Monitor",
  "board": "Arduino Nano",
  "schematic": {
    "components": [
      {
        "id": "U1", "type": "arduino_nano",
        "pins_used": {
          "VIN": "net_vin", "GND": "net_gnd", "5V": "net_5v",
          "A0": "net_mq_aout", "D2": "net_dht_data",
          "A4": "net_sda", "A5": "net_scl"
        }
      },
      { "id": "BAT1", "type": "battery_pack", "value": "6V", "description": "4ร—AA",
        "pins": { "positive": "net_bat_pos", "negative": "net_gnd" } },
      { "id": "SW1", "type": "spst_switch", "purpose": "Power on/off",
        "pins": { "pin1": "net_bat_pos", "pin2": "net_vin" } },
      { "id": "MQ1", "type": "mq135", "current_draw": "150mA", "warmup": "2-5 min approximate",
        "pins": { "vcc": "net_5v", "gnd": "net_gnd", "aout": "net_mq_aout" } },
      { "id": "DHT1", "type": "dht22",
        "pins": { "vcc": "net_5v", "data": "net_dht_data", "gnd": "net_gnd" } },
      { "id": "R1", "type": "resistor", "value": "10000", "unit": "ohm",
        "purpose": "DHT22 data pull-up",
        "pins": { "pin1": "net_5v", "pin2": "net_dht_data" } },
      { "id": "OLED1", "type": "ssd1306", "address": "0x3C",
        "pins": { "vcc": "net_5v", "gnd": "net_gnd", "sda": "net_sda", "scl": "net_scl" } }
    ],
    "nets": [
      { "name": "net_gnd", "nodes": ["U1.GND", "BAT1.negative", "MQ1.gnd", "DHT1.gnd", "OLED1.gnd"] },
      { "name": "net_vin", "nodes": ["U1.VIN", "SW1.pin2"] },
      { "name": "net_bat_pos", "nodes": ["BAT1.positive", "SW1.pin1"] },
      { "name": "net_5v", "nodes": ["U1.5V", "MQ1.vcc", "DHT1.vcc", "R1.pin1", "OLED1.vcc"] },
      { "name": "net_mq_aout", "nodes": ["U1.A0", "MQ1.aout"] },
      { "name": "net_dht_data", "nodes": ["U1.D2", "DHT1.data", "R1.pin2"] },
      { "name": "net_sda", "nodes": ["U1.A4", "OLED1.sda"] },
      { "name": "net_scl", "nodes": ["U1.A5", "OLED1.scl"] }
    ],
    "power": {
      "source": "4ร—AA via VIN (6V, regulated to 5V internally)",
      "total_current_ma": 193,
      "breakdown": "Nano(23) + MQ-135(150) + DHT22(2.5) + OLED(17.5)",
      "estimated_runtime": "~13 hours on 2500mAh AA batteries"
    }
  },
  "code": { "filename": "module11_air_monitor.ino", "language": "cpp" },
  "validation": {
    "expected_behavior": "OLED shows air quality level with bar and history graph, temp, humidity. MQ-135 warms up for 2 min, then sets baseline.",
    "common_mistakes": [
      "Upload fails: select 'ATmega328P (Old Bootloader)' in Tools โ†’ Processor",
      "No port appears: install CH340 driver for your OS",
      "MQ-135 reads constant 0 or 1023: sensor not powered, or AOUT not connected to A0",
      "Air readings never change: sensor hasn't warmed up yet (needs 2+ minutes minimum)",
      "Battery dies fast: MQ-135 draws 150mA โ€” calculated runtime is correct, consider larger battery",
      "Power bank keeps shutting off: current draw may be too low during idle periods"
    ]
  }
}

Self-Check: Module 11

Before moving to Module 12, make sure you can:


Key Terms Glossary

Term Definition
Arduino Nano Compact ATmega328P board (45ร—18mm) that plugs directly into a breadboard
CH340G Common USB-to-serial chip on Nano clones. May require driver installation
FTDI FT232RL USB-to-serial chip on official Nanos. Drivers included in most OSes
Old Bootloader Legacy bootloader on many Nano clones. Requires different upload timing
VIN Voltage Input pin. Accepts 6.5โ€“12V, feeds the onboard regulator
Soldering Joining metal with melted solder alloy to create electrical connections
Cold joint A failed solder joint. Dull, grainy appearance, unreliable connection
Solder bridge Unintended solder connection between two adjacent pins or pads
Strain relief Securing a wire where it enters an enclosure to prevent breakage from movement
MQ-135 Gas sensor for air quality monitoring. Detects multiple gases
Baseline A reference reading taken in known conditions for comparison
Boost converter Switching regulator that increases voltage (e.g., 3.7V โ†’ 5V)

Previous: โ† Module 10: Motors & Movement Next: Module 12: Troubleshooting & Debugging: The Essential Skill โ†’