Introduction: Blinking, Singing, Marioman

Use an attiny13a, two LEDs and a greeting card speaker to create a blinking Marioman that plays the Super Mario Brothers theme song.

This can be an easy low-cost project for anyone who is looking for a fun way to break into AVR programming!


The notes of the songs are generated by a square wave outputted on a single pin of the AVR microcontroller. The LEDs that alternate on each note are connected to 2 pins each of the same chip.

Step 1: Materials and Contruction

  • 1 attiny13a
http://www.mouser.com/Search/ProductDetail.aspx?qs=sGAEpiMZZMvu0Nwh4cA1wRKJzS2Lmyk%252bEP0e%2f7dEeq0%3d
Cost: $1.40

  • 2 LEDs - any LEDs will do
  • 1 lithium coin cell battery
http://www.sparkfun.com/commerce/product_info.php?products_id=338
Cost: $2.00

  • 1 coin cell holder
http://www.sparkfun.com/commerce/product_info.php?products_id=8822
Cost: $1.25

  • 1 small speaker from a musical greeting card

Total cost of materials ~ $5

The two LEDs were attached directly to two pins each of the attiny13A.
Two pins are used for each LED, the second pin is set low to use as a ground connection.

The current limit of the I/O pins on the AVR will prevent the LEDs from drawing too much so a resistor is not necessary to connect in series.

The speaker used is typical of one found in a musical greeting card, any small speaker will do, given that this is outputting a square wave tone, it's not too important to worry about driving the speaker or sound quality.

Step 2: Soldering the AVR to the LEDs and Speaker

For the LEDs to go reach out like arms one pin is bent over the AVR each side.
Orienting the AVR this way makes it easy to connect to the speaker (second image) since the connections are on the two bottom pins.

For aesthetics you want to the front of the chip facing out so be sure the speaker is facing the same way when it is attached.

Step 3: Programming the Attiny13a

There are plenty of different options for programming AVRs.
for this project the USBtiny was used which is available as a kit from ladyada's site
http://www.ladyada.net/make/usbtinyisp/index.html

To connect the AVR to the programmer you can either attach wires to the female socket and plug them into a breadboard or better yet get a cheap AVR programming adaptor like this
https://www.sparkfun.com/commerce/product_info.php?products_id=8508
along with 3x2 male headers to connect the plug.

Step 4: Creating the Firmware for Marioman

The attiny13A has 1K of programmable flash, and 64bytes of SRAM.
The attached tar file has the source file as well as compiled firmware for download.

Three arrays in the c code were used to generate the music

  • freq[] - frequencies of each note
  • length[] - length of each note
  • delay[] - pause between each note

The frequency array does not have the actual frequencies but rather the value to put in the TTCROB register to generate the square wave off the PB0 pin.

Here is a brief summary of the calculations and pin configuration for square wave generation:

  • The attiny13A has an internal oscillator set to 9.6MHz
  • The internal clock for IO is the oscillator divided by 8 or 1.2MHz
  • An internal timer is setup in a 8bit register to count up every clock cycle with prescale of 8.
  • This results in one tick equal to 1 / (1.2MHz / 8) = .006667ms
  • The attiny13A is configured to compare what is in the 8bit TCCR0B register with the timer and toggle a pin when they match.
  • For example, in order to generate a square wave at 524Hz (one octave above middle C) which has a period of 1.908ms.
1.908ms = 286 clock ticks (1.908/.0067)
Divide 286 by 2 to toggle the pin at t/2 (286/2 = 143)
Put 143 in the TTCR0B register to generate this note.

This is all the code that is necessary to set up the timer, do the compare and output a square wave:
    TCCR0A |= (1<<WGM01);  // configure timer 1 for CTC mode    TCCR0A |= (1<<COM0A0); // toggle OC0A on compare match    TCCR0B |= (1<<CS01);   // clk/8 prescale    TTCR0B = 143;  // generate a square wave at 524Hz

To delay the tones and the pauses between them a simple delay function was used:
void sleep(int ms) {	int cnt;	for (cnt=0; cnt<(ms); cnt++) {		int i = 150;		while(i--) {			__asm("NOP");		}	}}

This counts down from 150 where each NOP cycle is approximately .006667ms.

The last thing the code does is loop through the arrays, generate the music and blink the two LEDs.

This is done in a continuous for loop with the following code:
const uint8_t freq[] PROGMEM = { ... data };const uint8_t length[] PROGMEM = { ... data };const uint8_t delay[] PROGMEM = { ... data };...while (1) {		for (cnt=0; cnt<156; cnt++) {   		    OCR0A=pgm_read_byte(&freq[cnt]);		    output_toggle(PORTB,PB3);		    output_toggle(PORTB,PB4);		    sleep( pgm_read_byte(&length[cnt]) );		    output_toggle(PORTB,PB3);		    output_toggle(PORTB,PB4);		    // stop timer		    TCCR0B = 0;		    sleep ( pgm_read_word(&delay[cnt]) );		    // start timer		    TCCR0B |= (1<<CS01);   // clk/8 prescale		}}

There are 156 elements in the frequencies/lengths/delay arrays, this loop traverses them. Pin PB3 and PB4 are each toggled so they will alternate with each note The first sleep is the length of the note we play after setting the OCR0A register to the appropriate value. The second sleep is the pause between the notes we play.

In the code above you might have notice the two functions pgm_read_byte() and pgm_read_word() as well as the keyword PROGMEM.

With an embedded chip like the attiny the amount of SRAM is very limited, in this case only 64bytes. The arrays we are using for all of the frequency/delay/length data are much larger than 64bytes and therefore can not be loaded into memory. By using the special PROGMEM avr-gcc directive these large data arrays are prevented from loading into memory, instead they are read from flash.

Step 5: Letting the Marioman Loose



The above video shows Marioman in action.
The average power consumption is about 25mA so he can blink and make noises for about 10 hours before draining the lithium coin cell.

The only way to power him on and off is to remove the coin cell battery, the sturdy one listed in the materials is well suited for this. A switch can be added but there is something to be said for keeping it simple.

Comments

author
geeklord (author)2009-09-07

Made one a little earlier today, and its pretty sweet. Just wondering, how on earth did you get all those numbers for the frequency, length, and delay arrays?? That would have taken me forever, even with sheet music or something.

author
geeklord (author)2009-07-30

Any links for where I can get one of the little mushrooms?

author
geeklord (author)jarv342009-08-10

O, sweet i could get that. thx

author
thekanester (author)2009-05-19

Really liking this minimal circuit. It makes working with the arduino look positively bloaty! Great work!