So I’ve been thinking for a while, “wifi control of these lamps is all well and good, but I’d really rather push data over a serial connection so that I can avoid having to set up wifi networks. Also, serial just makes more sense for high throughput usecases, eg sending a continuous stream of updates”
“…Too bad WLED doesn’t have a serial API”
You know what they say about when you assume things? I don’t know why I never really looked it up, but I just figured that WLED didn’t have serial support. Turns out it actually supports multiple protocols, and as of 0.13.0 it can receive the same JSON commands via serial as it does via wifi.
So here’s a little video of a proof of concept I put together, to learn a couple of things. It’s my first time playing around with web serial – I lifted heavily from this Codelab to get things working.
Plastic backing piece – I used 2mm thick acrylic, cut to the size that I wanted the badge to be.
Brooch finding
Prepare your splash tag
You can screenshot your splashtag from Splatnet, but the resolution might not be high enough for a nice print. If have issues with the resolution, you can use the resources at https://leanny.github.io/splat3/collectibles.html to recreate the splash tag. The font files for the Splatoon 1 and Splatoon 2 fonts are handy for replicating the text.
After composing the splashtag, mirror the design.
Print it onto the clear film, and cut it out leaving a generous margin (at least 10mm) around the edges.
This design has been printed at 87.5mm wide by 25mm tall.
Assembly
Apply glue to the the side of the sheet that you printed the text on.
Now align the transparency with the plastic backing and press them together. Make sure to only handle the extra margin of the plastic film so that you avoid smearing the glue on the splash tag itself.
It’s done! You can now attach a finding to the back.
Oh boy, let me take you down the rabbit hole that keeps sneakily stealing hours of my life from me.
We’ll start with a topic I’ve covered a few times before:
Seals
I’ve written before about my mock sinograph signature – a pseudo Chinese-character sequence that I use to sign my artwork with.
I have also signed my work in the past with a signature stamp that I picked up at a dollar store in Japan, that simply contained the character of my surname.
In the intervening times, I’ve experimented with laser engraving seals of my sinograph, and modifying its design. I briefly hit on a design I absolutely adored that incorporated “Alethea” into the character 鴨 (duck), which when put together with my surname 林 would have correspondingly given me “forest duck” as my signature. This would allude to the name of the chenonetta jubata in Chinese, nicely tying all of my identities together.
Unfortunately, a Mandarin-speaking coworker cautioned me against using 鴨 as a pseudonym. They informed me that when referring to people, “duck” is sometimes used as a euphemism for a male prostitute. So with that knowledge, I decided to fall back to my made-up characters.
When I made the most recent revision to my signature, I decided to get it professionally carved into soapstone, and had the company confirm that I wasn’t going to run into any similar embarrassing misunderstandings with the design. The actual seal carving ended up being very expensive (considering I could have just laser engraved it myself), but I valued the peace of mind that came with having someone knowledgable vetting it. Experiencing how the seal design transferred so cleanly with good quality seal paste (the ink used to stamp the blocks with) also unlocked the next step in my journey.
QArt Codes
Some time ago, I read this blog post about embedding images into QR codes. As a tl;dr, QR codes are made to be tolerant to damage. Most QR codes that contain logos in them just cover the data contained in the code and take advantage of the error-correcting algorithm to ensure the right values are read out. “QArt Codes”, on the other hand, use a provided image to generate a URL that naturally encodes to something that resembles the source image.
I can’t remember what led me to the article initially, it was a looooong time ago. I may have been working on a puzzle hunt for AVCon that used QR codes to log people’s progress and I wanted to embed the AVCon Invader logo into it (so some time around 2014). But the puzzle hunt, and QR codes in Aus generally didn’t catch on so the idea just got relegated to the back of my mind.
Still, QArt codes are super neat and I’m surprised I haven’t seen them in the wild more. Actually, I think the page that generated the codes was down during the rise of QR codes in the pandemic, so there was a bit of a missed window. But the page is back now, and you can play with making your own! Or if you want to play with the code there’s a standalone version you can run locally.
(Side note, when I was researching game-parsing screen readers to work on Ikalog stuff, I ran into this blog post by Up Banking. That’s the only QArt code that I’ve recognised in the wild to date)
Adding 2+2…
This is the post that lit the lightbulb in my head.
I mean, having hit this point in my post it’s pretty obvious what we’re gonna do, right?
QArt Chopping and Changing
“So how did you lose hours of your life to this? There’s a page that generates them, you just put your picture in there and you’re done, right?”
Well, to start off with, as I mentioned above the page that generates them was actually not available for some time, so I had to mess around with the original QArt source code (with a few headaches) and then later had the fortune of running into the standalone version.
After that… I lost time to the search of perfection.
Here’s my first draft of a painterly QArt signature. The output of the QArt generator still had a lot of noise, so I used painterly brushstrokes to make the noise look more appealing. At this point I still only superficially appreciated the stuff in the article and while I knew about some areas that were more important to preserve than others I was mostly just drawing willy-nilly with the understanding that “QR codes can repair damaged data”.
It’s neat but it’s off-centre, it contains only my surname and it probably won’t scan properly when scaled down for overlaying on art.
I was satisfied for a while with the proof of concept, but later I started thinking about laser cutting myself a new signature chop anyway, as the soapstone one I’d purchased was too large to use on A4 and smaller art (the majority of my pieces!)
So I looked at the QR codes and realised that I should provide a source image that wouldn’t need to scale. I want to control the pixels of the code so I should provide a pixel art version of my signature.
This provides an okayish output – it’s a good basis on which to paint over parts to arrive at a more aesthetically pleasing version.
I did do some test runs with this kind of “corrected” design and to my delight they did scan when stamped.
However, I anticipate that the stamping process can be error prone and therefore it will be impossible to perfectly transfer the design. So I keep returning to these QArt codes to try to minimise the errors. First by lowering the amount of modifications that I make to the generated code…
Then, by changing the generation of the code itself.
One strategy was to reduce the area of the QR code that must be dedicated to my URL. I chose not to use a URL shortener. I intend to keep the chenonetta.com domain into the forseeable future but I can’t control what happens with any URL forwarding services.
I also opted to include the full http:// prefix in the URL. I did some playing around with readers and some automatically open pages if the URL starts with www. or ends with a .com but I didn’t want to rely on that behaviour. I kept the ale subdomain but that’s the least defensible decision and I might change my mind on it in the future.
So how to save space if I’m not shortening the input data? The original QArt coder uses byte encoding for the main part of the URL. This uses 8 bits per character. I modified the generator to create the URL in two parts – an alphanum encoded section for the main URL and then byte encoding just for the # that joins the URL and its throwaway anchor. Alphanumeric encoding uses 11 bits for every two characters. Overall I did still save a little space, even with the extra stuff needed to define the single-character byte encoded section.
I also played with manually specifying the masking strategy (the mask is a pattern that gets XOR’d over the generated QR code – read the original QArt code article for details).
After a lot of iterating, this is probably the closest I’ll get for now. I think this is technically still a damaged code but the areas that I drew through are part of the instructions about how to read the code, not the data. Like the data itself, there are some redundancies for the instructions so the codes still scan ok. Most of the time I’ve spent on these codes has been spent in the cleanup and tweaking stages – what can I get away with without introducing errors?
This is supposedly an error free code according this debugging website – though the scale of the source image definitely affects its assessment of whether the code is error free or not. The site also doesn’t recognise flipped QR codes (even though other readers seem to be fine with them)
Being forced to make compromises on the final outcome always keeps me coming back to tweak things again and again – can I change the orientation so that I don’t have to use a flipped code? Can I rebalance the density of noise around the main design so that it doesn’t distract from the centre as much? Can I smooth the curves in the image more? I’ll just keep searching and searching for the ideal version of this design…
To wrap up, here’s the current setup I use for transferring the print to paper. I’ve been experimenting with moving to block printing ink instead of seal paste, because the latter is oil based and takes days to dry. So far I haven’t had a high success rate with the new ink but I think I’m learning. Sometimes a dodgy print can be recovered with a little bit of hand editing, though it requires some deft brushwork!
It’s the festive blogging month of Blaugust, during which netizens all over challenge themselves to post regularly to their blogs.
I’ve actually posted more than once to my blog in the previous year so I’m actually ahead of the usual batting average that I have heading into Blaugust. Which is why I feel a little less pressured to output content for said challenge.
I’ve also had a lot less “WIP” stuff, or at least, WIP stuff that I’d want to document with more than just an image itself. It leads me to ask, what’s the purpose of this blog now? With Twitter being my primary outlet for just throwing out the little nascent ideas and WIPs, this blog’s purpose feels less meaningful.
Speaking of Twitter, I’ve been spreading out quite a bit on social media of late… I’ve revived my deviantArt account – my longest living portfolio of work. It’s not comprehensive, but when I look at it I think it has a lot of the main beats of what I’ve worked on over my internet-faring lifetime. I also hid the link to my “art” page on the main ale.chenonetta.com landing page, since it’s such old art, and not a great representation of what I do now.
I’ve started focusing on posting my finished pieces to http://twitter.com/chenonetta rather than my personal feed (which still gets the WIPs) in the last couple months, and a few days ago started posting to http://instagram.com/chenonetta. I don’t “get” Instagram but since August is also the month of the #AvianAugust challenge I figured I’d try and get involved with festivities there.
So! It’s Avian August. Last year I sort of cheated my way through Blaugust by posting all the birds here. But I’m not really sure that’s necessary this year. I’ll post them to my dA and insta accounts instead where they can pad out my portfolios and maybe expand my “social media cred,” or something along those lines. I will admit, I am looking for an audience at the moment, as I’ve just launched my latest online store. But I’m not trying too hard – for now I’ve resolved to selling the art stuff while it’s fun. It’s not going to be replacing my day job any time soon.
But… if you do want to monetarily support me in the extracurricular activities, I did also spin up a Patreon! I’ll credit the Patreon with actually making me do a couple blog posts this year (which were mirrored there and on this blog) but maybe I need to think about what direction to take that in, too.
Anyhow, that’s it for me for now. Please check out the #AvianAugust2022 tags on both Twitter and Instagram to support all the artists participating in the challenge. And good luck to all the brave Blaugustines !
Follow these steps to set up WLED colour changes as channel point rewards using Kruiz Control. These instructions are written specifically for my Squid Lamps but can be modified for use with any WLED project.
Example video of this setup in action:
EDIT updated 2022-12-21
Check out Riekelt’s project, KrakenCommand for an alternative setup!
Click the above link to generate a token. You’ll be prompted to authorize permissions as a Twitch account.
Do not share this token with anyone else! It has permissions to manage your channel redemptions, to send messages in chat as the Twitch account that you choose and to see the email associated with the account. (I dunno why email address is needed but Comfy.js won’t work without that permission)
Open settings/chat/oauth.txt and replace the “token” part of the file with the generated token. Remove any spaces.
Channel Name
In settings/twitch/user.txt set the name of the channel that you want to watch for channel point redemptions. (Usually, your channel)
Chat User (Optional – not currently used)
Set settings/chat/user.txt to a Twitch channel. Setting this would allow Kruiz Control to send messages on your behalf to that channel.
Replace the contents of triggers.txt with the following. Note that the OnChannelPoint triggers need to match the names of the rewards from the step above.
Replace the IP address on line 2 (http://192.168.0.113) with the IP of the lamp.
Your lamp needs to be connected to the same network as your streaming PC.
OnInit
API Url SquidBeakon "http://192.168.0.113/json/state"
API Method SquidBeakon POST
API Header SquidBeakon "Content-Type" "application/json"
OnChannelPoint "Rainbow Lamp"
API RawData SquidBeakon "{\"seg\": [{\"of\": 4, \"fx\": 110, \"sx\": 128, \"ix\": 128, \"pal\": 11}]}"
API Send SquidBeakon
OnChannelPoint "Blue Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[0, 0, 255]]}]}"
API Send SquidBeakon
OnChannelPoint "Cyan Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[0, 255, 200]]}]}"
API Send SquidBeakon
OnChannelPoint "Green Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[8, 255, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Yellow Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 200, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Orange Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 160, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Red Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 0, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Magenta Lamp"
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 0, 255]]}]}"
API Send SquidBeakon
Once this is implemented, we can update the trigger code to refund channel points if the lamp failed to update, and clear items out of the queue if it’s successful.
Alternatively, we could write our own code using Comfy.js!
Add a new browser source. Select “Local File” and pick the index.html file from the Kruiz Control directory that you extracted in step 1. Keeping this browser source active will listen for Channel Point redemptions.
Select a reward in Twitch and if everything has been set up correctly, the lamp colours will change!
If you make any changes to the files inside the Kruiz Control directory, including the settings or triggers.txt files, you must refresh your browser source in OBS for the changes to take effect.
Appendix: A single reward with user-provided colour
If you don’t want to crowd your rewards with the lamp options, you can create one reward and allow it to control the lamp colours with the redemption message from your viewers.
Using a single reward also allows for the Twitch cooldowns to be used. This means that a viewer can’t override the colours set by another viewer until the cooldown ends.
Replace triggers.txt with the text from the code block below. Create a single reward named “Set Lamp Color” and turn on the “Require Viewer to Enter Text” checkbox.
This trigger will search the text of the message that was attached to the points redemption and if one of the color keywords is found then the lamp colour will change. It’s worth suggesting to the user what to enter in their message in the reward description, eg:
Set my squid lamp to rainbow, blue, cyan, green, yellow, orange, red or magenta by including one of these words in your message!
OnInit
API Url SquidBeakon "http://192.168.0.113/json/state"
API Method SquidBeakon POST
API Header SquidBeakon "Content-Type" "application/json"
OnChannelPoint "Set Lamp Color"
Param Lower message
Param Keyword message "rainbow"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"of\": 4, \"fx\": 110, \"sx\": 128, \"ix\": 128, \"pal\": 11}]}"
API Send SquidBeakon
Exit
Param Keyword message "blue"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[0, 0, 255]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "cyan"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[0, 255, 200]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "green"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[8, 255, 0]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "yellow"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 200, 0]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "orange"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 160, 0]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "red"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 0, 0]]}]}"
API Send SquidBeakon
Exit
Param Keyword message "magenta"
If 3 {matched} == true
API RawData SquidBeakon "{\"seg\": [{\"fx\": 0, \"col\": [[255, 0, 255]]}]}"
API Send SquidBeakon
Exit
Appendix: Customising Eye colours
Add the following trigger commands to triggers.txt. Make sure to create the corresponding rewards in the Twitch dashboard!
OnChannelPoint "Red Eyes"
API RawData SquidBeakon "{\"seg\": [{},{\"col\": [[255, 0, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "Lime Eyes"
API RawData SquidBeakon "{\"seg\": [{},{\"col\": [[255, 255, 0]]}]}"
API Send SquidBeakon
OnChannelPoint "White Eyes"
API RawData SquidBeakon "{\"seg\": [{},{\"col\": [[255, 255, 255]]}]}"
API Send SquidBeakon
Appendix: Multiple Lamps
This sample sets up SquidBeakon1 and SquidBeakon2 with their own URLs so that they can be driven by separate rewards. Full support for multiple channel point settings is left as an exercise for the reader.
OnInit
API Url SquidBeakon1 "http://192.168.0.113/json/state"
API Method SquidBeakon1 POST
API Header SquidBeakon1 "Content-Type" "application/json"
API Url SquidBeakon2 "http://192.168.0.114/json/state"
API Method SquidBeakon2 POST
API Header SquidBeakon2 "Content-Type" "application/json"
OnChannelPoint "Rainbow Lamp 1"
API RawData SquidBeakon1 "{\"seg\": [{\"of\": 4, \"fx\": 110, \"sx\": 128, \"ix\": 128, \"pal\": 11}]}"
API Send SquidBeakon1
OnChannelPoint "Rainbow Lamp 2"
API RawData SquidBeakon2 "{\"seg\": [{\"of\": 4, \"fx\": 110, \"sx\": 128, \"ix\": 128, \"pal\": 11}]}"
API Send SquidBeakon2
Appendix: Tips for displaying your lamps on stream
The lamps are emitting light, which can be difficult to capture on camera. Some tips to improve the appearance of the lights:
Reflected surfaces
Nearby white or other reflective surfaces will convey the colours of the light
Ambient lighting
The lights will be washed out by bright ambient lighting. The frequencies of sunlight can be especially effective at washing out the lamp colours. Indoor lighting or a dimmed room are best!
Diffusion
A piece of printer paper or baking paper in front of the lights can be used to diffuse the colours. This file contains templates for paper cutouts that can be placed in or on the lamp.
WLED JSON API
The commands in this document send JSON data via the WLED JSON API.
You’ll notice that these instructions are very sparse on images. At this time I have only completed the text of the guide. Even though the images will be necessary to make sense of these instructions I am providing them now as an incentive for me to return to finish this guide at a later date.
This is a guide to making a USB powered squid lamp, similar to but not exactly like the one pictured below.
If you would like to commission a fully assembled lamp, please email me at ale@chenonetta.com. Current pricing is $150AUD per lamp before shipping.
Components
I have included some basic price guides including shipping fees, but you can likely source some parts for cheaper! Prices are in AUD. Some of the links are affiliate links – using these to order your parts helps support me!
Used to illuminate the eyes. 1 metre will supply almost 4 lamps.
You could cut individual LEDs from the 100IP30 strip and space them out instead of buying this separate strip type. Filling the entire eye space with a 100IP30 segment is overkill so I use this more sparse strip as a convenience.
Heatshrink to fit over the LED strips (approx 10-12mm diameter)
Glue that can bond plastic to plastic.
I usually use SciGrip Weld-On 3, a water-consistency solvent that bonds very quickly, and SciGrip Weld-On 16 which is more viscous. Super glues will probably work fine.
Equipment
You will need access to the following specialised equipment. If you don’t own these yourself look out for your local Makerspace or tool library!
Laser engraving machine
Oven and/or heat gun
You could use your home oven but I prefer to use a dedicated crafting oven.
Soldering Iron
Assembly Instructions
Step 1: Cut the acrylic
Peel the protective paper from the back sides of the black and frosted acrylic. Leave the paper on the side that faces upwards while in your laser cutter. The paper will provide protection for the parts while we work on assembly.
Frosted parts file: DXF / SVG (Dimensions: 434×219.9mm)
Black parts file: DXF / SVG (Dimensions: 367.58×201.26 mm)
In these files red lines should be cut, blue and green should be vector engraved (ie, cut but with less power).
Blue lines should be a kiss cut allowing for the front protective paper to be peeled off. The green line should be a slightly deeper cut to assist bending of the tentacles.
Step 2: Glue the face plates
Peel the areas of the frosted pieces that correspond to black parts.
You should now be able to align the black pieces with the exposed frosted sections and glue them in place.
I apply the Weld-On 3 by dipping an old paintbrush into the glue. I then touch the wet paintbrush to where the two pieces of acrylic meet and the glue is drawn into place via capillary action. This creates a strong bond within a minute.
⚠️ Wear appropriate PPE when working with solvent glues. Nitrile gloves, safety goggles and a respirator are recommended.
Step 3: Bend the side walls
Preheat your oven to 160°C
Peel the protective paper off the rectangular pieces of frosted acrylic. If left on, these pieces would leave sticky residue on the parts as we bend them.
I recommend working on one piece at a time. Place each piece in the oven and let it sit for about 5 minutes. It should be floppy when you pull it out. If the piece forms bubbles it has sat in the oven for too long.
Form the pieces into shape using the black outline of the face plate as a guide. You’ll be using the long piece to form the top head of the squid, the two identical pieces to make the left and right tentacles and the shorter piece with the groove in the middle of it to form the middle tentacles.
If you cannot fit the full length of the piece into the oven at once you can first bend it by heating it with a heat gun or by placing the piece in the oven with the door open so that half of the sheet can be bent.
If you don’t have an oven that you feel comfortable placing your acrylic into you can heat your pieces using a heat gun. You’ll need to work slowly, bending in sections rather than forming the full shape in one go.
⚠️ Wear heat proof gloves when handling the hot acrylic!
It can be difficult to bend the sheets correctly. I have included some files for jigs that can be cut from 3mm MDF.
To use the two-part jigs, rest the hot piece of acrylic against the bottom piece, then press the top piece into it to create the indentations.
The large jig is designed for the long piece of acrylic to be wrapped around it. Hold the ends in place so that they cool without expanding outwards again.
To speed up cooling of the piece, you can wave the pieces in the air so that cool air passes over them quickly, or blow cool air across them.
Step 4: Cut the socket hole
This guide assumes that you’ll wind the USB cable through a hole in the side of the lamp.
There are alternatives (my current lamp design provides a micro USB socket on the outside) but they’re complicated enough that I won’t go into them in this document.
Options:
Drill/cut a large hole in the side big enough for the whole micro USB cable to fit through
Cut an approx 5mm diameter hole then bisect the piece through the hole
The option you pick will depend on which aesthetic tradeoff you prefer. For 1, the large hole will cause the insides of the lamp to be seen from some angles. 2 will have a visible line across the wall where the piece was split into separate parts.
Step 5: Glue the sides
One of the face plates has a slot in its tentacle. Place it face down (with the black acrylic on the bottom, and the frosted on top).
Glue the walls of the lamp to the edges of this piece.
If you cut the side tentacle in half in the previous step, then remember to feed the USB cable through the hole before gluing the walls in place!
Step 6: Make the eye sheath
The eye sheath holds the two plates of the lamp together without any glue! It also holds the LED strips, allowing for beautiful illumination of the edges of the lamp.
Cut a length of 1mm boxboard to 38x265mm. I recommend cutting the long side against the grain – you want to be able to easily bend the long loop. This video explains how to find the grain of your sheet.
Mark two parallel lines 14mm away from the long edge. This marks a 10mm gap in the middle to align your LED strips to. Flip over the piece and mark lines on the opposite side, too.
Line both long edges of the piece with masking tape. The tape protects the edge of the cardboard and provides friction when inserted into the squid’s face plates.
Bend the cardboard in half, then slowly curl the cardboard in the opposite direction of this bend. You are aiming to make the shape of the eye mask of the squid.
It can help to slot the piece into one of the face plates as you work. There should be about a 3mm gap between the ends of the cardboard.
Join the loop with a piece of masking tape on the top and bottom, leaving a gap to allow the LED strip to pass through.
Step 7: Make the LED strip
When working with addressable LEDs, take note of the arrows denoting the direction of the data line.
Start of strip ➡️➡️➡️➡️ End of strip
Cut a length of 100IP30 strip to 26 LEDs long (26cm) – this piece will be called Segment A from now on
Cut a length of 30IP30 strip to 8 LEDs long (approx 26.6cm) – this piece will be called Segment B
Cut a piece of heatshrink, 1-2cm long
Slide the heatshrink over the start of Segment B, and push it clear of the solder pads. Align Segment A and Segment B, making sure to double check the direction of the data line and that the correct terminals are in contact.
The 5V, data and G pads of each segment should meet their corresponding pads on the other segment.
The arrows should face in the same direction, with Segment A leading INTO Segment B.
After joining the strips, pull the heatshrink over the join and shrink it there, providing protection for the connection you just made.
Solder power, data and ground wires to the start of Segment A. These should be about 7cm long.
Once happy with your wire joins, you can shrink a 1cm piece of heatshrink over them for protection.
Step 8: Attach the LED strip to the eye sheath
Crease Segment A after the 13th LED by facing the LEDs towards another and pinching the cut line.
Peel the backing off of Segment A and nestle the crease that you just made in the halfway fold of the eye sheath, lining up the strip with the guide lines you drew on earlier. Now stick down the sides of this segment, taking care to stay between the lines as you wrap the strip around the cardboard.
Feed the end of Segment B into the gap in the eye sheath and bend the heatshrink-covered area back over itself. You can now remove the adhesive from the back of Segment B and affix the strip to the inner face of the eye sheath.
Step 9: Prepare the controller
Connect the Wemos D1 mini into your computer using a micro USB cable. Install WLED to the controller at http://install.wled.me/
Desolder the LED on the board – otherwise the blue light may interfere with the appearance of your coloured LEDs.
Desolder the Reset button (optional – depending on how you orient the controller it may be more likely to bump the reset button accidentally).
Solder your wires from the LED strip to the adjacent 5V, G and D4 terminals. Take care to connect the correct leads to the right terminals! The LED strip has the 5V and G lines on opposite sides, while the Wemos has 5V and G next to one another.
If everything has been done correctly – plugging the D1 into power will light up 30 of the LEDs on the strip in an orange colour.
Step 10: WLED settings
Connect to the WLED Access point. Default SSID WLED-AP, password wled1234
If you have a favourite preset, you can specify it as the startup pattern on the http://4.3.2.1/settings/leds page.
If you’ve connected WLED to your home network, replace the 4.3.2.1 with the IP of the lamp. You can find the IP address by checking the list of devices on your router, or by installing the iOS or Android WLED apps and searching for devices.
Step 11: Enclose the lamp
Slide the Wemos controller into the slot in the frosted acrylic. This slot provides a snug home for it to stay in the lamp and hides a lot of the shadow that would be cast by the controller.
Check that the cardboard eye sheath is smoothly bent and slot it into the body of the squid (the face plate that you’ve attached the walls to).
The other face plate can now be fitted over the eye sheath. You may need to jiggle it somewhat for it to fit snugly. Be patient and feel for how the cardboard fits into its slot. Once it’s in place the black border of the face plate will be flush with the walls.
Optional: Before attaching the face plate, line the walls of the squid with double-sided sticky tape. This provides some additional adhesion to hold your lamp together while still providing the option to reopen the lamp in the future if you need to do maintenance.
Now that lamp is fully assembled you can remove all of the protective paper! It’s done!
Closing Notes
There are a few differences between the lamp in this guide and the lamps I am currently making. Incorporating the below changes are left as an exercise for the reader
The power port. My v4 lamp includes a micro USB socket on the side, instead of threading the cable through the side of the lamp. I also take the 5V power from this socket instead of from the 5V pin on the Wemos D1 Mini, allowing me to set a higher current limit in the WLED settings.
This guide advises permanent solder connections instead of temporary connectors. I’ve used connectors like the JST XH2.54 (Dupont connectors would also work) to allow me to swap various parts in and out – this can be good for making and testing many lamps at once or for replacing a single module of the lamp if it is damaged.
At the time, I was running Splatoon LAN events and I thought to myself…
What if… I made squid-shaped lights to match the player icons that appear at the top of the screen during gameplay?
What if… I also combined it with the uptime tracking code in Ikalog to dynamically change the status of each light based on whether a player was active or splatted?
Then at a LAN, we could have a light stationed in front of each player to emphasise what was happening to them throughout the game!
Then I did nothing with the idea. Every few months I’d longingly watch DIY RGB panel videos on YouTube before getting stuck on deciding how ambitious to make the build and then moving onto something else.
Motivation
When Splatoon 2 came out it set the idea back a bit. Ikalog didn’t receive any updates beyond the Splatoon 2 testfire. In particular, the code to track player uptime in Splatoon 2 needed some creative problem solving; the icons change size based on the game state, making it harder to get a lock on them to determine their correct state. In September last year I did get a version of the tracking working. (I might write a separate blog post about some of this?)
Somewhere in my brain, the Splatoon RGB Light project itched, but it wasn’t strong enough to pull me away from the other projects I was tinkering with at the time. I wasn’t going to be at any LANs for the foreseeable future, so was there any point?
Then, a year later, my dad was working on some lamps of his own – beautiful, intricate wood-carved pieces. I took the opportunity to throw together a nightlight to use with his LEDs.
I literally did the designs for the nightlight on the bus, and had it cut and assembled within an hour of getting home.
It was so simple and effective that I got thinking again about the Splatoon light panels. Even if I didn’t get the gameplay integration working, they were going to look cool on their own!
Lamp Design
Before making 8 (or 16, to include Octolings) light panels, I thought I’d start by making a single freestanding lamp, to test the light transmission and generally get a feel for the components involved.
What is a light box made up of? It’s simply a light source with a diffuser. A little distance between the light source and the diffusing material allows the light to have an even glow.
My original mockups for the lamp was a double-shelled container. The RGB light strip would run around the inner perimeter and then pass into another light-blocked area for the eyes, and the space between the two shells would provide room for electronics to be hidden. I ordered a 1m length of WS2812 lights as the light source.
While I have a laser cutter that allows me to cut pieces to accurate size, this design required curved shapes. I contacted 3D Prototypes And Models and Dan quoted >$100 for the printing. The large perimeters being printed up to 5cm tall resulted in an estimated 14 hour print job.
“Ok,” I thought, “I’ll drop the walls to 4cm. I’m willing to pay for one print, maybe I’ll just make the one lamp and end the project there.”
But then I started mocking up how the lamp would look and it felt… too small. I scaled up the design as far as I could to use the full meter of the LED strip. Well now it’s gonna cost even more to 3D print the shell and might be too large for the 3D printers available (not really, but I was starting to look for an excuse to not spend the money on 3D printing when the end goal was to make a number of these things).
Plus, Dan advised that the honeycomb structure of the 3D print would likely show through any illumination from inside the lamp. It was time to tackle things differently…
Acrylic Bending
I have been wanting to experiment with acrylic bending for a while, but the right opportunity hadn’t presented itself. I hadn’t seriously considered it for this project because it seemed too cumbersome to try to accurately bend the pieces. But then I found this video, where the side walls of acrylic lettering was hand-shaped using a heat gun, and I realised this was pretty similar to what I would be trying to achieve.
I asked to borrow my mum’s heat gun, but while waiting for her to dig it up I also had thoughts about making a DIY acrylic bender, or maybe heating up the acrylic in an oven.
Side Story: Toaster Oven
I had a toaster oven that I’d bought second hand to bake polymer clays in (I bought the oven from an older lady named Alethia who did a double take when I responded to her Gumtree post). But after just a few projects the oven had gone unused. So after many years, when I decided I wanted to use it to bend acrylic, I plugged it in and… it tripped the safety breakers in our house.
Tried again, tripped again.
Ok so the toaster oven is bust. Or is it?
I Googled and… there was the suggestion that maybe moisture had built up in the ceramic heating elements, and this was leading to ground leakage. Suggestions to dry them out? Use a hot air gun (still didn’t have mum’s on hand yet) or run it without RCD protection so that it would self-heat and dry.
I looked at the “No RCD” switch under my stove and decided – yeah nah, I better have someone with a little more expertise take a look. After all, did I really want to trust Dr Google with this diagnosis?
So I ended up at the Adelaide Repair Cafe, hosted by Makerspace Adelaide. The lovely folks there helped me to disassemble the toaster oven, to validate that ground leakage was indeed the problem, and to check for any internal corrosion or damage.
One of them did suggest the moisture issue with the elements – based on his own experience of working in physics labs where the equipment would regularly have these issues after going unused for periods of time. So we ran the toaster oven without ground protection and after about 15 minutes it was good to go.
Repair Cafes are great. A fantastic free service to breathe new life into things to save them from landfill – I was so delighted I volunteered to help at their future monthly events.
With that little Sunday afternoon adventure done, it was time to create the full squid assembly!
Structure
By now I’d been able to experiment with the RGB strip and the front and back plates of the lamp.
The plates are made from frosted and black acrylic. The black outline has been modified slightly from the original Squid design to allow for the lamp to rest on the tentacles without tipping to the side.
When cutting the frosted acrylic, I kiss-cut the outlines of where the black would be glued, so that I could find the right positions to place them. By weeding out only the areas where the black will be glued, it also reduces the risk of the frosted acrylic being damaged or marked during gluing and other construction steps.
By cutting the eye shape out of the middle of the frosted sheet it leaves a gap that can snugly hold a piece of cardboard. This cardboard serves a few different roles. Firstly, it is the mount point for the white LEDs that will illuminate the eye area. It also blocks the light that white light from blending into the rest of the lamp, and vice versa – keeping the coloured lights from bleeding into the eye area.
Because the cardboard is a tight fit, the two two faceplates can be held together by the cardboard only – and without any of the outer frame being added. Even in the final version of the lamp, I leave one faceplate unglued for easy future opening of the lamp.
This first mock-up of the barrier around the eyes is a bit messy, but for the final version I bent the cardboard along the grain so the curves came out nicer. The edges are also covered in tape to help with fitting into the gap in the frosted acrylic.
After recording the above video, I decided that I could also put the coloured lights on outside surface of the cardboard wall. This meant that I no longer needed the shell to hold the light strip, and with the light being directed outwards… why not allow it to also shine through the outer walls?
So my plan of bending 2mm black acrylic – which would be both easier to bend because of its thickness and (maybe) also because its colour would more easily absorb the heat – became a plan to bend 2mm white acrylic. But that didn’t transmit the light to my satisfaction.
The 3mm frosted (same as the front and back panels) became the goal. I decided to bend the acrylic in 4 segments, to avoid sharp corners. One for the ^ of the squid head, one for each of the sides, and a single curved piece on the base of the lamp, avoiding the pointedness of the individual tentacles.
Forming the Plastic
I made jigs to help form the heated acrylic. My first attempts to bend the acrylic over a jig didn’t work out well because the my gloved hands had trouble guiding the acrylic into the right position. So I added walls to the jig to hold the acrylic. I also added a guide to align the top piece into the bottom piece when pressing the halves together.
For the smaller pieces, I placed the bottom piece in the oven together with the acrylic piece to heat together. Annoyingly, this would affect the fit of my MDF pieces – the MDF would change shape in the heat and the joins would go loose. But other than this, the jigs were pretty effective – provided the acrylic was able to get soft enough. (“Soft enough” seemed to roughly correspond with “when the assembly appears to be smoking” but I need to find a better metric because fire and noxious fumes = bad).
The large piece over the squid head was a pain because it was too large to fit in the oven. I heated it from the ends with the oven door open and slowly it was able to bend enough for me to fit the whole thing in. A light etch in the middle of the piece allowed me to align it correctly with the jig.
The pieces aren’t bent perfectly, but they’re good enough. I glued them to one of the faceplates and the basic lamp is done!
Circuitry & Software
My LED controller software is wled – run on a Wemos D1 Mini, an ESP8266 board.
wled’s built-in colour palettes and effects are perfect for this use case, and it has a JSON API that I can use push updates from IkaLog if I ever get that integration going.
I chose a 5V LED light strip so that I could run the D1 on the same power source. The lights use 18W per meter and the plan was to use 1m per squid so I sourced a 5V 4A power supply. I didn’t use any logic shifter or resistor in my circuit… probably should, though.
I forgot the data line on the LED strip is directional when I did my first cut-up-and-resolder – which I could have gotten away with without realising if I’d happened to get it right.
The socket fitting was mounted low and centrally, so that the wires coming off it would not be visible through the frosted acrylic. The hole for the socket was cut after the acrylic was bent, and I cut a clear “washer” to affix it to. The end result is a socket that sits nice and flush with the wall!
Unfortunately, in the process of doing the final wiring and soldering… this happened.
Can you tell what the problem is? When trying to buy a bit more space to move the parts around, I unfastened this nut. Then once everything was reassembled I forgot to screw it back, and with the power plugged in the nut created a short circuit.
I fried most of my LEDs from this mishap. I salvaged a few unused ones and hey the lamp still looks… ok with partial lighting, but that’s the reason why the photos at the top of this post have a dark patch across one side.
In The Next Episode…
Thoughts for future builds:
Maybe I don’t need that extra loop of LEDs for extra brightness, it actually looks passable with only 12 LEDs (apart from the missing corner). Plus the original idea behind using three loops was so that I could provide data from either end – but that’s moot when the data line is directional.
I need to find a way to make the wire connections without needing to permanently solder things down. Manoeuvring in limited space when everything is stuck together is a pain. Even when we took apart the toaster oven, those connectors had slide on terminals… maybe I need to do the same. So spade connectors, LED strip coupling and header pins on the D1…?
To do the full 4v4 team light panel build, I think I’ll move to a 12V LED strip so that I can chain multiple panels off the same power supply. Using 12V LED strips will require extra components to step down the 12V that will power the LEDs to 5V for the the D1, as well as a logic shifter to convert the 3.3V data line to 5V (I’m getting away without a logic shifter for the 5V LED strip but it sounds like one will be needed for a 12V strip.)
Oh gosh if I do want to get that game integration working I should probably work on that code now before any Splatoon 3 footage appears and affects my motivation again…