All posts tagged Teensy

Azimuth Video Installation

Azimuth is a video capture and playback installation with simple wireless controllers. It’s based on the Déjà View Master, modified for the art show “Being and Time.”

The basic layout is a webcam feeding into a Mac Mini running a Max/Jitter patch, controlled by three wireless Arduino-based devices, and displayed on two monitors: a Zenith television on a table, and a projector mounted under the table, projecting onto the floor.

azimuthshow2

The screen normally displays a frozen image of the empty room. As you turn the clock-like controller, you scrub back and forward through a constantly-recording half-hour video buffer. The frames flash on screen as long as you’re moving the hand, but it fades back to the frozen frame when movement stops.

To add an element of unpredictability, it sometimes scrubs through a pre-recorded video of walking to the venue, or operates normally but with the image sliding off the TV and onto the floor via the projector.

Jitter works by using a matrix of pixel information to manipulate video. In Azimuth, the video buffer is accomplished by recording sequentially-numbered Jitter binary files (each matrix file is one video frame) to a hard drive, and separately reading the matrix files back and displaying them. Once the maximum number of frames has been written, the counter resets and writes over the first frames, letting you record in a loop.

Here are the basic components of this operation, set to record one minute at 15 fps (900 frames), and read back and display other frames, chosen by the number box on the right.

maxbufferrecord

Grab this Max patch here

———-begin_max5_patcher———-
976.3oc0XFsbiaBEF9Z6mBFM8RWM.BPhdU5ywNcxfjHNxUVxKBuwa2Ye26Aj
sih2HY4Ta4zKhmHDF94iCmyu4GymEjVuS2Df9CzWPyl8i4yl4ax0vr8OOKXs
ZWVopw2sfpsqS0lfEsu5o5JaSw+ncuhPCw6aF5TQUo15+Jj8MVu0BMY+9Fc6
7ETTYCVfBRUUKCP+09dsQYydtnZ4iFclssiBXj4LRR7BDg4lDTRh6SJNDe76
Uj6kWc5pemE7pLZmTuNnczbkZsWEA+ooPUFbbtMP6Vs4QckJsz2Cr6U+b9b2
GKFKizu.53vnZ067KjfUE1vWJpxqeAsoT88TU1eid.ff1rAQtJD0iR.oChSF
U3wICHXRjCjDgbHdRuXddcY1Zk0TrCwPYOqLnDdDhkfuJ7BF8GaG8KhZrnPJ
iwEI.5hFDcB4GMVLqtr1zN0X2LfCShjThv8eXIi5la2b9AP8ZcSiZo9WXsQq
xQ+FYApMLZ77k1GeGMQI7Pojw4QvYatOjL48AZL98AJYJBFypWmVToQvh4YD
D2fvnvU6dB8vFUdNr3fmwHN72CPH0xkZSChdIbj0KGufnSB.PIDpv4.WkCln
LlLEmrS2Zs0UAWdhrgVvwhPIIFNEBKXh.NNFwYh1U5.mF6I145EgTuQWkCbp
dI5o5x7qRRpQUirKOXvltDS4.OjzA2+Y2wL6Y0ack9PR7EkKmeF2DG9y83P.
CvSHki4IuEXwrAcVP64DC6pRr9RPmUV2nu8IlEQghHHZBRfvfzJQ3DobApsP
We4kID9EmXtyxa01FawSEYJaAjp3CdlrOr4NTd6oFjA1QM1ITKdXpIt6T6+V
stIuRW2DccqzM7OIHdR7v1W.3KlBqFbVc6CB6PGJARkISjNOA7nA8Twuidp9
zXvuK5X7PlLJNlcVC9DJ4SnC+AX8WsgKMpz6Ek6jkLgExSDIdOq33ggr3+OP
9qq0VSMRHtJm1OqwuN9X5T1QvGlmxo3Dusd4xRcvEemPi01Vxwk6v194mI+1
4t1G+XFTBUCO4lx75y09agPS8VS1gEz9KjB8pxx0PU6pi0r+xq+VLD8XmdtH
OW6e+g3k7hFm3x6+RoFqbbWJwY0C8M84VJm3QimIRO3QnmSX3MUOjwvG7joG
uU+yJHeN6ISQhOaJhNNEMcQ07wsoMgg0zwDVymN8v+jsic5lw6qH1DpnSmqd
1ynSVkrwgno7f+XN1eRAu6es0OZs9ViQpMa9l1zreL8RA7Atp01sXg+whp1G
8VtBL5uUbn+scPY.idVvk2VSqoycIBvxILO+b9+Bn2hk4C
———–end_max5_patcher———–

There is more math involved in keeping track of the current frame and rolling back through zero.

The projection on the floor is black, but image appears where the camera picks up movement. The patch subtracts the 8-bit value of each pixel of the previous frame from the current frame: where the pixels are the same, the value will be zero. Where the value is different, it will light up. It’s like velociraptor vision.

azimuthscreen

The button controller swaps the output monitors, putting the frame differencing on the TV screen and the freeze frame on the floor via the projector. The frame differencing is quite popular: the kids love dancing in front of it. But it has a practical function too. Part of the Max patch adds up the value of all the cells in the frame to determine whether anyone is in the room. The more movement, the higher the total value. If the number stays below a set threshold for more than a few minutes, it will assume that the room is empty and update the freeze-frame.

The other control box has a knob, which switches between five channels. Some channels read back from other matrix “banks,” where the five-digit matrix file begins with a different number. The main video loop is 10000-17200 (add 10000 to the counter value, max of 7200 for 30 minutes at 15 fps), a busy time saved from the show’s opening is 20000-27200 (add 20000), a pre-recorded movie of riding the subway and walking to the venue is 50000-53400, and so on. Another channel adds vertical roll to the live video feed, like an old TV. All adjust the brightness and color in some way.

Any controller will take over whatever’s happening in screen, and the result of pressing the button or knob will time out and revert to the empty frame if left alone.

azimuthboxes1

The boxes are all handmade oak frames with laser-cut semi-transparent acrylic front and back, echoing the Zenith television.

The big box has a rotary encoder with a clock hand attached, so it can spin continuously in either direction. The encoder is connected to a Teensy 3.0 microcontroller which runs Arduino code. It sends one command repeatedly if turned clockwise, and another command if turned counterclockwise, via a serial connection with an XBee wifi radio and adapter.

It’s powered by a 2,500mAh lipo battery (the Teensy and XBee operate at 3.3v), and uses Sparkfun’s Wake on Shake as a power switch. This device is brilliant. It has a gyroscope, and turns on if there’s any movement. It then stays on as long as there is power going to the wake pin — this comes from one of the Teensy pins, which is programmed to stay on for 15 minutes after the last time the controller’s been used.

I used a breadboard with power rails removed to hold the Teensy and XBee, since it provides a flush, solid connection. Double-sided tape, industrial strength Velcro, and hot glue keep everything in place. The back panel is held on with machine screws.

boxAinside2

The smaller boxes are similar, but use an Adafruit Trinket for the logic. One has a 10k linear potentiometer, and the other uses an arcade button. Each has a panel-mount power switch on the bottom of the box.

boxBinside

The receiver uses a Teensy 3.1, which relays incoming serial messages from the XBee to the Mac Mini over USB. I’d normally send a serial connection directly into Max, but since this installation needs to run reliably without supervision, I set the Teensy to appear as a standard keyboard. Messages from the controllers are sent as keystrokes, and the Max patch responds accordingly. This also made programming easier, since I could emulate controller action with keystrokes.

The receiver is housed in a spare Raspberry Pi case with a hole cut in the top for the XBee. I also added a kill button to stop the patch from running and quit Max by sending another keystroke. The Mac Mini is set to launch the Azimuth patch on startup, so between that and the kill button, no keyboard or mouse is needed from day to day.

Arduino code for the controllers and receiver is here.

azimuthRcv

The Mac Mini connects to the Zenith TV via a series of adapters: mini display port to VGA, VGA to RCA, and RCA to RF (on channel 3). The projector is configured as the second monitor, with a direct HDMI connection. I don’t recommend working on a complex Max patch on a 640 x 480 screen.

All in all, the installation runs well. Video is stored on a solid state laptop hard drive in a USB 3 enclosure, and most of the video processing happens on the GPU using the Gen object (jit.gl.pix) in Jitter. Some people were tentative when using the controllers, but others dove in and had a good time.

LED Strip Clock

I just put together a clock with Adafruit’s 60-NeoPixel LED strip, running off a Teensy 3.0 microcontroller. The flexible 1-meter strip has 60 RGB lights, so different colors represent the second, minute, and hour — you can read it like a normal clock if it’s in a circle, but you can also leave it in a straight line or drape it over something for the Salvador Dalí look.

Version 1 of the clock code advances the second using the delay() command, and moves the minute every 60 seconds and hour every 60 minutes. It’s a good exercise in procedural logic, but loses time quickly.

Version 2 uses a crystal soldered directly onto a Teensy 3.0, which will keep time if you attach a watch battery. Look at the Teensy Time Library page for more info.

The LED clock lets you pick different color schemes, add faint dots every 5 or 15 minutes (or none), and turn on blinking hour “chimes.” Right now you need to set these options in the Arduino IDE and re-upload, but I’ll add the ability to change that with buttons or a knob at some point.

View or download the code here.

pixelclock1

I don’t have any pictures of the final clock in action — I gave it to my dad.

pixelclock2

[UPDATE 5/24/14]

I’ve discovered some design problems with this project. First, Adafruit recommends adding a capacitor between the – and + on the NeoPixel strip, and a 300 to 500 ohm resistor between the Teensy’s data pin and the NeoPixel data-in (at the NeoPixel end of the connection). This doesn’t affect the clock’s performance, but protects the NeoPixels from damage.

Second, I’ve gotten reports from someone who built this project that occasionally the second-hand LED stays on until the next time it passes by. I got a lot of glitches the first time I had v1 hooked up, but that got resolved when I used a different power supply. But the Teensy 3.0 uses 3.3V logic, and the NeoPixels are powered at 5V.

The Adafruit NeoPixel Überguide says that the data has to be at least 70% of the power or its message will get lost, and 3.3V / 5V is 66%. Close enough to work most of the time, but I’m guessing that the glitches occur when the signal doesn’t get through.

The best thing to do is add an I2C-safe Bi-directional Logic Level Converter to boost the 3.3V data to 5V. But if you’re using a Teensy 3.1 which has 5V tolerance on all digital pins (and presumably won’t get damaged by talking to a 5V device), then try this revised code for v2. I added redundancy to the erase and write message, to give it a better chance of getting through.

I’m checking to make sure that, glitches aside, nothing will get damaged with this setup. Stay tuned…