Difficulty Level = 5 [What’s this?]
Like many parents, we make hand-made costumes for our kids instead of buying cheaply-made (and expensive) costumes based on licensed characters. This year, my youngest son wanted to be a robot. My wife did a great job making the costume, but I just had to add some cool electronics to take it to the next level.
The electronics are nothing fancy — a simple Atmel ATtiny13 microcontroller that interfaces with two 74HC595 shift registers to light up LEDs randomly. The technical details are below, but in the process of building this, I was really struck by how electronics and computing are being embedded into everything. This week I was making a TODO list and one of the items was “finish source code for robot costume”.
OMG, now the costumes we make have source code.
This is a great example of how technology is becoming increasingly ubiquitous. Ten years ago, this would have been far beyond my reach. But in 2010 I can build this easily. The microcontroller cost $1.04, the shift register chips are $0.25 each, the resistors are a penny each, and the LEDs probably average $0.20 each. Definitely less than $5 for everything.
Technical Details
Here’s the schematic:
And finally, the simple source code that runs on the chip. I use CrossPack for AVR development. I use avrdude and a Bus Pirate to upload the code onto the ATtiny13 chip.
/*
* ATtiny13 driving two 74HC595 shift registers
*
* Randomly turns on/off output pins of the shift
* register ICs.
* A random number of outputs are set high, then
* a random time delay occurs. Then the cycle
* repeats.
*
*/
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#define DATA PB0
#define CLOCK PB1
#define LATCH PB2
int main(void) {
int d;
char n;
char i;
// set DATA, LATCH and CLOCK pins to OUTPUT
DDRB |= (1 << DATA);
DDRB |= (1 << LATCH);
DDRB |= (1 << CLOCK);
PORTB = 0;
for(;;) {
// choose number of LEDs to light up.
// n will be between 4 and 16
n = 4 + (random() % 13);
for(i=0;i<16;i++) {
// for each LED, probability of it being lit
// is n/16
if ((random() % 16) <= n) {
PORTB |= (1 << DATA); // set DATA pin high
} else {
PORTB &= ~(1 << DATA); // set DATA pin low
}
// toggle shift register clock pin
PORTB |= (1 << CLOCK);
_delay_ms(2);
PORTB &= ~(1 << CLOCK);
}
// once we've shifted out all 16 values, toggle
// the latch pin.
PORTB |= (1 << LATCH);
_delay_ms(2);
PORTB &= ~(1 << LATCH);
// delay random amount of time between
// 100ms and 500ms
d = 100 + (random() % 400);
for(i=0;i<d;i++) {
// _delay_ms function must be called with a
// constant value, not a variable!
_delay_ms(1);
}
}
return 0; // not reached
}



This looks very interesting!