๐Ÿš€ AI Air Purifier Under โ‚ฌ25 ๐Ÿค– | No Cloud, No API, Learns Your Habits!

by TylerDDDD in Circuits > Arduino

144 Views, 0 Favorites, 0 Comments

๐Ÿš€ AI Air Purifier Under โ‚ฌ25 ๐Ÿค– | No Cloud, No API, Learns Your Habits!

Air Purifier AI
Filter2.png

๐Ÿ’จ A Smart Air Purifier That Thinks for You !

What if your air purifier could predict when you need clean airโ€ฆ without sensors, without subscriptions, and without expensive hardware?

๐Ÿ‘‰ Meet AirPurifierAI: A fully autonomous, AI-powered air purifier built on an ESP8266 that learns your daily habits.

๐Ÿ”ฅ Why You'll Love It

  1. ๐Ÿค– REAL Embedded AI (No API, No Internet)
  2. ๐Ÿ’ธ Ultra-budget: < โ‚ฌ25 total
  3. ๐ŸŒฟ Health-focused: cleaner air daily
  4. ๐Ÿง  Learns your routines automatically
  5. ๐Ÿ”Œ Fully automatic and autonomous system
  6. ๐Ÿ› ๏ธ Easy DIY build

๐Ÿ’ก The Big Idea

Instead of:

  1. Timers โŒ
  2. Apps โŒ
  3. Cloud AI โŒ

You get:

โœ… A purifier that observes your behavior

โœ… Detects patterns (morning, winter, etc.)

โœ… Automatically turns ON at the right moment

๐Ÿง  How the AI Works (Simple + Powerful)

The system:

  1. Records when you press the button
  2. Stores time patterns
  3. Detects repetition
  4. Predicts future activation

๐Ÿ‘‰ Example:

  1. You turn it on every day at 7:30
  2. โžก๏ธ After a few days โ†’ it starts automatically

๐Ÿ’ธ Cost Breakdown

Xiaomi filter: ~15โ‚ฌ

Electronics: ~10โ‚ฌ

TOTAL: < 25โ‚ฌ ๐Ÿคฏ

๐Ÿ‘‰ Cheaper than ANY smart purifier on the market.

Supplies

Ventilateur.png
Relais.png
ESP8266.png
Converter.png
Bouton.png
Filter.png

Parts List. Youโ€™ll need:

  1. 3D printer.. or ask a friend or your school !!
  2. PLA filament. I like it black to look .. professional
  3. ESP WROOM Arduino board
  4. Push buttons. One only. I choosed yellow :)
  5. Relay module . At least 2 relays (on one card :) ) . Choose a 12V relay
  6. Power supply. This to bring power to the relay AND to the DC adaptor
  7. DC converter 12V to 5V. This to bring power to the Arduino
  8. Wires + breadboard or soldered PCB
  9. 12V Fan. With 2 pins. Simple fan
  10. Xiaomi air purifier filter

( Sponsored links :) )

โš™๏ธ Wiring

airpurifierAI.png

๐Ÿ”Œ Pin Setup

D7 โ€” Button

D1 โ€” Eco

D2 โ€” Max

๐Ÿงฉ Connections

Button

D7 โ† Signal

3.3V โ† VCC

GND โ† GND

Relays

Eco (D1)

IN1 โ† D1

5V โ† VCC

GND โ† GND

Max (D2)

IN2 โ† D2

5V โ† VCC

GND โ† GND

Fan

12V โ†’ COM

NO โ†’ Fan +

Eco โ†’ Low

Max โ†’ Full

Power

220V โ†’ 12V

12V โ†’ Fan

12V โ†’ 5V โ†’ ESP8266

โšช Design rule

One relay at a time. Common ground everywhere.

๐Ÿ’ป Core Code Logic

Download the file AirPurifierAI.ino from GitHub : LINK

Important :

  1. Enter your WIFI identifier
  2. Enter your WIFI password
// ---------- WiFi ----------
const char* ssid = "YOUR WIFI";
const char* password = "YOUR PASSWORD";


Install Arduino IDE on your laptop. Compile the ino file and upload it to your Arduino.

Main blocks:

  1. Button detection (D7)
  2. Relay control (D1 / D2)
  3. Mode switching
  4. Time tracking
  5. Pattern learning

๐Ÿ‘‰ The AI part stores usage timestamps and detects repetition patterns.

Code below.

/**
AirPurifierAI
v1.0 - 2026.03.20 - Nicolas Christophe - Initial version

AI powered Air Purifier.

Main functions :
- Establish a WiFi connection
- Capture the push button: one press is ECO, two is MAX, three is AI
- Power accordingly the fan
*/

/***************************
* Include
**************************/

#include <ESP8266WiFi.h>
#include <EEPROM.h>
#include <time.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <U8g2lib.h>

#define EEPROM_SIZE 512
#define SCL 12 // D6
#define SDA 14 // D5

// ---------- WiFi ----------
const char* ssid = "YOUR WIFI";
const char* password = "YOUR PASSWORD";

// ---------- Pins ----------
const int buttonPin = 13; //D7
const int relayEco = 5; //D1
const int relayMax = 4; //D2

// ---------- OLED ----------
const int I2C_DISPLAY_ADDRESS = 0x3c;
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0,SCL,SDA, U8X8_PIN_NONE); // OLED initialize

// ---------- Modes ----------
enum Mode {OFF, ECO, MAX, SMART};
Mode currentMode = OFF;

// ---------- SMART DATA ----------
struct SmartData {
uint16_t weekUsage[24];
uint16_t weekendUsage[24];
float confidenceGlobal;
float avgSessionDuration;
uint32_t totalActivations;
uint32_t totalMinutes;
};

SmartData data;

// ---------- SMART timing ----------
unsigned long lastMinuteTick = 0;
unsigned long lastSmartCheck = 0;
unsigned long lastSave = 0;
unsigned long smartStartTime = 0;

// ---------- Constantes ----------
const unsigned long saveInterval = 6UL * 60UL * 60UL * 1000UL; // 6h
const float decayFactor = 0.97;
const float scoreThresholdECO = 0.3;
const float scoreThresholdMAX = 0.8;

/***************************
* Functions
**************************/

// ---------- Fonctions basiques ----------
void allOff() { digitalWrite(relayEco, HIGH); digitalWrite(relayMax, HIGH);}
void setEco() { digitalWrite(relayMax, HIGH); digitalWrite(relayEco, LOW);}
void setMax() { digitalWrite(relayEco, HIGH); digitalWrite(relayMax, LOW);}

// ---------- Wifi & NTP ----------
void setupWiFi() {
WiFi.begin(ssid, password);
Serial.print("Connecting WiFi");
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println(" Connected");
}

void setupTime() {
configTime(3600, 3600, "pool.ntp.org");
Serial.print("Sync NTP");
while (time(nullptr) < 100000) { delay(500); Serial.print("."); }
Serial.println(" OK");
}

int getCurrentHour() {
time_t now = time(nullptr);
struct tm *t = localtime(&now);
return t->tm_hour;
}

int getMonth() {
time_t now = time(nullptr);
struct tm *t = localtime(&now);
return t->tm_mon + 1;
}

bool isWeekend() {
time_t now = time(nullptr);
struct tm *t = localtime(&now);
return (t->tm_wday == 0 || t->tm_wday == 6);
}

float seasonWeight() {
int month = getMonth();
if (month >= 11 || month <= 2) return 0.8; // hiver
if (month >= 6 && month <= 8) return 1.2; // รฉtรฉ
return 1.0;
}

// ---------- EEPROM ----------
void saveData() { EEPROM.put(0, data); EEPROM.commit(); lastSave = millis(); }
void loadData() { EEPROM.get(0, data); }

// ---------- Apprentissage ----------
void learnUsage() {
if (millis() - lastMinuteTick > 60000) {
lastMinuteTick = millis();
if (currentMode == ECO || currentMode == MAX) {
int h = getCurrentHour();
if (isWeekend()) data.weekendUsage[h]++;
else data.weekUsage[h]++;
data.totalMinutes++;
}
}
}

// ---------- Dรฉcision SMART ----------
float computeDailyAverage(bool weekend) {
uint32_t sum = 0;
for (int i=0;i<24;i++) sum += (weekend?data.weekendUsage[i]:data.weekUsage[i]);
return sum/24.0;
}

void handleSmart() {
if (millis() - lastSmartCheck < 5000) return;
lastSmartCheck = millis();

int h = getCurrentHour();
bool weekend = isWeekend();
uint16_t usage = weekend ? data.weekendUsage[h] : data.weekUsage[h];
float avg = computeDailyAverage(weekend);
if (avg == 0) { allOff(); return; }

float score = (usage/avg) * data.confidenceGlobal * seasonWeight();

// --- Dรฉcision ---
if (score < scoreThresholdECO) { allOff(); return; }
if (score >= scoreThresholdECO && score < scoreThresholdMAX) { setEco(); return; }

// Forte habitude -> progressive
if (smartStartTime == 0) smartStartTime = millis();
setEco();

unsigned long ecoTime = data.avgSessionDuration * 0.3 * 60000; // 30% durรฉe moyenne
if (millis() - smartStartTime > ecoTime) setMax();
}

// ---------- Dรฉcroissance mรฉmoire ----------
void decayMemory() {
int h = getCurrentHour();
if (h == 3 && millis() - lastSave > 60*1000) { // 3h du matin
for (int i=0;i<24;i++) { data.weekUsage[i] *= decayFactor; data.weekendUsage[i] *= decayFactor; }
}
}

// ---------- Bouton ----------
void handleButton() {
bool reading = digitalRead(buttonPin);
bool lastState = HIGH;

//if (reading == LOW && lastState == HIGH) {
if (reading == LOW) {
currentMode = (Mode)((currentMode+1)%4);
Serial.println(currentMode);
delay(200); // anti rebond simple

if (currentMode != SMART) smartStartTime = 0;
}

lastState = reading;
}

// ---------- OLED ----------
void displayLCD() {
// header OLED
u8g2.clearBuffer();

// measures OLED
u8g2.setFont(u8g2_font_ncenB10_tr);
u8g2.setCursor(10,20);
u8g2.print(currentMode==OFF?"OFF":currentMode==ECO?"ECO":currentMode==MAX?"MAX":"SMART");

u8g2.setCursor(10,35);
u8g2.print("Score: "); u8g2.print(data.confidenceGlobal,2);

u8g2.setCursor(10,50);
u8g2.print("Season: "); u8g2.print(seasonWeight(),2);

u8g2.sendBuffer();
delay(20);

// display fan
static int angle = 0;
angle += 15; // rotation speed
if (angle >= 360) angle = 0;
displayFan(angle);

}

void displayFan(int angle) {
int centreX = 105; // to the right
int centreY = 22;
int rayon = 15;

// centre, then the 3 branches of the fan
u8g2.drawDisc(centreX, centreY, 3);
for (int i = 0; i < 3; i++) {
float a = (angle + i * 120) * 3.1416 / 180.0;
int x = centreX + cos(a) * rayon;
int y = centreY + sin(a) * rayon;
u8g2.drawLine(centreX, centreY, x, y);

}

u8g2.sendBuffer();
}

/***************************
* Setup
**************************/

void setup() {
Serial.begin(115200);
Serial.println("Start");

// OLED
u8g2.setBusClock(600000);
u8g2.setI2CAddress(0x78);
u8g2.begin();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(20, 14," Loading "); // Display resolution is 64 x 128
u8g2.sendBuffer();
delay(3000);

pinMode(buttonPin, INPUT);
pinMode(relayEco, OUTPUT);
pinMode(relayMax, OUTPUT);
allOff();

EEPROM.begin(EEPROM_SIZE);
loadData();

setupWiFi();
setupTime();
}

/***************************
* Loop
**************************/

void loop() {
handleButton();
learnUsage();
decayMemory();

if (currentMode == ECO) setEco();
if (currentMode == MAX) setMax();
if (currentMode == OFF) allOff();

if (currentMode == SMART) handleSmart();

if (millis() - lastSave > saveInterval) saveData();
displayLCD();
}

๐Ÿ–จ๏ธ 3D Case

Blender.png

๐Ÿ”ฅFollow the steps below.

  1. Download the file AirPurifier_Bottom.stl from GitHub and save it on your computer. LINK
  2. Install Ultimaker Cura from the official website.
  3. Open Cura and set up your 3D printer if itโ€™s your first time.
  4. Import the STL file into Cura (drag and drop or โ€œOpen Fileโ€).
  5. Check the model orientation and scale on the build plate.
  6. Adjust print settings (e.g., 0.2 mm layer height, 15โ€“20% infill, PLA material).
  7. Enable supports or adhesion if needed.
  8. Click โ€œSliceโ€ to generate the G-code file.
  9. Save the G-code to an SD card or send it directly to your printer.
  10. Start the print and monitor the first layers for proper adhesion.

๐Ÿš€ Final Result

Loading.jpg

The 3D print has one hole for the button and another for the ESP8266 display.

Assemble the components onto the 3D print, then place it on the filter and seal it. Thatโ€™s it :)

โš™๏ธ Features Overview

๐Ÿ”‹ Eco Mode

  1. Low power consumption
  2. Quiet operation
  3. Perfect for night use

๐Ÿ’จ Max Mode

  1. Full fan speed
  2. Rapid air cleaning

๐Ÿค– AI Mode (Game Changer)

  1. Learns your habits
  2. Predicts usage
  3. Fully autonomous

๐Ÿ”ฅ You built:

โœ… A smart air purifier

โœ… With embedded AI

โœ… Fully offline

โœ… Ultra low cost

๐Ÿ’ฅ Why This Project Is Different

Most devices:

  1. Require apps
  2. Send data to cloud
  3. Cost hundreds

๐Ÿ‘‰ This one:

  1. Respects privacy
  2. Works alone
  3. Costs nothing


๐Ÿ”ฎ Next Upgrades

๐Ÿ‘‰ Future improvements

  1. Add PM2.5 sensor
  2. Improve AI prediction
  3. Add local web dashboard
  4. Add silent night curve

Keywords

Air purifier, AI, Health, Arduino