Not long ago the old JamBox sitting in one of my office display case’s caught my eye.
After picking it up I noticed it used an ESP32 development board, so I had to flash it for ESPHome. I downloaded the PixelOperator8 font and uploaded it to my esphome/fonts folder in Home Assistant. Then I figured out the following YAML to get the buttons, potentiometers (knobs), and LED Matrix working.
After installing the YAML and installing the device to Home Assistant, here are the sensors in the device UI.
Screenshot
The device has a ton of inputs with the eight buttons and five knobs and the 8×32 LED Matrix can display text or maybe a simple graph. I haven’t thought of a good use for it though. Do you have any ideas?
ESP32 G -> CAN Board G -> RJ45 Pin 8 -> Capacitor stripe side
ESP32 3.3 -> CAN Board 3.3 -> Capacitor non-stripe side
ESP32 Pin 4 -> CAN Board TX
ESP32 Pin 5 -> CAN Board RX
CAN Board CANH -> RJ45 Pin 5
CAN Board CANL -> RJ45 Pin 4
Start with this YAML for your ESPHome device:
# Add your standard esphome, ota, api, and wifi sections here at the top
logger:
level: DEBUG
esp32:
board: esp32-c3-devkitm-1
framework:
type: esp-idf
canbus:
- platform: esp32_can
id: can
tx_pin: GPIO4
rx_pin: GPIO5
bit_rate: 125KBPS
can_id: 0x05
use_extended_id: false
on_frame:
- can_id: 0x000
can_id_mask: 0x000 # This catches EVERYTHING
then:
- lambda: |-
std::string res = "";
for (int i = 0; i < x.size(); i++) {
char buf[5];
sprintf(buf, "%02X ", x[i]);
res += buf;
}
ESP_LOGD("ALORAIR_FINDER", "Received ID: 0x%03X, Data: %s", can_id, res.c_str());
# ====== Periodic Polling to Request Status ======
interval:
- interval: 10s
then:
- canbus.send:
can_id: 0x123
use_extended_id: false
data: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
This will test sending and receiving. After you flash the device and have it connected to the dehumidifier, open the ESPHome device log and look for lines like below.
If you see errors after the send or don’t receive messages back, try changing the bit_rate from 125 to 50, install, and recheck the logs.
If you do receive messages back, make note of the value after Received ID, which is 0x123 above. Then open up the ESPHome device’s YAML again and replace everything below type: esp-idf with the following.
If your ID was different than 0x123 (0x3b0 seems common), change the can_id under on_frame. Update mobile_app_YOUR_PHONE for your phone. Install this new code to the device. Go to Settings -> Devices & services -> ESPHome. If your device isn’t already listed, add it, and click through to see the entities. Hopefully you see the Controls and Sensors with data.
Try to toggle the power and change the setpoint. If it’s working, the dehumidifier should respond. Good luck! If all is working, I suggest adjusting your logging level to WARN. There is some stuff in the YAML to alert if the unit sends data that isn’t recognized, because there might be flags or statuses not implemented.
If you install the stack-in-card via HACS, here’s some YAML for your dashboard. Make sure to update the entity names to match what you have.
One of our daily tasks is to clean out the cat litter boxes and we (on maybe I just wanted an excuse to automate part of the process!) run in to a couple of small problems:
We usually don’t know if the other has already cleaned them.
We obviously don’t want to forget.
Since I primarily took over this job, I’ve been using a daily reminder, but it’s on my iPhone nagging me all day, even though it’s set for noon. I only need a reminder when it doesn’t get done.
I thought of a solution with an ESPHome based device and Home Assistant. I used a WEMOS D1 Mini Lite, WEMOS OLED Shield, button, red LED, green LED, and 220 Ohm resistors. I connected everything on a breadboard for testing and then made it more permanent.
Key functionality:
During the day, the green LED will be lit if the litter boxes have been cleaned and the red LED if they need to be cleaned. If we’re walking by, green means keep going and red means stop here.
At night (8pm to 8am), the LEDs are off, unless the device is woken up.
Press the button to turn on the display and status LED if at night. The display shows the last time the litter was cleaned in one of three formats, depending on how long it’s been.
Today 1:23 PM
Yesterday 2:48 PM
2 days ago 11:00 AM
Press the button when the display is on to update the litter box last cleaned date and time. The LEDs flash to signify something is happening. The new date and time gets shown on the display.
After 30 seconds the display turns off.
At 4pm send a reminder to our phones if the litter boxes need to be cleaned.
In Home Assistant a toggle can disable the reminders. Useful when we’re on vacation.
I also added a couple of simpler helpers via Settings -> Devices & services -> Helpers:
Cat Litter Last Cleaned – Date and time
Cat Litter Reminders – Toggle
Finally, I added cards to a Home Assistant dashboard. See screenshots of the different states of each card below.
Here’s the dashboard YAML if you want it.
type: horizontal-stack
title: Cat Litter
cards:
- type: custom:mushroom-template-card
primary: >-
{% set last = states('input_datetime.cat_litter_last_cleaned') |
as_datetime %}
{% if last is none %}
Unknown State
{% else %}
{% set diff = (now().date() - last.date()).days %}
{% if diff == 0 %}
Cleaned Today
{% else %}
Needs Cleaning
{% endif %}
{% endif %}
icon: mdi:emoticon-poop
features_position: bottom
secondary: >-
{% set last = states('input_datetime.cat_litter_last_cleaned') |
as_datetime %}
{% if last is none %}
???
{% else %}
{% set diff = (now().date() - last.date()).days %}
{% if diff > 0 %}
{{ last.strftime('%b %-d') }} -
{% endif %}
{{ last.strftime('%-I:%M %p') }}
{% endif %}
color: |-
{% if is_state('binary_sensor.litter_needs_cleaning', 'on') %}
red
{% else %}
green
{% endif %}
tap_action:
action: more-info
icon_tap_action:
action: perform-action
perform_action: script.cat_litter_cleaned
target: {}
confirmation:
text: Are you sure you want to update the last cleaned date/time to now?
entity: input_datetime.cat_litter_last_cleaned
- type: custom:mushroom-entity-card
entity: input_boolean.cat_litter_reminders
name: Reminders
tap_action:
action: toggle
hold_action:
action: more-info
icon_color: amber
If we get a reminder, it looks like this. We can click I did it to update the date/time to now if we forgot to press the button on the physical device. With the automation set to run at 4pm, we should rarely see this though.
The final device lives right next to the waste bag dispenser I made. This way it’s easy to see the state and hit the button when cleaning out the litter. Here are photos in place with a few different states.
This project was so fun. Using Google Gemini for stuff like this makes it so much faster. I’ve had some of these microcontrollers and other parts for almost a decade so it’s nice to finally put them to use.
What other features or automations would you add to this? Have you built anything similar?
Over the years, I’ve seen many versions of a shop air filter, made from box fans and 20×20 inch furnace filters. A few years ago I picked up some old box fans on Facebook Marketplace and bought a pack of filters from Sam’s Club. They’ve been stacked in the corner.
It was finally time to build my air filter. I removed the back covers, feet, handles, and knobs from the fans. I got my first look at the switches inside, which are nearly identical.
I’d easily be able to wire the fans together, so I removed the switches and power cords.
I put together a frame from OSB, cut slots to feed the wires through, and screwed the box fans in.
Then I grabbed wood that had been salvaged from a pallet to construct a door.
On the back side, I used glue and brad nails to attach plywood rails. I also made tabs to hold the filters secure.
I attached the door with a couple hinges and made some notched tabs to hold the door shut.
A plastic screw container was a good side, so I used hot glue to secure the boards and then wired up all of the fan connections.
I’m not sure if I’ll ever use the button, but it allows me to cycle between the three speeds and turn it off. The three LEDs show which speed is currently running. The only thing I got wrong was reversing the low and high speeds, which was a quick fix in the ESPHome code. Speaking of the code, here’s mine.
I used Google Gemini to help and it had a great suggestion to track the run time and add a maintenance reminder when it was time to replace the filters.
In Home Assistant I created some automations. My dust collector uses a smart plug, so when it draws electricity, the air filter automatically turns on at high speed. When the dust collector turns off, the air filter continues to run for 15 minutes before turning off. If I had to remember to turn on the air filter all the time, it would rarely happen, so this is amazing.
I’m still on lifting restrictions for several weeks so Brandi helped me install the air filter on the ceiling.
The upgraded IKEA air quality monitors I did work great, but the LED indication isn’t great for a bedroom and the fan noise was annoying in my office. So I wanted to create a couple of my own devices for those locations. I used:
The SEN50 is a big upgrade over the PM sensors used in the IKEA devices and I used the Si7021 in place of the BME280 I had used because I think they’re a bit better. I soldered 47µF electrolytic capacitors from a big kit I’ve had (similar on Amazon) to the ENS150 modules to improve their power.
Then I attached 5 of the crimped wires to a 6P JST connector, which is what the SEN50 modules require. I’m note sure why buying the actual cable for these SEN50s are so expensive, but I got the entire JST kit for cheaper than a couple of the special cables.
All three sensors communicate with the microcontroller over I²C, so a breadboard test was easy to wire up. The SEN50 does require 5 volts instead of 3.3, so I’m glad I checked.
The ESPHome YAML code is very similar to the code used for the modified IKEA air quality monitors.
The project boxes had some standoffs on the bottom, which I snipped off and then sanded with a rotary tool. I pulled out my box of proto boards and found a size almost exactly double what I needed, so I cut out a sliver and ended up with a piece for each box. I also cut vent holes for the SEN50 sensors.
In order to get everything to fit I decided to put the microcontroller on the bottom of the board. After mocking things up I did all of the soldering. I was hoping to be able to mount everything with connectors so it could easily be taken apart, but there wasn’t enough room and I didn’t want bigger boxes.
I did some continuity testing along the way and everything worked when I connected power. With the boards ready I cut more access and ventilation holes in the boxes.
I soldered the Si7021 on to its wires outside of the enclosure so it wouldn’t be exposed to unnecessary heat and used hot gun to secure everything.
I’m really happy with how these turned out. Here’s a view of the office data on my Home Assistant dashboard.
This was definitely a project where I wished I had a 3D printer to design custom boxes. Some day, when I’m caught up on my project list and can give it proper attention. I know if I get one now I’ll spend a ton of time with it and neglect other projects in my pipeline.
IKEA recently discontinued Vindriktning, their older air quality monitor.
Inside the device, they put a cubic PM1006K particle sensor. I bought three for $16.95 each last year, because I’d seen people hack them by adding sensors and a Wi-Fi microcontroller to send all of the data to Home Assistant. For my modding I bought:
The YouTube video linked above is a great guide to follow. I didn’t connect wires to the fan or the light sensor since I had no use for them. I also didn’t stack my sensors because I wanted the BME280 to be outside of the enclosure, where it would be less affected by the heat produced by the ENS160 and D1.
Even with the sensor outside of the case, the BME280 still reads high, because it heats itself up. I actually tested different lengths of wires and placements of the sensor before realizing I was still going to have to adjust the data. An ESPHome filter made the adjustment easy, which I did individually for each unit after comparing to a mobile Ecobee thermostat sensor. This is the code from the unit for my shop.
Here is how I’m displaying the data on one of my Home Assistant dashboards.
As I was working on this project I knew I wanted a couple more air quality monitors around the house, which will be finished soon.
Update: I’ve had to make a small update by adding a 47uF capacitor to each ENS160 board, because they have power issues, causing the reading to stop for periods of time. My boards matched up with the right ones in the picture at that link. Here’s a picture of another ENS160 I modified, since it was a tight squeeze to made the modification on the devices I posted about here with everything already wired up. I also realized I was powering these through the 3V3 pin instead of VIN, so I fixed that.
I’ve also improved the display of the data on my dashboard by using mini-graph-card.
In order to automate the processes of getting the golf sim ready to play and shutting it all down when finished I needed to create a remote control device. I’m using Home Assistant (HA) to run my home smart system (more posts to come), but two things involved with the golf sim aren’t connected to the network:
The projector has an infrared (IR) remote and the light has a radio frequency (RF) remote. I’ve done somethings with IR and still had a stash of IR LEDs (for transmitting) and receivers. I’ve never attempted any RF stuff, so I ordered a 5 pack of 433mhz wireless RF transmitter and receiver pairs.
Since I’m using HA, I let ESPHome handle all of the main programming. All I had to do was wire everything properly and get the configuration correct. I made use of an old ESP8266 NodeMCU microcontroller and worked on the IR aspect of the project first.
When I took the picture I was using a 470Ω resistor, which I eventually switched to 100Ω, to increase the strength of the IR signal. The transistor is a PN2222A. Here’s the ESPHome configuration:
I used the receiver to intercept the codes sent by the projector’s actual remote when pressing the Power, Input, and OK buttons. Then I created some buttons.
It all went very smooth. Next I connected the circuits for the RF components, which was straightforward. Here are the pinouts from the Amazon product page.
I soldered on the antennas (smaller one to the transmitter) and connected everything on the breadboard.
By using examples from the documentation I was able to intercept RF codes.
When I tried to recreate those codes through the transmitter the results weren’t matching up and the spotlight wasn’t responding. It took some trial and error to configure the various parameters of the receiver. Here’s the end result, with the combined configuration for IR and RF.
After using the remote_receiver instances to get the button press codes I needed, I commented out that section of the code. If I ever need to add more functionality to my remote, I can enable the receivers at that point. Here are the button codes for the spotlight.
Then I was able to use both sets of buttons in scripts, which can feed to Alexa for voice commands.
Once everything was tested I wired and soldered a more permanent circuitboard. I included a folded dollar bill for scale.
I was planning to mount it in the ceiling, but the IR was having trouble, because the projector’s receiver faces the ground. Mounting it to the side of the PC cart worked great.
This was a lot of fun!
Update: Less than a week later I’ve already modified it, by adding a DHT22, which reports temperature and humidity. Might as well use that empty D7 pin on the microcontroller.