Contents

How to make an AC smart

I have a room that - in winter - needs some heating. Instead of connecting it to my central heating system, I decided to use my mobile AC which can also heat.

The idea

The AC can be remote-controlled with an IR remote - which unfortunately cannot send through walls. So it is not possible to comfortably start the AC automatically or activate/deactivate it while sitting at the desk.

So the idea is (a) to read the IR signals for on/off from the original remote - and then (b) send those signals with my ESP 32 microcontroller to the AC. The ESP 32 is then connected to my smart home system, so that it can be automated or controlled via UI.

Additionally, (c) a photo transistor is used to detect if the AC is on or not. The transistor is taped to one of the LEDs on the AC - so whenever the photo transistor detects some light I can assume that the AC is active. This is especially useful as the ON and the OFF signal of the remote are the same - so would be hard to determine automatically if the AC is currently running or not.

The circuit(s)

Actually there are two circuits: One for reading the original IR signal initially and another permanent one to “make the AC smart”. The circuit described below focuses on the latter. For reading the IR signal you can just open IRremote->SimpleReceiver from the example section in your arduino IDE or check it here.

For the permanent circuit I am using another one of my trusted ESP 32, a BPW 40 NPN photo transistor and a KY-005 IR emitter. Furthermore, a 100kΩ resistor is used to pull up the data pin which is connected to the BPW 40 emitter.

From deviceFrom pinTo deviceTo pinDescription
BPW 40EmitterESP3234
BPW 40CollectorESP32Ground
ESP3234ESP323.3 VPull up pin 34 with 100kΩ resistor. The higher the resistor, the more sensitive the phototransistor is
KY-005MinusESP32Ground
KY-005VddESP325 V
KY-005DataESP3232

The sketch

The sketch uses the IRremote library to send IR signals and PubSubClient to receive and publish messages via MQTT.

#include <IRremote.hpp>
#include <PubSubClient.h>
#include <WiFi.h>

WiFiClient espClient;
PubSubClient client(espClient);

char charBuf[40];
bool acActive = false;

void loop()
{
  checkACActive();
  
  delay(200);
}


/**
 * Every loop: Read the photo transistor
 * If the returned value is within a certain threshold, the AC is active
 * If the status changed: send corresponding MQTT event 
 */
void checkACActive()
{
  int photodiodeValue = analogRead(PHOTO_DIODE_PIN);
  bool newActive = photodiodeValue < PHOTO_DIODE_THRESHOLD;

  if (newActive != acActive) {
    acActive = newActive;
    String boolAsString = acActive ? "true" : "false";
    client.publish("mqtt.0.climateremote.actual_state", boolAsString.c_str());
  }
}

/**
 * Called by the MQTT callback function when a certain message is received
 * Check full Github repo for details
 */
void sendOff()
{
  checkACActive();
  // if AC is already off: do nothing
  if (acActive == false) {
    return;
  }

  client.publish("mqtt.0.climateremote.message", "OFF");
  IrSender.sendNEC(0x80, 0x9C, 3);
}

/**
 * Called by the MQTT callback function when a certain message is received
 * Check full Github repo for details
 */
void sendOn()
{
  checkACActive();
  // if AC is already on: do nothing
  if (acActive == true) {
    return;
  }

  client.publish("mqtt.0.climateremote.message", "ON");
  IrSender.sendNEC(0x80, 0x9C, 3);
}
}

The functions sendOff and sendOn are called by the MQTT callback function whenever a certain message arrives for a certain topic. For the full sketch including web updater, wifi setup etc. visit the ClimateRemote repository.

The result