Home

Working on software for a second system

January 18, 2010

As regular readers (if any exist) know, I am slowly developing a better bike light for my own amusement. Said light will have 3-10 watts of LED light, meaning 3-10 1-watt power LEDs, at an incremental cost of $10 per LED, so it will actually provide a useful amount of light. One of the hurdles to cross is programming an embedded processor, in particular one with interrupts, because some events (wheel spins) will happen whenever they will. I am using CrossPack AVR to develop and download code. I got my starting code from Instructables, and an 8 pin AVR development board (not necessarily necessary, but sometimes I do make a time/money tradeoff) from Sparkfun, and USBtinyISP programmer (made from a kit) from Adafruit (this was much easier than dealing with the finicky Windows-centric programmer from Sparkfun). An 8-bit board is suitable for an ATtiny13 and ATtiny25, 45, and 85; that had been my original plan, but now I think that ultimately I will use a larger chip. However, all the hard (i.e., “new”) stuff can be tested with this setup.

I added an LED (with limit resistor) to pin PB4 on the development board:
Untitled

LED+resistor detail:
IMG_1235 copy

Backside detail (notice the LED wire end wrapped over to ground):
Untitled

First interrupt program

This blinks the LED on and off at (about) 2.5Hz. I am not 100% sure of the chip’s clock rate yet, it appears to be pretty close to 1 MHz (is it 1,000,000Hz or 1,048,576Hz?). The empty interrupt vector serves only to awaken the processor from its sleep. The magic numbers come from the Atmel documents; the sleep code is taken from “man avr_sleep”.


/* Blinker Demo */

/* Include useful pre-defined functions */
#include     // Defines pins, ports, etc to make programs easier to read
#define F_CPU 800000UL	      // Sets up the default speed for delay.h
#include 
#include 

EMPTY_INTERRUPT(TIM0_COMPA_vect)

/* WGM02:0 = 2 Clear Timer on Compare Match */
/* TCCR0A = 2 = WGM02 */
/* OCR0A = max timer value */

int main(){

  cli();
  TCCR0A = 2; /* Clear timer on compare match */
  TCCR0B = 5; /* /1024 prescalar = 1024 Hz */
  OCR0A = 205; /* 1024/205 = 5 = 2.5 Hz */
  TIMSK0 = 4;   /* OCF0A */
  DDRB = _BV(PB4);		      /* enable output on port B, pin 4 */

  /* Enter loop with interrupts disabled. */
  while(1){

     sleep_enable();
     sei();
     sleep_cpu();
     sleep_disable();
     PORTB = _BV(PB4);
     
     cli();
     sleep_enable();
     sei();
     sleep_cpu();
     sleep_disable();
     PORTB &= ~_BV(PB4);
     cli();

  }

  return(0);
}

The second program dynamically adjusts the counter interrupt comparison value to vary the blink rate; it should change from slow to fast and back again. This code is not strictly kosher, in that there would be a risk of the counter and the comparison value crossing, if the counter rate were not downsampled by a factor of 1000, and the minimum value is far clear of zero.


/* Blinker Demo */

/* Include useful pre-defined functions */
#include     // Defines pins, ports, etc to make programs easier to read
#define F_CPU 800000UL	      // Sets up the default speed for delay.h
#include 
#include 

short ocr_max = 240;
short ocr_min = 50;
short direction = 8;
short ocr_val = 205;

ISR(TIM0_COMPA_vect) {
  if (ocr_val >= ocr_max)
     direction = -8;
  else if (ocr_val <= ocr_min)
     direction = 8;
  ocr_val += direction;
  OCR0A = ocr_val;
  /* Sleaze by on the compare value, it is large and downscaled. */
}

/* WGM02:0 = 2 Clear Timer on Compare Match */
/* TCCR0A = 2 = WGM02 */
/* OCR0A = max timer value */

int main(){

  cli();
  TCCR0A = 2; /* Clear timer on compare match */
  TCCR0B = 5; /* /1024 prescalar = 1024 Hz */
  OCR0A = ocr_val; /* 1024/205 = 5 = 2.5 Hz */
  TIMSK0 = 4;   /* OCF0A */
  DDRB = _BV(PB4);		      /* enable output on port B, pin 4 */

  /* Enter loop with interrupts disabled. */
  while(1){

     sleep_enable();
     sei();
     sleep_cpu();
     sleep_disable();
     PORTB = _BV(PB4);
     
     cli();
     sleep_enable();
     sei();
     sleep_cpu();
     sleep_disable();
     PORTB &= ~_BV(PB4);
     cli();

  }

  return(0);
}

Makefile prologue (for completeness, includes edits for my configuration):

# WinAVR Sample makefile written by Eric B. Weddington, Jrg Wunsch, et al.
# Modified (bringing often-changed options to the top) by Elliot Williams

# make all = Make software and program
# make clean = Clean out built project files.
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
#                4.07 or greater).
# make program = Download the hex file to the device, using avrdude.  Please
#                customize the avrdude settings below first!
# make filename.s = Just compile filename.c into the assembler code only
# To rebuild project do "make clean" then "make all".

# Microcontroller Type
MCU = attiny13
# MCU = attiny2313
# MCU = atmega8

# Target file name (without extension).
# TARGET = LED_Demo
TARGET = LED_IntDemo2

# Programming hardware: type avrdude -c ?
# to get a full listing.
AVRDUDE_PROGRAMMER = usbtiny              # official name of 

# AVRDUDE_PORT = /dev/parport0           # linux
AVRDUDE_PORT = lpt1		       # windows

############# Don't need to change below here for most purposes  (Elliot)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: