AVR: Programming the EMSL Target Board from Mac OS X
The EMSL Target Board is built around the ATmega 168 micro-controller (same controller as the Arduino — which, frankly, I couldn’t care less about other than as a source of knowledge…).
It is an extremely easy to use and surprisingly powerful micro-controller. If it weren’t so convenient, I wouldn’t be writing this.
Seriously. If you have any interest in screwing around with micro-controllers, there is little excuse not to dive in now. It is cheap, easy, and powerful.
Beyond the EMSL Target Board, you’ll also need a Lady Ada USBTinyISP programmer that has been appropriately patched (when assembled).
First, grab and install AVR Mac Pack from the fine folks at Objective Development (same source of LaunchBar and Little Snitch — both awesome products in their own right).
AVR Mac Pack has everything needed to talk to the AVR, a compiler that can target the AVR, and support for Xcode based development.
Once installed, the next step is to verify that the programmer can talk to the board using avrdude (all commands assume that $PATH has been updated to include the AVR Mac Pack stuff — be forewarned that the installation of AVR Mac Pack will edit some files in /etc/ to change the shell. It doesn’t work if you are using tcsh):
avrdude -p m168 -c usbtiny -P usb
avrdude: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.
Uh oh! That ain’t good! Oh, that happened because I hadn’t flipped on the “power the target board” switch on my programmer. With the stock USBTinyISP, it’ll be a jumper. Replace it with a switch. You’ll be happier.
Anyway, once on:
avrdude -p m168 -c usbtiny -P usb avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.01s avrdude: Device signature = 0x1e9406 avrdude: safemode: Fuses OK
Woot!
You could use AVR Mac Pack’s avr-project command to create an Xcode project, but it produces an Xcode project that can’t install the built executable from within Xcode. I find it easier to start with the Peggy Makefile. Xcode’s Organizer can be trivially configured such that cmd-b will cause the makefile to build and install the desired chunk of code.
Firs,t you’ll need to edit the opening bits of the maekfile to successfully target the m168 part (this assumes that your source file
PRG = buttflip OBJ = buttflip.o PROGRAMMER = usbtiny PORT = usb MCU_TARGET = atmega168 AVRDUDE_TARGET = m168 OPTIMIZE = -Os DEFS = LIBS =
Now, the makefile claims no need to edit below that particular header. It lies. There are these evil things called “fuses” in AVR micr-controllers that you have to deal with exceedingly carefully. Seriously. Wrong value can lead to a nice bit of inert plastic encased silicon.
Actually, you really want to change the makefile preamble to also include a CPU speed indicator (which is set via the ungodly confusing fuse values mentioned below):
AVRDUDE_TARGET = m168 OPTIMIZE = -Os DEFS = LIBS = HZ = 1000000
And, slightly below that, change the definition of CFLAGS to this:
override CFLAGS = -g -DF_CPU=$(HZ) -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
You’ll see why in a second.
Ben pointed me to the AVR Fuse Calculator. God send. For now, I’m sticking with the default fuse values because I’m too lazy to go read the spec sheet closely enough to figure out what the more optimal settings might be:
install: $(PRG).hex
avrdude -p $(AVRDUDE_TARGET) -c $(PROGRAMMER) -P $(PORT) -v \
-U lfuse:w:0x62:m \
-U hfuse:w:0xDF:m \
-U efuse:w:0x01:m \
-U flash:w:$(PRG).hex
I totally don’t understand the fuse values. The default fuse calculator came up with a different value for efuse. avrdude complained. I set it to 0×01 because that was the value avrdude indicated was expected. It works. I have no clue why.
OK… great… now… need some kind of Hello, World! for a micro-controller. Sounds like it is time to Blink an LED or something.
Of course, you’ll need an LED. I used a random red LED because they are the cheapest and most commonly available. Thus, if I melted the LED, no real pain incurred.
You’ll also need a resistor to drop the voltage a bit for the LED. I used a 120 ohm resistor as that was handy — anything in the 120 to 220 ohm range should do fine.
LEDs have polarity. That is, they only work one way. The lead coming out of the flattened side of the LED is the negative lead (or, if you haven’t clipped them, the longer lead is the positive lead).
To make this code make the most sense, I wired up the LED such that it turns on when the output pin is turned on and turns off when off. That is, the positive lead of the LED — the round side — is connected to the PB0 pin of the ATmega168 chip. The negative is connected to one lead of the resistor. The other lead of the resistor is then connected to ground (GND) on the target board.
Aside: Usually, the LED will be hooked from VCC [positive] to the chip through the resistor. I’m not fully sure why, but it makes the code backwards– setting the bit turns off the LED, and vice-versa. Confusing. For this, I hooked it up the intuitive way.
The code is rather straightforward:
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
DDRB = 255U; // Make all PB* pins output
while (1) {
PORTB = 0x1; // high
_delay_ms(250); // 1/4 second on
PORTB = 0X0; // low
_delay_ms(2500); // 2.5 seconds off
}
}
That is it!
Setting DDRB simply configures all PB# pins to be outputs. Overkill for only one pin, assuredly.
Setting PORTB to 0×1 simply turns on pin PB0 — takes pin PB0 high [5v]. If the LED were hooked to PB1, that would be 0×2. PB3? 0×4. PB4? 0×8. Etc… It is just basic bitwise I/O.
The calls to _delay_ms() entirely rely upon the setting of HZ in the makefile (which sets F_CPU). The ATmega168 part has an internal oscillator running at 8 MHZ, but that is subdivided to yield a 1 MHZ CPU speed.
End result?
The LED should blink; short tim on, longer time off.
Next up?
Two LEDs & some useful tools for manipulating bits. And the circuit will be refactored into a more standard form (LEDs connected to VCC).
The latest source code for this project is available in my personal subversion repository here: http://svn.red-bean.com/bbum/trunk/avr/ATmegaXX8/one-led-blinker/.




March 15th, 2008 at 10:42 am
> If you have any interest in screwing around with micro-controllers, there is little excuse not to dive in now.
I still have two AVR microcontrollers (ATMega32?) in my electronics stash from a piezo->MIDI converter I started in high school but lost momentum while at college. Great to know that there is a good toolchain for Mac, but my excuse now is that there are more pressing matters I should be attending to in Xcode. (I must ship.) I’ve bookmarked this, though, in hope of having a chance to return. Maybe when I have kids, I can get them interested in this kind of stuff!
March 17th, 2008 at 7:43 am
Don’t knock Arduino…it’s a nice little widget with a free development environment, written in Java, ready to go. The language is very C like. Forty bucks will get you an Arduino board with microcontroller and away you go. I’ve done dozens of projects on that little board, it’s very useful…and yeah, I use XCode the rest of the time for my other stuff.
March 17th, 2008 at 12:10 pm
Arduino is a terribly useful/cool platform, for what it is. It just happens to not be something I care about in that it is too close to a computer for what I need.
If I were to build, say, something like the Stoker, I would base it on an Arduino so I could have a TCP stack.
March 19th, 2008 at 1:47 am
Usually, the LED will be hooked from VCC [positive] to the chip through the resistor. I’m not fully sure why…
It’s because most microcontrollers can sink more current than they can source. Page 80 of the datasheet for the AVR Tiny12 chip I’m playing with shows the ability to sink up to 50mA, but it can only source 4(!) mA while providing 4.5V of the 5V supply. Pull as much as 16mA from it as a positive output and it drops the voltage to just 2V.
April 5th, 2008 at 1:41 am
[...] left is a simple EMSL AtmegaXX8 Target Board (same board I have written about before) 3 bit up/down counter [...]