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!