The Core Decision: Choosing the Right Conditional Construct

The arduino if then else structure is the foundational decision-making tool in embedded C++. However, applying naive binary thresholds to physical hardware causes rapid relay cycling (chatter), which destroys mechanical contacts and burns out motor windings. When designing control logic, you must map your physical requirement to the correct software construct before writing a single line of code.

Condition TypeBest ConstructHardware Example
Binary threshold (True/False)if / elsePushbutton debounce toggle
Multi-tier analog rangesif / else if / elseTemperature bands with hysteresis
Discrete integer statesswitch / caseMenu navigation on an LCD
Complex multi-variable logicState Machine (Enum + Switch)Multi-stage battery charger
Concrete Pick: For single-sensor environmental threshold control, use if / else if paired with a hysteresis variable. Do not use nested if statements for analog ranges, and never use switch/case for floating-point sensor data.

Parts List and Pin Mapping for a Hysteresis Controller

This build targets the Arduino Uno R4 Minima (ABX00080). The R4 Minima operates at 5V logic but features a 32-bit RA4M1 core, meaning it processes floating-point math for our hysteresis calculations significantly faster than the legacy 8-bit ATmega328P, without requiring the dtostrf() workarounds for serial printing.

Bill of Materials

  • MCU: Arduino Uno R4 Minima (ABX00080)
  • Sensor: DHT22 / AM2302 (Wired module variant with onboard 10kΩ pull-up resistor)
  • Actuator: Songle SRD-05VDC-SL-C 5V Relay Module (Active-LOW trigger)
  • Indicators: 2x 5mm LEDs (Red for Heat, Blue for Cool) with 220Ω current-limiting resistors
  • Wiring: 22 AWG solid core hookup wire

Pin Mapping Table

ComponentModule PinArduino Uno R4 PinNotes
DHT22 SensorVCC5VRequires 5V for stable internal regulator
DHT22 SensorGNDGNDCommon ground with relay module
DHT22 SensorDATAD2Module has internal 10kΩ pull-up
Relay ModuleVCC5VPowers the optocoupler and coil
Relay ModuleGNDGNDCommon ground
Relay ModuleIND3Active-LOW (LOW = Coil Energized)
Red LED (Heat)Anode (+)D4Via 220Ω resistor
Blue LED (Cool)Anode (+)D5Via 220Ω resistor

Compilable Code: Dual-Threshold Logic with Error Handling

The following code implements a heating controller with a ±1.5°C hysteresis band. This prevents the relay from clicking on and off rapidly if the room temperature hovers exactly at the 24.0°C setpoint. It also includes critical error handling for sensor disconnects.

#include <DHT.h>

// --- PIN DEFINITIONS ---
#define DHTPIN 2
#define DHTTYPE DHT22
#define RELAY_PIN 3
#define LED_HEAT 4
#define LED_COOL 5

// --- CONTROL PARAMETERS ---
const float TARGET_TEMP = 24.0;
const float HYSTERESIS = 1.5;

DHT dht(DHTPIN, DHTTYPE);
bool heaterState = false; // Track state to maintain hysteresis band

void setup() {
  Serial.begin(115200);
  
  // Initialize pins
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_HEAT, OUTPUT);
  pinMode(LED_COOL, OUTPUT);
  
  // CRITICAL: Songle relay modules are Active-LOW. 
  // HIGH = Coil de-energized (Relay OFF). Set HIGH immediately to prevent startup spikes.
  digitalWrite(RELAY_PIN, HIGH); 
  digitalWrite(LED_HEAT, LOW);
  digitalWrite(LED_COOL, LOW);
  
  dht.begin();
  Serial.println("DHT22 Hysteresis Controller Initialized.");
}

void loop() {
  float currentTemp = dht.readTemperature();
  
  // --- ERROR HANDLING ---
  // Check if any reads failed and exit early (to try again).
  if (isnan(currentTemp)) {
    Serial.println("ERROR: Failed to read from DHT sensor! Check wiring.");
    // Fail-safe: Turn off relay if sensor fails to prevent runaway heating
    digitalWrite(RELAY_PIN, HIGH); 
    digitalWrite(LED_HEAT, LOW);
    digitalWrite(LED_COOL, LOW);
    delay(2000);
    return;
  }

  // --- DECISION LOGIC (IF / ELSE IF WITH HYSTERESIS) ---
  if (currentTemp < (TARGET_TEMP - HYSTERESIS)) {
    // Temperature dropped below the lower threshold (22.5°C)
    heaterState = true;
  } 
  else if (currentTemp > (TARGET_TEMP + HYSTERESIS)) {
    // Temperature rose above the upper threshold (25.5°C)
    heaterState = false;
  }
  // Note: If temp is between 22.5 and 25.5, heaterState remains unchanged.
  // This is the hysteresis band that prevents relay chatter.

  // --- ACTUATOR CONTROL ---
  if (heaterState == true) {
    digitalWrite(RELAY_PIN, LOW);  // Active-LOW: Energize coil
    digitalWrite(LED_HEAT, HIGH);
    digitalWrite(LED_COOL, LOW);
  } 
  else {
    digitalWrite(RELAY_PIN, HIGH); // Active-LOW: De-energize coil
    digitalWrite(LED_HEAT, LOW);
    digitalWrite(LED_COOL, HIGH);
  }

  // DHT22 requires ~2 seconds between reads
  delay(2000); 
}

Debugging: Syntax Errors and the First 3 Logic Checks

When writing conditional logic in the Arduino IDE, a single misplaced character will halt compilation. The most common syntax failure when chaining conditions is:

Exact Error String: error: expected primary-expression before 'else'

Ranked Causes for this Syntax Error

  1. Stray Semicolon: You placed a semicolon immediately after the if condition.
    Wrong: if (temp > 30); { ... }
    Fix: Remove the semicolon. The compiler sees the semicolon as the end of the if block, making the subsequent else an orphan.
  2. Missing Curly Braces: You omitted {} around a multi-line if block before the else.
    Fix: Always use curly braces for if/else blocks in embedded C++, even for single-line statements, to prevent scope bleeding.
  3. Assignment vs. Equality: You used = instead of == inside the condition, and the compiler's strict mode flags the resulting type mismatch before hitting the else.
    Fix: Use == for comparison.

The First 3 Things to Check When the Logic Fails (Hardware Runs Wrong)

If the code compiles but the relay chatters or ignores thresholds, check these three physical/logical traps:

  1. Floating-Point Exactness: Never use == to compare floats (e.g., if (temp == 24.0)). Sensor noise means the value might be 24.00001. Always use >, <, or >= with a hysteresis band.
  2. Active-LOW Inversion: Most 5V relay modules use an optocoupler triggered by pulling the IN pin to GND. If your relay clicks on when the code says HIGH, invert your logic or change your pin definitions.
  3. Sensor Read Timing: The DHT22 has a maximum sampling rate of 0.5Hz. If your loop() runs every 50ms and you call dht.readTemperature() every cycle, the library will return NaN (Not a Number) or stale data. Enforce a delay(2000) or use a millis() timer.

Extending the Build: State Machines vs. Nested Ifs

As your project grows—perhaps adding a humidity exhaust fan, a defrost cycle, and an alarm buzzer—your arduino if then else chains will become deeply nested and impossible to debug. This is known as "spaghetti logic."