top of page
Search

NYC Problems: Automated AC Controls V2 (w/ code)

Initially, I had to manually modify the code to adjust the AC settings, which quickly became tedious. To streamline the process, I upgraded to two Wemos controllers connected over a local network and wrote some simple code that allows them to communicate. One controller is attached to a servo that adjusts the AC, while the other, located across the room, is connected to a temperature sensor. Now, the AC (or heater, depending on when the building switches over—New Yorkers know the struggle here) automatically turns on or off based on our preferences. I also designed and 3d printed a stronger base for the servo with a little box for the Wemo controller. Attaching the code below and some pictures---might have been easier to just move to a house.






Wemos Temperature Unit Code: 

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#include <Encoder.h>
#include <ESP8266WiFi.h>
#include <espnow.h>

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

// DHT sensor setup
#define DHTPIN 2 // GPIO 2, D4 on the Wemos D1 Mini
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

// Rotary Encoder setup
#define ENCODER_PIN1 14  // GPIO 14, D5 on the Wemos 
#define ENCODER_PIN2 12  // GPIO 12, D6 on the Wemos 
Encoder myEnc(ENCODER_PIN1, ENCODER_PIN2);

// Wi-Fi credentials
const char* ssid = "SSID goes here";
const char* password = "Password goes here"; // not today hackers

// Variables for temperature
float currentTemp = 0.0;
int setTemp = 72;  // Default Set Temperature in Fahrenheit
long oldPosition = -999;  // Rotary encoder position

// Peer MAC Address for Wemos AC
uint8_t wemosACAddress[] = {x, x, x, x, x, x}; // MAC address of Wemos AC

void onDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("Delivery success status: ");
  Serial.println(sendStatus == 0 ? "Success" : "Fail");
}

void setup() {
  Serial.begin(115200);

  // Start the DHT sensor
  dht.begin();

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  delay(1000);

  // Initialize WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println(" Connected!");

  // Initialize ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  esp_now_add_peer(wemosACAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
  esp_now_register_send_cb(onDataSent);
}

void loop() {
  // Read temperature from DHT11 (convert to Fahrenheit)
  currentTemp = dht.readTemperature(true);

  // Print temperature to Serial Monitor
  if (!isnan(currentTemp)) {
    Serial.print("Current Temperature: ");
    Serial.print(currentTemp);
    Serial.println(" F");
  } else {
    Serial.println("Error reading temperature!");
  }

  // Update set temperature using rotary encoder
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    setTemp = constrain(setTemp + (newPosition / 4), 50, 85);  // Adjusting the setTemp with constraints between 50 and 85 Fahrenheit
    myEnc.write(0);  // Reset encoder reading
    Serial.print("Set Temperature: ");
    Serial.println(setTemp);
  }

  // Update OLED display
  display.clearDisplay();

  // Display Set Temperature (slightly larger)
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("Set: ");
  display.print(setTemp);
  display.print(" F");

  // Display Current Temperature (larger, without label)
  display.setTextSize(3);
  display.setCursor(0, 25);
  display.print((int)currentTemp); // Remove decimals
  display.print(" F");

  // Draw a sun icon with rays next to the current temperature
  int sunX = 110;
  int sunY = 35;
  int sunRadius = 5;
  // Draw sun circle
  display.fillCircle(sunX, sunY, sunRadius, SSD1306_WHITE);
  // Draw sun rays
  for (int i = 0; i < 360; i += 45) {
    int rayLength = 10;
    float angle = i * 3.14 / 180;
    int x1 = sunX + cos(angle) * (sunRadius + 2);
    int y1 = sunY + sin(angle) * (sunRadius + 2);
    int x2 = sunX + cos(angle) * (sunRadius + rayLength);
    int y2 = sunY + sin(angle) * (sunRadius + rayLength);
    display.drawLine(x1, y1, x2, y2, SSD1306_WHITE);
  }

  display.display();

  // Send signal to Wemos AC if the temperature crosses the threshold
  if (!isnan(currentTemp)) {
    if (currentTemp < setTemp) {
      // Send command to Wemos AC to rotate servo to 170 degrees
      char message[] = "OPEN";
      esp_now_send(wemosACAddress, (uint8_t *)message, sizeof(message));
      Serial.println("Sent command to OPEN AC");
    } else if (currentTemp >= setTemp + 2) {
      // Send command to Wemos AC to rotate servo back to original position
      char message[] = "CLOSE";
      esp_now_send(wemosACAddress, (uint8_t *)message, sizeof(message));
      Serial.println("Sent command to CLOSE AC");
    }
  }

  delay(500);  // Update every 500 milliseconds
}

___________________________________________

Wemos Servo Motor Code: 

#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Servo.h>

// Servo setup
#define SERVO_PIN 2 // GPIO 2, corresponding to D4 on the Wemos D1 Mini
Servo acServo;

// Minimum delay between servo commands (in milliseconds)
#define COMMAND_COOLDOWN 2000
unsigned long lastCommandTime = 0;

void onDataRecv(uint8_t *mac, uint8_t *incomingData, uint8_t len) {
  // Get the current time
  unsigned long currentTime = millis();

  // Check if enough time has passed since the last command
  if (currentTime - lastCommandTime < COMMAND_COOLDOWN) {
    Serial.println("Ignoring command: Cooldown period not finished");
    return;
  }

  // Print MAC address of the sender
  char macStr[18];
  snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  Serial.print("Received data from MAC: ");
  Serial.println(macStr);

  // Convert incoming data to string command
  char command[len + 1];
  strncpy(command, (char *)incomingData, len);
  command[len] = '\0'; // Null-terminate the string

  Serial.print("Received command: ");
  Serial.println(command);

  // Update the last command time to now
  lastCommandTime = currentTime;

  // Reattach the servo each time to make sure it is active
  acServo.attach(SERVO_PIN);

  // Process command
  if (strcmp(command, "OPEN") == 0) {
    // Rotate servo 170 degrees (closer to max range)
    Serial.println("Executing command: OPEN - Moving servo to 170 degrees");
    acServo.write(180);
    delay(500); // Small delay to ensure stable signal
    Serial.println("Servo set to 170 degrees");
  } else if (strcmp(command, "CLOSE") == 0) {
    // Rotate servo back to 0 degrees
    Serial.println("Executing command: CLOSE - Moving servo to 0 degrees");
    acServo.write(0);
    delay(500); // Small delay to ensure stable signal
    Serial.println("Servo set to 0 degrees");
  } else {
    Serial.println("Received an unrecognized command.");
  }

  // Detach the servo after use to minimize jitter or power draw
  acServo.detach();
}

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Wemos AC Setup...");

  // Initialize Servo
  Serial.println("Initializing Servo...");
  acServo.attach(SERVO_PIN);
  acServo.write(0); // Start at 0 degrees
  Serial.println("Servo initialized at 0 degrees");

  // Initialize WiFi in Station mode
  Serial.println("Initializing WiFi...");
  WiFi.mode(WIFI_STA);
  Serial.println("WiFi initialized in station mode");

  // Initialize ESP-NOW
  Serial.println("Initializing ESP-NOW...");
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  Serial.println("ESP-NOW initialized successfully");

  // Set up ESP-NOW to receive data
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(onDataRecv);
  Serial.println("ESP-NOW receiver callback registered");
}

void loop() {
  // Nothing needed here, commands are received asynchronously
}










11 views

Recent Posts

See All

Comments


Commenting has been turned off.
bottom of page