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 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 –
arduinoserial.write(chr(int(float(items[meta_vpos_index])*255)))
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[2]*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…
oh, 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.