rasperry pi usb power switching

Switching Raspberry Pi USB Power via Home Assistant and Octoprint

This post may contain affiliate links. Please see the disclaimer for more information.

Over the last week, I’ve been continuing my 3D printing journey by getting my Octoprint system up and running. I’ve also been integrating Octoprint with Home Assistant. One of the annoyances I encountered along the way is that the Ender 3 will accept power over the USB connection. This is useful for programming, but annoying in normal use. This means that the control board to the printer and the display will always be powered when the Raspberry Pi running Octoprint is powered up, even if the printer power supply is powered down. In order to solve this, I began looking into ways of switching the power of the USB ports on the Pi 4. The solution I found is more generally useful in home automation.

rasperry pi usb power switching
Without this trick the annoyingly bright LCD display is always on when the Octoprint system has power

If you’ve followed my approach to home automation, you’ll know I make heavy use of the Raspberry Pi in my media systems and elsewhere. The latest addition of the Octoprint systems brings the number of Pis in the house to five. Most of these have some kind of USB peripheral plugged into them. Being able to power cycle a misbehaving peripheral without interrupting other operations on the device or trying to reach into whatever crevice hosts the Pi is very useful. This approach also opens up more avenues when integrated with Home Assistant. Dumb USB devices can now be powered off and on easily.

Some of this post it relevant to a stand-alone Home Assistant based setup and the rest is more relevant to Octoprint. I’ve tried to separate the two parts so you can skip the sections you’re not interested in.

Getting Started

The key to this is a utility called hub-ctrl.c, which as it sounds is a utility for controlling USB hubs, in a single C file. There is also a package in the raspbian repositories called uhubctl, but in my testing this didn’t work with the Raspberry Pi 4. hub-ctrl.c must be compiled from source, but since it’s a single C file this is trivial. The following commands will download, compile and install it along with it’s dependencies:

$ sudo apt install libusb-dev build-essential git
$ git clone https://github.com/codazoda/hub-ctrl.c.git
$ cd hub-ctrl.c
$ gcc -o hub-ctrl hub-ctrl.c -lusb
$ sudo mv hub-ctrl /usr/local/bin/

Once this process is complete you can start playing around with your USB ports (use the -h flag to see the arguments). Passing the -v flag will show a detailed listing of the current port status.

In my experiments I found that the power to my ports would not shut off unless I individually powered down all the ports on hub’s 1 and 2. It’s possible that this would interfere with the Ethernet if it were in use, but it’s perfectly fine over wifi. Basically it seems that the USB implementation on the Pi 4 is somewhat buggy. The upshot of this is that I must also power down the attached USB webcam. This adds some complications to my scripts later. It’s worth trying this on some of the other Pi models to see what the experience there is like.

I implemented the following script to power down the USB ports (in /usr/local/bin/psu_off.sh):

#!/bin/bash

systemctl stop webcamd
sleep 2

hub-ctrl -h 2 -P 1 -p 0
hub-ctrl -h 2 -P 2 -p 0
hub-ctrl -h 2 -P 3 -p 0
hub-ctrl -h 2 -P 4 -p 0
hub-ctrl -h 1 -P 1 -p 0

There is also a corresponding power up script (/usr/local/bin/psu_on.sh):

#!/bin/bash

hub-ctrl -h 2 -P 1 -p 1
hub-ctrl -h 2 -P 2 -p 1
hub-ctrl -h 2 -P 3 -p 1
hub-ctrl -h 2 -P 4 -p 1
hub-ctrl -h 1 -P 1 -p 1

sleep 2
systemctl start webcamd

The systemctl lines in there are for stopping and starting the webcam service, due to the aforementioned issue. You’ll either want to substitute in any services that may be dependent on the USB devices (and won’t detect the disconnect/reconnect) or just remove these lines.

Permissions

The hub-ctrl tool typically needs running via sudo. Since we’re going to want to run this tool from another system we should allow our normal user permission to do this without a password. You may even want to create a new user just for this purpose if you really want to lock down this ability.

To allow the use of our scripts without a password run the command sudo visudo /etc/sudoers.d/usb-power and add the following contents:

pi ALL=NOPASSWD: /usr/local/bin/psu_on.sh
pi ALL=NOPASSWD: /usr/local/bin/psu_off.sh

Of course you can update the username here if you opted to use another user. For my later use case with Octoprint, I need to use the Pi user.

Integrating with Home Assistant

We can integrate this with Home Assistant via a command line switch:

switch:
  - platform: command_line
    switches:
      pi4_usb_power:
        command_on: /usr/bin/ssh -i /config/id_rsa -o StrictHostKeyChecking=no pi@IP_ADDR sudo psu_on.sh
        command_off: /usr/bin/ssh -i /config/id_rsa -o StrictHostKeyChecking=no pi@IP_ADDR sudo psu_off.sh

You’ll obviously need to substitute in the address of your Pi as well as set the path to your SSH key. This key should be installed on the Pi. Right now I’ve left this open so this key can execute any command within the permissions of the Pi user. If you want to lock this down you need the ability to execute multiple remote commands. Follow this ServerFault thread to implement this.

Integrating with Octoprint

If you just came for the USB power switching with Home Assistant, you can skip the next couple of sections and go to the conclusion. However, if you are interested in Octoprint and getting it better integrated with HASS read on!

This approach can easily be integrated into Octoprint via the PSU Control plugin. This allows us to control the status of the USB power directly within Octoprint. To make this work nicely, we need to give Octoprint some idea of the status of the power supply. It would be nice to do this by checking the USB power state and reporting it back. However, I decided to cheat and use the status of the webcam service! Here’s the resulting script (/usr/local/bin/psu_status.sh):

#!/bin/bash

status=$(systemctl is-active webcamd)

if [[ $status = "active" ]]
then
    exit 0
else
    exit 1
fi

We then simply set up the plugin to use our three scripts:

octoprint raspberry pi usb power settings
Note that the status script doesn’t need sudo!

With that in place, you should be able to switch your USB power on and off via the little lightning bolt icon at the top of your Octoprint screen. It’s worth noting that the status script can also be integrated into the HASS switch above by adding the command_state item to it’s configuration.

I’m eventually going to add relay control to my printer to control the main power supply. At this point I’ll update my scripts to also control the relay. I’ll probably query the state of the relay for the status script as well. When I do this, I’ll update this post with the details. In the meantime the following video describes the hardware side of it (as well as a more basic software setup):

Because being on fire is the least desirable state for your printer to be in!

Switching the Octoprint PSU from Home Assistant

Now that we have our scripts integrated with Octoprint we can one-up our integration with HASS by using the Octoprint API to switch the USB power on and off:

switch:
  - platform: command_line
    switches:
      octoprint_psu:
        command_on: '/usr/bin/curl -s -H "Content-Type: application/json" -H "X-Api-Key: OCTOPRINT_API_KEY" -X POST -d ''{ "command":"turnPSUOn" }'' http://IP_ADDR/api/plugin/psucontrol'
        command_off: '/usr/bin/curl -s -H "Content-Type: application/json" -H "X-Api-Key: OCTOPRINT_API_KEY" -X POST -d ''{ "command":"turnPSUOff" }'' http://IP_ADDR/api/plugin/psucontrol'
        command_state: '/usr/bin/curl -s -H "Content-Type: application/json" -H "X-Api-Key: OCTOPRINT_API_KEY" -X POST -d ''{ "command":"getPSUState" }'' http://IP_ADDR/api/plugin/psucontrol'
        value_template: '{{ value.isPSUOn }}'

I decided to continue using the command line switch here, rather than a REST switch. This was because the REST switch requires state feedback via a GET call, which the Octoprint API doesn’t support. Instead we are calling the API via curl, which works fine. Don’t forget to update the code to include your IP address/hostname and also your Octoprint API key. You probably even want to have the whole command in the secrets.yaml file in order to protect these when sharing your config (since HASS doesn’t support templating in secrets).

Bonus: Shutting Down Octoprint from HASS

Now that we have a feel for the Octoprint API, we can use it in HASS to do other things. For example, it’s useful to be able to shutdown the server when we are done with it:

shell_command:
  octoprint_shutdown: '/usr/bin/curl -s -H "Content-Type: application/json" -H "X-Api-Key: OCTOPRINT_API_KEY" -X POST http://IP_ADDR/api/system/commands/core/shutdown'

This is basically the same as above and you can call any API method you like with this approach. To actually make use of this, it needs to be added to a script or automation. For example:

script:
  octoprint_shutdown:
    sequence:
      - service: shell_command.octoprint_shutdown

This can then be added to the HASS UI to get a nice button to shut down the system. You probably want to add a condition on this for real world use, in order to prevent the server being shutdown while a print is in progress. I’m going to leave this as an exercise for the reader!

Conclusion

With this in place I’ve made the use of my 3D printer via Octoprint a little more streamlined. It’s also nice that the USB power switching is more generally useful. I’m sure I’ll find other applications for it in future, since I didn’t know that it was possible until now.

As you can see from the above, I’m aiming for a deeper integration between HASS and my 3D printer than is provided via just the native Octoprint integration. This is just step one. I’m hoping to eventually automate some of the safety procedures and best practices around running the printer, such as ensuring that it is turned off when not in use and possibly even an emergency shutdown. I’ll be sure to update you on the progress of these in future articles.

If you liked this post and want to see more, please consider subscribing to the mailing list (below) or the RSS feed. You can also follow me on Twitter. If you want to show your appreciation, feel free to buy me a coffee.

3d print switch cover

Solving Smart Bulb Problems with 3D Printing

This post may contain affiliate links. Please see the disclaimer for more information.

If you ask the question “should I go for smart bulbs or smart switches?” on pretty much any home automation forum and you’ll undoubtedly get a mixture of answers. Most likely many of these will come down on the side of smart switches as the superior technical solution. This is generally because they replace the existing switch and so can be actuated manually. Also, you don’t have pesky switches that aren’t supposed to be touched, lest the smarts go out of your smart bulbs.

For a variety of reasons (pretty colours among them!), I only have smart bulbs in my house. I’ve written before about how I’ve added manual control back to some of these where required. Of course this still leaves me with certain switches in the house which “shall not be pressed”. I’ve had a nice non-invasive solution in mind for this for a while, but I’ve only been able to realise it since getting a 3D printer.

People Problems

I actually see this problem as less of a technical one and more of a people one. In the normal operation of our house, it rarely occurs that a smart bulb is turned off at the switch. This is because we are used to the way the house works and trust that the automation system will do the right thing.

Of course, when we have guests this all falls apart. People just can’t help flicking a switch if one is presented to them. Even if they just entered a room where the light came on automatically, they will switch it off on exiting. The only solution is to remove the temptation by removing or covering the switch.

The low tech/ugly solution to this would have been a piece of tape with “do not switch off” scrawled on it in marker pen. However we can do better than that. There are little plastic widgets available which can be stuck over the top of a switch and will restrict its use. I haven’t seen any that will fit the switches here in NZ, which are more square in comparison with British or US switches. So I decided to make my own.

OpenSCAD to the Rescue

As a programmer, it’s probably not a surprise that my 3D modelling software of choice is OpenSCAD. I’ve dabbled in using is before and managed to learn the basics before getting my 3D printer. However, this is the first physical object I’ve actually attempted to produce with it. I’m actually really happy with the result.

Note: the first version of these had the logo flipped for some reason. I’ve since updated the files in GitLab and Thingiverse (links below). The photos below show the original versions with the reversed logo. Thanks to @templarian on Twitter for pointing this out.

3d print switch cover
Yes, these are Home Assistant themed! My way of saying “don’t touch, HASS will take care of it”!
3d print switch cover
Mount the cover by sticking double sided tape or blu-tack to the tabs
The covers look pretty good once mounted. Note the Zigbee switch above for automation override (if needed).

This has been made for my PDL-600 series switches, but the design is parametric, so should be trivially adaptable to other NZ/Australian switches, since most of these seem to maintain the squarish form factor. I’ve also made a double switch cover for two switches arranged horizontally. This was done by elongating one side and centring the logo.

3d print switch cover
Parametric modelling FTW!
3d print switch cover
I made the tabs slightly narrower here so that the cover would fit onto the switch plate
Just fits!

Model Parameters

The model parameters are available at the top of the OpenSCAD source and have comments, which allows the software to present you will a nice dialog for editing the parameters. You can even set presets and switch between them. I’ve already included the presets for my single and double switches.

The available parameters are as follows:

  • wall_thickness – The thickness of the main wall around the switch. Defaults to 1mm and you probably won’t need to change it;
  • button_length – The length of the cover (from top to bottom as you look at it mounted, since the reference is to the flat surface as it’s printed). Adjust depending on the size of your buttons;
  • button_width – The horizontal width of the cover, to allow for non-square buttons and also multi-button arrangements. I doubled this to produce the double cover;
  • button_height – The height of the button from the switch plate. Used to create the internal cavity to cover the switch;
  • logo_x_offset – X coordinate offset of the logo. Use this to move it around if you change the cover dimensions above;
  • logo_y_offset – Y coordinate offset of the logo. Use this to move it around if you change the cover dimensions above;
  • tab_width – the width of the mounting tabs on either side;
  • tab_height – the thickness of the mounting tabs.

Wait, I want some of these…

If you have a 3D printer you can download the OpenSCAD file and STLs (for the variations I’ve printed) on GitLab or Thingiverse. I’ve also included GCode files for the Ender-3 in the Git repo, but I recommend you slice the models yourself with your own settings. You’ll need to print with supports enabled for the internal cavity, but these pop out quite nicely.

If you don’t have a printer, you are welcome to use any of the available 3D printing services online, but I’m afraid I can’t recommend one. I also found them rather expensive when I looked into it.

If there is sufficient demand I might put up a Tindie or Etsy store for these and charge a couple of dollars (plus shipping of course!). Let me know in the comments if you’d be interested in this.

Conclusion

I’m really happy with these, especially considering they are my first custom 3D printed object. They’ve actually solved a real world problem for me, since we recently had guests again and nobody switched off any of the smart lights!

I’m interested to hear if anyone else has used 3D printing to solve smart home annoyances like this. There seems to be a lack of HA related designs on Thingiverse. Let me know if you’ve come up with anything useful!

If you liked this post and want to see more, please consider subscribing to the mailing list (below) or the RSS feed. You can also follow me on Twitter. If you want to show your appreciation, feel free to buy me a coffee.

ender 3 successful benchy

3D Printing: Getting to Benchy with the Ender 3

This post may contain affiliate links. Please see the disclaimer for more information.

I recently bought a 3D printer in the form of a Creality Ender 3. I thought I would take the time to document how I got up and running, since this area is completely new to me. Hopefully this will be useful to those who are just starting out in 3D printing, specifically with the Ender 3. It’s not going to be a complete guide, but more of a high level overview of the steps I took. I’ll link to more detailed instructions where relevant.

About the Ender 3

The Ender 3 is a budget 3D printer from Creality 3D. It has a pretty standard feature set, including a heated bed. Levelling of the bed must be performed manually, but there are several addons which can automate this. The whole design of the printer has been made Open Source, including the firmware. There are also a whole load of 3D printed addons that can be added to the printer to improve its design and performance.

I opted for the base model with a glass bed as an additional addon. This was because I’ve heard of people having issues with warping of the metal build plate over time (and heat). The glass bed will always remain flat and avoid this issue. When I actually received the unit I saw that with the bundle I purchased I got the original flexible build surface as well. So I have the choice between the two. I also purchased a Raspberry Pi to host an Octoprint setup (which I haven’t got around to setting up yet) and three rolls of PLA filament. My filament took ages to arrive. I’d probably advise you to grab try and grab a bundle that includes a roll of filament if you want to get going quickly. The available bundles are always changing, so have a search around for the best deal.

Putting it Together

The printer arrived very quickly (just a few days). It comes in kit form and requires some assembly. This shouldn’t be difficult for anyone who’s put together anything moderately complex from a kit before. However, the instructions in the box leave something to be desired so I’d advise you to follow some of the 3rd party instructions available online. I was able to complete the build in 2-3 hours spread over a couple of weekday evenings.

Why You Should Upgrade the Firmware

The Ender 3 ships with an older version of the Marlin firmware. This lacks some features available in newer versions. Most notable of these is the lack of thermal runaway protection in the stock firmware. This is an important safety feature, which will cut power to the heating elements of the printer if the firmware detects that something is wrong. This can happen if some part of the heating or feedback systems becomes loose. I think it’s really important to upgrade the firmware on the device to the latest Marlin, since the stock firmware may literally burn your house down! Of course even with the latest firmware accidents can still happen, so this isn’t a substitute for taking other safety precautions!

The firmware upgrade process, whilst not trivial is easy enough for anyone whose programmed an Arduino or ESP8266. That’s because the Marlin firmware is itself an Arduino sketch! Basically, doing the update is a two step process. First we must flash the Arduino bootloader to the mainboard. This will then allow us to upload our new firmware (and any subsequent updates) via the printer’s USB port.

Performing the Upgrade

ender 3 flashing bootloader
The bootloader programming setup, note the resistors between 5V and reset (together these make 120ohm)

Flashing the bootloader is the most tricky part of this. It requires making some connections to the main board from another Arduino. This will act as the programming device (I used my old Arduino Duemilanove). I also found that I had to insert a 120 Ohm resistor between the 5V and ground pins of the Arduino to prevent it being reset when the IDE connected to it. This is because we want the reset to be passed through to the printer mainboard, not to reset the programming sketch on our Arduino. I couldn’t flash the bootloader from platformio, which is my preferred tool for doing Arduino stuff, so I had to download the latest version of the Arduino IDE.

Once the bootloader was flashed I cloned a copy of Marlin from Github, checked out the latest 1.x release and copied over the Ender 3 example configuration. I did a quick double check to make sure thermal runaway protection was enabled in the config. I was then able to build and flash the new firmware via platformio and the USB port on the printer.

This whole process is covered in much more detail in the following videos, which I used as a basis for getting this done:

Levelling the Bed

I found levelling the bed to be somewhat tricky. I think the main problem was that I kept getting the extruder too close to the bed which would inhibit the flow of plastic from the nozzle. However, after a few goes I was able to get it dialed in reasonably well. From the performance of the printer so far it looks like this doesn’t have to be perfect, just good enough. The following video shows the process that I followed:

First Prints

For my first print I just started one of the test gcode files that come on the SD card. This was supposed to be a pig. However, I knew that it wouldn’t complete because the only filament I had was the small amount which is supplied with the printer. I was mainly just wanting to see the printer running!

ender 3 first print
Well that’s half a pig, right?

I had to wait another two weeks for the first of my rolls of filament to arrive, which was pretty frustrating. Once that arrived I sliced the 3DBenchy test model using Cura and printed it. To my dismay it didn’t come out as I expected on the first try:

ender 3 failed benchy
Oops!

After a little bit of head scratching I realised that I had a Cura setting enabled from a previous model which I had been slicing. The specific setting was “Spiralize Outer Contour” A.K.A “Vase Mode”, which explains the issue. After disabling this setting and re-slicing, the resulting gcode produced a pretty nice Benchy in around 2 hours.

ender 3 successful benchy
Finally, success!

Conclusions

Since proving that the printer is functioning correctly with a decent benchy print, I’ve done a few other prints. I’ll probably cover some of these in future articles. For my regular readers – don’t worry! This isn’t going to turn into a 3D printing blog. However, there will be the occasional post on the subject (probably more than occasional in the next couple of months as I’m learning about it).

I’m actually really impressed with the whole 3D printing ecosystem and the Ender 3 specifically. I really like how my whole 3D printing pipeline is Open Source. This goes right from creating the models (with OpenSCAD, FreeCAD or Blender), through slicing (Cura) and down to the machine itself and the Marlin firmware (and Octoprint, eventually).

Coming back specifically to the Ender 3, I’m pleased with the print quality. So far I’ve only printed with a 0.2mm layer height, but it supports down to 0.1mm. The objects I’ve produced, whilst obviously 3D printed, are of good detail and finish and are very strong. Overall, I’d recommend this printer to anyone who has the technical know how to get it up and running and perform the required firmware update.

Next Steps

Print more things! I really love the feeling of holding an object which just didn’t exist a few hours before. I have a whole list of objects to print, including some upgrades to the printer. For some of these I’ve been waiting for my black filament to arrive, so I should be able to get on with them soon.

I also need to get my Octoprint setup completed. It’s actually mostly there, I just have a couple more configuration steps to go. I also want to print a case for the Pi, which will fit underneath the bed of the printer. I hope to report back on my progress with that pretty soon.

If you liked this post and want to see more, please consider subscribing to the mailing list (below) or the RSS feed. You can also follow me on Twitter. If you want to show your appreciation, feel free to buy me a coffee.