January 24, 2025

Making my Ceiling Fans Smart with Arduino, ESPHome and Home Assistant

Many years ago, I purchased a WeMo Smart Light Switch for the bedroom, which at the time was an incredible piece of tech and the first piece of smart home goodness to grace my home. Many years later, I have sensors throughout, multiple smart light switches on various different rooms, and the ability to control it all with my voice. But in that time, I have also had ceiling fans installed, which are controlled via radio remotes. Surely there is a way to incorporate these into the smart home... And there is!

I would like to give a shout out to Yonatan's Dev Blog who provided the initial guidance I required to get this project rolling. You can read his guide on how he did a similar implementation in his own home here

The Hardware

The first thing that needed to be identified was what frequency the fans operated on. While this can be checked with something like a Flipper Zero using the Frequency Analyzer, my remotes helpfully listed the frequency on a sticker inside the battery compartment.

This certainly made my life a lot easier

Now that I had confirmed that my remote operated on 433Mhz (The decimal places are not a concern), I purchased some transmitter and receiver modules off AliExpress. The exact modules I purchased can be found here, but I recommend shopping around to see if there is a better deal. 

I also purchased an ESP32 Development Board, which will features USB-C for power and firmware flashing, as well as WiFi for connecting back to Home Assistant. The exact board I purchased can be found here, but again I recommend shopping around. 

Once these parts arrived, I wired them up in the following arrangement:

ESP32

Receiver


ESP32

Transmitter

3V3

VCC


D5 (GPIO5)

DATA

DATA (Right)

D4 (GPIO4)


GND

-

GND

GND


Note: + does not need to be connected



Now that the hardware was complete, it was time to move onto the software. 

The Software

While I initially attempted to go with MQTT like Yonatan's Dev Blog did, I found it quite cumbersome. 

Instead, I went down the ESPHome route, which has many awesome features, including a Web Flasher, simple YAML configuration, and Over-The-Air update support, which is very handy when trying to debug and fine tune. 

Please note that beyond this point, an installation of Home Assistant is required. More information can be found on the Home Assistant website here.

From within Home Assistant, I installed the ESPHome Device Builder Add-on. This allows for the generation of configurations for ESPHome devices, but also for these to be installed. 

Once it is installed, it can be accessed from the Home Assistant sidebar.

While it looks simple, ESPHome is very powerful

Please note that the next few steps require the use of a browser that supports WebSerial, which at the time of publishing is any Chromium-based browser, such as Google Chrome or Microsoft Edge. Hopefully Firefox adds support in the future.

From here, plug your ESP32 board into your computer and ensure that it appears as a COM port on Windows or a ttyUSB device on Mac and Linux. 

Next, click on 'New Device' in ESPHome Device Builder and set a name for your device.

On the next screen, it will ask to connect to the ESP32. Click 'Connect' and follow the prompts from your browser to find your device.

At this point, the ESP32 is connected to the ESPHome Builder

Once the Serial port has been selected, the browser should show 'Connecting'. In my case, I had to hold the 'BOOT' button on the ESP32 board to get it to successfully start configuring. Once it shows 'Preparing installation', give it a few minutes as it creates all the necessary files. Eventually, it should change to 'Installing' which is when it is flashed to the ESP32 board. 

In my case, after the install completed, ESPHome was unable to find the device on the network. To resolve this, I had to add a couple lines into the configuration file, which can be accessed by clicking 'Edit' on the device. In here, I had to add the following:

wifi:
    ssid: !secret wifi_ssid
    password: !secret wifi_password

    manual_ip:
        static_ip: 192.168.XXX.XXX
        gateway: 192.168.XXX.XXX
        subnet: 255.255.255.0

Note that the above is only necessary if it does not automatically find your device. It also requires that you set this as a static lease on your router/DHCP server so that what you set in the configuration does not later become assigned to a different device. 

Once the ESP32 can be successfully communicated with wirelessly, the configuration for the radios can be created. 

Note: ESPHome does not auto save! Make sure to click 'Save' before closing the configuration editor.

 The first configurations that needed to be added were for the 'remote_receiver' and 'remote_transmitter' components. If following the pinout provided earlier in this post, the following can be appended to the configuration file:

remote_receiver:
    pin: GPIO4
    dump:
        - rc_switch
    # Settings to optimize recognition of RF devices
    tolerance: 50%
    filter: 250us
    idle: 4ms

remote_transmitter:
    pin: GPIO5
    carrier_duty_percent: 100%

Further explanation of the above configuration can be found in the ESPHome documentation here.

After the above configuration is entered, click 'Install' in the top right to send it to the board wirelessly. This process should take about a minute. 

Now when a button is pressed on the remote to be replicated, it should appear in the log output in ESPHome. 

The green text shows a radio signal being received by the ESP32

For each button that is pressed, at least one of the green lines in the above screenshot should appear. Note down the binary data, as well as the protocol number, as these will be required later. Also note if it says 'RCSwitch Raw' or some other code.

With this information at hand, the button can be appended to the configuration:

button:
  - platform: template
    name: XXXXXXXXXX
    id: XXXXXXXXX

    on_press:
      - remote_transmitter.transmit_XXXXXXXXXXX:
          code: '00000000000'
          protocol: X
          repeat:
            times: XX
            wait_time:
            microseconds: XXX

Firstly, the name is what the button will appear as in Home Assistant. Subsequently, the ID should be a lowercase, no spaces version of the name that can be used to reference this button from other things, such as switches.

Next, 'remote_transmitter.transmit_XXXXXXXXXXX' should be replaced with the relevant protocol based off the log output from earlier and the available options listed here

After that, the code should be replaced with whatever was received as 'data' in the debug logs. Protocol should also be replaced with the number that was in the logs. 

Finally, 'times' is how many repeats there should be of the transmission, and 'microseconds' is how long the pause is between each. These values will need to be tinkered with on a per-device basis to find the sweet spot between the signal not being detected by the device, and the signal being detected multiple times.

November 23, 2022

DIY Drone Update #2 - Actually Building It!

This project has been a long time in the making. My first post about this drone was all the way back in November 2019, where I sourced all the parts but didn't actually build it. But at the end of 2021 (I know, also a long time ago), I actually built and successfully flew it!

Stepping back to 2021, I still had not replaced the broken motor, so I ordered one of eBay, which this time came with all the accessories. I guess you get what you pay for. I also ordered a proper 12V power supply for the battery charger, not because the DIY version was dangerous or failed, but because it used more space than necessary, and was probably not that efficient. Maybe I'll build one of those custom desktop power supplies out of it one day.

The First-Person View (FPV) module connected to the Flight Controller


 (FC)
 
I started by connecting up the FPV module to the Flight Controller, since it was the easiest component to start with and allowed me to see if the camera and On-Screen Display (OSD) on the Flight Controller worked correctly. Thankfully, when I powered the board via the USB port, I was successfully able to connect to the video feed from my headset (which after purchasing, I have now realised is illegal to use in Australia without authorisation that I don't have). 

At this point I met up with some friends who had slightly more experience with RC aircraft than me, and we got going on connecting the transceiver to ensure that reliable control could be made when the motors are connected. To do this, the PPM pads were shorted to specify which protocol was to be used. After configuring the FC within Betaflight Configurator, the switches, dials and sticks all could be seen to be working. Mainly, I was able to configure the throttle to be the correct stick and in the correct direction, and that a safety switch would be able to instantly disable the motors when activated. 

Now that all the simple (and in the case of the transceiver, essential) components were connected, I began to connect all the motors. Firstly, the motors were connected to each of the 4 Electronic Speed Controllers (ESCs), which control the amount of current going to the motors, and allow for the drone to know what speed the motors are rotating at. These ESCs also have extra connectivity, allowing for their BLHeli firmware to be updated, but also configured beyond that of pure Betaflight. 

The (amazing) workspace much of the drone was built in

The flight controller I used only had one pad for soldering all the live and ground wires from the motors to, so I purchased a distribution board which had pads for each of the 4 ESC's power cables, as well as the battery and the power for the Flight Controller. The rest of the wires were soldered directly to the FC, which facilitate the control of each of the individual motors.

While soldering it together, I had to make sure the wires were long or short enough to get to where they want to go, but also make sure that nothing would interfere with the props on each of the motors. I prevented wires from getting snagged using electrical tape, which I also used underneath live components such as the ESC's and Flight Controller to ensure that nothing shorted on the carbon fibre frame.

Once it was all within the frame, I did a quick test of each motor through Betaflight (with the props removed), to check that all the motors worked, were in the correct layout, and that they were all spinning the correct direction. I quickly discovered one of the motors spinning the wrong direction, which was easily fixed by unsoldering and swapping the wires around. 

Eventually, once everything seemed like it was working correctly, including the safety switch on the controller, I attached the props and took it outside to test if it would fly. And it did! Although I am not very good at flying it, especially landing... It's still in one piece, but I have a lot of practice to do in the simulator before flying it properly. 

The completed drone (minus battery)
So now it is complete and works, I hope to fly it soon once I've spent some more time in the simulator. I also have an RC plane now, which I also cannot fly well, so there may be more aerospace related content in the future if either of those get off the ground (pun intended). 

July 31, 2022

DIY UV Curing Station

When I first got into resin printing, I found the whole process extremely messy and tedious. There were also so many chances for something to go catastrophically wrong. In light of this, I didn't want to invest significant amounts of money into it, as my goal was only to get an idea for what it is, and if it has a viable future as a hobby. This meant I had to DIY many steps of the process, mainly around the post-processing. 

Through some quick internet searching, I came across many pages which recommended that the sun is a viable alternative to a curing station, since it produces UV light. And since curing stations can cost upwards of AU$100, this was an easy solution. The only downsides were that curing can only happen when it is sunny, and it takes longer as the concentration of UV is lower outside compared to dedicated LEDs. 

Looking into how a UV curing station worked, I realised it would be really easy to build my own for much less. And especially since every COVID-19 kit I had bought came with an UV torch, which just happened to be within the correct wavelength, I had a whole bunch of UV LEDs ready to go. 

The COVID-19 self-test kits I had ordered were from Hough, and by reading the instructions I could see that the torch wavelength should be 365nm, as this is the wavelength the test reacts to. By comparing this to the range that my resin reacts to, I discovered that it lay within the range, being 355-410nm. 

Since these torches are essentially free, and in huge supply, I chose to build a curing station based around them. To start, I had a look at what curing stations for sale look like, and how their LEDs are arranged. I found that most have a vertical strip, with some also having an overhang on a hinge to better illuminate the tops of objects. Based off this research, and my limited modelling skills (which I hope to work on), I decided to start with just the vertical stick design. 

Firstly, I started brainstorming different ways to make the torches stay in place in the most simple way possible. I ended up using a combination of a small shelf, as well as a hole through the model with a little lip to prevent it falling out the end to hold the torches in place.

The small shelf with the lip to prevent the torch falling out. 


While making the shelves, I first tried to model them manually, which ended with a very poor, hard to replicate or re-dimension design. Because of this, I stumbled across the 'arc slot' shape under the draw menu, which allowed for the perfect shape for the shelf, all with easy to assign dimensions that aligned perfectly with the hole. 

The hardest part to get right, which still has issues, was the base. Since the torches are quite heavy, and the batteries are quite far away from where they are attached to the model, it makes the design's centre of mass very far over, meaning it falls over quite regularly. 

The first design I tried was a solid rectangular base, which was simple to model and would serve a solid starting point. 

The first iteration of the stand.

I quickly realised that the base was not large enough, and when loaded up with torches could not stand up correctly.
I also discovered that I had entered the dimensions on the hole and shelf incorrectly, meaning that I had to make them larger to actually fit the torches without friction. Thank goodness I put the time in to dimension properly, and I hope this serve as a lesson for everyone who doesn't already do this. 

My next attempt at fixing the leg issue was also an attempt at saving time and filament by turning the large rectangular base into two small legs. This also allowed me to practice using the different forms of dimensions to make sure the angles matched, as well as the lengths. 

After printing this second iteration, I found that the holes were not the correct size, but it still did not stand up on it's own when all the torches were inserted. 

The second iteration of the stand.

Although it could not stand by itself, I soon realised I could use both of the stands in combination to support the two ends of the torch, which worked wonderfully. 

The two stands used together to hold all the torches.

 Now that the stand was mostly complete, I began to consider how to rotate the models so the light reaches all sides. Looking at how the proper stations achieved this, I ordered a solar turntable that can both be powered by batteries as well as the UV lights themselves. This works great, as I don't need to keep removing the battery when it is not in use.

The solar turntable. 


 
This also provided a potential solution to the torch issue, where the base can be held in place by the turntable and it's weight, especially when using batteries. The only issue with this method is that all the previous designs had been designed so they could be printed face down without supports, although having parts jutting out both sides means that it needs to be printed vertically with supports for all the shelves, increasing filament waste and also print time. It also has the potential to weaken the model, as the adhesion between the layers is aligned with the force from the weight of the torches, meaning it could just snap, although I can only speculate as I have not tried printing this way as of writing. 

As you may have noticed, all these models were printed on my filament-based Ender 5, which highlights how much easier filament is to work with, since, especially for these non-aesthetic models, it does not require much, if any, post-processing. And, since I have limited time to spend printing and processing, it makes more sense for me. 

So while I plan to try this out with prints in the future, as of writing I had no projects pressing enough or the time to actually complete them with resin, although I do plan to do a follow-up in the future about my experiences with resin printing, and comparing it to filament-based printers. Hopefully in that post, I can shed some more light (pun intended) on how effective this design is. 

Ad