The Hardware Reality Behind Arduino If Else Logic

Most beginner tutorials teach if/else logic using simple binary examples: if a button is pressed, turn on an LED; else, turn it off. But when you move from digital buttons to analog physical sensors—like temperature, humidity, or light—naive if/else logic falls apart.

Consider a basic thermostat. If you write if (temp > 30) { relay.on(); } else { relay.off(); }, sensor noise will cause the temperature reading to jitter between 29.99°C and 30.01°C. Your relay will click on and off dozens of times per second. This phenomenon, known as relay chatter, will weld your relay contacts shut or destroy your switching transistor within a week.

To fix this, we use hysteresis (a deadband) and the if / else if structure. This guide walks through building a physical thermal controller using an Arduino Uno R4 Minima, demonstrating how to write robust conditional logic that survives the noise of the real world.

Parts List and Pin Mapping

This build targets the Arduino Uno R4 Minima (running the Renesas RA4M1 core), chosen for its 5V logic tolerance and robust power regulation, which is critical when driving relay coils. All code is fully compatible with the classic Uno R3, but the R4 Minima is the recommended 2026 standard for new builds.

Bill of Materials

ComponentExact Variant / Part NumberEstimated Cost
MicrocontrollerArduino Uno R4 Minima (ABX00080)$20.00
SensorDHT22 (AM2302) with 3-pin breakout board$6.50
Relay Module5V Optocoupler Relay (Songle SRD-05VDC-SL-C)$3.00
Load12V DC 120mm PC Cooling Fan (4-pin PWM)$12.00
Power Supply12V 2A DC Wall Adapter (for fan and relay VCC)$8.00
Display0.96" I2C OLED 128x64 (SSD1306 driver)$5.00

Pin Mapping Table

ModuleModule PinArduino Uno R4 Minima PinNotes
DHT22VCC5VDo not use 3.3V
DHT22DataD2Breakout includes 10k pull-up
DHT22GNDGND
RelayVCCVIN (or external 5V)See power warning below
RelayIND8Active LOW on most modules
RelayGNDGND
OLEDSDAA4I2C Data
OLEDSCLA5I2C Clock
Power Warning: A standard 5V Songle relay coil draws roughly 70mA to 90mA. The Arduino Uno R4 Minima's onboard 5V regulator can handle this, but if you add more relays, power the relay module's VCC from an external 5V buck converter tied to the 12V supply to prevent microcontroller brownouts.

Wiring and Setup Steps

  1. Wire the Sensor: Connect the DHT22 VCC to 5V, GND to GND, and Data to D2. If you are using a bare 4-pin DHT22 without a breakout board, you must solder a 10kΩ pull-up resistor between VCC and the Data pin, or the sensor will return NaN (Not a Number) errors.
  2. Wire the Display: Connect the SSD1306 OLED SDA to A4 and SCL to A5. Connect VCC to 3.3V or 5V (check your specific module's silkscreen) and GND to GND.
  3. Wire the Relay (Low Voltage DC): Connect the relay IN pin to D8. For the load side, connect the 12V power supply positive to the relay's COM (Common) terminal. Connect the NO (Normally Open) terminal to the red wire of your 12V fan. Connect the fan's black wire directly to the 12V power supply ground.
  4. Verify De-energized State: Before plugging the Arduino into your PC, ensure the 12V power supply is unplugged. Double-check that no 12V wires are touching the Arduino's 5V or 3.3V pins.

The Complete Compilable Code with Hysteresis

This code targets the Arduino Uno R4 Minima. It uses the if / else if structure to implement a 2°C deadband. The fan turns on at 28°C, but it will not turn off until the temperature drops to 26°C. This completely eliminates relay chatter.


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

// --- PIN DEFINITIONS ---
#define DHTPIN 2          // Digital pin connected to the DHT sensor
#define DHTTYPE DHT22     // DHT 22 (AM2302)
#define RELAY_PIN 8       // Digital pin connected to Relay IN

// --- THRESHOLDS (Hysteresis Deadband) ---
#define TEMP_HIGH 28.0    // Turn fan ON at this temperature
#define TEMP_LOW 26.0     // Turn fan OFF at this temperature

// --- DISPLAY DEFINITIONS ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C

// --- OBJECT INITIALIZATION ---
DHT dht(DHTPIN, DHTTYPE);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// State variable to hold relay status between loops
bool fanState = false; 

void setup() {
  Serial.begin(115200);
  
  // Initialize Relay Pin
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, HIGH); // HIGH = OFF for active-low relay modules
  
  // Initialize DHT Sensor
  dht.begin();
  
  // Initialize OLED Display
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Halt execution if display fails
  }
  
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.println("System Initializing...");
  display.display();
  delay(2000); // DHT22 requires 2s startup time
}

void loop() {
  // Wait 2 seconds between measurements (DHT22 max sample rate)
  delay(2000);
  
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  
  // --- ERROR HANDLING ---
  // Check if any reads failed and exit early (to try again)
  if (isnan(temperature) || isnan(humidity)) {
    Serial.println(F("Failed to read from DHT sensor! Check wiring."));
    updateDisplay("DHT ERROR", 0.0, 0.0);
    return;
  }
  
  // --- CORE DECISION LOGIC: HYSTERESIS ---
  if (temperature >= TEMP_HIGH) {
    // Temperature exceeded upper threshold: Force ON
    fanState = true;
  } 
  else if (temperature <= TEMP_LOW) {
    // Temperature dropped below lower threshold: Force OFF
    fanState = false;
  } 
  // IMPLICIT ELSE: If temp is between LOW and HIGH, fanState retains its previous value.
  
  // --- ACTUATE HARDWARE ---
  if (fanState) {
    digitalWrite(RELAY_PIN, LOW); // LOW = ON for active-low modules
  } else {
    digitalWrite(RELAY_PIN, HIGH); // HIGH = OFF
  }
  
  // --- OUTPUT DATA ---
  Serial.print(F("Temp: "));
  Serial.print(temperature);
  Serial.print(F("C | Fan: "));
  Serial.println(fanState ? "ON" : "OFF");
  
  updateDisplay("NORMAL", temperature, humidity);
}

// Helper function to update the OLED
void updateDisplay(String status, float temp, float hum) {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.setTextSize(1);
  display.print(F("Status: "));
  display.println(status);
  
  display.setTextSize(2);
  display.setCursor(0, 20);
  display.print(temp, 1);
  display.print(F("C"));
  
  display.setTextSize(1);
  display.setCursor(0, 50);
  display.print(F("Hum: "));
  display.print(hum, 1);
  display.print(F("% | Fan: "));
  display.println(fanState ? "ON" : "OFF");
  
  display.display();
}

Debugging: When Your Logic Fails in the Real World

When physical hardware meets software, things break in ways the IDE compiler cannot predict. If your build fails, here are the first three things to check, followed by exact compiler errors you might encounter.

The First 3 Things to Check on Failure

  1. Floating Input Noise on the DHT22: If your serial monitor spams Failed to read from DHT sensor!, your data pin is likely floating. Even if your breakout board claims to have a pull-up resistor, cheap clones often omit it. Solder a 10kΩ resistor between the VCC and Data pins on the sensor.
  2. Relay Chatter (Missing Hysteresis): If the relay clicks rapidly when the temperature hovers around 28°C, you have accidentally implemented a simple if/else instead of the if / else if deadband structure provided above. Verify your thresholds.
  3. Microcontroller Brownout: If the Arduino resets itself the exact moment the relay clicks on, your 5V rail is sagging. The relay coil inrush current is pulling the voltage below the RA4M1's minimum operating threshold. Power the relay VCC from an external supply.

Exact Compiler Error Strings and Fixes

Exact Error StringRanked CauseThe Fix
fatal error: DHT.h: No such file or directory 1. Missing library.
2. Typo in include statement.
Open Library Manager (Ctrl+Shift+I), search for DHT sensor library by Adafruit, and install it. Also install the required Adafruit Unified Sensor dependency.
no matching function for call to 'DHT::DHT(int)' 1. Outdated library version.
2. Incorrect object initialization.
The modern Adafruit library requires the sensor type as the second argument. Ensure your code reads DHT dht(DHTPIN, DHTTYPE); and not just DHT dht(DHTPIN);.
exit status 1 (accompanied by SSD1306 allocation failed in Serial) 1. Wrong I2C address.
2. SDA/SCL swapped.
Run the I2C Scanner sketch. If your OLED is at 0x3D instead of 0x3C, change #define SCREEN_ADDRESS 0x3C to 0x3D in the code.

Decision Tree: Choosing the Right Conditional Structure

Not every problem requires an if / else if hysteresis loop. Use this decision path to select the exact conditional structure your specific embedded project needs.

Hardware ScenarioRecommended StructureConcrete Example
Single Threshold Trigger
(e.g., Limit switch, water leak detector)
if
(No else required)
if (digitalRead(LEAK_PIN) == HIGH) { triggerAlarm(); }
Binary Toggle
(e.g., Manual button toggling an LED)
if / else if (buttonState == PRESSED) { led = ON; } else { led = OFF; }
Environmental Control
(e.g., Thermostat, humidifier, battery charger)
if / else if
(Default Pick)
The hysteresis logic used in this article's code block.
Discrete State Machine
(e.g., OLED menu navigation, RGB color modes)
switch / case switch(menuState) { case 1: showTemp(); break; case 2: showHum(); break; }
How to Extend or Simplify this Build:
To Simplify: Remove the OLED display code and rely entirely on Serial.print() for debugging. This reduces memory footprint and eliminates I2C library dependencies.
To Extend: Add a secondary conditional block to check for critical over-temperature faults. For example, add if (temperature > 45.0) { shutdownSystem(); } at the very top of your loop to act as a hardware-protection watchdog, independent of the normal hysteresis control.

By treating if/else not just as a software syntax rule, but as a physical control mechanism, you bridge the gap between writing code that compiles and writing code that survives on the workbench. Always define your thresholds, protect your inputs, and respect the deadband.