Skip to content

Latest commit

Β 

History

398 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SML logo
${\color{#ff0000}S}{\color{#ff6e00}m}{\color{#ffdd00}a}{\color{#b2ff00}r}{\color{#48ff00}t}\ {\color{#00ff26}M}{\color{#00ff95}u}{\color{#00fbff}s}{\color{#0091ff}i}{\color{#0022ff}c}\ {\color{#4d00ff}L}{\color{#b700ff}a}{\color{#ff00d9}m}{\color{#ff006a}p} $

GitHub repo size GitHub License GitHub stars GitHub forks GitHub top language GitHub contributors Watchers

⭐ Give me a star β€” it will motivate me to keep improving!

Table of Contents
  1. About the Project
  2. Getting Started
  3. Build and Flash
  4. Web Interface
  5. LED Effects
  6. Random Mode
  7. Power Management
  8. OTA Updates
  9. To Do
  10. Contributors
  11. License
  12. Contact
  13. Tools
  14. Acknowledgments

About the Project

${\color{#ff0000}S}{\color{#ff6e00}M}{\color{#ffdd00}L}$ (Smart Music Lamp) is a project that started with the idea of creating a Wi-Fi controlled lamp and ended up becoming much more than that. It began with the intention of making a personal version of a Sonoff, and the ESP32 was chosen because its power was more than enough for the task.

Thinking it over, it was a shame to waste so much power on a simple task of turning a lamp on and off.

So what should I add to truly leverage the ESP32 and end up with a more complete and functional product?

Watching my wife cook while listening to music on her phone, which she would leave anywhere, the idea came to me: give the lamp an audio system (Bluetooth speaker). I told her, wouldn't it be great to cook while listening to music without having to leave your phone somewhere random? You'll be able to control the lamp and stream music from your phone via Bluetooth to the lamp, having music in the kitchen.

If I already have a lamp that plays music, why not make it more cheerful and add colors?

To do this, I added a Neopixel strip that is also controlled via the web from your phone, offering lighting effects including effects that sync with the music the lamp is playing.

Still not satisfied, I added a temperature and humidity sensor to display that data on the web interface embedded in the ESP32.

Since I live in a country where power outages are very common, and I had the ability to play music through the lamp, why not take advantage of it?

I implemented a dual power supply system (mains and battery) that allows you to keep controlling the lamp via the web and listen to music after a power outage. Of course, I couldn't use the Neopixels since they consume too much power.

Goals

  • Control the lamp on/off from your mobile phone.
  • Play music through the lamp via Bluetooth from your mobile phone.
  • Control the Neopixel strip for different lighting effects.
  • Monitor battery charge and usage.
  • Monitor temperature and humidity.
  • Web-based control of the Bluetooth speaker's physical buttons.
  • Embedded web interface for real-time control from any mobile device.


Getting Started

Arduino

Place a video of SML in action here

Components

The ESP32 was chosen for this project because of its power, number of analog inputs, and Wi-Fi connectivity. It features dual power supply, using a 5V power source and a 3.7V battery. A protected charger handles battery charging, and a DC-DC step-up converter boosts the battery voltage to 5V to power the ESP32 and all modules except the Neopixel strip, which is always powered from the mains supply.

A dual relay module controls the LED lamp and the Bluetooth module. A DHT22 sensor measures temperature and humidity. Additional components implement supporting circuits.

For audio playback, I used one of those common portable Bluetooth speakers that can be found very cheap, like the one in the image below.

BTspeaker

Required components:

  1. ESP32, any variant

esp32

  1. Battery charger module, TP4056 5V 1A with protection

tp4056

  1. Mini DC-DC step-up booster MT3608

mt3608

  1. 5V power supply
  2. Dual relay module

relay

  1. WS2812B Neopixel LED strip, 24 LEDs

neopixel

Note: The number of LEDs depends on the lamp size and power supply capacity. You can change this value in the code.

  1. LiPo 3.7V battery or 18650 3.7V Li-Ion

LiPo 18650

  1. Temperature and humidity sensor DHT22

DHT22

  1. Resistors:
  • 5 x 1K
  • 3 x 10K
  • 2 x 4.7K
  • 1 x 220 ohm
  1. Capacitors:
  • 2 x 0.1 uF
  • 1 x 1 uF /10v
  1. Diodes:
  • 2 x 1N4148
  • 1 x 1N581x Schottky
  1. MOSFET transistors
  • 1 x P-Channel MOSFET
  • 3 x N-Channel MOSFET
  1. Bluetooth speaker control board with its speaker

  2. LED lamp to transform

Note: For this project I used a circular LED lamp, considering it more aesthetic and elegant. You can use any lamp that suits your needs and taste.


Installation

Below is a table showing the ESP32 pins to connect and their designations.

ESP32 PINS NAME FUNCTION
4- D4 STRIP_PIN LED strip control
5- D5 VOLUMENUP_PIN V+/FF Bluetooth button
18- D18 SWITCH_PIN Bluetooth power control
19- D19 VOLUMENDOWN_PIN V-/REW Bluetooth button
21- D21 PLAY_PIN Play/Pause Bluetooth button
23- D23 DHTPIN DHT sensor control
32- D32 LAMP_PIN Lamp power control
33- D33 ADC_PIN Battery monitor
34- D34 CHARGE_PIN Charging signal
35- D35 FULL_CHARGE_PIN Full charge signal
36- VP AUDIO_IN_PIN Audio input

Note: Since Wi-Fi is enabled on the ESP32, you cannot use any ADC2 pins for analog readings.

Diagram

The following schematic illustrates the power connections for the project.

smlpower

Note: The output voltage of the lamp's power supply that feeds the high-brightness white LEDs is not the one shown in the schematic; it is much higher. It is not important to know it for this project.

πŸ‘‰ You can find the schematic here. ⭐

For a better understanding of the dual power supply (load sharing) used, here is the following diagram.

loadsharing

When 5V power is applied, this circuit turns off the MOSFET and stops current flow from the battery to the load (DC-DC module), effectively disconnecting the battery. As long as the ${\color{#ffdd00}input\ voltage\ minus\ the\ Schottky\ diode\ drop}$ is above the ${\color{#ffdd00}battery\ voltage\ minus\ the\ drain-source\ voltage\ drop}$, the load draws power from the 5V supply through the Schottky diode. This allows the battery to charge normally without external disturbances.

The chosen MOSFET must have the lowest possible RDS(on) to minimize power loss, must handle the current your circuit draws from the battery, and must have a VGS(th) between 0V and -2.4V.

The diode prevents current from flowing from the battery back to the 5V power supply. It must be a Schottky diode that can handle the maximum current draw of the loads. The RG resistor (10K) ensures the MOSFET turns on and connects the battery to the load when the 5V power supply is removed.

The DC-DC boost converter must be adjusted so its output voltage is 5V whether powered from mains or battery.

To monitor the battery voltage, place a resistive voltage divider at the output of the TP4056 charger module and connect its output to pin D33 of the ESP32.

battmon

With the excellent library by danilopinotti/Battery18650Stats, the battery voltage is read and expressed as a percentage. Since batteries in use don't always reach the ideal 4.2V maximum, danilopinotti's library didn't give practical values. So I modified the library to include configurable maximum and minimum voltage values in its parameters for more accurate percentage readings.

The TP4056 module has 2 indicator LEDs β€” one to indicate charging ${\color{#ff0000}(red)}$ and another to indicate the battery is fully charged ${\color{#0022ff}(blue)}$. Analyzing the module's diagram, these LEDs connect to pins 6 (standby) and 7 (charge) of the TP4056 IC. To activate the LEDs, these pins output a logic low, which we detect on our ESP32 to know the charger status. To detect a logic low, implement the following circuit.

zero

As shown in the diagram, if pins 6 or 7 output more than 0V, the LEDs are off and diode (D17) does not conduct, so 3.3V reaches the ESP32 input. When the module is charging or the battery is fully charged, there will be a logic low on those pins. The corresponding LED turns on and diode (D17) conducts, reflecting a low level on the ESP32 pin. In code, this is represented by the variables ${\color{#ffdd00}isCharging}$ and ${\color{#ffdd00}fullyCharge}$.

During testing I faced another challenge: when the Bluetooth speaker is turned on, the volume is always at half. This seems to be normal behavior for these Bluetooth speakers, so to control the volume we need to use the physical buttons. But since the lamp will be in an inaccessible location, we can't. And even if we turn up our phone volume to max, we may not achieve the desired level. So how can we remotely control physical buttons?

Analyzing the schematic of some common Bluetooth speakers on the market (Chinese ones), I noticed the buttons switch to ground (GND) on an IC pin. This makes it easy to emulate a button using the ESP32. The following diagram shows the solution.

bt

The solution basically uses MOSFETs as simple switches β€” when activated, they ground the Bluetooth IC pin. In this Bluetooth speaker model, each button has dual functions depending on the press duration, which is also emulated in code. We only need to control 3 buttons: Volume+(FF), Volume-(REW), and Play(Pause). By controlling the pulse duration to the MOSFET gate in code, we simulate the button press duration.

The diagram also shows how to sample audio from the module's audio output. A voltage divider circuit is implemented, and the signal passes through a resistor and electrolytic capacitor to pin D36(VP).

As seen in the power connection diagram earlier, turning the Bluetooth module on and off is done through a relay (IN2) controlled by the ESP32 from pin D18.

Finally, the DHT22 temperature and humidity sensor connects to pin D23. This sensor can be powered with 5V or 3V, so there's no issue choosing either. For better temperature and humidity monitoring, it is recommended that the sensor be exposed to the outside air.

Here are some photos of the finished lamp:

lamp indicator inside


Code

The project essentially boils down to controlling the lamp via the web from any connected device. The ESP32 stays in station mode, waiting for another device to enter AP (portable hotspot) mode with the correct credentials to connect. Why did I choose station mode?

On the web interface, you'll notice Wi-Fi signal strength indicators in the bottom right corner showing the connection quality between your device and the lamp. This can only be achieved if the ESP32 is in station mode.

The ESP32 creates an asynchronous server (ESPAsyncWebServer), meaning it can handle multiple clients simultaneously (8) and sends data in JSON format via WebSocket. With this setup, up to 8 devices connected to the lamp receive real-time updates, and changes are reflected on all devices simultaneously.

The ESP32 hosts an embedded website in SPIFFS memory; the web content is in the project's ${\color{#ffdd00}data}$ folder. The code is heavily commented, so here's a summary.

Three objects are created:

  • StripLed β€” Neopixel strip control
  • Led β€” ESP32 onboard LED control
  • Battery β€” Battery control and monitoring

The remaining libraries handle lighting effects and music-synchronized effects (VU), along with the web server, battery monitoring, and DHT22 sensor. Below are the most important variables you may need to adjust.

  1. Debug variables
  • #define DEBUGLEVEL β€” set to DEBUGLEVEL_DEBUGGING for serial debug output
  • #define DHT β€” comment out with (//) to hide DHT22 messages
  • #define BATTERY β€” comment out with (//) to hide battery monitoring messages

Note: Some debug messages, such as connection and web service info, are mandatory.

  1. Neopixel strip variables
  • #define N_PIXELS β€” number of LEDs in your strip
  • int brightness β€” initial brightness (default 130, a bit over half brightness)
  1. Battery management variables
  • #define MAXV β€” Maximum voltage when battery is fully charged
  • #define MINV β€” Minimum voltage to start charging (default 3.2V)

Note: For accuracy, charge the battery using the TP4056 module. When the full charge LED turns on, measure the battery voltage and use that as the maximum value. For the minimum value, the DC-DC step-up module specifications state that to achieve 5V output, the input must be at least 2V. However, 3.2V is recommended for safety.

  1. Web variables
  • const unsigned long refresh β€” delay for sending information (default 3 seconds)

Note: The project currently uses PlatformIO as its development environment. The platformio.ini file in the project root contains all build configuration, dependencies, and serial port settings.


Build and Flash

Requirements

Compile and Upload

# Compile the project
pio run

# Upload firmware to ESP32
pio run --target upload

# Monitor serial port
pio device monitor

# Clean build files
pio run --target clean

Upload Web Interface Files

The HTML, CSS, JS, and image files are in the data/ folder and are stored in the ESP32's LittleFS (SPIFFS). After modifying any web files:

pio run --target uploadfs

Debug Configuration

In src/config/debug_config.h you can control which messages appear on the serial port:

Macro Description
DEBUGLEVEL_DEBUGGING Enables all debugging
#define DHT Shows DHT22 sensor messages
#define BATTERY Shows battery monitoring messages
#define DEBUG_POWER_MANAGEMENT Shows power manager state transitions


Web Interface

The ESP32 runs an asynchronous web server (ESPAsyncWebServer) with real-time WebSocket communication. It supports up to 8 simultaneous clients, and changes are reflected instantly on all connected devices (ideal for family control).

WebSocket

The interface is organized into 8 tabs accessible from the sidebar (or bottom bar on mobile):

πŸ’‘ Lamp

Main lamp control:

  • On/Off for the main LED lamp
  • On/Off for the Neopixel strip
  • Color picker with color wheel (iro.js)
  • Brightness slider for the Neopixel strip
  • Light effects (see Effects section)

Lamp

🎡 Music

Bluetooth speaker control:

  • Play / Pause
  • Volume + / Volume -
  • Fast Forward / Rewind
  • On/Off for the Bluetooth module
  • VU effects β€” music visualization

Music

πŸ‘οΈ Live Preview (Peek)

Real-time LED strip preview via a canvas updated over WebSocket (~30 FPS). Displays the 24 LEDs interpolated as 33 virtual LEDs with two view modes:

  • Strip β€” horizontal linear layout
  • Circle β€” circular layout (simulates the lamp's real shape)
  • Quick config button for the active effect
  • FPS indicator and stream status

Live Preview

🌑️ Weather

DHT22 sensor data:

  • Temperature (Β°C)
  • Relative humidity (%)
  • Updates every 3 seconds

Weather

πŸ”‹ Battery

Detailed battery status:

  • Charge percentage
  • Current voltage
  • Status: charging / fully charged / discharging
  • Historical voltage graph
  • Visual power source indicator (AC or battery)

Battery Battery Graph

βš™οΈ Config

Advanced configuration panel:

  • Themes: SML Classic, WLED Dark, Midnight AMOLED
  • WiFi: change SSID and password without re-flashing firmware
  • Firmware Update: direct link to ElegantOTA
  • System Info: uptime, free heap, WiFi RSSI, firmware version, MAC and IP address
  • Connected clients: list of active WebSocket connections
  • Activity logs: record of actions performed from the web interface

System Info

❓ Help

Quick reference guide for all lamp features.

ℹ️ About

Project information, version, and links.

About


LED Effects

The project includes over 40 visual effects organized into categories. Access them from the Lamp tab β†’ Effects section.

Categories

Category Description
⭐ Favorites Your favorite effects (star-marked)
πŸ“‹ Playlist Custom playlist for random mode
πŸ”§ Fundamentals Base effects: solid, flash, fade
πŸƒ Moving Motion effects: dot, comet, sinelon, scan
⚑ Dynamics Dynamic effects: fire, lightning, aurora, popcorn
🎨 Patterns Patterns: rainbow, theater chase, sweep, dissolve
🌑️ States Status effects: battery, temperature
πŸ”€ Random Random mode (see next section)

VU Effects (Music Visualization)

In addition to traditional visual effects, there are VU effects that react to audio playing through the Bluetooth speaker. They are located in the Music tab and activate automatically when there's audio input. Examples include:

  • Rainbow VU β€” multi-colored bars in sync with the music
  • Ripple VU β€” concentric waves reacting to the rhythm
  • Frequency Spectrum β€” equalizer-style visualization

VU Effect

How to Configure an Effect

  1. Single click/tap β€” selects and activates the effect
  2. Second click/tap (on the same active effect) β€” opens the configuration panel where you can adjust:
    • Speed β€” effect speed
    • Color β€” palette or primary color
    • Intensity β€” brightness or effect intensity
    • Effect-specific parameters

Effect Config


Random Mode

The lamp can cycle through effects automatically without intervention. There are two modes:

Random FX

Cycles through visual effects on the Neopixel strip with configurable duration per effect.

Selection modes:

  • All β€” any available effect
  • Favorites β€” only your star-marked effects
  • Categories β€” choose one or more specific categories
  • Playlist β€” custom sequence that you order yourself

Random VU

Similar to above but with VU effects (music visualization). Ideal for leaving the lamp in ambient music mode.

Controls

  • Duration per effect β€” how long each effect stays active (configurable)
  • On/Off from the Random FX or Random VU card in the effects list
  • Preview of the current effect in the Peek panel


Power Management

The ESP32 implements an automatic power management system with a state machine that detects the power source and optimizes consumption.

States

State Power Source WiFi CPU Neopixel Consumption
AC_MODE Mains Always ON 240 MHz On ~180 mA
BATTERY_CONNECTING Battery 10s ON / 30s wait 240 MHz Off ~120 mA
BATTERY_ACTIVE Battery + client connected Always ON 240 MHz Off ~120 mA
BATTERY_SLEEP Battery, no client 10s ON / 60s OFF 80 MHz Off ~25 mA

Transitions

  • AC loss β†’ try to connect 10s β†’ wait for client 30s β†’ sleep if no client
  • Client connects β†’ instant wake from any state
  • Client disconnects β†’ wait 30s for reconnection β†’ sleep
  • AC restored β†’ immediate return to full operation
  • Battery < 15% β†’ force maximum power saving

Power Source Detection

Uses the TP4056 pins: if charging or battery is full, it assumes AC power is present. Includes 3-second debounce to prevent rapid state changes from power flickers.


OTA Updates

You can update the ESP32 firmware without a USB cable, directly from your browser:

  1. Connect to the ESP32's WiFi network
  2. Open http://<esp32-ip>/update
  3. Select the compiled .bin file
  4. Click Update and wait for the ESP32 to reboot

Or from the web interface, go to Config tab β†’ Firmware Update section.


To Do

  • Scheduled alarm system (turn on lamp at set times)
  • Push notifications to mobile when battery is low
  • Collaborative effects (multiple synchronized ESP32s)
  • Home Assistant integration
  • Native Android/iOS app
  • User profiles (save complete configuration)
  • Support for larger addressable LED strips (>100 LEDs)
  • Real-time graphic equalizer on the web interface
  • Alarm clock mode (simulate sunrise with LEDs)


Contributors

Alexminator
alexminator


License

The SML project is released under the GNU General Public License v3.0.


Contact

Need help? Contact me πŸ“¨ alexminator99@gmail.com

GitHub followers Twitter Follow


Tools

  • VSCODE β€” Code editor.
  • PlatformIO β€” C/C++ programming IDE for hardware.


Acknowledgments


⬆ Back to top

About

Smart Music Lamp

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages