@madpilot makes

Twilio + AWS Lamba + Rev = Easy call recording!

I have been doing a bunch of user interviews at work. It’s been difficult to get our users in front of a computer, or to get them to install video conferencing software, so I’ve been calling them on the telephone. I find that taking notes while I interview people kills my flow, and I’m really not very good at it, so I needed a way to easily record these phone calls, and then get them transcribed.

There are a bunch of solutions out there, but they all seem to rely on a third party app that make a VoIP call. This presented me with three problems:

1. Our spotty office wifi caused drop outs – and when it did work, the quality was terrible (thanks Australia!);
2. The incoming number was a either blocked or some weird overseas number, which users promptly ignored
3. Automatic transcription of phone calls is woeful – because of the low bandwidth, the audio signal isn’t great, and computers do a really bad job at translating it to text.

When I was last at JSConf, I got chatting to Phil Nash who is a developer evangelist at Twilio. I asked him whether I could setup a number that I could call, have me enter a number, dial that number and record the call. He said it should be easy.

Challenge accepted.

Spoiler alert: It is.

Note: This code and deployment process isn’t actually the one I used at work. We use Golang, which is way more lines of code, and has way more boiler plate – and I needed to write an abstraction around TwiML – so I chose to rewrite it in Python here for simplicity’s sake. We also use CloudFormation to create Lambdas and API gateways, and have a CI build pipeline to deploy them, which isn’t conducive to a pithy blog post. Does this process work? Yes. Would you use it in real world in a production environment? Up to you. 🤷‍♀️

An overview

At a high level, this is what happens when you dial the number and request an outgoing call:

  1. Twilio answers your call
  2. Twilio makes a request to an Amazon Lambda via an API Gateway, which returns some TwiML instructing Twilio’s voice engine to ask you to enter a phone number.
  3. It waits for you to enter the phone number followed by the hash key
  4. When it detected the hash key, it makes another request to the lambda, this time with the number you entered. The lambda returns an instruction to dial the number (after some normalisation – more on this later), join the calls, and to record both sides of the conversation.

After this happens, you can log in to the Twilio console, download the MP3, and upload that to Rev.com where real-life humans transcribe the conversation.

The code

from twilio.twiml.voice_response import VoiceResponse, Say, Gather, Dial
from urllib.parse import parse_qs

LANGUAGE="en-AU"
AUTHORISED_NUMBERS = ['ADD YOUR PHONE NUMBER HERE IN INTERNATIONAL FORMAT ie +61400000000']

def authorized_number(number):
    return number in AUTHORISED_NUMBERS

def say(words):
    return Say(words, voice="alice", language=LANGUAGE)

def get_outgoing_number(request):
    response = VoiceResponse()

    action = "/" + request['requestContext']['stage'] + "/ivr"
    words = say("Please dial the number you would like to call, followed by the hash key.")

    gather = Gather(action=action)
    gather.append(words)
    response.append(gather)

    return response

def add_country_code(number):
    if number[0] == "+":
        return number
    elif number[0] == "0":
        return "+61" + number[1:]
    elif number[0:2] == "13":
        return "+61" + number
    elif number[0:2] == "1800":
        return "+61" + number

def hangup():
    response = VoiceResponse()
    response.hangup()
    return response

def handle_ivr_input(params):
    to = params['Digits'][0]
    dial = Dial(add_country_code(to), record="record-from-answer-dual", caller_id=params['Caller'])

    response = VoiceResponse()
    response.append(say("Calling."))
    response.append(dial)
    return response

def handler(request, context):
    path = request['path']
    params = parse_qs(request['body'])

    response = ""
    if path == "/incoming":
        if authorized_number(params["Caller"][0]):
            response = get_outgoing_number(request)
        else:
            response = hangup()
    elif path == "/ivr":
        response = handle_ivr_input(params)
    else:
        return {
            'body': "Action not defined",
            'statusCode': 404,
            'isBase64Encoded': False,
            'headers': { 'context_type': 'text/plain' }
        }

    return {
        'body': str(response),
        'statusCode': 200,
        'isBase64Encoded': False,
        'headers': { 'content_type': 'text/xml' }
    }

Code is also on GitHub.

I’m in Australia, so there is a little bit of localization happing here: I set the voice of Alice (the most human sounding robot that Twilio has) to Australian, and I insert the Australian country code if it is not already set. Twilio doesn’t do this automatically, and it’s a pain to replace the first 0 with a +61 for every call.

When the call is made, the caller ID is set to the number you called from, so the call looks like it came from you. You need to authorise Twilio to do that.

I’ve included a hard-coded allow-list (AUTHORISED_NUMBERS) of phone numbers who can make outgoing phone calls. If a number that is not on the list tries to call the number, they just get hung up on. You wouldn’t want someone accidentally stumbling across the number and racking up phone bills. I guess at least you would have recordings as evidence…

Note: the code doesn’t know about area codes, so if you are calling land lines (Wikipedia entry if you are under 30 and don’t know what they are) you will always need to include your area code.

Cool. So what do you do with this code? It needs packaging and uploading to Amazon.

Packaging the script

(Want to skip this bit? Here is the ZIP – you can edit it in the Lambda console once you upload)

You will need Python 3.6 for this. Instructions for OSX, Linux and Windows. Good Luck.

git clone git https://github.com/madpilot/twilio-call-recorder
cd twilio-call-recorder
pip install twilio -t ./
find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
zip -r lambda.zip *

Creating the Lambda

  1. Log in to your AWS account, and go to https://console.aws.amazon.com/lambda/home
  2. Click Create function
  3. Then Author from scratch
  4. Name your lambda: twilioCallRecorder
  5. Select Python 3.6 as the runtime
  6. Select the Create new role from template(s) option
  7. Name the role: twilioCallRecorderRole
  8. Click Create Function

Your screen should look similar to this:

Screen Capture of the AWS Lambda Setup.

Important! Don’t Add a trigger from this screen! We need to set the API gateway in a non-standard way, and it just means you’ll have to delete the one this page sets up.

Uploading the Code

  1. Upload ZIP File
  2. Set the handler to recorder.handler
  3. Click Save
  4. In the code editor, Add all the phone numbers who can make outgoing calls to the AUTHORISED_NUMBERS list (include +61 at the beginning)
  5. Click Test
  6. Set the event name to Incoming”
  7. Set the payload to
    {
      "path": "/incoming",
      "body": "Caller=%2B61400000000",
      "requestContext": {
        "stage": "default"
      }
    }
    
  8. Click Create
  9. Click Test

GIF of the Code uploading Process

Setting up the Web API Gateway

  1. Click Get Started
  2. Click New API
  3. Name the API Twilio Call Recorder
  4. Click Create API
  5. From the Actions menu, select Create Resource
  6. Check the Configure as Proxy Resource option
  7. Click Create Resource
  8. Start typing the name you gave the Lambda (twilioCallRecorder) – it should suggest the full name
  9. Click Save
  10. Click Ok
  11. Click Test
  12. Select Post in the Method drop down
  13. Select /incoming as path
  14. Set RequestBody to
    Caller=%2B61400000000

    replacing 61400000000 with one of the numbers in your allow list

  15. Click Test

If that all worked, you should see a success message.

Screen Captures of setting up the API gateway

Deploy the API Gateway

  1. From the Actions menu, select Deploy API
  2. Enter Default as the name
  3. Click Deploy
    1. Screen Captures of the Deployment

      Copy the invoke URL. In a terminal (if you are on a Mac):

      curl `pbpaste`/incoming -d "Caller=%2B61400000000"
      

      Testing the endpoint in the command line

      Congratulations! You have setup the API Gateway and Lambda correctly!

      Setup Twilio

      See the documentation around webhooks on the Twilio website – paste in the URL from the API gateway, and you are good to go.

      Making a call

      The part you have been waiting for! Pick up your phone, and dial the incoming number you setup at Twilio. If all is well, you should hear a lovely woman’s voice asking you the number you wish to dial. Enter the number, and hit the hash key. After a moment, the call will be connected!

      Once you hang up, you can log in to the Twilio console, browse to the Programmable Voice section and click the Call log. You should see the call you made. Click on it and you will be able to download a WAV or MP3 version of the recording.

      Now, you just need to download it (I chose the MP3, because it will be faster), and upload it to Rev.com. After a couple of hours, you will have a high quality transcription of your conversation. It’s really very easy!

Converting a Makibox – Building the Y-axis

I’ve now built the aluminium frame and completed the Y-axis. Of course, this was not without it’s problems.

Firstly, I misordered – I was one set of uprights short. This may not be a massive problem though, as I hadn’t taken into account the size of the spindle when designing the X-axis, and it wouldn’t have fitted in the configuration I had designed for – That’s what you get for forging ahead with out good engineering drawings.

Other minor issues were easily fixed by reprinting some parts – I added limit switches into the motor and bearing holders (though I haven’t worked out how to make the switch on the bearing holder work yet), I made the driver carriage wider so the whole anti-backlash nut fitted completely and I changed the shape of the passenger carriage so it could slide over the entire stroke.

A render of the new Y-Axis

Everything went together quite well – I did my best to square everything up, using a shim I printed – the holders may not be exactly in the middle, but they are all consistently out, which is the main thing.

I was a little concerned that both carriages were rotating around the z-axis, but realised that was because they weren’t joined yet, so there was only two points of contact, rather than four.

To fix that, I cut out a 205mm x 205mm MDF spoil board, and attached it using a 0.33mm feeler gauge squared it against one of the uprights.

I’m not sure I can do more alignment without having a X-axis, which requires a redesign.
See the video below for the test! (Excuse the upright video – I need to get an iPhone holder)

IKEA hacks: A microwave interface for the Duktig kids kitchen

The finished product

Hugo just turned one, and to celebrate we bought him a Duktig kitchen from IKEA. Like everyone else we painted and added fake subway tiles, but I wanted to take it a bit further and add a working microwave panel.

Hugo is obsessed with pressing buttons and turning knobs – We were staying at an AirBNB recently that had a microwave that you controlled using one big knob and he loved it – so I thought I would model that.

I ordered a 4-digit 7 segment display, a rotary encoder and an aluminium knob, which I planned to run off an Arduino Nano.

Rotary Encoders

A rotary encoder looks a lot like a potentiometer, however they work quite differently. For starters, there is no limiter so they rotate through a full 360 degrees.

But the main difference is how you interface with them: they output a digital code called a Gray code. Named after Frank Gray, it ensures that one-bit only ever changes at one time so we can be sure of the direction the shaft turns.

Of course, the library we are using hides this from us, so all we care about is the value that comes back.

The encoder I’m using also has a push button, which I’ll use to start and stop the timer. The library also abstracts this.

The display

The four-digit seven-segment display has a built in driver chip that means we only need two pins to drive it: a clock and data. Again, there is a convenient library that deals with pushing data to the board.

Buld progress

The LEDs

I had six yellow LEDs that I pulled out of the night light I gutted to make an interim night light, so I repurposed them for this project. As the draw a total of about 120mA when on, they can’t be driven by the Arduino directly – I’m using a BC547 transistor to drive them.

The speaker

I added a cheap, 8 ohm streaker than I’m driving directly off one of the Arduino digital outputs. There is a tone library that turns a GPIO on and off quickly enough to create a tone. I maybe regretting this already though – it can get quite annoying.

Sleeping

This microwave controller needs to be battery operated. To do that without costing me a small fortune in batteries, the controller needs to turn itself off. Luckily, the Arduino Nano supports a deep sleep which reduces it’s current draw. The Nano can then be woken up by a pulse on either pin 2 or pin 3.

By feeding the signal from the rotary encoder and the switch into those pins, any rotation of button pressing will wake up the processor.

There is a slight problem though: there are two pins on the rotary encoder, and one on the switch: we need another input.

Or do we?

Rotary encoders have a physical “click” (called a segment). On the particular encoder I have, each click goes through a complete Gray code cycle, meaning there is a guaranteed two logic level transitions on each pin per segment. And, if you have ever watched a small child spin a knob, you would have noticed that their developing fine motor skills result in big rotations. In this case I can happily take the output of one of the encoder pins, and be confident that it will always wake.

So, the switch is wired to GPIO 2, encoder pin A is wired to GPIO 3 and pin B is wired to GPIO 4.

The Controller Schematic

The code

There are four main parts of the code: reading the encoder, the display code, the code that puts the MCU to sleep, and the interupt handler that wakes it back up again.

Most of the heavy lifting for interfacing with the encoder and display is done by two libraries.

The encoder library uses polling rather than hardware interrupts (which is good because I would have run out of interruptible pins). Every millisecond it checks the state of the encoder, and can work out if it has been spun or not. This library exposes the delta, we we use to increment or decrement the display.

The library also provides a callback that is fired on button clicks. Each clock toggles the running variable and the returns control back to the loop.

The display library at it’s lower levels takes four bytes – one for each number. Each bit of each byte represents a segment of the display. Thankfully there are some helper methods to display common things like numbers.

You can download the code on Github.

The loop

Because all of the inputs are handled via interupts, the loop just needs to deal with updating the display.

The left variable represents the number of seconds remaining. The first thing to do is adjust it if the encoder changed. We simply add the delta to it. Note that his happens regardless of whether the timer is running or not – this means you can add or remove time even when the microwave is running.

If the timer is running and the LED is off, I turn it on (and vis-e-versa).

If the timer is running the variable automatically gets decremented every 1000 milliseconds.

If the variable is 0, the timer stops and I display the word end and sound the beeper. (The LEDs will also go off)

The display routine gets called every 500ms. Why every half second? So we can flash the dot to show that the timer is running!

The build

I was hoping this would be a quick weekend project, so I threw the circuit together using perf board. Of course everything always takes longer than you expect, but it kind of worked out well, because the perf board made the feature creep easier to deal with.

I 3D printed a “case” though my printer’s build area was too small to cover the whole area, so I made an MDF backing plate. Pro tip: don’t use pin to mark construction lines: paint won’t stick to it. Also: prime MDF – it absorbs paint like no body’s business. What should have been two coats required four.

Power

During testing I realised that there were LEDs on both the Arduino and the display that stayed on regardless of whether the Arduino was asleep or not. I measure the power draw whilst sleeping at it was sitting at about 15mA. A AA battery has a capacity of around 2400mAH, so a set would last around 160 hours or 6 days.

Clearly that is too high.

I removed the LEDs and that brought the draw down to 2mA, which buys me 1200 hours or 50 days. Better, but not amazing. Unfortunately, the Nano isn’t great as a lower power device. If I could be bothered removing the chip from the perf board, I could remove the FTDI drive and power regulator and probably claw back a bit of quiescent current.

I have ordered a boost converter so I can run the board off two batteries at 95% efficiency rather than the four at the moment so I might just use a couple of C cells which have 8,000 mAH capacity (nearly half a year).

See the microwave in action!

Converting a Makibox – Aluminium frame is done

I’m pretty happy with how the aluminium frame has come together. I’ve kept the X-axis pretty simple, though I tried a few iterations before coming to this shape.

Originally I had the vertical X-axis supports butted on the top of the horizontal Y axis base, but I was concerned with keeping the vertical… vertical. I could have used right angle brackets, but decided that by putting them in the inside of the base, I can add additional points of contact that would better support them. This configuration also gives a slightly larger base, so should make it slightly more stable. They are now attached in two dimensions which effectively works like a right-angle bracket.

The motor mount and bearing mounts are pretty simple, bridging the two verticals on each side. I toyed with running the bolts in a horizontal extrusion that would stop them from slipping down, but that would stop me from adjusting the heights when tramming.

On the topic of adjustments, I’m starting to regret the dual-carriage design, as there is an extra dimension that needs to be aligned – not only do I need to align the X, Y and Z axes, I need to make sure both slides are exactly parallel. I’ve bought a digital dial indicator which should help in squaring everything up – we’ll see how that goes.

I now have a complete bill of materials for the frame:

Qty Description Length
3 40×40 Aluminium Extrusion 285mm
4 40×40 Aluminium Extrusion 260mm
2 40×40 Aluminium Extrusion 401mm
1 40×40 Aluminium Extrusion 205mm
16 8mm Square Washer
32 16x16x6/M8 Square nut
32 M8x16 Button Head Socket Screw
8 End cap 40×40 Black

The order cost me just shy of $200, which already takes me over my $250 budget, but I’ve been reconsidering how much I’m spending, as I assumed I could use my Dremel 4300. After a bunch of reading, I think I’ll need to by a different spindle that has less runout.

Hugo’s Nightlight: Modelling and Printing the Mold Master

Initially I thought about mounting the electronics in the back of the H, trying to fit everything in the footprint of the mold. But if I could get lights on the back, there would be some cool effects I could achieve. To get a consistent glow, the LEDs would need to be wedged in the middle of the H.

This did make mounting the PCB difficult though. I decided that I would mount the H on a small plyth that would house the electronics.

Autodesk Fusion 360 can extrude type, so all I needed to do was pick my type face. I wanted something childlike (not Comic Sans) so I went with Titan One.

Next, shelled, then mirrored to form the two halves. I added some alignment holes, to make gluing easier and finally created some nubs that will act as anchors for the plyth. The nubs were printed as separate parts so I didn’t need to print supports.

Printing

Each of the two halves took around 2 hours to print. Of course, because of how FDM printing works, the result was pretty streaky. The silicon I had literally talks about how fine detail it is, so I would need to do something about the streaks.

My dad used to make scale model aeroplanes, and I always remember him filling the joints with wood putty and then sanding to get a smooth finish, so I thought I would try that.

It turns out the gaps were just too big, and using a water based putty while wet and dry sanding meant the putty would come off.

Next I tried an auto sealer that was supposedly sandable. This didn’t work either because it was too rubbery.

At this point I spent AGES wet and dry sanding, starting at 80-grit and worked my way up to 240 before I found out about auto primer/filler.

This stuff is designed to cover up small scratches in car body work, and is sandable, allowing you to get a really smooth finish.

I did two coats, and sanded with wet and dry, 400 grit, and then a final coat before finishing with an 800 grit. It worked really well. It also saved a lot of time – sanding to a smooth finish is hard.

Converting a Makibox – Designing the Y-Axis

I’ve been iterating the Y-axis in Fusion 360. A common design I have seen on other moving-bed designs is four linear bearings – one bearing at each corner of the bed. The problem with this design is you lose the distance between the bearings in travel. Since I have only have a maximum of 165mm on this axis, I didn’t want to lose too much to dead play.

Example of a moving bed with 4 bearings

Round 1 – Two Bearings

My first thought was use a single bearing on each side, introducing a minimum lost travel of 12mm (the width of the bearing). This looked like it would cause rotation problems, though – especially when dive cutting in the outer edges of the build area.​​​

Drilling on one side of the axis, causes excessive rotational forces at the bearing

Round 2 – Four Bearings

I went back and looked the parts I could salvage from the Makibox, and it turns out I have four 170mm linear rods at my disposal. This means I can create a passenger carriage – one that isn’t driven by the lead screw, but instead is pushed along it’s rails by the bed itself. This design gives four points of contact, eliminating the radial moment of the two bearing design (Note: this doesn’t deal with linear rod or bed flex, just the rotation issue). The disadvantage is the base is now double the size, but as the bed would have moved outside of the frame envelope during operations, it’s not that big of a deal.

Here is a render of the Y-axis. If you imagine a bed on top of it, attached to the two carriages – the left (driver) carriage is driven by the lead screw, while the right (passenger carriage is pushed by the bed. (I tried making a video, but the Fusion 360 animation workspace doesn’t support animating joints!)

Dual Y Axis Render

The Y-axis will have a 131mm travel – the loss is 7mm from the ball bearing, 7mm from the coupler and 20mm from the anti-backlash nut.

Issues

There are still a couple of side issues I still need to work out:

  1. ​The mount holes for the anti backlash nut are too close to the shaft, so I can’t heat fit brass inserts to screw in to – I may have to thread the plastic. I may be able to find some small nuts to secure it. Ideally once the mill is working I’ll be able to machine a bracket from a small plate of aluminium
  2. I have brass inserts in the carriages because I initially thought I would screw the bed down from the top – making replacement of the spoil board easier. This may not be an actual problem though – I’m not sure how often the spoil board needs changing. I may just make them screw holes, and be done with it. I have to think about it a bit more.

Next up: the X-axis

Turning a Makibox into a PCB Mill

You might remember the Makibox A6 – it was a sub-$400 3D printer that, like a lot of cheap printers at the time, was crowd-funded. It took forever to deliver, and there were a lot of problems with it.

The MakiBox A6LT

Personally, I managed to print a single cube on my first print. On my second print something went wrong and I blew up the control board. I suspect because of the stalled extruder motor. The extruder needed replacing, as did one of the plastic lead screws (that was my fault – I over tightened it).

In the process of trying to get the parts replaced, the delivery got lost – they claimed it had been delivered, but I hadn’t received yet. While trying to work this out, I had to quickly move interstate for work. To make matters worse, the company that made the Makibox disappeared around the same time, so I resolved myself to writing off the printer.

I decided to move to Melbourne permanently, so I flew back to Perth to collect my belongings – included what was left of the Makibox – and jammed it into my car for long drive over the Nullarbor.

And there is sat almost four years – dejected, in a cardboard box in my workshop.

On a recent trip back to Perth, my mother handed me a package which a person I worked with have given her. Apparently. it was delivered to the office years ago – so I had no idea what it was.

Low and behold, It was the replacement parts from my Makibox! Well, this was a sign. I put the parts next to the printer, as I wasn’t sure what I was going to do with it. I had an M3D printer which was pretty terrible – maybe I could frankenstein the two designs and get one printer out of them?

Fast forward a couple of months – I come in to a bit of spare cash after selling off my time tracking application, and I decide to bite the bullet and buy a real 3D printer – a Lulzbot Mini. After setting it up and kicking out a number of awesome prints, I placed the M3D next to the Makibox. I now had a collection of old, cheap and not very good printers. I had to do something about that.

Upcycling a Makibox

The Makibox has some decent steppers and screws in it (the M3D really doesn’t – half the problem really) so I started looking at the parts and wondering if I could convert it to a PCB mill. Ideally I’ll eventually want a proper mill that can do aluminium and stuff, but I reckon I can cobbled together something good enough to grind a few hundred micros of copper off some fibre glass. Bonus points if it’ll drill through holes.

What’s the worst that can happen? I have a broken Makibox?

Research

I’ve been doing some research into PCB mill designs over the past couple of weeks, and I’ve decided to go with a fixed gantry design (based heavily off the cheap Chinese machines). This means I only need three motors, and three lead screws.

I’m giving myself a $250 budget for the conversion.

Due to the existing hardware that I want to reuse, the actual build area for this machine will be relatively small, so I’m hoping that will help with the rigidity of the system (smaller builds should be stronger than larger ones). Given that this PCB mill gets decent results with a wood base, I’m feeling pretty confident we can get some good results with this.

Stocktake

  • 4 x NEMA 17 sized motors (Longs: 17HS 42BYGH 1.8°)
  • 1 x 218mm T8.8 (8mm diameter, 8mm travel per revolution) trapezoidal lead-screw
  • 1 x 165mm T8.8 trapezoidal lead-screw
  • 1 x 147mm T8.8 trapezoidal lead-screw
  • 2 x 226mm x 4mm steel rod
  • 1 x 170mm x 4mm steel rod
  • 1 x 164mm x 4mm steel rod
  • A bunch of cap hex screws
  • Plastic couplers
  • Plastic anti-backlash nuts

The plastic anti-backlash nuts are surprisingly good – I can’t detect any backlash (with the naked eye). The injected plastic piece has some thread that acts as a preloader – quite clever really. Regardless, I decided to order some metal anti-backlash nuts – I’m not sure how the plastic will hold up to the additional force of milling.

I also ordered some aluminium couplers (to replace the plastic ones), LM4UU linear bearings (to slide on the steel rods), and round bearings to hold the lead screws. Total cost so far: $79.68.

Everything else looks useable (at this stage) – I’m a bit concerned that the steel rods aren’t straight enough, but I’ll run with them for the moment.

I’m going with 4040 aluminium t-slot for the frame. I’ve found a Melbourne based supplier so I should be able to get high-quality stock quickly (and cut to size!). But before I order them, I’m going to design the mill in Fusion 360 so I can test for fit and size.

You can see the render of the Y-axis here:

Render of the Y-Axis

The X-axis will be a (wider) copy, rotated 90 degrees. The Z-axis will still need some thinking.

I will print the motor bracket, bed and bearing holder on my Lulzbot Mini. This is is the cause of the weird design – it needs to fit in the 150mm x 150mm build envelope of the 3D printer.

Based on the dimensions from Fusion 360 the design should allow a Y-axis travel of around 168mm 156mm (Update: I didn’t take in to account the linear bearing width). I still have to work out the X-axis travel.

Hugo’s Nightlight: Part I

Long before Hugo was born, I had hatched a plan to build him a nightlight. Originally inspired by this, I decided to go for something less fragile – a simple H with some RGB LEDs.

Just before Hugo was born, I added a LIFX bulb to our bed side table, and added some Flic buttons that gave us better control on the lights. Using a Node Red flow, I setup the light to go to 5% brightness on a single click, 20% on a double click and a 2 second hold set the light to 100%. This worked really well: if we wanted to check on the baby, we could just single click, and get enough light to see him without waking him.

The downside was if the Flics stopped working we needed to use our phones, so the second requirement was a hardware switch to turn the light on and off. It should have configurable single, double and hold actions.

After Hugo moved to his own room, I wired up the same LIFX and Flic setup, adding a slow fade to the lights, so as to not startle the little fella when the lights switched on or off. I wanted the night light to do the same, so it would need some sort of tweening library.

Finally, a mate of mine was telling me about his kids grow light that turns on in the morning to let the child know that it’s time to wake up. I thought it would be kind of fun to have a cute sun rising animation. I thought about adding an alarm feature in to the light, but decided that I can do that using home assistant and node red, which saved me adding a Real-time clock and having to deal with times and other such nonsense.

Giving these requirements I went and ordered a tape of WS2812B LEDS from AliExpress ($12 for 100!) and got to work.

Making a plastic H

I needed a translucent H. My first thought was to try the usual places to see if there was something I could buy off the shelf. There was a few places that sold acrylic signs that would have been suitable, but they weren’t quite what I was looking for. I really wanted a completely milky white H with the LEDs embedded in the middle.

Well, I have a 3D printed, could I do something with that? I went in a hunt for translucent white filament. It turns out (for reasons I will discover later) that isn’t a thing. Odd.

I picked up some light blue translucent filament and did a small test print, but the print came out really streaky. Not what I wanted.

Then I remembered reading about resin casting. What if I could print a master, cast a mold in silicon, then cast the whole thing in resin? A quick Google for some tutorials and it sees plausible – in fact a bunch of people embed LEDs for cos play jewellery.

The problem is, all the examples I see are clear. You can get pigments to embed in the resin, but a white translucent one alludes me. Hmmm.

At this point I decided to go in to the local Barnes (a store that specialised in casting and other craft stuff) and had a chat with the staff. Apparently white translucent is really hard. The lady I spoke to thought that I might be able to get the effect I want by using a really small amount of pigment. Like, really small (she says that fully opaque happens at about 2%).

I buy a starter pack which has the 500mL of pink silicon, 500mL of resin and a bunch of measuring cups, containers and stirrers. I also bought some modelling clay and some spray on wax as I needed to make a two part mold. Unfortunately, this stuff ain’t cheap – all up it cost me $150.

Next step: Make the master.

Installing IKEA Filur bins into a kitchen cupboard without drilling holes!

We have two IKEA FILUR bins that we use in our kitchen – one for waste and one for recycling. To stay out of the way, they live in the butler’s pantry. This is a little bit inconvenient though – moving scraps around inevitably means dirty floors.

The IKEA FILUR bins

My wife decided to do a spring clean, and managed to free up a cupboard with the intention of installing cupboard bins. Easy enough. We started looking around, and found them quite small – we’d become accustomed to the good size bins that we already had. Not only that, but new units seemed quite expensive. We weren’t going to spend a lot of money and end up with something worse.

So I decided to build some.

The cupboard have shelf support holes, as most modern kitchens do, so I set myself a constraint: No drilling holes into the existing cupboards. This would allow us to restore the shelves if the bin-in-a-cupboard thing didn’t work, or we decided to move them to another cupboard, or we decided to move house, or some other reason that forced us to remove them.

The first step was the make sure the bins would both physically fit in the cupboard – and they did. By placing them sideways (Which actually made a lot of sense in this case) they fit with just enough space around them. This also allowed us to test a MVP – would having the bins in the cupboard work for us? After a week, we didn’t hate it, so on to the next step.

Time to jump in to Fusion 360, and have a bit of a play around with a few ideas and some dimensions.

My first thought was to have attach some drawer runners to two rectangles of wood that ran around the inside of the cupboard, but this seemed overkill, and the dimensions were a little too tight to make it really work. Next, I wondered about 3D printing some brackets that would hold the drawer runners. I jumped on to the Bunnings web site to find some drawer runners, and I found some likely candidates for just $11. The problem was (as always) no accurate design drawings or dimensions.

But for $11 (and Bunnings’ generous returns policy), I was willing to take a punt.

The Drawer runners attached to the shelf

The next problem was how to attach the brackets to the walls of the cupboard. 3D printed plastic nubs probably wasn’t going to cut it – I could see them snapping off in the holes. Next, I thought about embedding some 5mm metal rod, or perhaps removing the plastic off the existing shelf supports. I then did a quick search on the Bunnings website and found these all metal shelf supports with metal lugs that would work perfectly (for a grand total off $2.67!). Off to Bunnings!

One sausage sizzle later, I had the bits I needed.

Now I had the dimensions of the drawer runners and the supports, I whipped up a quick design, and 2 hours later I had printed the first bracket to test for fit. Initially, I was going to rely on brass inserts and screws to secure the runners, but I added a small curve to add a some additional support. This worked out better than expected – the curves would happily hold the runners without the screws (although I still added two screws on the back off the runners to keep them in place when pulling out the bins). When it came to attaching the metal inserts, I thought of using heat like I did with the brass inserts, but it turned out a hammer and friction was enough to hold them in – and the platform that the bins would live in would actually push the runners out, holding the whole thing together.

So over the next 6 hours, I printed the remainder of the brackets.

Two of the printed bracket

Once the were done and installed, I could get final measurements for the shelf. This was where designing it in CAD helped – according to my calculations, it would need to be 420mm, and I was dead on. Initially, I was going to buy some melamine coated MDF, but then I decide to cut the existing shelf (which just so happened to be melamine coated MDF) to size.

Cutting the 500x550mm panel to 420x550mm was easy work, but the internal holes for the bins were a little more challenging as I couldn’t find my jigsaw. I used a multisaw, which in theory should be the same, but was ended up being slower and more difficult to use. As a result, the holes looked like it was cutout by a drunk monkey. Nothing a bit of rasping couldn’t fix. Besides – the bins will cover a multitude of sins. All in all, the result was good enough.

Fitted

It was at this point, I made a minor mistake in drilling the holes for the runners – they are offset from centre, and I drilled one side on the wrong side, but that was easy enough to fix, just by drilling them on the other side of the centre line.

Putting it together was slightly more challenging, as I needed to screw in the support screws whilst in-situ, and had to do a bit of a contortion act to get them in. But once it was in, it all worked really well. The shelf could have possibly done with 1mm extra cutout, so the run was a little smoother, but it’s totally fine as is.

The bins installed on the drawer

The other thing I would change it to make the non-door side thinner, so the there wasn’t such a massive gap between the cupboard wall and the runner – the gap on he door side is needed to give clearance from the hinges, and I went for symmetry, but it does look a little odd. It would have made the print time much less too. Oh well – next time!

So for a grand total of $13.67 (plus about $3 in plastic), 45 minutes off design time, and 8 hours of print time, our bins now live in a cupboard!

Download the design on Thingiverse.

A case and POE for the OrangePI

Technically, the OrangePI Zero supports a type of Power of Ethernet, but this makes it compliant.

..and uses a cheat – you can buy POE splitters off Aliexpress – this hack removes the Ethernet port off the OrangePI, and permanently attaches the splitter. I also 3D printed a case for it, which is the interesting part, as I experiment with post production.

I use an OrangePi as a server for my Flic bluetooth buttons. I use POE to power it, so I don’t need to bother with plug packs, however, it all looks a little untidy (why do Pi clone manufacturers always put the power plug on the front!?).

I’ve also been meaning to experiment with sanding and spray painting 3D prints, so I thought I’d kill two birds with one stone.

Adding the POE splitter to the OrangePi

  1. Desolder the Ethernet socket from the OrangePI. I used a desoldering needle.
  2. Desolder the ethernet and power cable from the POE splitter
  3. Use ethernet cable to join to the two Ethernet pads. Make sure you maintain the twists between pairs. I also soldered two pin headers into the support holes either side of the Ethernet sockets, to give some physical support.

Printing the Case

  1. You can download the models from Thingiverse
  2. No need for to print supports – 20% infill is fine. Once printed, you need to cut off the board support clips at the top of the pylons – they don’t work. Drill two 2.5mm holes in the two rear pylons.
  3. Insert brass inserts into the corner holes.

Painting

FDM 3D printing is quite streaky, and looks… well, like it was 3D printed. I print in PLA, so acetate vapor is out off the question, making good, old fashioned sanding and painting the easiest way to get it looking it good.

The first time I tried this I sanded the thing completely smooth, and it took ages. I found other people have had success using automotive primer/filler which fills smaller scratches.

I tried this, but the gaps were too big. I went aggressive, and started with 120grit wet-and-dry sand paper. I added another two coats of primer/filler. Next, I went to town with 400 grit, then 800 grit.

I wanted to see if I could paint a logo in the top, so I did an undercoat of satin silver, placed a sticker over it and then painted a top coat of satin grey.

It looked terrible.

  1. The sticker lifted, so the edges off the logo were blurry.
  2. Satin shows up ALL the gaps, so even after all the sanding, the lines were still visible
  3. I over painted, so there was drips, and it looked thick and gross
  4. The colour wasn’t… great.

I re-sanded with 400-grit to get rid of the paint, and polished again with 800-grit. This time I omitted the extra coat of primer/filler, and just applied two LIGHT coats of flat (matt) black paint. This time the result was great!

Matt paint actually fills gaps a little bit, so the result is much better. There are still some visible lines (in the right light), so clearly I need to sand more. Also – I missed some bits on the bottom section. Clearly I still need some practice.

I wouldn’t mind trying the satin finish again, with out being so heavy handed on the pain

Next