Tiffany Cheng

Made [almost]


Embedded Programming

The task of this week was to program my button+LED board from week 06 to do something, using the FabISP we made in week 03. I was lucky that both my circuits worked correctly from the beginning! I learned how to load code onto the ATtiny44 with .c and .make files. If you have uploaded code with Arduino, you may already be somewhat familiar with C; however, Arduino does obscure many details of what happens under the hood - for example, bytes andd bit masks.


DDRA = B11111110;  // sets pins 1 to 7 as outputs, pin 0 as input
PORTA = B10101000; // sets pins 7,5,3 HIGH

Manipulating ports...
Direction Register - DDRA or DDRB [ read/write ]
Input Pin Register - PINA or PINB [ read only ]
Data Register - PORTA or PORTB [ read/write ]

Read more here!

  • T O O L S
  • Milling Machine: Roland Modela MDX-20
  • Software: Eagle, WebStorm, WinAVR, Arduino
  • Languages: C, Arduino (which is really C)
  • Listening to: Fugees, Erykah Badu, The Beatles

The first step is to read the microcontroller datasheet; to which pin does the LED and button go? For me, it was PA7 (physical pin 7) and PA3 (physical pin 10), respectively. Be certain that your make file references your C code by checking the name of the PROJECT variable. Then compile and upload the program by using:

make -f buttonON.make
make -f buttonOn.make program-usbtiny-fuses 
make -f buttonON.make program-usbtiny

Basically, the first command creates a hex file out of buttonOn.make (which references your project C code). The second line sets the fuses (only needs to be done once) and the third loads the program onto the board. Sweet!!

Here I've added a delay on the condition of button press.

#include   < avr/delay.h >


But I felt that my one color was a little bit limiting. I wanted more than just yellow/orange, so I redid my design in Eagle to include a RGB LED instead. Then I milled the new board on the Modela and stuffed it. I soldered in record time... less than 10 minutes! I'm getting really speedy at this :D

I longed to have a rainbow of colors fading through the cycle at my fingertips, which turned out to be more advanced than I thought. Fortunately, Andrew Mao from last year documented his process on how to implement independant 3-pin software PWM very well (ATtiny44/84 only has hardware PWM on 2 channels). Some notes:

//this color table, values determined through trial and error, scale brightness for PWM
//each LED have different brightnesses at full power (blue requires more power as an example)

const int COLORS[][3] = {
    { 200, 0, 0 }, // red   
    { 120, 45, 0 }, // orange
    { 100, 75, 0 }, // yellow   
    { 0, 150, 0 }, // green 
    { 0, 0, 255 }, // blue  
    { 100, 0, 180 } // violet   

//this function executes one PWM cycle by first turning all the lights on and then off
//brightness is an array that stores the current intended brightness values of the lights

void pwmCycle() {
    set(led_toggle, led_red | led_green | led_blue);    
    int i;
    for(i = 0; i < 256; i++) {
        if (i == brightness[0]) set(led_toggle, led_red);
        if (i == brightness[1]) set(led_toggle, led_green);
        if (i == brightness[2]) set(led_toggle, led_blue);

//this function executes the above several times

void pwm() {
    int j;
    for( j = 0; j < CYCLES; j++ ) {

Another pro tip from Andrew: set the LEDs to output, and turn them off by driving them high. This part was unintuitive to me at first, but I realized that my RGB LED had a common anode with three cathodes for each of the colors, connected to the microprocessor. In order to turn an LED on, the pins have to sink current, which is accomplished by driving them low.

The main loop of this code goes through the color table defined earlier. A nested loop inside of that interpolates from the previous color to the current one, running the PWM cycles to display the color for each interpolated value.

note to self - resolder this with 499 ohm resister isntead of 1k for blue led