Archive for the ‘gEEk’ Category

Fun with MIDI, CNC and vector maths (mid2cnc.py)

More playing:
Castlevania end credits
Tetris
Mario Bros. theme

Update: I fixed up the script to pull (usually) proper timing from the MIDI, threw together some minimal documentation and released it to the public (see link below).

Downloads
mid2cnc.py, sparse documentation and samples

Basically, it’s possible to compute a combination of (distance, feedrate) along an axis that will cause the stepper motor for that axis to spin at an exact frequency corresponding to a musical note. With a little vector magic, the same can be done for (x, y, z, feedrate) to produce chords as the machine follows a 3D line through space.

(For anyone wondering, the song is Jonathan Coulton‘s Still Alive, better known as the end credits theme from Portal. The MIDI is from topazstorm.)

*whew* That was the easy part. The real magic will happen in a future post, if I ever get around to it :-) Hint: The fact that notes can and do swap arbitrarily among different axes (while still sounding passable) is important.

How This Works (for CNC-heads):

We have code G1 [pos]x F[feedrate] for linear interpolation at a specific feedrate. Thus need to convert between feedrate in IPM and frequency in Hz (steps per inch or inches per step). My machine as currently configured is 36000 steps/in, so if we wanted it to play middle A (440Hz) (440*60 = 26400 steps/min) we would want to move along a single axis at feedrate (26400/36000 = 0.7333..) IPM.
or more generally, (freq/600) IPM.

Here are the frequencies for one octave. The formula to convert semitones (notes) to their actual frequencies is

f = fRef*2^(x/12)

where fRef is an arbitrarily chosen reference frequency corresponding to a specific note, and x is the number of semitones difference between the note you want and the reference. Middle A (440Hz) is as good a reference note as any, and its MIDI note number is 69, so the formula to calculate frequency for any MIDI note number becomes:

f = 440*2^((x-69)/12)

; C4 = 261.63Hz
; D4 = 293.66
; E4 = 329.63
; F4 = 349.23
; G4 = 392.00
; A4 = 440.00
; B4 = 493.88
; C5 = 523.25

And the G-code with the resulting feedrates to play this scale on my machine:

G1 X1 F0.43605
G1 X2 F0.48943333333333333333333333333333
G1 X3 F0.54938333333333333333333333333333
G1 X4 F0.58205
G1 X5 F0.65333333333333333333333333333333
G1 X6 F0.73333333333333333333333333333333
G1 X7 F0.82313333333333333333333333333333
G1 X8 F0.87208333333333333333333333333333

; Unfortunately, our note duration is now frequency-dependent. If we wanted it to play for 1 minute, we should make the distance
; equal to the feedrate in IPM (or 1/60 of that to play for 1 second, etc.). Easy-peasy so far.

Now let’s complicate things a bit. Suppose we want to play 2 or 3 notes at once. G-code linear interpolation scheme is that in, say, an XYZ move, all the axes arrive at the same time. Feedrate is the speed the tool moves along this *vector*, not the speed of the fastest/arbitrary axis. In other words, you cannot specify individual feedrates for the (x,y,z) axis moves, only one for the resulting vector as a whole. So, since the vector that results from adding 2 ore more axis moves will always be longer than either of the individual axis moves (for the 2-axis case, think the hypotenuse of a right triangle) the feedrate we set will be faster than the highest note, and will depend on the individual notes and their contributions to that vector.

Assume the bog-standard C-E-G chord. To play each on its own for 1 second…

G1 X0.0072675 F0.43605 ; move this distance
G1 X0.0164238 F0.54938 ; move 0.009156333…
G1 X0.0273126 F0.65333 ; move 0.010888833…

…but we want to combine these into a single (x,y,z) vector at a single feedrate.
The vector is obviously (0,0,0 to .00726, .00915, .01088), and its length is given by sqrt(x^2 + y^2 + z^2). Remember we are playing all three notes for the same length of time. The vector has lengthened, but the desired playing time has not, so we need to choose the feedrate for this new distance that yields the same travel time.

Regardless of how the length or rate changes, the (x,y,z) components remain proportional to one another. Just pick one of the individual axes/notes as a reference, compare the final vector length to the length of the reference note and bump the feedrate proportionally to the change in length. In this case we arbitrarily select the highest note as the reference, and the ratio of the final feedrate (unknown) to the reference feedrate (known) should equal the ratio of the 3D vector length (known) to the reference length (known). It’s almost too easy!

3D Vector length: 0.015975658808286373765422932349422

Feedrate: (newlength/oldlength) * oldfeed

= 1.4671598699591015644580950363551 * 0.65333 = 0.9585395578403798251074072301019

G1 X0.0072675 Y0.009156333 Z0.010888833 F0.95853955

Just remember that *any* change of any note requires computing a fresh new vector, so long notes will have to be split up wherever another concurrent note changes.

(Also: An experiment…)

In the last post, I made the unspeakable blargger mistake of linking to an article on a news site, which means in 7 days or so, instead of said article this link will return absolute crap and/or a “Buy membership now!” nag screen. Trying to keep up with such link rot (if anyone bothered) is a problem that grows linearly with the number of posts/articles written, until it reaches 100% of the blogger’s time and he/she/subject/verb has to stop writing any more posts and become a forest ranger. I’ve ranted this before with some possible solutions, but as you may have guessed based on my project completion record to date, didn’t get around to it (got maybe as far as writing a toy script that wget’s pages and stuffs the contents into a database record).

So a little experiment: Instead of linking to the article directly, I linked to a carefully-constructed “I’m Feeling Lucky” Google query containing unique phrases contained in the article. The idea is that as the site shuffles stuff around / deletes content / recycles numeric links, rather than a 404* the link should preferentially return a clean copy of the article from somewhere else on the Internet if it exists (syndicated copy, fulltext copy-paste into a blog/slashdot post somewhere, etc.).

Let’s see if it lasts any longer than a regular news-site link!

(For anyone interested, the actual query is:

http://www.google.com/search?q=%22A+company’s+backroom+mass+of+servers+and+switches+is+cloudlike.+So+are+social-networking+sites+like+Facebook+Inc.%2C+or+the+act+of+buying+a+book+on+Amazon.+Some+clouds%2C+like+Google’s+email%22&btnI=Lucky

The “%22″ at the beginning and end of the query string itself is the URL-safe encoding for a double-quotation mark (ASCII code 0x22), so that the quote marks in the query don’t conflict with the quote marks in the <a href=”…”> tag. To simulate a click of the “I’m Feeling Lucky” button, replace the button-type code that normally appears in the query (btnG=Search) with “btnI=Lucky”. Also note that apparently Google limits queries to a maximum of 32 words.)

* Modern commercial sites seldom, if ever, actually return a HTTP 404 code when a document is not found, since software including search-engine spiders detect these and drop 404’d pages from their listings. it’s far more profitable to pretend the user/bot has reached some kind of non-error document, swap in a generic landing page and stuff it full of keywords and advertising.

Optical Mouse Hacks: 2D Micropositioning using cheap mouse cameras

Optical mice work by pointing a tiny cheap camera at the surface of your desktop, tracking the motion of ‘interesting’ points in the surface texture (woodgrain, imperfections, highlight/shadow) as the mouse slides around over it, and converting this to an X and Y motion. An LED is used to light the surface beneath the sensor, typically at a very low angle to help highlight any surface roughness (so the sensor still works on rough, but solid-colored, surfaces such as paper). Many of these sensors allow you to read out the raw image, too. Historically, the sensors in optical mice have been a standalone chip with SPI interface, leaving a separate microcontroller to handle button clicks and PS/2 or USB interface – so you could hack a cheap optical mouse to output position or image data for unique scanner or robotics projects. Unfortunately, more and more of these high-volume, low-cost devices are moving to all-in one camera+micro+USB chips under an epoxy blob, so you can’t just buy any old optical mouse and expect any access to this internal data.

Videos:
Absolute microposition sensing using image recognition
Relative position sensing (i.e. just like a mouse) using the DELTA_X/DELTA_Y registers
Downloads:
Arduino Library


Naked mouse cam and lens wired to a microcontroller

Fortunately, standalone SPI sensors are still alive and well. Mouser.com (no pun intended) sells some of these (Avago ADNS-2610 and ADNS-2620) for the exhorbitant price of $1.56 each. It’s a CAMERA for a buck fifty. Not exactly a *good* camera (grayscale, 18×18 resolution), but you can still do some neat tricks with it. Of course, you will still need a cheap optical mouse to steal the lens off of (or maybe an old CD player, etc.).

If you want to be all lame and boring, you could use this mouse camera as, well, a mouse. An onboard DSP is constantly watching the surface below as it slides by, giving you an up-to-date relative position (DELTA_X and DELTA_Y) just by reading a pair of registers. Each ‘delta’ reading contains the number of +/- pixels the mouse has moved in each direction since the last time you read it. Since you are only reading 2 registers, you can read this information at very high speed. There are some additional registers that will give you the max and min brightness, sum of all pixel values, and a ‘surface quality’ value that represents the number of trackable points (divided by 2) under the imager.

But if you want to dig deeper, a builtin diagnostic feature lets you bang some other registers and return the entire image under the camera. A few things worth mentioning before you go further, though: this IS meant as a diagnostic feature only; they sell these things as mice and not cameras after all, and this feature is not the best implemented. There are 324 pixels (18×18 array), but you can only grab one pixel per frame. So when you get the image, you are actually seeing pixels composited together from 324 separate frames across maybe 1/2 second. If the camera is moving during this time, you’ll get a garbled image, so if you have this puppy strapped to a robot to take pictures (or position the robot), your robot has to stop for pictures. Also, your maximum full-image rate is only a couple images per second.

Following are some demos of monochrome and color image acquisition, surface identification and micro-position sensing down to the um range.

Circuit:
The ADNS-26xx parts only require a couple external components: an oscillator and a couple capacitors to stabilize its power supply and internal reference voltage. The oscillator frequency (about 20MHz-25MHz) is not critical; any cheap ceramic resonator will work fine here. So your complete parts list is:

1x ADNS-2620 mouse cam
1x 24MHz resonator (speed not critical)
1x 2.2uF capacitor
1x 0.1uF capacitor (optional but recommended power-supply bypass; value not critical)

Grabbing images:


The sensor’s great for reading that pesky fine print.

Above is a sample image taken from the sensor, looking at the little “Equal Housing Lender” glyph on some credit card junkmail. See below for some more. The process is straightforward; write once to the PIXEL_GRAB register to arm it, then read it 324 times (18*18) to read out the image bytes starting from the top left pixel. (Or use my Arduino library ;-)

And no, I’m certainly not the first to think of this. See here for a demonstration where someone combined the image and position readouts to use the mouse as a crude handheld scanner. I haven’t tried it, but I wonder how well this can see your fingerprints if the angle is right. (I assume not very well, otherwise mouse companies would have already enabled frame-grabbing on USB mice and tried to sell it as combination mouse and biometric ID thingy.)

Color imaging:
The grayscale sensor can be used as a crude color imager by replacing the standard red lighting with an RGB LED, and taking one frame with each color lit in turn. Depending on the LED, you may have to scale the R/G/B frame data differently for more accurate color representation. I assume like most photodiode technology the mouse cam pixels are most sensitive to the red-IR range, but the LED I used had a pretty weak red, so it was kind of a wash. (The image here is scaled red=0.75, green=1, blue=0.75).

2D position finding using the “Christopher Carter Algorithm”:
Very simple position-finding routine I wrote for testing purposes; named after a magician’s trick where the blindfolded practicioner (renowned hypnotist Christopher Carter, in the first case I saw it) “reads” a name written on a dry-erase board by swiping a finger across it at a few different heights. This is a similar idea, using a basic edge-detection to identify regions (“where to read”), then read them by the brightness at the center of each region.

In this method, you create a known optical pattern (in this example I used Gray Code) and apply it to the surface whose position you want to measure. Then aim the camera at it so that it looks at a small subset of the optical pattern at any given time. Ideally, each ‘pixel’ of the optical pattern should cover a 2×2 or more (3×3 or 4×4) pixel area on the sensor, since the optical pattern and the sensor’s pixels will never be *perfectly* aligned, and thus will blur across a couple neighboring pixels. Now you can identify the unique pixel pattern under the sensor and match it its position in the full optical pattern.


In a project at work, we needed to know how far a visual indicator pin on a piece of machinery was extended at any given time, and whether its position was in tolerance (reducing human observation error in dark and foul weather conditions). Since the sensor could not be permanently attached, we also wanted to be able to measure slop or shifting of the sensor itself relative to the pin, which would produce an incorrect reading. The small space, large pin travel and need for sensor cross-checking made common 1-D proximity sensors less attactive.

Definitions: The “pixel grid” is the actual sensor array. For ADNS-26xx, this is always 18×18. A “region” is one individual mark in the optical pattern, corresponding to a 3×3 (etc.) region of the pixel grid as mentioned above. The “region grid” is the array of these regions overlaid somewhere on the pixel grid. For example, with an 18×18 pixel grid and each region 3×3 pixels, the region grid overlaid onto the sensor can be as large as 6×6.

By performing this 2-stage lookup (find region grid offset on pixel grid, match region grid to known optical patterns), the total computation time is reduced by mainly working with only a small subset of the pixel data (the region grid), and the positioning resolution is at least (region size) and at most (pixel size). Working with only the center pixel of each region, to the extent possible (rather than e.g. averaging the entire region’s pixel values), is also beneficial since the regions may not be perfectly aligned to pixels and the focal plane at close range is very narrow (<1mm), thus the image may not be completely in focus – especially if looking at a curved or otherwise 3D surface. So all the pixels toward the edges of the region will tend to dilute the reading.


Absolute 2D position encoding/decoding using a Gray Code pattern. Position is resolvable generally to 1 pixel, in this case measured at about 2.4 mils (about 70um). The top-right shows the raw image with region grid (black squares) overlaid aligned to the strongest edges (pink crosshairs). The bottom-left shows the edge-detection itself, and finally, the top-left shows the recovered optical pattern. The actual position is the index of this pattern in the known fullsize pattern + the region grid’s offset.

Assuming an 18×18 image sensor:

Perform edge detection by taking the derivative of the image. Embedded systems such as Arduino are barely suited for non-integer math, let alone calculus, but we can take a poor-man’s “discrete derivative” easily by just subtracting neighboring pixels. Neighboring pixels on a uniform surface will not differ by much, so subtracting two neighbors will yield a low number, while along an edge, one will be very different from the other. We want to figure the vertical and horizontal edges separately. And we don’t care about the exact location of ALL the edges per se, just want to know on which rows and columns they occur. Once at least one good, strong edge is detected in each direction (horizontal and vertical), we know where to align the region grid so it is centered on valid regions.

For each horizontal row: For each pixel, its edginess (likeliness of being along a *vertical* edge) is given by the absolute value of (pixel – left neighbor) + the absolute value of (pixel – right neighbor).

v_edginess[row][col] = int(abs(image[row][col] – image[row][col-1]) + abs(image[row][col] – image[row][col+1]));

And of course that entire row’s vertical edginess is the sum of the edginess of all pixels in the row.

For each vertical column: Same thing, only going by columns, taking the pixel directly above and below. Again, the column’s edginess is the sum of the edginess of all the pixels in the column.

Obviously, the leftmost pixels has no left neighbors, and the rightmost pixels has no right neighbors (same goes for the top and bottom rows, they are missing neighbors on one side), so the easiest approach is to exclude them from the loops, e.g. for the 18×18 array, valid results start at (1,1) and end at (17,17). The result is an ‘edginess’ array of 16×16 pixels.

Once the region grid is positioned, threshold the region centers to black/white, then take the resulting region grid (4×4 in this example) and slide it around on an array containing the ‘known’ pattern until the best match is found. Obviously, in a real-world system subject to bad lighting, specks of dust, misalignment or misfocus, the match will not always be perfect. You might also want to know how well you can trust the measurement, so I compute a confidence value too. The confidence value is a function of the absolute % of regions matched, and the difference between the best match and the next best match. For example, if two different positions matched equally well (even if they are both “pretty good” percentage wise), you can’t uniquely identify a position and so your confidence must be zero.

Another thing briefly tested was to place an LED behind the pin and observe its side profile (Alfred Hitchcock Algorithm?), which worked surprisingly well.


Side profile of the pin showing the lower part of the indicator groove.

NinBendo (cont’d): Zero-knowledge, realtime music tweaking example

This is a followup to this post.

Quick video example of finding and bending the music data that plays during Super Mario Bros. 3’s World 1 map, using the FCEUX emulator’s advanced 6502 debugging features. Full-screen if you’ve got it – the video did not survive compression well, and I don’t feel like investing hours tweaking around with it…

Video: Using FCEUX features to bend SMB3’s World 1 map music

Once on the screen of interest, go to the Debug menu and open the Trace Logger window. Tick the two ‘Only log new data…’ boxes, choose a filename for ‘Log to file’, and press Start Logging. These options require the Code/Data Logger to also be running, so FCEUX will prompt you to open it (hit Yes). Pay attention to the ‘Bytes logged as data’ count, it is slowly increasing as data is fetched from the cartridge. Most of the game code is running a complete loop every frame, so the ‘Bytes logged as code’ count should max out quickly. Likewise, MOST of the data being accessed here (e.g. sprites, etc.) will go through their entire rotation within a second or so, but the music takes over 20 seconds to do a complete loop (you can see the data byte count roughly keeping time with the music). Thus the last >20 seconds of data in the logfile will consist of music data fetches. Open the log, scroll near the bottom and notice the resulting disassembly, consisting largely of e.g.:

$E47A:B9 71 A7 LDA $A771,Y @ $A7C5 …

In English that is: Cartridge address $E47A onward contains an instruction with data bytes (B9 71 A7). The first byte is a CPU opcode (LDA $xxxx), telling the CPU to load the data at memory address (specified by the next two bytes, $A771) into its A register. Some subsequent code (purposely omitted from your trace log since it runs every time new data is fetched) processes the sound data. Thus corrupting one or more of those address bytes will cause incorrect sound data to be fetched and parsed, causing audible glitching depending on what the fetched data tells the sound loop to do.

NinBendo – circuit bending by corrupting 8-bit game code.

Yeah, back in junior high I had not enough friends and too much time, and discovered that keying in random Game Genie codes would sometimes cause a NES game to (harmlessly) glitch out in interesting ways. :-p Some codes just locked up the game (drat!), while others caused screen glitches, messed with colors, and rearranged levels. Still others would screw up the game music or sound effects. I was always strangely mesmerized by the bleepy sonic barf of a good sound loop crash.

Of course, now that I’m all old and exposed to the Internets, I come to find out there are entire groups devoted to pretty much exactly this–glitching out electronic toys to produce interesting sound effects (circuit bending). So for those folks, here is some info and samples from codebending on the original NES. Hardcore circuit benders might consider this software-bending stuff cheating since the case never comes off ;-)
(more…)

Better Better DXF Output for Inkscape (layers!)

I started using Inkscape, a sweet open-source vector graphics program, to produce (and/or steal from the internet and convert) designs suitable for carving on the CNC as Inkscape has a plugin to export the file as a .DXF. Converting some files, I discovered the current export script does not correctly handle all types of transforms, so some parts of the file may export out-of-proportion to each other or in strange size units regardless of the drawing units of the original drawing (Inkscape’s internal drawing unit is apparently equal to 1/90 of an inch, wait, wtf?). Also, if the drawing contains curved (Bezier) lines, these will be exported more or less as-is (DXF splines) and many free/cheap/itch-scratch-ware programs will not handle the resulting file (since the ‘correct’ representation or interpretation of splines is never disclosed in the published DXF file specifications, so everyone kind of does them in their own way, with less-than-stellar results).

Bob Cook noticed these limitations and updated the script to fix many of the ‘unusual transforms’ scaling issues, and convert Beziers to standard polylines that any program will import. It also adds some support for layers, including special ‘drill’ layers whose drawing objects will be output as single points (no lines) for hole drilling.

In theory, the layer support as he implemented it ought to work (it’s correct and in conformance with the DXF spec, which allows drawing objects to be assigned to arbitrarily-named layers throughout the file). In practice, many of the same free/OSS, low-cost and weekend-warrior tools do not handle this any better than splines. I dug up a copy of the DXF spec, played around a bit and found that these programs expect all layers to be formally declared in a DXF LAYER table in the header section of the file before use. So here is an update to the export script that generates a proper LAYER table, allowing a wider variety of toolpath generating programs to import them correctly. So far it has been tested with ACE Converter and CamBam and seems to work well, but as always this is a quick n dirty, not exhaustively tested script and there is no lifeguard on duty. (Inspect the imported files for problems before commanding your big machine to cut them!)

Better Better DXF Output for Inkscape

Just unzip into your \Inkskape\share\extensions directory. Note that the updated ‘simpletransforms.py’ replaces an existing file.

Note: There is still an outstanding issue with Grouped objects in Inkscape being exported with incorrect size. As I understand it (assuming the document structure sent to export scripts is substantially an SVG file), transforms are applied at the Group level, which is sort of a container that has the actual drawing objects (and possibly further nested groups) as its children. Guessing that to handle this correctly, rather than looking for transforms at the node itself, it must also maintain a stack of transforms that have been applied at the node’s parent level, and parent’s parent, etc. For now, it is an easy workaround to ungroup everything before export. Maybe someone with freetime can update this and release it as ‘Better Better Better DXF Output’ :-) (b3dxf?)

Cypherpunk’s Wet Dream meta-entry

I once said that this blog would eventually reach a point where any possible entry could be expressed as a sum of references to previous entries. In this case, it’s this one, this one and this one.

I have maintained that a point will be reached where plain old ordinary Web sites will be forced to turn on SSL encryption by default, or otherwise resort to client-side validation to ensure the page content hasn’t been tampered with during transit. Not because they are running online shops or otherwise dealing with sensitive information – to ensure their users view the original site as it was meant to be seen, protect their users against malware injected by man-in-the-middle attacks, protect/ensure their ad sales, and protect themselves from liability (lost sales from angry customers, frivolous ADA/etc. lawsuits, computer repair bills) arising from unauthorized third-party “enhancements” to their site. And I figured the detonator for all of this (besides Comcast’s broken BitTorrent filter) would be local-yokel small-town ISPs, where bored and too-clever midnight admins sit, Perl Cookbook in hand, trying to make a few bucks on the side by replacing random Web sites’ ads with their own, or injecting other forms of malware into customer HTTP streams to gather saleable profiling data.

Nope. It’s the big boys. Among them: Charter Communications, one of the world’s largest ISPs, and British Telecom have secretly tested, or intend to test (respectively) technologies against their paying customers which do exactly that. According to an internal British Telecom memo (fulltext PDF via Wikileaks), the company partnered with online marketing company Phorm, which specializes in consumer profiling and delivery of targeted advertising. According to Wired,

“From late September to early October 2006, British Telecom secretly partnered with Phorm to let the company monitor and track 18,000 of the BT’s customers. Phorm installed boxes on BT’s network that redirected web requests through their proxy server.

Those boxes inserted JavaScript code into every web page downloaded by the users. That script then reported back to Phorm the contents of the web page, which Phorm used to create ad profiles of a user.”

The report goes on to detail the ability of the Phorm proxy box to intercept requested pages and replace the site’s advertising with its own, based on the collected profile for that customer. The report also indicates several deleterious side-effects of this injection, such as flickering problems on some Web pages (which led users to believe their PCs were infected with spyware), frequent browser crashes, and insertion of the rogue code when users tried to post to Web forums. However, they concluded that the test was “successful” since no user was able to successfully pin the blame on BT/Phorm:

“The operation of the system does have noticeable side effects, which included web-page tag insertion and navigation bar flutter.

From the postings, no user correctly determined the source of these effects and users did not post that the system was causing poor performance.

However all postings suspected that their machines had a virus, a malware or a spyware infection.”

*sigh* Remember kids, you (probably) heard it here first. Let’s hope that in the brave new world of encrypt-everything-to-avoid-getting-fucked-by-ISPs, Firefox 4 doesn’t continue to perform that tired 5-warning song and dance every time you visit a non-corporate Web site.

Trance vibe vs. Windows Vista x64

So I have started getting support emails – “Hey, how do I get your hardware to work in Vista?” Seeming invariably to be the 64-bit version. That’s weird, as far as I know there is a 64-bit build of the drivers included…

Of course, you may have correctly guessed that as an IT semi-professional, I
1) don’t let that poisonous crap anywhere near my home/work machines,
2) am not keen on buying a copy of every Microsoft OS just so I can test free give-away software against some obscure bug(s).

Last night I was able to ‘borrow’ a copy of Vista 64 and set up a test machine. And I discovered the cause of the problem! You can thank our good friends at Micro$oft for this: Vista-64 will not allow drivers to run unless the driver’s author is willing to pay for a digital signature, which starts at US$499 per year :-(

There are some apparent (but ugly) workarounds:

If you press the F8 key right as Windows is beginning to boot, you should get a black screen marked ‘Advanced Boot Options’. Select the last option – “Disable Driver Signature Enforcement” – and press enter. This should allow the driver to operate (bypass the microsoft tax) until the next time you reboot. Unfortunately this means that even if it works, you will have to repeat this step EVERY time you start the computer if you want to use the device.

You could try typing in a command prompt: bcdedit -set loadoptions DDISABLE_INTEGRITY_CHECKS (yes, ‘DDISABLE’ is correct and not a typo). But it appears M$ have disabled this in some later updates.

You could get friendly with hackers and install a sneaky loader on behalf of your customer (sad when forcing a product to work as intended requires “sneaky”) – until you get caught and they not only add your drivers/loader to the global blacklist that gets pushed out to every Vista system with the “security updates”, but revoke your expensive certificate with the CA so you can never program drivers again (or get a new certificate, unless you can find a CA that missed the memo).

You could force your customers to get friendly with hackers to bypass signing more completely – well, until M$ releases a patch around it.

* * *

I wonder if it is possible to hack around on my (hardware developer) end. The hardware is a USB device, the firmware source is published and the device can receive firmware updates. Possibility for special “F***in’ Vista” firmware build: If the device detects a cold-boot, device enumerates as a USB keyboard, sends simulated ‘F8’ keypress and selects the Disable Signing boot option without any user intervention required. Feasible? Legal?…

VMWare Player Network driver (and video, SCSI, etc.)

Problem: After installing some operating systems such as Vista* in a virtual machine (i.e. as a ‘guest’ OS) under VMWare Player, they cannot access the internet because they don’t have a driver for VMWare’s virtual network card.

Solutions: This driver (and many others such as SVGA, SCSI, sound) are available in the ‘VMWare Tools’ package. Unfortunately this does not come with the free(beer) VMware Player, only higher-end products such as Server and Workstation that require payment and/or a ‘free’ (revocable at any time; costs your time and one valid email address) license key. They’re also a rather hefty download to scavenge out one lousy driver and copy it over. VMWare Tools includes .iso files, notably ‘windows.iso’ that can be mounted as a CDROM in the guest OS to install the drivers. This is the part you really want.

Windows.iso download direct from VMWare’s site: VMware ESX Server vmxnet Driver Update for Windows NT (.tgz file, use 7-Zip or similar freeware to extract)

This file contains basically an updated copy of Windows.iso (to fix a bug in a particular old version packaged with VMWare ESX Server) and nothing else; no registration or 200MB downloads required. (Despite the ‘for NT’ description, the .iso contains the full set of drivers for other Windows versions.) Score!

* for Vista and maybe others, you may have to explicitly force VMWare Player to present a specific virtual network card interface corresponding to one of the drivers included with VMWare Tools: open the .vmx file for your virtual machine in a text editor, find the network section and ADD the following line for each card:

Ethernet[n].virtualDev = “vmxnet”

replacing [n] with the virtual network card’s number shown in the other lines of settings, e.g. ethernet0. The ‘vmxnet’ driver is included in the Tools. Other choices I have heard of besides ‘vmxnet’ for this field include ‘vlance’ and ‘e1000’, though I don’t know where or if a full list of possible choices is publicly documented anywhere. Of those options, only the ‘e1000’ card seems to have a driver available for Vista x64 (the Tools does not appear to contain 64-bit drivers).

Tease…

It’s not quite finished yet, but here are some pictures of what I’ve been working on this week, when not making you-know-whats in my basement dildonics facility.



Petty Joule Thief

You might be familiar with the original Joule Thief, a simple, homebrewable step-up converter often used to drive LEDs (with Vf of several volts) from a single 1.5V battery, or extract the last remaining juice from a battery that’s too dead for use in most real-world gadgets. The basic Joule Thief can suck power from low voltage sources where reasonable current is still available, but what if you want to go even lower? What if you want to suck juice from your neighbor’s WiFi signal originating just on the other side of the wall? RFID or other sensitive inductive-powering mutual-inductance shenanigans? Harvest power from a Peltier device across a relatively small thermal gradient? Solar-power a gadget on even the cloudiest of days? How about scavenging useful power from those annoying radio broadcasters who can find nothing better to talk about than celebrity gossip and which sports mogul was caught with steroids this week?

Recently I discovered a copycat energy-harvesting company trying to claim trademarks on the term “Joule Thief”, which, having been a staple of DIY electronics for about the last decade, cannot stand. So here’s a variation on the classic which a) timestamps the first use of another clever circuit name, and b) genericides the crap out of the bogus mark. So, without further crap, here is the Petty Joule Thief(r)(tm)(c)(processed cheese food):

This one, based on a monolithic IC designed for bootstrapping bigger step-up converters (Seiko S-882Z series), will start-up on voltage sources as little as 300mV, and continue boosting at even lower voltages, stepping it up to 2.4V – enough to drive most LEDs and a good many low-power microcontrollers these days. The circuit is not exactly innovative either (the off-the-shelf chip and a couple caps; basically right from the datasheet), but hey, 300mV guaranteed start! Unfortunately, actually laying hands on these chips is nontrivial for the average hobbyist; they’re not available on Digikey, or indeed any direct-sales establishment in quantities less than 300 units. You might get lucky if you call up your nearest Seiko sales rep and beg really, really nicely for samples (an office at an engineering company and a big mahogany conference table might help). So really this is more of an excuse to get the funny name out there while we wait for these guys to grow a clue and sell on Digikey, or someone like Sparkfun to buy a reel and start selling them by the each.

Unlike the real Joule Thief circuit, this chip implements a switched-capacitor charge pump scheme rather than an inductive one. Both require converting a DC source to AC using a low-power oscillator, but the similarity ends there. Imagine wiring a 1.5V AA battery to a breadboard and placing a capacitor across it, which of course then charges up to 1.5V. Now yank the charged capacitor out and plug it back in so that the pin that was on the battery’s “-” terminal is now on the “+” terminal, and the one that was on the + terminal is now tied to your load. The 1.5 of the battery is now in series with the 1.5V on the cap, so there is now 3V at the load.

The capacitor on the input (10uF or so should be plenty) is for power supply bypass; this may be helpful where the input source is low-current as well as low voltage. For simple constant loads like an LED, the output capacitor should be maybe just a few uF or could possibly be omitted entirely (I haven’t tested this). For “bursty” loads (e.g. intermittently-running sensor / microcontroller), the output capacitor should be sized large enough so that the load can get its business done before the voltage drops below a usable level. You could do some math, but experimentation is more fun. The chip’s output will automatically switch ON when the large output cap is full (2.4V), and OFF again when the voltage drops to about 1.8V.

The efficiency of boosting power from 0.3V to 2+V is not great, but it does allow you to use many extremely low-voltage sources (maybe at low duty-cycles, like a once-per-hour wireless sensor/transmitter) that otherwise wouldn’t be usable at all. Consider the possibilities…


Crap to non-crap generator. Patent pending! (yeah right) And no, this is not a very efficient way to harvest radio waves, but it shows the concept.

Weatherball

Last night I finished throwing together a workable version of the Weatherball, currently displaying a color code at the end of my flagpole to indicate whether tomorrow holds any interesting weather. Apparently cities and radio stations have been doing it since the 1950s, but now I have my own! The data is grabbed from the NOAA’s National Digital Forecast Database server (XML) using a quick C++ program, and currently acts on five variables: chance of precipitation, chance of hail, chance of tornado, chance of extreme wind, and cloud cover percentage. Any ‘interesting’ values in these fields are evaluated in order of decreasing importance (beginning with hail/tornadoes), and the most significant weather condition is sent to the das Blinkenlichten node in the ball at the end of the flagpole.

In the spirit of virtually all known Weatherballs to date, here is a not-very-catchy jingle expressing the color code:

If the weather ball is yellow/green, the sun’s expected to be seen
If the weather ball is gray, anticipate a cloudy day
If the weather ball is blue, it probably will sprinkle too
If the weather ball’s maroon, be prepared for a typhoon
And if the weather ball is red, forget the beach – head for the basement instead!

(And if the weather ball draws half an amp, the electronics have gotten damp – the Blinkenlicht inside the ball has been outside for nearly a year (just waiting for me to get around to writing the software) and seems to still work fine, but I really should weatherproof that sucker.)



Weatherball showing no interesting weather for tomorrow (yellow-green). Know what it needs now? More Power!


Here are the main parts – the ball is supposed to be a curtain rod capper.


The program to fetch weather reports from the interwebs and drive the ball

The DON’T PANIC flag* (Hitchhikers Guide reference; the house number is 42) is showing a bit of weathering, but is still intact. The flag pole is a piece of lightweight enameled metal rod from the big-box hardware store, intended for hanging stuff in closets. The bubbly clear ball on the end is a decorative curtain-rod endcap from Ikea. A set screw on the side allows it to be attached to rods of various diameters. The exposed clear plastic extends through the inner diameter of the endcap some on the inside, allowing the LED node placed in the base to light up the ball (though not brightly enough for my tastes; may beef it up a bit later). The material can also be drilled out to embed the LED further into the ball, if desired.

* If McCain gets elected, it will be replaced by a bright red PANIC! flag, and the weatherball recoded to display the current terrist alert level. It will operate briefly in this manner while I search for a homebuyer and a cheap one-way ticket to Canada…

Assembler Interpreter for microcontrollers – sane?

I’m thinking of how much work it would be to write an assembler interpreter in PIC assembler. Probably sounds like the dumbest idea in the world, right ;-)

I’ve been toying with this idea lately for sort of futureproofing microcontroller-based designs, and adding some new possibilities for specific applications (polymorphic / self-modifying code, security applications, Arduino shields with their own drivers built in, etc.). Basically, the ability to load executable code from some arbitrary source and run it from RAM, the way we’re used to with general-purpose computers. The key problem in this idea of course is that typical microcontrollers can only execute code from their internal Flash memory, not RAM. There are few hacks out there that straddle the line between bootloading and execution, e.g. load code from (arbitrary source) and write it to an unused block of Flash, then execute it, then load some more code over it, etc., but this could wear out Flash memory pretty quickly. The only way to execute something directly from RAM is if it’s an interpreted language. Rolling my own interpretive language and its interpreter in ASM doesn’t sound like much fun, let alone getting anyone else to adopt it. It seems like the “least-work” approach would be for the interpreter to take its input in the form of MCU opcodes directly, looking them up in a jump table and executing the corresponding instruction from Flash ROM. That avoids having to write your own language and some complicated parser for it, and documentation for the language, and debugging tools, and…

This simplistic explanation works for basic operations (register reads and writes; you could use this to bitbang some new piece of hardware on the GPIO pins that didn’t exist when you released your gadget), but breaks down a bit when dealing with handling calls/gotos and code addresses, and where to safely stash all the interpreted code’s variables. I think I need to put a bit more baking into this idea for that reason, but it seems mildly promising so far.

(And no, I’m evidently not the first person to have this idea. When searching to see if someone had already done it, no working implementations, but Michael Millikan mentions a similar idea on PICList (see Mar 3 2004 entry).

Fixing Dell Precision T3400 USB not working

This is an update to a previous rant about the mysterious Windows XP “Dee-Dunk” error (and the novel concept of presenting an “error message” when an error condition exists), possibly in conjunction with broken or intermittent USB functionality. This post is mainly for Googlers – my friends are more than welcome to skip it.

I haz solved the mystery! It turns out that some Dell Precision T3400 machines (my work machine was one of them) ship with buggy/broken BIOSes and/or chipset support. Anyway, to fix:

Worm your way onto Dell’s support site for updates, enter your model number; download and run the following three patches:

  • BIOS Update (T3400A08.EXE, or whatever is newest)
  • Chipset Software update (R174616.exe)
  • Desktop System Software update (R160758.exe)

The above are intentionally not linked; the filenames and/or URLS may shift around as newer versions of this crap come out. Also, exact support packages may be different for other Dell products exhibiting the same malfunctions.

Symptoms include:

  • USB devices do not work, or only work intermittently (every Nth reboot); behavior may change slightly by enabling/disabling different combinations of USB ports in the BIOS (or this may be a placebo effect on my part, who knows)
  • Dreaded “Dee-Dunk” noise shortly after Windows desktop appears
  • USB devices such as keyboards, mouse, etc. work for a while, then mysteriously stop working until machine is rebooted
  • “USB Device Not Recognized”…
  • “There was a problem installing this hardware: <blah> The device cannot start. (Code 10)”
  • After installing a certain USB driver, machine crashes/hangs with a black screen for several minutes before the Windows desktop appears (may depend whether the corresponding device is plugged in)
  • Machine hangs when trying to install USB device driver
  • Software hangs trying to scan the bus or access a USB device

WinLIRC stuff

Yes, it means I’m hacking around on a MythTV setup again. LIRC is Linux Infrared Remote Control, a program for receiving keypresses from a remote control (TVs, etc.) on the computer, and/or blasting out simulated remote-control keypresses. WinLIRC is the same thing, for a Windows box*. Its documentation is a bit lacking however, so this is just a post to save the time of people who Google the error messages and wind up here.

In short: Upon first run, the program expects “Learn” to be the first and only option you ever think about touching (not “OK”, which you, like me, probably thought was the logical choice). And it is expecting a “.cf” file for its config file, not a .cfg or .rc or any of the others suggested in the Config ‘Browse…’ dialog. On first run, type a fresh new (not yet existing) file name (ending in .cf) in the Config box and press Learn, and the resulting steps will create this file. Do not select ‘winlirc.rc’ as the config file, even if this is one of the two logical choices. (You can select ‘sample.cf’ as the config file, but it probably won’t do anything useful with your remote.)

Also beware that the initial configuration screen defaults to “COM2” as your initial port for some stupid reason. This does not mean that your COM1 or connected device are broken, or that COM1 was in use by another program, etc. It’s just a braindead default (and does not necessarily mean that COM2 is the best choice, or that your machine actually has a COM2 for that matter).

Error message: “WinLIRC failed to initialize. Would you like to change the configuration and try again?”

Solution: This occurs on the first run of the program, since no config file has yet been specified. If you already know you’re going this route, it might be worthwhile to look at the “sample.cf” file in a text editor to see what’s in there. If you’re just trying it out and want to see if your hardware works, just enter any old filename in the ‘Config’ box and press LEARN. (Again, not ‘OK’.)

Error message: “Could not create dialog boxes.” (In a dialog box…)

Solution: This unclear message means any kind of generic failure to read info about your remote from a config file, probably because the config file doesn’t exist or hasn’t been specified yet. It could also occur if the config file exists, but is in the wrong format, or corrupted, or otherwise does not contain the info WinLIRC is looking for (for example, if you chose ‘winlirc.rc’ as the config file).

*Heresy, I know. The Myth box is a real Linux system, honest. I’m trying the untested IR receiver hardware on my Windows box first since running it there is a double-click rather than dicking around with why the LIRC kernel driver is barfing errors, and that machine actually has a free serial port vs. the uncertainty of whether all this timing-based stuff has any hope of working over a USB-to-serial converter.

It’s a mean old bitch and it has stupid name, bitch bitch bitch bitch bitch bitch bitch

So, I got an email back today from a contractee, whereupon I learned:
1) A technology I created, which I envisioned as having significant pro-consumer subversive uses, will instead be used as a carrier for evil (“hey, can it collect usage data to sell to credit-card companies every time they use it? That would be gr-rrreat!”)
2) It’s going to have a really stupid name. The kind of short, vowel-laden nonsense syllable combination used by start-up Web marketing firms and overly cute Web 2.0 niche services for the Myspace generation. But stupider.

Bleh.

First New England RepRap User’s Group Meeting at Olin College

Toward the end of July a couple friends and I had the chance to drop in to the first New England RepRap usergroup meeting. RepRap is short for Replicating Rapid Prototyper (a.k.a. 3D printer), the goal being an open-source machine design capable of making most of its own parts. The machine itself consists of a lightweight metal scaffold (made from inexpensive standard aluminum tubing and/or Home-Despot-grade threaded rod), a flat (wood/plastic) table, a printhead, and some stepper motors to move the table up and down (Z) and the printhead in the X and Y directions. The “printhead” (rather, extrusion head) pulls a thin strand of thermoplastic from a reel (kind of like extremely thick fishing line) into the moving head, where it is heated to its melting point and, on command, pooped (extruded) out of a nozzle onto the table starting at surface level. Successive layers of molten plastic are laid down, one on top of the next, to create a finished 3D plastic part.

[RepRap Usergroup Meeting Photos]

Here are some photos and a video of a machine in action. This particular machine is an older design, and didn’t seem to have survived the transport to the meeting very well (and based on the printed parts shown at the meeting, might have still been a work in progress – the RepRap blog shows the machine is capable of some much nicer parts). Still, it was cool to see an emerging disruptive technology such as this one in a state that proves its feasibility.

Howto: Talk to arbitrary USB devices with Processing (1.0 Beta)

I’ve been playing with the Processing language (http://processing.org) a little bit and liking it so far. For anyone not familiar, it’s a Java-based rapid-prototyping language that includes very friendly libraries for graphics, sound, video and select hardware (e.g. serial port). One thing I couldn’t find much info on was talking to arbitrary USB devices (not USB-to-serial based gadgets, but sending and receiving raw packet-level data).

Anyway, I found a solution that works in Processing with only minimal tweaking. You need:

Processing (of course) – http://www.processing.org
libusb or libusb-win32 – http://libusb-win32.sourceforge.net (Windows) or http://libusb.wiki.sourceforge.net/ (Linux)
Libusb Java wrapper – http://libusbjava.sourceforge.net/wp/

I only tried this on Windows so far, so the following assumes a Windows installation.

(I know, wrappers upon wrappers. So in the end you end up with device -> OS -> libusb -> libusbjava native DLL -> libusbjava JNI wrapper -> Processing. Probably not the most efficient approach in the world, but in the era of multi-GHz machines I’m not sweating too hard about it :-)

Follow the author’s recommendations on setting up libusb-win32 for your device, if it’s not already been done. Then, (for Windows users) extract the LibusbJava.dll file and drop it somewhere Processing/Windows can find it. The author recommends \Windows\System or equivalent; if this seems a bit forward, dropping it in the same directory as processing.exe works fine too.

Finally, making the library appear for Processing: create a new folder(-nest) for it in Processing’s libraries folder (blahblah\processing-0135\libraries\libusbjava\library), and drop the .jar file in it. Rename it to something more sane; Processing doesn’t seem to like all those extra dots and numerals. After renaming the .jar file sanely and restarting Processing, it will appear in the Sketch->Import Library menu. Clicking on the menu item automagically fishes out the correct class names and adds the appropriate (import…) lines to your sketch. From here on out, programming for the libusbjava wrapper appears to follow the actual libusb API pretty closely.

Here’s the program I tested it with. All it does is connect to a Rez/Drmn trance vibrator, send a USB packet to turn the motor on at about 2/3 intensity, then exit.


import ch.ntb.usb.testApp.*; // these four lines were automatically added by clicking it
import ch.ntb.usb.*; // on Processing's Sketch -> Import Library menu item
import ch.ntb.usb.usbView.*; // ...
import ch.ntb.usb.logger.*; // Some of these can probably be removed safely.

void setup()
{
noLoop();
}

void draw()
{
LibusbJava.usb_init(); // required inits for libusb-win32
LibusbJava.usb_find_busses(); //
LibusbJava.usb_find_devices(); //

// retrieve a object tree representing the bus with its devices and
// descriptors
Usb_Bus bus = LibusbJava.usb_get_busses();

// Find a specific USB device on the bus (by its VID/PID) and return a handle to the device in 'dev'
// This diverges a bit from native libusb-win32 code in that you don't have to loop through all the devices/busses searching for it.
Device dev = USB.getDevice((short) 0x0b49, (short) 0x064f); // VID/PID combination of Drmn' Trance Vibe device

// Note: Since this is just a quick n dirty "hey, is this possible?" test, I've added no error checking whatsoever.
// For anything more than a tightly-controlled quick hack / demo, you will want to do so!! (for starters, check if the device was found at all...)

try {
// data to write to the device. I don't want to write any data, so leaving this array empty.
byte[] data = new byte[] {};
// data read from the device
byte[] readData = new byte[data.length];

// open the device with configuration 1, interface 0 and without
// altinterface
// this will initialise Libusb for you
dev.open(1, 0, -1);

// ^^ Note, this may also diverge from native libusb-win32; I've never seen the choice of "-1" for alt. interface before (I assume it's interpreted as "any/all/none/don't-care"), but it seems to work.

// This device uses Control messages on endpoint 0. The following packet turns ON the motor at about 2/3 intensity (0xAA).

// Fields are: Request type (0x41-Out+Write), bRequest, WValue, wIndex, byte[] data, size, timeout, bool reopenOnTimeout
dev.controlMsg(0x41, 0x00, 0xAAAA, 0x0000, data, 0, 1000, false);

// The "reopenOnTimeout" field is a new one. It sounds either flaky-hardware-friendly or extremely dangerous.

// ok, motor turned on! I'm satisfied that you can control arbitrary USB devices from Processing at the raw (bulk/interrupt) packet level, so this is as far as I go for now.

// close the device
dev.close();
} catch (USBException e) {
// if an exception occures during connect or read/write an exception
// is thrown
e.printStackTrace();
}
}

DIY Magnetic Fridge Poetry

Like the idea of magnetic poetry kits, but they don’t come with the types of words you want? Here’s an easy way to make your own, specialty kits.



Supplies needed:
Printer in working condition
Magnetic Sheeting – any kind that will feed thru your printer (such as Staples Inkjet Magnetic Sheets), or most any kind of magnets/sheets/tape with a suitably modified (gantrified) printer, etc.
Word processor
Plain text editor (aka format sanitizer)
Teh intarwebs
Scissors and/or paper cutter
Lacquer/enamel

Some other handy items:
Hex Editor
GOOD text editor supporting flexible find&replace… or scripting languages, etc.

“Oh great”, you’re thinking, another HOWTO telling me how to use my printer with specialty paper. For me, the hard part was in finding data sources and choosing all the words, so I’m not going to dwell much on feeding your printer.

1. Make Words
You might have some idea already of what you want on them. If you don’t have the list (or relative quantities) already pinned down, the Intertubes are your friend. In this example I make a lolchem (lolcat/chemistry) set for my gf. So here’s the nasty bit, getting your data sources in order. In this case, I started by kind of just ad-hoc throwing words seen on e.g. icanhascheezburger.com into the text editor, with some of the very common ones repeated a few times. For relevant chemistry terms (some of which I was not at all familiar with), I pulled them from this chem dictionary site by refreshing the random words link repeatedly and pasting any that I liked into the text editor. Depending on your browser or where (if not a web site) you copy/paste from, all the special formatting/markup might come along with it (links, funky fonts, etc.) if you paste directly into a word processor. I find it easier to just paste everything into Notepad first to strip the unwanted formatting. Finally, I needed to know what the most common words of the English language were for the remaining tiles. After a couple dead ends, I hit paydirt. Known as the General Service List, this page contains exactly that: A list of every (common) word in circulation, sorted by frequency (by analyzing a huge corpus of standard literature…this list circa 1991). All the words are listed one per line and prefixed by various numbers (frequency, etc.) that are of no use to us. To strip them, you could paste it into a spreadsheet program and copy only the last column back into a textfile, or find/replace for each of [0..9] and space. I did the latter, which was mildly annoying but only takes a minute.

The next step was to pipe the entire compiled list (chemistry and general terms) through the lolcat translator (http://speaklolcat.com/). This appears to enforce an output size limit, so only a handful of pages at a time if you have a lot of translating to do. Of course, choose data sources and any necessary translations/conversions based on your own needs. If your data sources are inconsistently capitalized, or you just want to change their case, something like http://www.convertcase.net/ will come in handy.

Now you have a list of words in plaintext, it needs to be formatted for printing efficiently. For example, all linefeeds have to be stripped and replaced by spaces. Many text editors’ find/replace doesn’t handle special characters like CR/LF, so I used a hex editor to make this substitution (a Windows CR/LF is ASCII code 0x0D followed by 0x0A). This done, it can be pasted into a word processor. Adjust the inter-word and -line spacing to your liking, leaving some room to cut the words apart. For mine, 3 spaces between words (again, find/replace works wonders here) and line spacing of 1.5 worked well.

2. Print Words
First, set your inkjet printer to “high-quality” or whatever they call the darkest, most ink-gobbling mode (temporarily disable any ‘econo-‘ settings too). You paid a bundle for this magnetic paper, no sense ruining it with drab gray text trying to save a nickel worth of ink. DO NOT USE IN LASER PRINTERS / PHOTOCOPIERS, unless the product is specifically desgned for this! Products not designed for high temperatures might just melt to your laser printer’s innards instead. If your magnetic sheets come with instructions, they probably say to print a test page on plain paper first and make sure you like the layout. You’ll definitely want to do this. You’ll also want to do at least one blank “test page” of the magnetic sheet itself, to see if it feeds through your printer and if any special assistance is required (e.g. gently pushing/pulling on the sheet as it prints). If the printer has an eject / forcefeed process (e.g. holding down the power button), you can use that, or simply print a blank document. You can see my first attempt ran into a bit of trouble from not following this advice. If you run into problems, it may help to hold down the forcefeed and wipe down any accessible paper rollers with a wet rag, rubbing alcohol or your fingertip, which will remove any paper dust and provide a bit of added grip.



Sheets printed and dried


What happens if you a) don’t test-feed your paper first, b) rub the ink with your finger.

3. Lacquer words
Let your printed sheets dry thoroughly (several hours), then pick an expendable area/word on the sheet and use a wet fingertip to test if the ink stays put. If it smudges at all when rubbed, you’ll want to spray it with a coat of protective lacquer. This is good practice in general when dealing with greasy hands and sweaty fridges. Specialty ink-fixative products are available, but screw that – a light spray of Rust-Oleum High Gloss will leave your tiles smudge-free and virtually waterproof.

4. Cut Words
You could do this entirely by hand using scissors, but having access to one of those guillotine-style paper cutters to seperate the lines will speed things up considerably, not to mention provide straighter cuts. These can be found in the administrative area of most wage-slave environs (ask your secretary nicely), or most anyplace that has an “art department” (ask the guy with the beret nicely). Once all the lines are cut out, slice into individual words with scissors. Make sure you’re cutting a single strip; it’s easy to get a couple stuck together without noticing.



Use one of these to burn witches, roll heads, and cut your sheets neatly into strips


Finished product


These of course needed a container…

Blinkenlichten RGB LED controller: protocol / firmware (1.2)


This is the protocol spec and PIC10 firmware download for Das Blinkenlichten (1.2). This version improves handling of the ‘Identify’ command by end devices. Backward compatibility to 1.1 is not affected.

I don’t have pretty datasheets, application notes, timing diagrams, or much example code / pseudocode, but I’m sick of sitting on this thing until I get around to those :-P So I figured I’d just stick it on the internet and see what happens. The rest might be filled in in my future spare time (or by some nice person in the comments)…

Description:
Das Blinkenlichten is an open-source RGB LED lighting system and protocol written for the PIC10F200 microcontroller. A complete node consists of this chip, an RGB LED, three current-limiting resistors and a small capacitor for power-supply smoothing. A single chain can have up to 255 unique nodes (or as many non-unique ones as the wires will carry power/data for, without burning up!). Everything is coordinated by a single master device, which can be any low-cost microcontroller or equivalent with a free I/O pin. The beginnings and goals, etc. of the design are described on this page.

Pretty Pictures
Pic: Blinkenlichten in melty, icicle-like resin
Pic: Swirled around by a girl dancing
Video: Very simple random-color-generator demo
Video: Cool video of blinkenlichten who react to music

Features / Commands in brief:

  • Cheap! At 34 cents each (qty:100), the PIC10 is probably one of the world’s cheapest and simplest microcontrollers. Complete parts cost can be less than $1US per node.
  • Fast 1-wire data bus – complete operation with only 3 wires (power, data, ground)
  • 3 colors (R,G,B) can each be set to one of 9 intensity levels – total 729 possible colors
  • Set Group Address command: control groups of LEDs at a time with a single command
  • Deferred Update command: Allows simultaneous color changes even with a large number of devices.
  • Identify command: Discover the addresses present on the bus.
  • Power Save command: Stop all clocks and enter low-power mode until the next command

Arduino/Wiring library and example
Library and example sketch showing common usages (move to /hardware/libraries in your Wiring folder, close and re-open Wiring. The example will then appear under Sketchbook -> Examples -> Library-Blinken). This library is released under the GPL.

Firmware and source code (PIC10 assembler)
Version 1.3 (“It’s Log!” edition) can be donwloaded in this zip file. A few lines at the beginning will have to be set according to your hardware configuration (see below). The “#define MYADDR …” line contains the address the chip should respond to – change this and rebuild for each chip you program. This version adds a logorithmic color table so that the color intensities you specify will appear linear (evenly-spaced steps) to the human eye. Adding this meant some idiotproofing had to be removed – sending an invalid (>8) intensity value will cause undesired operation. Starting with 1.3, this code is released under the GNU General Public License v3.

Version 1.2 (‘dumb’ linear color table) can be donwloaded in this zip file. A few lines at the beginning will have to be set according to your hardware configuration (see below). The “#define MYADDR …” line contains the address the chip should respond to – change this and rebuild for each chip you program.

Hardware/Schematics:

Basic schematic for an individual node. The schematic shown uses a common-anode LED (common is connected to VCC); for a common-cathode, tie the LED common to Ground instead and change the appropriate #define at the beginning of the code. Different LED packages have different pinouts; test and make sure of them before wiring it up – or especially making boards. (The R/G/B connections to the LED can be easily remapped in software, but you have to get the LED’s common right the first time!)

Basic wiring diagram for a complete string with several nodes and a controller. There is a pulldown resistor between the data wire and ground (recommended value 100k ~ 1Meg). This is necessary for the ‘IDentify’ command to work, and it also helps prevent your string of lights from going haywire if the controller takes some time to start up and the voltage on the line is floating.

The maximum cable length, and maximum nodes reliably driven on it (or maximum speed), depends on how strong your controller drives the data line. As you add length and extra loads (inductance and capacitance) to this wire, the voltages on it will take longer to rise and fall, and be more difficult for the nodes to reliably consider a ‘1’ or ‘0’. I’ve run them with 6+m of cable without incident, but if you run into problems, reducing the data rate should help. If you don’t care about the IDentify feature, you can add a beefy buffer here to drive the data line harder. If driving long strings, you might also want to add decent-sized electrolytic capacitors between the power and ground wires at intervals along the string.

PCB and Parts List (Bill Of Materials)
This file contains a parts list for both DIP/breadboard and tiny surface-mount versions. Also included is an EAGLE schematic and Gerber files for a miniaturized, wearable board using surface-mount components. These data (schematics, BOM and Gerbers) are released into the public domain.

A picture of the finished SMT boards (panel) is shown below. With a jumbo 10mm RGB LED, the board is almost completely concealed behind the LED and only the sewable connections stick out.

Programming the chips
To write the firmware to these chips requires access to a PIC programmer. The official ones made by Microchip Inc. are quite expensive; fortunately there are many clones out there that work just as well, and some open-source designs you can build yourself. Just make sure that the programmer supports the PIC10 devices; some very simple/cheap designs (e.g. direct to PC serial port) may be designed only for “low voltage program” devices and won’t generate the +13V or so necessary to program this chip. The DIP variants can be programmed in or out-of-circuit; for the SMT variants, you will probably need to solder them to your board (with an appropriate pin header / etc for the programming lines), program the chip, and THEN add the LED (since it shares some of the programming pins and will interfere). For the ready-made SMT circuit board above, the following drawing indicates the pinout of the programming header on the edge of the board. For this, I soldered the wires from the programmer to the “wrong” side of a 5-pin 1.25mm connector (such as Molex 53047-05), then just press the other end into the PCB during program.

Command packet format: (forgive the horrible ASCII art)


     <start> <addr[7..0]><cmd[7..0]><stop>
_____- - - -. . . 16 data bits . . .______

The bus idles low.

Start condition: Bus goes HIGH and stays high for longer than the longest possible loop run (min. ~ 17uS), so that all devices are guaranteed to catch it.

Data bits consist of a low period (low half) followed by a high period (high half). A 1 is denoted by making the LOW half longer than the HIGH half, and a 0 by making the HIGH half longer. Ideally, all bits should total the same length, but since the low half sets the baud rate on a bit-per-bit basis, this is not required. However, any half should be a minimum 18 device clocks (18/1MHz=18uS) for most accurate timing, and should not exceed 255 device clocks (255uS).

Stop condition: Give some time for the cmd to be processed before sending a new one (bus idles low). If you’re in a hurry, this time depends on the specific cmd. Otherwise, you can just wait about 90uS (time for the longest 1-way cmd, activate_deferred, to complete) and not worry about it. (*See special timing notes for Identify cmd.) This is the preferred approach, but you could also just make the START condition longer.

Address BYTE format:

bit <76543210>
AAAAAAAA

where AAAAAAAA is an 8-bit device address (or group address). Address 0 is the broadcast address. Since the ‘Group Address’ cmd only supports addresses up to 64 (0x40), I recommend a handful of low addresses (0x01 ~ 0x0F) be set asdie for group addresses if you plan to use this feature.

Cmd BYTE format:

bit <76543210>
ERGBIIII

E: Extended Command flag. If ‘1’, decode remaining bits as Extended Cmd as described under Extended Commands. Otherwise,
RGB: Which color(s) cmd applies to (set ‘1’ for each color this intensity applies to)
IIII: Set intensity (0 ~ 8)

Extended Commands

11xxxxxx : Set Group Addr to value xxxxxx
10XXyyyy : Poke "Virtual reg" XX with contents yyyy (see below), where XX is the address of a virtual 4-bit reg and yyyy is the value to poke.

Vreg 00: Flags [x identify activate_deferred power_save]
Vreg 01: Defer buf R
Vreg 02: Defer buf G
Vreg 03: Defer buf B

Detailed description of the virtual registers:

Vreg 01 ~ 03 allow a deferred update to be sent for the R, G and B channel respectively. The new intensity value(s) are stored in memory, but the old intensity values continue to be displayed until an activate_deferred command is executed, at which point the new intensities are displayed. This will be particularly useful for trickling new values over the bus, then sending a single activate_deferred to all devices (addr 0) to give the appearance of a simultaneous update.

Vreg 00 is a virtual register among virtual registers: Rather than writing a value to it, you write to it setting an individual bit to perform the requested action. Once the action is performed, the bit can be considered automatically cleared.

  • Unused (bit 3): “No-Op” – Dummy command, doesn’t do anything.
  • Identify (bit 2): On receipt of this cmd by a given device address, this device shall pull the data line HIGH (internal weak pull-up) for a period of about 512 device clocks (or whatever, plenty long enough for master device to see it). Normal operation is then resumed. (Note that this may disrupt other devices on the bus, who interpret the pullup signal as a new START command. If this is bothersome an Identify command may be followed immediately by a dummy command if a device responds. The device’s response will be seamlessly eaten by the dummy cmd’s START, so it just looks like an extra-long start bit to all devices.)
  • Activate_deferred (bit 1): Replaces the currently displayed intensities with the contents of the Defer (R,G,B) regs if they contain a valid update.
  • Power_save (bit 0): This command will effectively stop the CPU and any pulse modulation activities and enter a low-power SLEEP mode. The device will remain in SLEEP mode until the next bus activity occurs, at which point it will re-awaken. Technically it will be waking up occasionally due to WDT, but these activity periods will be brief.

Quick Examples

Set device id 02 Red to max (8):
<start><02><01001000><stop>

Set device id 02 to bright white (Red, Green, and Blue to max):
<start><02><01111000><stop>

Set device id 02 to arbitrary color (Red 8, Green 2, Blue 3):
<start><02><01001000><stop>
<start><02><00100010><stop>
<start><02><00010011><stop>

Set device id 07 off (Red, Green, and Blue to 0):
<start><07><01110000><stop>

Clear all group addresses to 0 (default):
<start><00><11000000><stop>

Assign device id 0x9F to group (address) 05:
<start><9F><11000101><stop>

Set all devices to power save:
<start><00><10000001><stop>

Advanced Examples

Identify all the devices on the bus (pseudocode):

for (id = 1 to 255)
{
    Send1Wire(id, b'10000100'); // Extended cmd: Identify
    Delay(100); //delay 100 uS, to give device time to respond
    DATA_WIRE = 'INPUT'; // However you switch this pin to an input on your preferred platform
    gotResponse = DATA_WIRE; // read the data line to check if anyone is responding (pulling the data line high)
    DATA_WIRE = 'OUTPUT'; // Switch it back to an output (retaining same value as was read)
    if (gotResponse == 1) // Was there a response?
    {
       print("Found device " , id); // do something with this information, e.g. store active IDs to a table
       Send1Wire(0, b'10001000'); // send dummy command if there was a response.
                                        // Or you can just wait a few hundred msec for the other devices to reset
    }
}

Specific firmware points of interest

The intensity of the LED colors is controlled using pulse width modulation (PWM). The basic operation is that the intensity value for each color (0 ~ 8) is converted to that many ‘1’s and stored in a register, and this register’s contents are continually rotated in circles. Each time, the last bit is used to determine the on/off state of the LED. So with 8 bits in a register, it can be on 0/8 of the time (off) or 1/8 of the time or … 8/8 of the time (full brightness).

To provide the fastest possible update rate, it’s necessary to squeeze as much performance out of these cheap tiny PICs as possible. The PIC10 supports only a handful of instructions, no interrupts, and only a rudimentary 8-bit timer. For the PIC10F200, the entire program is limited by memory to 255 instructions. Therefore we can’t afford to be too sloppy.

The code uses look-up tables in place of any loops/math wherever possible. The chip does not support table-indexing operations in ROM (Flash), so this is done using computed GOTO: In many microprocessors including this one, the Program Counter register (which acts as the processor’s bookmark in the code’s execution) can be modified by the program directly. Thus, by writing a new value to the Program Counter you can force the processor to lose its place, resuming program execution from the address you just wrote. By performing math operations directly on the program counter, this method can be used to index a lookup table nearby. In the example below, the intensity value is added to the program counter to make it an index into a table stored just after it. The ‘retlw’ instruction returns from the function with a specific value saved in a register. This code snippet converts the (0 ~ 8) value to a value containing that many ‘1’s, using only a few clock cycles.


; Want to return a value containing the number of '1's specified in the intensity
; value. But want to spread them out for faster switching and less perceivable flicker.
setpwm:
    movf INDF, w ; cmd value
    andlw B'00001111' ; mask off bogus bits
    addwf PCL, f ; skip that many instructions
    retlw B'00000000' ; 0x00
    retlw B'00000001' ; 0x01
    retlw B'00010001' ; 0x02
    retlw B'01001001' ; 0x03
    retlw B'01010101' ; 0x04
    retlw B'01010111' ; 0x05
    retlw B'01110111' ; 0x06
    retlw B'01111111' ; 0x07
    retlw B'11111111' ; 0x08 ; last valid value

This same method is used to allow the PWM loops to keep running while receiving data. Each time a bit is received, the PWM loop “jump table” is called. The count of the number of bits received is used as the index into the jump table; instead of a list of data values, each table entry contains a jump (GOTO) to the address of either the red, green or blue updater.

Determining between ‘1’ and ‘0’ bits on the data wire also takes just a few instructions. For each bit, the line is held low for some amount of time by the controller, then held high. Whether the low or high half was longer determines whether it was a 1 or 0. The way to measure this can be thought of as a stopwatch that counts up during the first half, then down during the second half. If the count goes negative, the second half was longer and we record a ‘0’, else we record a ‘1’. The ‘stopwatch’ here is the chip’s 8-bit counter/timer register. But it can’t count down, it can only count up! So a little cheating: when finished timing the first half, we complement (invert) the contents of the timer register. Now it’s still counting up, but if the original count was 7, now it’s (256-7) or 249. If the 2nd half is longer, the timer will reach its maximum value (255) and roll over to zero again like an old car odometer (and ending at a low number again, the Most Significant Bit will be a 0). Otherwise it will be a high number, and the Most Significant Bit will be a 1. So, at the end of one up/down cycle on the data line, the timer’s MSB will automatically contain the correct bit as it was sent on the data wire.

You might also have noticed that the PIC10 only has 3 pins that can function as outputs; according to the datasheet the 4th (which I’ve used for the data wire) is input only. The 3 output pins are already being used to drive the 3 LED colors. So how does a node send data back to the controller in response to an IDentify command? There is a register setting that enables weak pullup resistors (~10k-20k) on all the pins. On the output pins this does nothing, but on the input (data) pin this applies voltage to the wire, overpowering the even weaker pulldown resistor (~100k) added to the controller side. (The controller stops driving the I/O pin briefly to await this response.) So by toggling the pullup resistor on and off, we can send data the ‘wrong’ direction :-)

Version History and Compatibility:

  • v0.x (2005) Nora Nightlight edition. Quick n dirty hack with hardcoded timer to distinguish 1/0 data bits. Set Group Address is the only valid extended command. Didn’t get around to touching it again for a long time.
  • v1.0 (2007) Beloved edition, demoed at VNV Nation concert April 07. Changed from fixed-frequency to variable baudrate data encoding/decoding; re-ordered some bits in the command packet format to make more sense.
  • v1.1 (2008) Proper edition; first public release. Implemented remaining Extended commands: power save mode, deferred update stuff, and device identification.
  • v1.2 (2008) More-Proper edition. Improved handling of IDentify cmd; now can avoid flashes during identify as non-responding devices on the bus reset. Compatibility with v1.1 devices is not affected.
  • v1.3 (2009) It’s Log! edition. This version implements a logorithmic color scale in order to better match the human visual response (intensity steps now appear evenly-spaced). Compatibility with v1.1 and v1.2 devices is not affected, unless you are sending invalid (>8) intensity values, which you shouldn’t be!

v1.1, v1.2, v1.3 are backward / forward compatible and can be used on the same bus. V1.0 supports only the basic command set (Set Colors and Set Group Address). Versions prior to 1.0 are not compatible at all…luckily, they basically don’t exist in the wild.