Mulitiple Feature Smart Lamp

by Muhammad Kemal Ardiansyah in Circuits > Electronics

618 Views, 0 Favorites, 0 Comments

Mulitiple Feature Smart Lamp

Multiple Feature Smart Lamp with ESP32
TR_IoT_Bahan1.png
TR_IoT_batre.jpg
kapasitor.jpg

A Basic Controllable Smart Lamp


By:

Budicahya Rama Bagaskara (2440113433) & Muhammad Kemal Ardiansyah (2440105513) -- Computer Engineering -- Binus University

Hello everyone,

Did you guys know that colored light could affect mood and there is a therapy using colored lights called chromotherapy, which is pretty cool fun fact! Then the idea of making colorful lamp from scratch is popped in our mind. But to make it more cooler and more modern, we will make it 'smart' where we will use internet to interact with lamp and cloud service to store the lamp data.

In this instruction, we will show you, step by step, on how to build basic smart lamp which are using Adafruit Neopixel as lamp's LED, ESP32-DOIT-DEVKIT as project's microcontroller, and Firebase Firestore to store our lamp data.

The smart lamp in this article will be able to change its light color based on user's choice or enable its 'rainbow' light mode where the lamp able to illuminate many colors in one setup. Those two feature can be controlled directly in IDE (In this article, we use Visual Studio Code with Platform IO extension) or edit in Firestore Data.

This article will guide you on how to setup your Firestore for the first time, link your Firestore to IDE, building the lamp from scratch, and lastly transmit the code from IDE to your lamp.

That is all the brief information that overall conclude this article. Now we can continue to build the smart lamp with the help of instruction below.

Supplies

Hardware

  • ESP32 DOIT DEVKIT
  • Breadboard
  • Neopixel WS2812 (in this project we use 8-bit round neopixel)
  • Jumper Wires
  • 50V 10uF capacitor
  • Battery holder 3 slots
  • 3 pcs 1.5V AA Battery

Software

  • Visual Studio Code
  • Firebase Console

Block Diagram & Flow Chart

blok diagram.png
TR_IoT_FlowChart.png

Schematic

skematik fix.png

Assemble all the supplies as in the photo

Create Firestore Database

FIRESTORE_addproject.png
FIRESTORE_enterprojectname.png
FIRESTORE_clickcontinue.png
FIRESTORE_selectdefaultaccount.png
FIRESTORE_gotoauthentication.png
FIRESTORE_clickemailpass.png
FIRESTORE_enableemailpass.png
FIRESTORE_clickadduser.png
FIRESTORE_addemailpass.png
FIRESTORE_clickfirestoredatabase.png
FIRESTORE_testmode.png
FIRESTORE_projectsetting.png
FIRESTORE_neededinfo.png
  1. First, search "firebase console" on your web browser, open the website backed by google then login.
  2. Then click add project, enter your project name then click continue, enable google analytics then continue, choose a default account then click continue.
  3. After you have seen the home page, go to "Authentication" on the left side then click "Get started".
  4. You will open the "Sign-in method" menu, then click "Email/password and enable "Email/password".
  5. Go to "Users" menu then Add user.
  6. Add your email and password. you need to remember the password. I suggest you to note it. Then click "Add User"
  7. After that go to the "Firestore Database" menu on the left side, then click "Create database". Click test mode and click next.
  8. You will see the page of your firestore database. there will be collections, documents, and fields after you programmed it on Visual Studio Code.
  9. Go to project settings, you will see the information needed for this project.

Code

  1. Open your visual studio code, and create a new project in PlatformIo with ESP32 DOIT DEVKIT as a board.
  2. Don't forget to add libraries from PlatformIo. In this project, we need 3 library which is Adafruit Neopixel from Adafruit, Firebase from mobitz, and WifiManager from tzapu.
  3. Copy the code below and paste it into your main.cpp file. Don't forget to input your Firestore Database API key, Project ID, user email, and user password (you can get it in your project settings). Then upload it.
  4. After successfully uploading, connect your smartphone, tablet, or laptop to WifiManager SSID (in this project called "AutoConnectAP"). It will drive you to the WifiManager IP address.
  5. Press "Configure WiFi" and then choose what connection you want to use. Input the WiFi password. Then press "save"
  6. It will make your ESP32 connect to the WiFi.
  7. You can control the Neopixel through your Firestore Database by changing the value on the fields section
#if defined(ESP32)
#include <WiFi.h>
#include <DNSServer.h>
#include <WiFiManager.h> 
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <Firebase_ESP_Client.h>
#include <Adafruit_NeoPixel.h> 


// Provide the token generation process info.
#include <addons/TokenHelper.h>

#define API_KEY "xxx"
#define FIREBASE_PROJECT_ID "xxx"
#define USER_EMAIL "xxx"
#define USER_PASSWORD "xxx"


#define PIN 15 //used pin on esp32
#define NUMPIXELS 8 //number of pixels


// Define Firebase Data object
FirebaseData fbdo;

FirebaseAuth auth;
FirebaseConfig config;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

unsigned long dataMillis = 0;

bool taskcomplete = false;

String getDevice() { //get ESP32 unique ID
  char name[23];
  uint64_t chipid = ESP.getEfuseMac(); // The chip ID is essentially its MAC address(length: 6 bytes).
  snprintf(name, 23, "%04X%08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
  
  return name;
}


String devicename = getDevice(); //accomodate ESP32 ID into a variable


String documentPath = "Neopixel/"+devicename; //making document path in the firestore database


int ambildata(String field) {
    
        if (Firebase.Firestore.getDocument(&fbdo, FIREBASE_PROJECT_ID, "", documentPath.c_str(), field.c_str()));
            // Serial.printf("ok\n%s\n\n", fbdo.payload().c_str());
        else
            Serial.println(fbdo.errorReason());


        FirebaseJson payload;
        payload.setJsonData(fbdo.payload().c_str());


        // Get the data from FirebaseJson object
        FirebaseJsonData jsonData;
        payload.get(jsonData, "fields/"+field+"/integerValue", true);
        int value = jsonData.intValue;
    return value;
}




void setup()
{
    WiFi.mode(WIFI_STA); 
    Serial.begin(115200);
    WiFiManager wm;
    Serial.println(devicename);
    pixels.begin();


    wm.resetSettings();
    bool res;
    res = wm.autoConnect("AutoConnectAP","password");


    if(!res) {
        Serial.println("Failed to connect");
        // ESP.restart();
    } 
    else {
        //if you get here you have connected to the WiFi    
        Serial.println("Connected to Wifi");
    }



    Serial.printf("Firebase Client v%s\n\n", FIREBASE_CLIENT_VERSION);


    /* Assign the api key (required) */
    config.api_key = API_KEY;


    /* Assign the user sign in credentials */
    auth.user.email = USER_EMAIL;
    auth.user.password = USER_PASSWORD;


    /* Assign the callback function for the long running token generation task */
    config.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h


#if defined(ESP8266)
    // In ESP8266 required for BearSSL rx/tx buffer for large data handle, increase Rx size as needed.
    fbdo.setBSSLBufferSize(2048 /* Rx buffer size in bytes from 512 - 16384 */, 2048 /* Tx buffer size in bytes from 512 - 16384 */);
#endif


    // Limit the size of response payload to be collected in FirebaseData
    fbdo.setResponseSize(2048);


    Firebase.begin(&config, &auth);


    Firebase.reconnectWiFi(true);
}


void loop()
{
    
    // Firebase.ready() should be called repeatedly to handle authentication tasks.


    if (Firebase.ready() && (millis() - dataMillis > 5000 || dataMillis == 0))
    {
        dataMillis = millis();


        


        // For the usage of FirebaseJson, see examples/FirebaseJson/BasicUsage/Create.ino
        FirebaseJson content;


        // aa is the collection id, bb is the document id.
        


        // If the document path contains space e.g. "a b c/d e f"
        // It should encode the space as %20 then the path will be "a%20b%20c/d%20e%20f"


        if (!taskcomplete)
        {
            taskcomplete = true;


            content.clear();
            content.set("fields/Power/integerValue", String(1).c_str());
            content.set("fields/Red/integerValue", String(255).c_str());
            content.set("fields/Green/integerValue", String(255).c_str());
            content.set("fields/Blue/integerValue", String(255).c_str());
            content.set("fields/Rainbow/integerValue", String(1).c_str());


            Serial.print("Create a document... ");


            if (Firebase.Firestore.createDocument(&fbdo, FIREBASE_PROJECT_ID, "" /* databaseId can be (default) or empty*/, documentPath.c_str(), content.raw()))
                Serial.printf("ok\n%s\n\n", fbdo.payload().c_str());
            else
                Serial.println(fbdo.errorReason());
        }
        
        content;
        content.clear();
        


        
        int powervalue = ambildata("Power");
        int redvalue = ambildata("Red");
        int greenvalue = ambildata("Green");
        int bluevalue = ambildata("Blue");


        // mencetak value dari variabel
        Serial.print("Power: ");
        Serial.println(powervalue);
        Serial.print("Red: ");
        Serial.println(redvalue);
        Serial.print("Green: ");
        Serial.println(greenvalue);
        Serial.print("Blue: ");
        Serial.println(bluevalue);


        // code untuk memprogram neopixel
        for (int i = 0; i <= NUMPIXELS; i++)
        {
            if (powervalue == 1)
            {
                int rainbow = ambildata("Rainbow");


                Serial.print("Rainbow: ");
                Serial.println(rainbow);
                if (rainbow == 1)
                {
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(255, 0, 0)); 
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(255, 128, 0));
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(255, 255, 0)); 
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(128, 255, 0)); 
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(0, 255, 0)); 
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(0, 255, 255)); 
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(0, 0, 255)); 
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(127, 0, 255)); 
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(255, 0, 255)); 
                        pixels.show();
                        delay(100);
                    }
                    for (int i = 0; i <= NUMPIXELS; i++)
                    {
                        pixels.setPixelColor(i, pixels.Color(255, 0, 127));
                        pixels.show();
                        delay(100);
                    }
                }
                else
                {
                    pixels.setPixelColor(i, pixels.Color(redvalue, greenvalue, bluevalue));
                    pixels.show();
                    delay(200);
                }
            }
            else
            {
                pixels.setPixelColor(i, pixels.Color(0, 0, 0));
                pixels.show();
                delay(200);
            }
        }
    }
}

Evaluation

The downside of this project is that we only use WiFi to connect the ESP32 to the Firestore Database. If you have a bad internet connection, it will take affect the performance of the lamp. You can add a Bluetooth connection. You can also add manual input to change the light color or lamp mode using some push button.

This project also gives a 200 ms delay for the Neopixel, you can change it to 20 ms - 15 ms to get a smoother transition. You can also change the power supply with a power bank or even use a 5V adapter. If somehow your voltage source is less than 3.5V, then you may consider utilizing a level converter between the power source and ESP32 to convert your voltage into 5V and vice versa.