Monday 21 December 2020

Slack & WhatsApp controlled Christmas Tree Lights

December 2022 update: I've developed this idea further, giving the project more features, including the ability to blink lights in morse code. The original post remains below.

With the Covid-19 pandemic still dragging on, it looks like things won't be back to normal in time for Christmas.

At work there was discussion about Christmas parties, team building exercises, and other such things to try to boost morale.

I'm currently working on a project that uses WS2812 RGB LEDs (which'll no doubt wind up published here eventually), and on a whim, wondered if there existed fairy lights that use the same chip.

Turns out, there are. So obviously I had to buy some.

My Christmas tree is positioned so that is can be seen in the background when I'm on Zoom calls with work, so I thought it'd be fun if I could setup some system that would let my colleagues interact with the lights.

Once the lights arrived and I'd tested them, I got to tearing them down.

Wiring

The power supply/controller is a USB unit. I was powering it from a phone charger adapter. That also contained an infra-red receiver for the included remote. I thought about potentially working that angle, but the remote had limited options, and I wanted to offer more granular control.

From the controller to the lights was just 3 leads, which I rationalised must be +5V, Ground, and Data.

I cut the wire, figured out which was which, and connected in an Arduino. It wasn't able to provide enough current to drive the LEDs itself, to I made use of the existing charger - the charger continued to be connected to +5V and Ground, sharing the ground with the arduino's ground, and then the data line connected to the arduino.

The circuit. It works fine like this for short periods, although I later found adding a 470 Ohm resistor between arduino D12 and the first LED increased reliability over time.

 

Arduino code

I ended up using the PololuLedStrip library, and modifying the existing code for that.

Initially I'd hoped to be able to provide full RGB control, but it just seemed that the sheer amount of data being sent meant bytes were being lost, or I had to slow the data rate down to unusually slow.

Eventually I settled on using 10 preset colours, defined with numbers 0-9, being sent as a 100-character serial string - 1 character (colour) per LED. This seemed to be the best trade off of functionality and reliability.

The code can be found here.

 

The 'server'

This is a simple web server that accepts GET requests for one endpoint, and is simply there to provide a go-between for the messaging apps and the serial port.

As each LED is individually addressable, I wanted to create a format that would give users control at that level. I settled on messages with the following JSON structure

[1,"colour"]

or

[[1,2,3], "colour"]

where the numbers are the IDs of the LEDs, and the string is one of the available colours.

This would let them control either an individual LED or a series of them in an individual command.

Hooking into Slack and WhatsApp

As at work we use Slack, and we have some previous integration with it, it seemed like the obvious choice.

However, their API functionality is heavily focused on HTTP endpoints, and requires a server to interface with it. That's fine for 'proper' development, but when I'm just messing around at home, I don't really want to be dealing with opening up my home network and all that entails.

Really what I wanted was some client-side plugin functionality. There isn't an official API or interface for one, so I had to improvise.

Using the web-browser interface, and making use of Firefox's Javascript console, I added a MutationObserver to the page, and made use of the DOM to narrow in on the message elements, and get the contents of the latest message in whatever chat/channel the user was in.

The javascript for Slack can be found here.

Once retrieved, some basic checks are done to make sure that the message is in a usable format and hasn't been acted upon already, it's then passed to a local server via HTTP, where it's processed, converted to the serial format used by the arduino, and sent onward to it.

After realising how useful MutationObserver is for things like this, it was quite trivial to do the same for WhatsApp.

The finished product


Thursday 10 December 2020

Live-edge oak spotlight light fixture - part 2 - adding ambience

In my previous post, I built a hanging light fitting of live-edge oak and recessed GU10 spotlights.

There is actually more to the project.

Sometimes, spotlights can be a bit overpowering, and it's preferable to have some ambient, indirect light.

During construction, I had the idea of creating this light in a way that would allow use of the spotlights, an ambient light, or both.

To create the ambient light, I used LED strips on the reverse (upward-facing) side, to reflect light off the ceiling.

I cut some thin strips of oak with a 45-degree angle and mounted them in a rectangle on the back - angled side outward, to help direct the light. An RGB LED strip was mounted all around this.

Control

I initially thought of using the LED driver that tends to come standard with rolls of LED strip, but as the existing wiring leads to only one switch, without some rewiring through the ceilings/walls, it would be limited to either having both the spotlights and the ambient light on, or just the spotlights on without the ambient light - it would not be possible to have the ambient light on without the spotlights.

In order to combat this, and to lay groundwork for a potential future project, I included a solid-state relay and an Arduino. The arduino would drive TIP31 transistors to drive the 3 channels for the LEDs red, green and blue, and additionally control a solid state relay which would act as the switch for the spotlights.

The idea would then be that the light switch would remain on, more like a utility switch, and then all control of the light fitting would be handed over to the Arduino.

 

Power

 

The original wiring sketch.
it's just a rough sketch,
not a proper wiring diagram.
 
The LED strips take 12V, and the microcontroller takes 5V, so a PSU is needed to bring the power down to usable levels.

For this I used an old net-book power supply. This was wired into the back of the light fitting. Caution is needed to make sure that nothing too powerful is used, as typically a houses' lighting circuit breaker is tripped at a much lower current than the mains sockets.

 

Revised to include the additional components
This would normally be plugged into a wall socket, where it's plug would have a fuse. However in order to wire this into the lighting wiring, the plug would need to be removed - obviously this introduces a safety concern. To ensure that this would still be fused, I replaced the wall switch for the light to one that includes a fuse, ensuring that the light is behind the fuse.

 

Communication

To communicate with the Arduino, I used a cheap HC-05 bluetooth to serial adapter, the same as I've used in other projects like the Bluetooth Macro keyboard app.

The arduino receives 4 bytes, followed by newline characters. These correspond to 1 byte each for the red, green and blue channels in the LED strip, and the final byte is either a simple 0 or 1 to indicate if the spotlights should be on.

For now this is sent by pairing with my phone and using a bluetooth serial terminal app from the Google play store. I'll probably create a more custom app in future, but for proving the concept, this works just fine.