TEKTŌN is an on-going collaboration between Mike Faulkner and Paul Mumford. A series of virtual machines are driven parametrically to make light patterns in space.
TEKTŌN ONE THREE's mechanism is two horizontal bars of light points that animate up and down. At time of writing, this mechanism is modelled and animated in Touch Designer by Paul, realised on-screen in an audio-visual recording Paul made, and realised in physical space... with what you see here, by me, Toby Harris.
This physical machine was developed to be a centrepiece of the D-Fuse gallery show "Pattern & Noise" at Wood St. Galleries, Pittsburgh, USA. This meant we – D-Fuse, our artist collective – had a budget to work from, but also a hard deadline to ship to.
Tekton One Three - Touch Designer Simulation from Labmeta on Vimeo.
Initial discussions of models, lightweight structures and hacking filming equipment fell to the wayside as desire for the aesthetics of industrial machines aligned with the forces of filling the large gallery space and running reliably for three months. The brief that formed was for a machine that could move two LED filled bars ~1.5m long vertically for a 2m run, to paint light in space without any structure visually interfering with that image. We knew dynamic constraints of a physical machine couldn't get us to where the screen based simulation was, but we wanted to get as close as we sanely could.
The project was well-timed to take advantage of the new APA102 individually addressable LEDs, 'dotstar' as sold by Adafruit. Unlike previous WS2812 'neopixels', they can be driven by a Raspberry Pi, and driven fast. Using a Raspberry Pi was interesting as amongst other things having a full wifi stack and linux software for, say OSC could mean easy sync between multiple controllers and realtime control from Touch Designer.
Mechanically, research led to either buying a pre-made linear slide or assembling one ourselves from a system of parts. Assembly ourselves also implying disassembly for transport, we opted for the latter knowing that shipping was going to be a much easier problem if we could break down the machine into standard, smaller packages. There was also the benefit of no lead time, as they're parts taken from stock rather than requiring a factory to make the slide to length.
There are countless Aluminium profile systems but only the MB Building Kit for Mechanical Engineering from Item had the range of niche accessory parts to solve whatever need I had while spec'ing up options for the machine. And they had a US operation, too. The option that won had 3-4m long floor-ceiling bars that we would buy locally rather than ship, with a 2.3m bar we would mount slide rails on, and a 1.6m bar to cantilever out with LEDs. The mechanical fittings for the belt drive we could remove for transport, giving quite an efficient pack: two tubes and a flight case or two.
Item don't supply motors but Zapp Automation – who we almost bought LEZ slides from – had the full range of keenly priced Leadshine Easy-Servo motors in-stock which seemed a good bet, particularly in having a driver unit qualified for the motors that would isolate any controller I made from the realities of motors, mechanics, and what would happen if something went wrong there.
The design process was mostly scribbles and an ever-growing spreadsheet, but it did at some point need an accurate drawing as sanity check for dimensions. And so, the above.
The mechanics arrives. Seeing the boxes is quite a moment, but also reassuring: we can ship this to America. Life never being as simple as it could be, this was a day I had to look after my 15 month old daughter, and so childcare had to be within 100m of the makerspace, which itself was still a building site, abound with danger.
It's big! That's quite a cantilever. Eeeeek.
I spent a long time figuring out what was best to run the LED bar up and down. Roller wheels on a solid bar came out best, as roller wheels are fast and being at the corners good for torque, and if what they're running on is incompressible then the carriage should hold square. After asking some specific questions about the various Item linear bearing parts to their staff, got a duff answer and what came out the box had ball bearing races. This part was chosen as being aesthetically the neatest, so there's still good in having them, but there's more friction than I'd like, and ball races have turned out to be fragile. If there was to be a Tekton One Three mkII, this is something I'd change.
A real win for reading datasheets and being picky: what a beautiful fit. These LEDs could just have been taped to a bar, but higher standards for this.
Preparing the slide bar #1: preparing for the end fixings. I should have got these factory modified. This involved a bike race across all of south London's hills to get a 20mm drill bit before the shop shut. But: machining! It starts!
Preparing the slide bar #2: pressing in the slide rails. While everything looks better with *spark packing tape – of course – this was holding wood pieces to not damage the metal. Holding the end there is @stefanoromano, who was in the space and stayed to help. This was the first of many sessions with his help; grazie mille and then some.
Verifying the modifications required for the carriage to fit the baton, the belt bar, and the controller. 11 holes from M3 to M6, some with recessed heads, some tapped.
Boom! Aesthetically it's a shame the carriage plate comes with four existing holes, but at least the two under black bar will shortly have end-stop posts in them.
This work was also done on the same day as Makerspace had it's official opening. The effect was a little like a zoo exhibit: "look at that maker making things in the back of a makerspace, how exotic"
PCBs came back from http://hackvana.com – highly recommended, run by somebody who cares – and it's time to turn a PCB, a bag of parts, and a Raspberry Pi into the machine's controller. Lurking in this task is a 0.7mm pitch FFC to solder down, and this being a new thing to me this photo is taken on the bench of ninja friend Arron Smith.
Controller assembled and in-situ. Also see in the back: the low-density LED strips are fitted. 'Dotstar' 60/m LED is ordered by the meter but comes in reels of up to 5m. We needed 2x 1.5m, so went to cut in two but instead found solder joints of 0.5m strips. Desoldered and separated, wired on my own power and data lines, and pulled through the bar, into place. An action liberally aided by silicone lubricant. Lots of silicone lubricant. The gotcha here is that the rubber sheath stretches as you pull the assembly through, so woe betide you if you need to adjust afterwards or pull out again (which, this being both prototype and first assembly, you'll end up doing a few times).
Lights! Made up the 3m ribbon cable from PSU to controller, extended Adafruit's strandtest.py. It's alive!
...but, this is only the rear LEDs. The high-density (144/m) LED strips on the front have caused trouble. 144/m strips can only be bought in 1m lengths, already made up with connectors. Cue an afternoon spent removing all the end-caps, then the sillicone that sealed them on and is gumming up where the wires are soldered on. Then cue a night trying to solder these strips together and them test good afterwards. To remedy this took a trip back to ninja friend Arron Smith, for whom it wasn't straightforward either. Suffice to say I went shopping the next day and bought his lovely – poisonous – solder (Multicore 3096095-M and 3096525-M)
Yet more wiring up the LED baton, now with high-density LEDs. Did I say this is fiddly and time consuming. It is. Very. And I balked at the price of the crimp for the connectors I chose, something I now regret for time and quality reasons.
To this point, everything has been to plan and as per researched data sheets. The motors do not prove that way, in any way. Mechanically mating them to the pulley end-unit proves to be fraught with issues; likewise for their control.
The particular motor chosen has a shaft that matches the diameter of the bore in the pulley, this I had checked. What I had overlooked, is that unique to this particular motor in the range, the shaft length is much less than the others. So short, that engaging into the pulley is an issue. This requires making a motor mating plate as thin as possible, and some horrible work arounds with offset grub screws, taps and holes where they shouldn't be, and access holes where they shouldn't be to be able to tighten the result up. Eventually it was done, but it was a bruising night.
Having got a mechanical fit of motor to frame and pulley, then onto control. A quick implementation in the python script running the controller, and the vertical position is being read from the text file and translated into stepper pulses to sync the mechanical position. Code
So... it's alive! It works....
...but actually it doesn't. The control isn't giving smooth operation. It hurts just thinking about the jittery movement and how the cantilevered LED bar amplifies that.
Time to break out the logic probe to examine the control signals – thanks again to Arron. The result is not good. Stripping the control script down to create a constant turn, the pulses would often be regular as expected:
But then scroll along in time and suddenly there's patches like this:
No wonder the motor doesn't have smooth motion, with the shuddering action making horrible noises and vibrations through the structure. Realisation one is that it's not possible to get the timing precision to get near the pulse frequency to drive the motor at a decent speed, and realisation two is that the timing accuracy is just not there. Running this machine from a python script on a Raspberry Pi with it's stock linux installation was an experiment, and this is where "let's try the future" fell down. Simply, it's not a realtime environment. However, a bare bones sketch on an Arduino, flipping a digital out between delayMicroseconds() of 5 and up did work beautifully. Somehow a middle-ground had to be reached.
The first stage of that was to simulate the 60fps commands of the driving animation while being a stand-alone program. A sin calculation also takes ~120µs on an Arduino, considerably longer than the minimum pulse time of around 5-10µs. The beautiful step signal above is the output of calculating sin(time) every 1/60s, and for every loop in-between, calculating a linear interpolation between the last two sin points, comparing that with the current position, and issuing a step and/or direction change if needed.
Arduino loops to the microsecond to give smooth motion weren't the only performance-critical bit of code required. The animation sequence wasn't playing far too slowly - nowhere near the 60fps the animations were authored for, and now we can see it moving, it was clear it needed to be that fast and smooth to play with your perception as you looked on. Updating the OLED display and addressing the LED pixels was taking too long. I knew you could drive this kind of OLED crazy-fast as I'd written my own library from scratch for the mixer hardware, and I knew there was a lower-level way of driving the LED strips. So: abandoned updating the OLED for the time being, and advanced the controller python code to construct a bytearray per strip rather than set each LED individually... and voila! Naked-eye illusion. Code. Tho', somewhat by definition, the above video doesn't quite capture that (tho' watch the LEDs as the bar accelerates up...).
What the above skips over is that if an Arduino is now going to sit by the stepper and drive it, the main Raspberry Pi controller now needs to control the Arduino, not the stepper drive's pulse pins. And so, perhaps inevitably, the custom board I made to extend the Pi gets a hack to disconnect two direct control lines and rewire them to the Pi's hardware serial pins. At least the PCB design was good, it's just that the spec changed!
To get this working, the Arduino just interpreted the last byte received as a 0-255 value and scaled this up to the step range, around 20,000. That was pretty coarse and certainly less than the precision of the float value supplied in the animation sequence, and so while the machine was in transit I developed a protocol to pack an integer that could represent that kind of number into a series of bytes, keeping things as efficient as possible.
In python, on the controller: from a single byte, coarse and with no messaging capability –
Which the receiving Arduino handles like so...
To three bytes each with two bit command type and six bit payload –
#Command 01 = Sequence run vpos start
vpos_steps = int(meta*drive_max_steps
arduinoSerial.write(chr(0x40 + ((vpos_steps >> 12) & 0x3F)) + chr((vpos_steps >> 6) & 0x3F) + chr(vpos_steps & 0x3F))
Which the Arduino handles like so...
Aaaand did I mention there's two of everything? The model is actually two floor-ceiling bars each with the rails of slide bar, carriage running on them, and LED bar cantilevered from the carriage. Being way over schedule and needing to ship the model to the gallery in the US, here is the excellent David Meckin helping to wire up LED bar #2.
Last possible ship date is tomorrow, and here is one of the new motors... not the best timing, I'd admit. This would have happened at least a week earlier, but it was hard to verify the suitability of the motor while the motor control wasn't reliable. We seemed to be at the edge of the 3Nm's ability: it could do that sinusoidal cycle video'd above, but that took a few iterations of settings and was slow and only travelling half the range. The 3Nm choice was made by calculation and looking at the torque curves, and reassured by having same shaft size as pulley it mates with... but this was out, an 8Nm was in.
And with a new motor, new mounting issues. Things are painful for a while. Here's the motor mating plate that never happened, as after various false starts guaranteed-good bested over-engineered and we used the Item 50Nm coupling and assembly, with some machining from Gary at Zapp Automation.
Nonetheless, the machine needs to ship to the gallery in the US, and so it's disassembled and packs down into two 2.5m long tubes and two peli cases. Pretty compact, and standard sizes for UPS / FedEx / etc.
Thanks to Trotec for the laser cutter at makerspace: that perfectly sized and zip-tie slotted clear piece of perspex replaces a bit of wood I had to hand as I first mounted the ribbon cable. See the rear shot below for it in-situ and semi-invisible.
Aside from the ongoing motor issues, the last thing to be done in London was upgrading the test Arduino used to drive the motors to two production units, complete with 12v boost circuitry to run the induction sensor used to detect the half-way point of the belt. Thanks to Artists & Engineers who made these white custom Arduinos available to us.