Cirkit Designer Logo
Cirkit Designer
Your all-in-one circuit design IDE
Home / 
Project Documentation

ESP32-Based Temperature-Controlled Fan with OLED Display

Image of ESP32-Based Temperature-Controlled Fan with OLED Display

Circuit Documentation

Summary

This circuit involves an ESP32 microcontroller interfacing with an LM35 temperature sensor. The ESP32 reads the temperature data from the LM35 sensor and displays it on an OLED screen. Additionally, the ESP32 controls a fan using a TRIAC based on the temperature readings.

Component List

ESP32 (30 pin)

  • Description: A powerful microcontroller with built-in Wi-Fi and Bluetooth capabilities.
  • Pins: EN, VP, VN, D34, D35, D32, D33, D25, D26, D27, D14, D12, D13, GND, Vin, D23, D22, TX0, RX0, D21, D19, D18, D5, TX2, RX2, D4, D2, D15, 3V3
  • Purpose: Acts as the main controller for reading temperature data, displaying it, and controlling the fan.

Temperature Sensor (LM35)

  • Description: A precision integrated-circuit temperature sensor with an output voltage linearly proportional to the Centigrade temperature.
  • Pins: +Vs, Vout, GND
  • Purpose: Measures the ambient temperature and provides an analog voltage output corresponding to the temperature.

Wiring Details

ESP32 (30 pin)

  • D34: Connected to Vout of the LM35 temperature sensor.
  • GND: Connected to GND of the LM35 temperature sensor.
  • 3V3: Connected to +Vs of the LM35 temperature sensor.

Temperature Sensor (LM35)

  • Vout: Connected to D34 of the ESP32.
  • GND: Connected to GND of the ESP32.
  • +Vs: Connected to 3V3 of the ESP32.

Code Documentation

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

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1  // Reset pin (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define LM35_PIN 34          // ESP32 analog input pin connected to LM35
#define TRIAC_PIN 12         // Pin controlling the TRIAC (GPIO 12)
#define ZERO_CROSS_PIN 13    // Pin connected to zero-cross detector (GPIO 13)
#define FAN_MAX_DELAY 8333   // Max delay in microseconds (100% off at 60Hz)

// Baseline temperature in °C (adjust this to your desired baseline)
float baselineTemp = 20.0;
int delayTime = 0;  // Delay for phase angle control

void IRAM_ATTR zeroCrossDetected() {
  delayMicroseconds(delayTime);
  digitalWrite(TRIAC_PIN, HIGH);  // Fire the TRIAC
  delayMicroseconds(10);          // Keep TRIAC on for a few microseconds
  digitalWrite(TRIAC_PIN, LOW);   // Turn off the TRIAC
}

void setup() {
  pinMode(TRIAC_PIN, OUTPUT);
  pinMode(ZERO_CROSS_PIN, INPUT);

  // Attach interrupt for zero-cross detection
  attachInterrupt(digitalPinToInterrupt(ZERO_CROSS_PIN), zeroCrossDetected, RISING);

  Serial.begin(115200);  // ESP32 operates faster, so use a higher baud rate
  
  // Initialize the OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // Address 0x3C for most OLEDs
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);  // Don't proceed, loop forever
  }
  display.clearDisplay();  // Clear the buffer
  display.setTextSize(4);  // Set text size (increase for bigger text)
  display.setTextColor(SSD1306_WHITE);  // Set text color
  
  delay(2000);  // Give display some time to initialize
}

void loop() {
  int sensorValue = analogRead(LM35_PIN);  // Read analog value from LM35
  
  // Convert the analog value to temperature in Celsius
  // LM35 outputs 10mV per degree Celsius, powered at 5V
  float voltage = sensorValue * (5.0 / 4095.0);  // Convert analog reading to voltage at 5V
  int currentTemp = (int)(voltage * 100);  // Convert voltage to temperature in Celsius as whole number

  // Display the temperature in the Serial Monitor
  Serial.print("Current Temp: ");
  Serial.println(currentTemp);

  // Display the temperature on the OLED
  display.clearDisplay();  // Clear the display each loop
  display.setCursor(0, 0);  // Start at top-left corner
  display.setTextSize(2);   // Set text size
  display.print("Temp: ");
  display.print(currentTemp); // Show only whole degrees
  display.println(" C");

  // Display fan speed (based on the delay time)
  float fanSpeed = map(delayTime, FAN_MAX_DELAY, 0, 0, 100);  // Calculate fan speed as percentage
  display.print("Fan: ");
  display.print((int)fanSpeed); // Show fan speed as whole number
  display.println(" %");

  display.display();  // Update the display with the new data

  // Calculate the delay for the TRIAC phase control based on temperature
  if (currentTemp > baselineTemp) {
    float tempDiff = currentTemp - baselineTemp;
    float fanPower = map(tempDiff, 0, 10, 0, 100);  // Scale temperature difference to 0-100% power
    fanPower = constrain(fanPower, 0, 100);        // Constrain to max 100% power
    delayTime = map(fanPower, 0, 100, FAN_MAX_DELAY, 0);  // Larger delay = less power
  } else {
    delayTime = FAN_MAX_DELAY;  // No power to the fan if temp is below baseline
  }

  delay(1000);  // Update every second
}

This code initializes the ESP32 to read temperature data from the LM35 sensor, display it on an OLED screen, and control a fan using a TRIAC based on the temperature readings. The fan speed is adjusted using phase angle control, which is synchronized with the AC zero-crossing signal.