projects | about

USB Powered Blinking IR motion sensor mounted in a Mario Brothers Candy Tin

(or fun blinky motion detector thingy to put in your cube)
mario

If you have trouble seeing the video above, or you just hate flash download the movie direct here.

With an attiny13A, an IR motion sensor, and a candy Mario Brothers mushroom tin, this project turns them into a USB powered IR sensor that also blinks and sings. This is a variation of the marioman project but unlike that one this *this* is practical ;)

Here are the features:

Construction

Materials

materials assembled1 assembled2

Total cost of materials ~ $20

Construction

Drilling the Candy Tin

The wires pirctured below on the right were soldered together and attached to the three wire plug which will plug into the headers on the main circuit board for power, gnd, and the sensor line.

tindrill1 tindrill2 tindrill3

Main Circuit

                           GND
                            |
                           ___
               ----------  --- .1uF
              |          |  |
          5V--| PB5  VCC |--------- USB power (5V)
     ---------| PB3  PB2 |--LED2
     |  LED1--| PB4  PB1 |---|
     |   |----| GND  PB0 |-
    /         |          | |
    | GND 5V   ----------   /switch
    |  |  |                 |   
   ---------                \   /
  | IR      |                \||
  | sensor  |             GND-||   
   ---------                    \

layout

To fit everything in the candy tin a protoboard was cut into a small rectangle and the components were arranged on it. Headers seen on the left next to the LED (pictured above) are used to connect to the computer cable which is a three wire connection to the IR sensor. (one pin is unused on the connector)

An IC socket is essential to make it easy to re-program the chip, the LEDs on each side will bend to protrude outside of the tin.

proto1 proto2 proto3

Software

The attiny13A has 1K of programmable flash, and 64bytes of SRAM.

Firmware for the attiny13A as well as the source can be downloaded here - attiny13_mario.tar

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

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:

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 delay function was used that counts down from 150 where each NOP takes approx .007ms.

void sleep(int ms) {
	int cnt;
	for (cnt=0; cnt<(ms); cnt++) {
		int i = 150;
		while(i--) {
			__asm("NOP");
		}
	}
}

Here is the main code loop:


const uint8_t freq[] PROGMEM = { ... data };
const uint8_t length[] PROGMEM = { ... data };
const uint8_t delay[] PROGMEM = { ... data };

...


        for (;;) {
                static uint8_t cnt=0;
                static int time_delay=0;
                static uint8_t led1 = 1;  //initial value is on
                static uint8_t led2 = 0;  //initial value is off

                if ( (PINB & 1<<SENSOR) && time_delay > 20) {
                        //start playing the tune
                        //restore LED values
                        (led1) ? (output_high(PORTB, LED1)) : (output_low(PORTB, LED1));
                        (led2) ? (output_high(PORTB, LED2)) : (output_low(PORTB, LED2));

                        //start timer
                        TCCR0B |= (1&&CS01);   // clk/8 prescale
                        OCR0A=pgm_read_byte(&freq[cnt]);
                        output_toggle(PORTB,LED1);
                        output_toggle(PORTB,LED2);
                        sleep( pgm_read_byte(&length[cnt]) );
                        output_toggle(PORTB,LED1);
                        output_toggle(PORTB,LED2);
                        //save values
                        led1 = read_value(PORTB, LED1);
                        led2 = read_value(PORTB, LED2);
                        // stop timer
                        TCCR0B = 0;
                        sleep ( pgm_read_word(&delay[cnt]) );
                        // start timer
                        TCCR0B |= (1<<CS01);   // clk/8 prescale
                        cnt++;
                        if (cnt > 155) cnt=0;
                } else if (PINB & 1<<SENSOR) {
                        output_low(PORTB,LED1);
                        output_low(PORTB,LED2);
                        sleep(300);
                        output_high(PORTB,LED1);
                        output_high(PORTB,LED2);
                        sleep(300);
                        time_delay++;
                } else {
                        time_delay = 0; // reset the time delay
                        //turn of leds
                        output_low(PORTB,LED1);
                        output_low(PORTB,LED2);
                        //stop timer
                        TCCR0B = 0;
                }



    }

The cnt variable keeps track of the index into the musical sequence. This is so that if the song is triggered it won't always start from the beggining but instead begin where it last left off.

Large amount of read-only data and pgmspace.h

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.




Copyright (c) jarv.org Verbatim copying and redistribution of this entire page are permitted provided this notice is preserved.
Validate (nerd)