Project tutorial
DIY Air Humidifier with Backlight Controlled by Alexa

DIY Air Humidifier with Backlight Controlled by Alexa © MIT

An easy-to-build humidifier with RGB backlight that can be controlled by Amazon Alexa.

  • 1,153 views
  • 0 comments
  • 6 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)
3drag
3D Printer (generic)

Apps and online services

About this project

Intro

We get really cold winters here in Kyiv, Ukraine so central heating is essential to keep our apartments warm. Yet, apart from warming up my home, central heating also dries up the air in my apartment. Dry air parches my sinuses and makes it difficult to get through the winter season without getting sick. Tired of getting sick, I decided to manage the dry air in my home this year. While there are plenty of humidifiers available at the stores, I decided that making a smart, Alexa-powered humidifier for myself would be an interesting challenge.

Reverse Engineering of Numidifier

To control the humidifier module we need know how to turn it on and off and how to get the current status of the humidifier (whether it is turned on or turned off).

On the image we can see the bottom side of the humidifier board. It has a power connector and button. From the module's manual I know that the inner contact of the round power connector is positive power and outer contact is the ground. The module is controlled by clicking the button. On the image we can see that the button has 4 pins: two of them are connected to the ground, one is not connected, and one is connected to route which is connected to 4th pin of the black square chip. To toggle the module we need to short this pin with the ground. I figured out which point on the board is changing its voltage when the module is turning on or turning off by clicking on the button continuously and checking the voltage at random points of the board. The 5th pin of the black square chip is 0v when the humidifier is turned off and 2.5v when it is turned on. So the status of humidifier can be known by reading state on this pin.

Now we have almost everything needed to control this module. The fives pin of the chip is looks like output. I measured the frequency on this pin and it is about 110 kHz. It is not convenient to measure the modulated signal like this with Arduino because it can be HIGH or LOW (at any time) so I decided to use passive integrator circuit to transform PWM signal from module to DC signal easier to read with Arduino.

The LED Lightning

To make humidifier look nicer I decided to add some back light to it. I chose the WS2812 RGB LEDs for this purpose.

There are many libraries available to control these LEDs and it is easy to connect them using just a few wires.

Schematics

The connections between all components are exhibited on the schema above. I soldered the wires to the GND, +5v, Button and State pins and inserted into the breadboard. the Rest elements were assembled on the breadboard. I connected the power cord to the breadboard power supply and placed it all under the humidifier's lid.

The Code

The device connects to the Internet using the MQTT protocol. I used test.mosquito.org for the demonstration because it does not require authentication and does not call for additional settings. After the device connects to the network which you may indicate directly in the sketch code, it connects to broker and subscribes to the following topics:

"humidifier/on" - to receive the "turn on" command

"humidifier/off" - to receive the "turn off" command

"humidifier/reportState" - to receive a status report (on/off) command

"humidifier/reportColorState" - to receive a backlight status report command

"humidifier/color" - to receive a backlight color change command

Whenever the device receives one of these messages, it executes the corresponding command and messages back information about the status of the device.

#include <SoftwareReset.h> 
// Select your modem: 
#define TINY_GSM_MODEM_ESP8266 

//setup pins for your board 
#define LED_STRIP_PIN 5 
#define TOGGLE_PIN 4 
#define STATE_PIN 2 
#define ESP_ENABLE_PIN 6 
#define LED_NUM 8 

uint32_t color; 

#include <Adafruit_NeoPixel.h> 
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_NUM, LED_STRIP_PIN, NEO_GRB + NEO_KHZ800); 

#include <TinyGsmClient.h> 
#include <PubSubClient.h> 

const char ssid[]  = "ssid"; 
const char pass[] = "password"; 

//// Use Hardware Serial on Mega, Leonardo, Micro 
#define SerialAT Serial1 

TinyGsm modem(SerialAT); 
TinyGsmClient client(modem); 
PubSubClient mqtt(client); 

//setup the broker 
const char* broker = "test.mosquitto.org"; 
const char* mqttDeviceId = "yourDeviceId"; 
const char* mqttUsername = ""; 
const char* mqttPass = ""; 

//setup the topics 
const char* topicTurnOn = "humidifier/on"; 
const char* topicTurnOff =  "humidifier/off"; 
const char* topicReportState =  "humidifier/reportState"; 
const char* topicStateReport = "humidifier/stateReport"; 
const char* topicReportColorState =  "humidifier/reportColorState"; 
const char* topicSetColor =  "humidifier/color"; 
const char* topicColorStateReport = "humidifier/colorStateReport"; 

long lastReconnectAttempt = 0; 

//set the color of the strip or any ws2812 nodule 
void setStripColor(uint32_t c) { 
 // Fill the dots one after the other with a color 
 for (uint16_t i = 0; i < strip.numPixels(); i++) { 
   strip.setPixelColor(i, c); 
 } 
 strip.show(); 
} 

// turn on or turn off humidifier 
void ToggleHumidifier() { 
 digitalWrite(TOGGLE_PIN, LOW); 
 delay(100); 
 digitalWrite(TOGGLE_PIN, HIGH); 
} 

void setup() { 
 pinMode(TOGGLE_PIN, OUTPUT); 
 digitalWrite(TOGGLE_PIN, HIGH); 
 pinMode(ESP_ENABLE_PIN, OUTPUT); 
 digitalWrite(ESP_ENABLE_PIN, HIGH); 
 pinMode(STATE_PIN, INPUT); 
 // Set console baud rate 
 Serial.begin(115200); 
 delay(100); 
 // Set GSM module baud rate 
 SerialAT.begin(115200); 
 delay(100); 
 modem.restart(); 
 Serial.print("Connecting to "); 
 Serial.print(ssid); 
 if (!modem.networkConnect(ssid, pass)) { 
   Serial.println(" fail"); 
   SWRST_STD(); 
 } 
 Serial.println(" OK"); 
 // MQTT Broker setup 
 mqtt.setServer(broker, 1883); 
 mqtt.setCallback(mqttCallback); 
 strip.begin(); 
 strip.show(); // Initialize all pixels to 'off' 
 setStripColor(strip.Color(0, 0, 0)); 
} 

//connect to broker 
boolean mqttConnect() { 
 Serial.print("Connecting to "); 
 Serial.print(broker); 
 if (strlen(mqttUsername) > 0 ) { 
   if (!mqtt.connect(mqttDeviceId, mqttUsername, mqttPass )) { 
     Serial.println(" fail"); 
     return false; 
   } 
 } else { 
   if (!mqtt.connect(mqttDeviceId)) { 
     Serial.println(" fail"); 
     return false; 
   } 
 } 
 Serial.println(" OK"); 
 //subscribing to topics 
 mqtt.subscribe(topicTurnOn); 
 mqtt.subscribe(topicTurnOff); 
 mqtt.subscribe(topicSetColor); 
 mqtt.subscribe(topicReportState); 
 mqtt.subscribe(topicReportColorState); 
 return mqtt.connected(); 
} 

//main loop 
void loop() { 
 if (mqtt.connected()) { 
   //handle mqtt connection 
   mqtt.loop(); 
 } else { 
   // Reconnect every 10 seconds 
   unsigned long t = millis(); 
   if (t - lastReconnectAttempt > 10000L) { 
     lastReconnectAttempt = t; 
     if (mqttConnect()) { 
       lastReconnectAttempt = 0; 
     } 
   } 
 } 
} 

//handle mqtt messages 
void mqttCallback(char* topic, byte * payload, unsigned int len) { 
 Serial.print("Message arrived ["); 
 Serial.print(topic); 
 Serial.print("]: "); 
 Serial.write(payload, len); 
 Serial.println(); 
 // Only proceed if incoming message's topic matches 
 if (String(topic) == topicTurnOn) { 
   if (!digitalRead(STATE_PIN)) { 
     Serial.println("turning on"); 
     ToggleHumidifier(); 
     delay(100); 
   } 
   mqtt.publish(topicStateReport, digitalRead(STATE_PIN) ? "1" : "0"); 
 } else if (String(topic) == topicTurnOff) { 
   if (digitalRead(STATE_PIN)) { 
     Serial.println("turning off"); 
     ToggleHumidifier(); 
     delay(100); 
   } 
   mqtt.publish(topicStateReport, digitalRead(STATE_PIN) ? "1" : "0"); 
 } else if (String(topic) == topicSetColor) { 
   if (len = 3) { 
     uint8_t r = payload[0]; 
     uint8_t g = payload[1]; 
     uint8_t b  = payload[2]; 
     Serial.print("red "); 
     Serial.println(r); 
     Serial.print("green "); 
     Serial.println(g); 
     Serial.print("blue "); 
     Serial.println(b); 
     color = strip.Color(r, g, b); 
     setStripColor(color); 
   }     
   mqtt.publish(topicColorStateReport, String(color).c_str()); 
 } else if (String(topic) == topicReportColorState) { 
   mqtt.publish(topicColorStateReport, String(color).c_str()); 
 }   else if (String(topic) == topicReportState) { 
   mqtt.publish(topicStateReport, digitalRead(STATE_PIN) ? "1" : "0"); 
 } 
}  

Smart home skill is based on Lambda, which I created using Pyhton. I used this repository as the groundwork with some modifications. Namely, I added the handling of individual devices in separate files. Secondly, I added file names to the endpoint descriptions. This will allow me to simply add an endpoint according to the set file schema endpoints.json and add the file to the handlers folder whenever adding a new device. I implemented the state reporting for back-light and humidifier so any changes of the device state by voice are visible int the Alexa Companion App. To deploy the skill you need to configure the new smart home skill in the Amazon developer account and configure the Account linking(the easiest way is to use Login With Amazon). Then you need to create a Lambda function and upload the zip archive of /lambda/smartHome/ folder contents from my repository.

Building the Device

To build this project, I designed 4 elements to be printed on the 3D printer. These elements were designed using Kompas 3D software.

The water is supplied to the humidifier via a cotton wadding-filled tube, which was printed on a 3D printer. The diffusion ensures that the cotton is evenly dump. Even when there's just a little water left on the bottom of the tank it can still wet all the cotton in the tube and deliver water to piezo element that placed in the top of the tube.

On the photo below you can see all the parts together with cross-section to see whats inside and how to assemble it.

Demonstration

Below you can see the video demonstration of my project.

Code

Custom parts and enclosures

bottom
all together
CAD filed of 3d printed parts
you need to open it in the KOMPAS 3D software

Schematics

Schematic
sch_7x1D2GJl24.fzz

Comments

Similar projects you might like

Smart Pool: Alexa Controlled Pool Manager

Project tutorial by Benjamin Winiarski

  • 1,360 views
  • 2 comments
  • 7 respects

Hygge Home - Alexa Smart Bath

Project tutorial by J Howard

  • 5,356 views
  • 2 comments
  • 18 respects

Scent-terrific Smart Candle

Project tutorial by Darian Johnson

  • 3,023 views
  • 0 comments
  • 33 respects

Alexa Controlled Door Sign Demo

Project tutorial by 3magku

  • 1,880 views
  • 0 comments
  • 5 respects

Rampiot - Cool Smart Lock

Project tutorial by Robinson Mesino

  • 4,095 views
  • 1 comment
  • 28 respects

Voice Controlled RGB Lamp

Project tutorial by Pham Hoang Son

  • 3,009 views
  • 1 comment
  • 13 respects
Add projectSign up / Login