For hack #2, I started looking at how I could program an Arduino; an affordable hobby development board which uses an Atmega AVR microcontroller. More information here. We add a twist by not using the Arduino IDE and instead using the old faithful text editor.
Stuff You Need
- Arduino – I was using a Duemilanove
- AVR-GCC
- Avrdude
- Your favorite text editor
- 6 x LEDs
- 6 x 220 Ohm Resistors
- A breadboard
- Cables
- USB cable
- C knowledge
Total cost, £30 or so. All of the software is free and open.
Implementation
On the web you will find the Arduino port map. From here you can figure out how to hook 6 LEDs (with a resisitor each) up to port B pins 0-5. It’s pretty simple stuff, you don’t need a schematic. Now we need to make those leds-a-blinken.
What I needed then was a tutorial. Google quickly lead me to Chris Kuethe’s Arduino tutorial. As it turns out, ckuethe is the avr-gcc maintainer for OpenBSD — small world. By following these tutorials, you can easily get up to speed. Half an hour later and I had a “Knight Rider Emulator” using 6 LEDs:
/* $CSK: lesson1.c,v 1.3 2009/05/17 06:22:44 ckuethe Exp $ */
/*
* Copyright (c) 2008 Chris Kuethe <chris.kuethe@gmail.com>
*
* Permission to use, copy, modify, and distribute this software
* for any purpose with or without fee is hereby granted,
* provided that the above copyright notice and this permission
* notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Adapted as Knight Rider LEDs on an Arduino Duemilanove
* (c) Edd Barrett 2010
*/
#include <avr/io.h>
#include <util/delay.h>
int main (void)
{
uint8_t leds = 1;
/* set PORTB for output*/
DDRB = 0xFF;
while(1) {
for (leds = 1; leds <= (1 << 5); leds <<= 1) {
PORTB = leds;
_delay_ms(200);
}
for (leds = (1 << 4); leds >= 2; leds >>= 1) {
PORTB = leds;
_delay_ms(200);
}
}
return 0;
}
Uploading with AvrDude
But how do we upload the binary onto the storage of the arduino?
This part I had already figured out the night before and it took me quite some time, partially because I did not know what baud rate the Arduino was expecting. Once I had it figured, I adapted the sample makefile found on the arduino wiki — this one is for BSD make (suffix rules work a little differently to GNU make).
# tools
AVRDUDE=avrdude -F -V
OBJCOPY=avr-objcopy
CC=avr-gcc
RM=rm -f
# parameters
MCU=atmega328
F_CPU=16000000UL
BIN_FORMAT=ihex
PORT=/dev/cuaU0
BAUD=57600
PROTOCOL=arduino
PART=ATMEGA3290
CFLAGS=-Wall -Os -DF_CPU=$(F_CPU) -mmcu=$(MCU)
PROG=addr
SUDO=sudo
.SUFFIXES: .elf .hex
.c.elf:
$(CC) $(CFLAGS) -o $@ $<
.elf.hex:
$(OBJCOPY) -O $(BIN_FORMAT) -R .eeprom $< $@
.PHONY: all
all: ${PROG}.hex
${PROG}.hex: ${PROG}.elf
${PROG}.elf: ${PROG}.c
.PHONY: clean
clean:
$(RM) ${PROG}.elf ${PROG}.hex
.PHONY: upload
upload: ${PROG}.hex
${SUDO} $(AVRDUDE) -c $(PROTOCOL) -p $(PART) -P $(PORT) \
-b $(BAUD) -U flash:w:${PROG}.hex
Conclusion
I was pretty impressed with how easy it really was to program an AVR on OpenBSD. The compiler is familiar – it’s just GCC cross targeting, and the editor is familar — in my case it’s vim and not a bloated java GUI.
Ofcourse, this just scratches the surface. Expect further hacks later.
Thanks to ckuethe@ for his tutorial.
Very nice Ed, loved the elegance of the solution.
Pingback: Programming Arduino Uno in pure C « Balau
I suspect “PART=ATMEGA3290″ is wrong, but the warning is being suppressed by the -F option passed to avrdude.
The Duemilanove either has a ’168 or a ’328, so the partno is going to match that. If you have a later device, the partno is going to almost certainly be “ATMEGA328P”.
In fact, the PART and MCU variables in the makefile can be set to this same string.