May thy dice chip and shatter

Introducing GameByEmail's Dice-O-Matic. Made from Legos, a USB camera, and a bit of software, it's a home-grown, dice-rolling monster. Don't let it's rickety looks deceive you; this puppy can easily crank out the 50,000 rolls a day consumed by GamesByEmail. In fact, at full speed it averages almost one roll a second, well over 80,000 a day!

Let's take a close look at the hardware. It has 5 major parts:

1) The Hopper

2) The Shoe

3) The Camera

4) The Throwing Wheels

5) The Catcher



The Hopper. The hopper collects and stacks the dice vertically. The cycle is fast enough that only three dice need to be in the system. The dice I use are 15mm, exactly fitting into a 2x2 brick space. Sometimes the dice stuck though, so the hopper chute is 3x3. Dice in the hopper start out resting on the top surface of the shoe.

The Shoe, Part 1. The shoe moves back and forth at the bottom back of the hopper. It is 2 wide, 1 & 1/3 tall with a bumpless top, just short of the height of a die. When the cycle starts, the shoe is almost all the way into the hopper, with the dice stacked on top. The bottom die poses through a window for the camera.

The Camera.

The cheap USB camera is mounted using a few holes I drilled in its housing to accept pegs. It's is mounted on an old time hinge and swivel to make orienting easy. The camera has an external button on it's housing to take still shots. Rather than try to rig up something to poke this button directly (which would jostle the camera, blurring the picture, and probably reorient it), I sacrificed a long Lego wire jumper. I cut the jumper in half, opened the camera housing, fed the wires of a half jumper through a small hole I drilled in the housing, and then soldered the wires to the camera's push button leads. I can now easily use a Mindstorm push button sensor to trigger the camera. The sensor is depressed at the right time by a peg on the shoe connecting rod, and the camera sends a black and white picture to the computer.

The Shoe, Part 2. After the picture is taken, the shoe slides back, allowing the stack of dice to drop 1 level. It then moves forward again, pushing the bottom die out from under the stack and toward the throwing wheels. A ramp at the end lifts the die directly between the wheels.

The Throwing Wheels. The throwing wheels are two 81.6x15s spaced 13 holes apart, exactly enough room to get a good grip on a die in between them. They have their own motor and gear train as they do not need to synchronize with the rest of the cycle. The wheels are geared together so they spin at the same rate, but in opposite directions. They spin pretty fast, using a 40 to 24 increasing gear set. When the die is pushed up the ramp, it gets pinched and thrown into the air, spinning, but more or less straight up. Unblocked, they reach about 2 feet high. However, the catcher is positioned to grab them before they peak.

The Catcher. The catcher is a deflector plate attached to the hopper. The upward bound die hits the angled plate which sends the die into the funnel of the hopper. There are a few tumbling blocks in the hopper that help roll the die. The die tumbles to the stack at the bottom, where it begins the journey again. There must be at least three dice in the system to help gravity feed and position the die for the camera. I run it with a few extra.

Next, the software. It has 4 parts:

1) The Camera

2) The Preview Box

3) The Still Image Box

4) The Pip Counter



The Camera. The USB camera is a TWAIN device. I'm programming in .NET which currently has no built-in TWAIN libraries. I'm too cheap to buy an aftermarket TWAIN library for .NET, and too lazy to figure out all the details of using twain_32.dll as an extern to capture the incoming still images directly. So I let the TWAIN events get handled by the simple preview and still image applications that came with the camera, and simply do screenshots of the still image application box, and process that.

The Preview Box. The first time you click the camera button, the preview box opens, looking like so. I've set the image filter to drop the color as I'm only interested in black and white.

The Still Image Box. When the preview box is open and the camera button is clicked again, the image is sent to the Still Image Box. Every time the button is clicked, a new image is in the box.

The Pip Counter. I wrote a .NET application to count the pips on the dice. It does this by constantly monitoring the Still Image Box. Every quarter second, it captures a partial screen shot of the Still Image Box. It then compares this image to the previous image. Even with consecutive rolls, the images are slightly different. If the images are the same, no new picture was taken and nothing happens.

If the images are different, it scans for pips. The image captured is not of the whole box, it is just the part where the dice should be. The image is scanned in a simple left to right, top to bottom fashion, looking for a black pixel.

When a black pixel is found, the scanning process pauses, and it goes into Fill Pip mode. This mode recursively checks a pixel and returns it's "Fill Count". If it is white, the count returned is 0. If it is black, the pixel is made red, the count is set to 1, and then it's neighbors are checked, recursively adding their fill count to the total. In the end, you have the number of pixels in a black group. If the group was large enough, it is counted as a pip, else it is ignored. Since the black pixels in the group were turned red, the same group will not be counted again when the scan resumes.

The scan is done stepping 5 pixels at a time. This is both faster and allows the pip fill to traverse reflection streaks that might otherwise split a single pip into two.

The rolls are appended to a text file, with an automated nightly upload to the game server. If so inclined (and I had the bandwidth), the image of each actual roll could be stored and uploaded as well, and shown to the player. Just make sure they cannot be viewed before they are consumed!

Presto! Dedicate an old 266MHz machine to the task, and the rolls are as random as I can make them.