This is one of those projects.
The Wi-Fi enabled Bedlamp
4 Kids aged between 7 and 13 and their parents each built their own Bed side lamp. We started off with the woodwork. We encouraged them to do as much of the work themselves, even with the larger machinery (With good and careful adult supervision).
Some kids and dads while doing the woodwork. |
Functional Diagram showing main components |
The button was connected to allow for in place programming. With Tx and Rx connected, if you powered the circuit on while holding down the button, the ESP8266 would boot into firmware mode, otherwise it would start-up normally.
Circuit diagram |
Vera/Strip board component layout |
We made use of a 5V USB charger, which was stripped of it's case and had the 5V rail tapped off to power our circuit. This provided a nice opportunity to integrate the original USB charger into the side of the lamp, where your phone will probably be during the night anyway, ;-)
When the lamp is initially turned on in a new network, the lamp comes up as a WiFi access point. Connecting to it opens a web interface allowing you to search, configure and connect to your local Wi-Fi network. Once that is done, your Wi-Fi router should provide the lamp with its own IP address (You can easily find the new IP address by looking on your router configuration page.
We wired the relay up to be off while GPIO2 (Also connected to the LED on the module) was on so that it would shine through the clear plastic round bar used to press the power button. This made the on switch glow blue while the light is off. This makes it nice and easy to find the light switch at night.
The video below is a really short view of the basic operation of the finished lamp.
As always, I would love to hear your thoughts in the comments below.
Bill of Material
- LM1117-3,3 3.3V Liear Voltage Regulator
- 10µF capacitor
- 100µF Capacitor
- Momentary push tactile button
- Mains rated relay with 5V actuator
- 4 x 3K3Ω Resistor
- 1N4001 Diode
- BCM337 NPN transistor
- ESP-01s ESP8266 module
- Cheap 5V 1AMP USB charger
Firmware Source Code
/* * Copyright 2017 Gineer RnD * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Relay control using the ESP8266 WiFi chip // Import required libraries #include <ESP8266WiFi.h> #include <DNSServer.h> #include <ESP8266WebServer.h> #include <WiFiManager.h> //Room Name const String RoomName = "Switch"; //Response from Client String request = ""; // The port to listen for incoming TCP connections #define LISTEN_PORT 80 // set pin numbers: const int buttonPin = 0; // the number of the pushbutton pin const int relayPin = 2; // the number of the SWITCH pin int relayState = LOW; // the current state of the output pin int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin long lastDebounceTime = 0; // the last time the output pin was toggled long debounceDelay = 50; // the debounce time; increase if the output flickers // Create an instance of the server WiFiServer server(LISTEN_PORT); WiFiClient client; void setup(void) { // Start Serial Serial.begin(115200); delay(10); Serial.println(); Serial.println(); Serial.println(); Serial.println(); //initialise WiFi Manager WiFiManager wifiManager; //first parameter is name of access point, second is the password wifiManager.autoConnect("GineerLamp", "secureme"); pinMode(buttonPin, INPUT); pinMode(relayPin, OUTPUT); // set initial SWITCH state digitalWrite(relayPin, relayState); Serial.println(""); Serial.println("WiFi connected"); // Start the server server.begin(); Serial.println("Server started"); Serial.println("You can connect to this Switch at this URL:"); Serial.print("http://"); // Print the IP address Serial.print(WiFi.localIP()); Serial.println("/"); } void loop() { request = ""; // Handle REST calls WiFiClient client = server.available(); if (client) { Serial.println("User connected."); while(!client.available()){ delay(1); } Serial.print("Request Received:"); request = client.readStringUntil('\r\n'); Serial.println(request); client.flush(); } //process the request if (request.indexOf("/SWITCH=ON") != -1) { relayState = HIGH; } if (request.indexOf("/SWITCH=OFF") != -1) { relayState = LOW; } // read the state of the switch into a local variable: int reading = digitalRead(buttonPin); // If the switch changed, due to noise or pressing: if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the SWITCH if the new button state is HIGH if (buttonState == HIGH) { relayState = !relayState; } } } digitalWrite(relayPin, relayState); // save the reading. Next time through the loop, // it'll be the lastButtonState: lastButtonState = reading; if (client) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html; charset=UTF-8"); client.println(""); client.print("<!DOCTYPE html><html><head><title>"); client.print(RoomName); client.print(": Gineer.Home.SmartSwicth</title><style>body {background-color: black;color: white;text-align: center;}#switchSlider {display: inline-block;left: 28px;position: relative;border: 4px solid gray;width: 40px;height: 120px;vertical-align: central;}#switchToggle {display: inline-block;left: -30px;position: relative;border: 4px solid gray;width: 60px;height: 20px;vertical-align: central;}#switchSlider.off {background-color: silver;}#switchToggle.off {top: -20px;background-color: silver;}#switchSlider.on {background-color: yellow;}#switchToggle.on {top: -80px;background-color: yellow;}</style></head><body><h1>"); client.print(RoomName); client.print("</h1><a href=\"/SWITCH="); if(relayState == HIGH) { client.print("OFF"); } else { client.print("ON"); } client.print("\" border=\"0\"><div class=\""); if(relayState == HIGH) { client.print("on"); } else { client.print("Off"); } client.print("\" id=\"switchSlider\"></div><div class=\""); if(relayState == HIGH) { client.print("on"); } else { client.print("Off"); } client.print("\" id=\"switchToggle\"></div></a><br /><br /><a href=\"/\">Refresh</a> <br /><br />Brought to you by <a href=\"http://www.gineer.co.za/\">Gineer R&D</a><p style=\"font-size: x-small;\">Rest: http://"); client.print(WiFi.localIP()); client.print("/SWITCH=ON or http://"); client.print(WiFi.localIP()); client.print("/SWITCH=OFF</p></body></html>"); Serial.println("htmlsent"); } }