CategoriesBuilds, Projects & Solutions

Adding OTA Updates to Your ESP8266 Fan Controller

In our ongoing quest to improve our custom fan controller project, we’re taking a major step forward by introducing Over-the-Air (OTA) updates. This addition will allow us to push new sketches to our ESP8266-based fan controller without needing to physically access the device, making maintenance and updates a breeze.

If you missed our previous posts, you can catch up here:

Why Use OTA Updates?

OTA updates are incredibly useful for devices installed in hard-to-reach places, such as our fan controller tucked away in a server rack. Our rack is security controlled and audit logged, making it quite a hassle to physically access the ESP8266 for every update. With OTA, we can update our device’s firmware wirelessly, eliminating the need to disconnect and reconnect it to our computer every time we make a change.

Setting Up OTA Updates

First, make sure you have the ArduinoOTA library installed. This library simplifies the process of adding OTA capabilities to your ESP8266 projects.

Install the ArduinoOTA Library

  • Open the Arduino IDE.
  • Go to `Sketch > Include Library > Manage Libraries`.
  • Search for `ArduinoOTA` and install it.

Modify Your Code for OTA

In addition to adding the OTA libraries, we also included one more minor change which is to display the current fan status within the remote web viewer as well!

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#include <ArduinoOTA.h>

#define DHTPIN 2 // GPIO2 corresponds to D4 on the ESP8266
#define DHTTYPE DHT11 // Define the sensor type
#define RELAY_PIN 5 // GPIO5 corresponds to D1 on the ESP8266

const char* ssid = "YOUR SSID";
const char* password = "YOUR WIFI PASSWORD";

DHT dht(DHTPIN, DHTTYPE);
ESP8266WebServer server(80);

bool fanOn = false;
const float ON_THRESHOLD = 30.0; // Temperature to turn the fan on
const float OFF_THRESHOLD = 28.0; // Temperature to turn the fan off

void handleRoot() {
  float temp = dht.readTemperature();
  String fanStatus = fanOn ? "ON" : "OFF";
  String html = "<html><head><meta charset=\"UTF-8\"></head><body><h1>Fan Controller</h1>";
  html += "<p>Current Temperature: " + String(temp) + " °C</p>";
  html += "<p>Fan Status: " + fanStatus + "</p>";
  html += "<p>On Threshold: " + String(ON_THRESHOLD) + " °C</p>";
  html += "<p>Off Threshold: " + String(OFF_THRESHOLD) + " °C</p>";
  html += "</body></html>";
  server.send(200, "text/html", html);
}

void setup() {
  Serial.begin(115200);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW); // Ensure the fan is initially off
  dht.begin();
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  
  Serial.println("Connected to WiFi");
  
  server.on("/", handleRoot);
  server.begin();
  Serial.println("HTTP server started");

  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  // Start OTA
  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_SPIFFS
      type = "filesystem";
    }
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) {
      Serial.println("Auth Failed");
    } else if (error == OTA_BEGIN_ERROR) {
      Serial.println("Begin Failed");
    } else if (error == OTA_CONNECT_ERROR) {
      Serial.println("Connect Failed");
    } else if (error == OTA_RECEIVE_ERROR) {
      Serial.println("Receive Failed");
    } else if (error == OTA_END_ERROR) {
      Serial.println("End Failed");
    }
  });
  ArduinoOTA.begin();
}

void loop() {
  server.handleClient();
  ArduinoOTA.handle(); // Handle OTA updates

  float temp = dht.readTemperature();

  if (isnan(temp)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  Serial.print("Temperature: ");
  Serial.println(temp);
  
  if (!fanOn && temp > ON_THRESHOLD) {
    digitalWrite(RELAY_PIN, HIGH); // Turn on the fan
    fanOn = true;
    Serial.println("Fan turned ON");
  } else if (fanOn && temp < OFF_THRESHOLD) {
    digitalWrite(RELAY_PIN, LOW); // Turn off the fan
    fanOn = false;
    Serial.println("Fan turned OFF");
  }

  delay(2000); // Wait a bit between readings
}

Upload the Initial OTA-Enabled Sketch

  • Connect the ESP8266 to your computer and upload the modified sketch via USB.
  • Open the Serial Monitor (`Tools > Serial Monitor`) and check the IP address printed by the ESP8266.

Upload New Code Over-the-Air

  • Disconnect the ESP8266 from your computer.
  • In the Arduino IDE, go to `Tools > Port` and select the IP address of your ESP8266 (it will appear in the list of ports).
  • Upload the new code as usual. The Arduino IDE will handle the OTA upload.
  • We did not set a password for OTA updates, so if the IDE requests a password, just enter in any random characters

By implementing OTA updates, we’ve made our fan controller project easier to maintain. Now, updating the firmware is as simple as connecting to the ESP8266 over WiFi and pushing the new code. No more climbing into the server rack!

Oh hi there 👋
It’s nice to meet you.

Sign up to receive awesome content in your inbox

We don’t spam! Read our privacy policy for more info.

Leave a Reply

Your email address will not be published. Required fields are marked *