As I mentioned in a previous post I've been working on a simple adaptor to let me quickly and easily program ATMega chips though an standard AVR ISP header. After a few delays I've made a fair bit of progress on this (and even got a test sketch transferred an running through the bootloader I programmed on an ATMega8). It's by no means complete but I'm well on the way.
The Programming Adaptor
The programmer I'm using is a variant of the USBASP programmer with a 10 pin ISP header (they also come in 10 pin variants - see this page for more details). If you are using a different programmer the command line you use will be slightly different - look at the documentation for avrdude for more information.
The schematic for the adaptor is shown in the image to the left (all the files for this post are available on my Arduino GitHub project in Fritzing format). It's really quite a simple circuit (although I'm embarrassed to say I managed to muck it up pretty badly in the beginning, hence the fairly large revision number on the schematic).
The inputs from the ISP header are fed to the appropriate places on the ATMega (and this should work for a range of ATMegas including the 8, 48, 88, 168 and 328). The SIL (Single InLine) pin-out is for the ISP header breakout module I built, you can get the Fritzing part from my Fritzing parts project. The pin numbers on the schematic represent the pins of the breakout board - not the pin numbers on the ISP header. The mapping is as follows:
Breakout Pin|ISP Pin|Breakout Pin|ISP Pin ------------|-------|------------|------- 1 MOSI |1 |6 Vcc |2 2 NC |3 |7 GND |4 3 RESET |5 |8 GND |6 4 SCK |7 |9 GND |8 5 MISO |9 |10 GND |10
If you are using a 6 pin ISP header you could create a compatible adaptor fairly easily. Or you can just download the Fritzing file and modify it to suit your needs.
Apart from the ISP header there is a 10K resistor that keeps the RESET pin pulled high until the ISP pulls it low. Some similar circuits I researched recommend using a 100nF capacitor between RESET and GND and I did have this in the circuit originally. Unfortunately I could never get it to work, I think it kept RESET low for too long or the inherent capacitance problems with breadboards was interfering with it somehow. I've taken that out of the final circuit although it may go back in once I've moved it from the breadboard to a real PCB.
The other thing I've added is a 16MHz ceramic resonator to provide the clock input. A brand new AVR chip is configured to use it's internal 8MHz clock with a clock divider of 8 (leaving it running at 1MHz) so it doesn't need it. If you need to reflash a chip that has been set to use an external oscillator though it does expect some sort of clock source. I chose a resonator over a crystal because timing is not that critical in this situation and it reduced the component count.
The circuit does expect to be powered by the programmer (this is a jumper switch on most USBasp programmers). If the type of programmer you use doesn't support this you will need to provide a 5V supply (and disconnect the 5V line from the ISP header).
Testing the Adaptor
The weapon of choice for programming AVR chips is avrdude which is part of the Arduino IDE. I'm using CrossPack on my laptop (it's a MacBook running OS/X) so I have avrdude on my command line already.
The first step is to try and read the flash memory from the chip. This will confirm that the programmer is working, the board is wired correctly and won't try and push anything to the chip that will potentially damage it. The command I used was:
avrdude -p m8 -c usbasp -U flash:r:myflash.bin:r
My testing was done with an ATMega8 so the -p m8 tells it what part to expect. The -c usbasp tells it what programmer to use and the rest of the command indicates we want to read the contents of the flash to a file called myflash.bin.
If it doesn't work, you will get something like this ...
avrdude: set SCK frequency to 93750 Hz avrdude: warning: cannot set sck period. please check for usbasp firmware update. avrdude: error: programm enable: target doesn't answer. 1 avrdude: initialization failed, rc=-1 Double check connections and try again, or use -F to override this check. avrdude done. Thank you.
My first tests didn't work. Initially it was because I really mucked up the circuit (I blame an ongoing cold and late nights). Once I'd redesigned and rebuilt the circuit (and, of course, double checked all the connections) I tried again. Another failure. This was because of the capacitor I had between the RESET pin and GND, I discovered that my monitoring the RESET pin with a multimeter.
The next failure was a bit of a gotcha. If you have a fresh AVR straight from the factory it's configured to run at 1MHz which means the default programming speed is too high for it. As you can see from the warning above the USBasp I have doesn't support changing the programming speed through software, there is a pin header that needs to be shorted out to put it in a low speed mode. Once I did that everything started to work and the response from avrdude looks like this ...
avrdude: set SCK frequency to 93750 Hz avrdude: warning: cannot set sck period. please check for usbasp firmware update. avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.02s avrdude: Device signature = 0x1e9307 avrdude: reading flash memory: Reading | ################################################## | 100% 48.71s avrdude: writing output file "myflash.bin" avrdude: safemode: Fuses OK avrdude done. Thank you.
Burning a Bootloader
To be Arduino Compatible it really needs to play nicely with the Arduino IDE so that means putting a compatible bootloader on the chip. I really don't want to be mucking around with this programmer much - I'd prefer to be able to just push new code to the chip directly through an FTDI cable.
Following the instructions on this site I set up my Arduino environment to add an ATMega8 based board using the internal clock and the bootloader they provided. Once the board and programmer type were selected I successfully burnt the bootloader through the Arduino IDE.
To make sure it actually did something I repeated the command show earlier to read the flash from the chip into a different file and compared the two of them - they were definitely different and different in the expected place (the bootloader area of the flash).
Building a Babyduino
It turns out you can make an Arduino compatible circuit with just 4 components - 2 resistors, a LED and the ATMega chip itself. You could even skip the LED and one of the resistors if you don't want any visual feedback (most Arduino sketchs assume there is a LED connected to PIN13 though - it's worth keeping it there).
You can see the circuit for the system to the left. This can be built up very easily on a breadboard and then extended with your own circuitry (which was the point of all of this after all). All you need to provide is an FTDI cable header so you can load new code onto the chip directly from the Arduino IDE.
All that is provided is a 10K pull-up resistor to keep reset high and an LED with an appropriate current limiting resistor on what Arduino considers PIN13. There is no reset button (I am considering adding a pin header that can be shorted out to cause a reset though) and starting with these basic components you can build your custom circuit around it and lay out a PCB without the restrictions of the Arduino shield footprint.
Loading a Sketch
Given that the main goal of this was to make something that can be used through the Arduino IDE just like a real Arduino we need to be able to compile, load and run a Sketch on the target system. Unfortunately this bit isn't really working properly yet.
Using the same configuration I got the bootloader code from I can't send a Sketch to the target board directly from the IDE - I get an error 'Yikes! Invalid device signature.' even though I correctly detect the device signature when programming the bootloader (even when I re-program the bootloader after a failed Sketch transfer).
Turning on verbose output for transfers I can see that the IDE and the bootloader are happily talking to each other, it's only the device verification that is failing. If I copy and paste the command that the IDE is using and add the -F (force) option it correctly writes the the Sketch and it runs just fine (the Sketch I'm testing with has a command interface over the serial port - I can enter commands and get the response I expect). I think this is a software problem (in the bootloader code).
Another problem I'm having is electrical, the board is built using an external power source but if I cut that source I'm still getting power through to the ATMega chip (enough that the LED is very faintly lit) until I unplug the FTDI cable. I'm not using the 5V supply from the FTDI cable at all so I'm not really sure where this power source is coming from.
At this stage I can load sketches through the bootloader (but not via the IDE) and powering down the unit requires unplugging the FTDI cable as well as cutting the external power source. Not insurmountable problems but problems all the same.
I'm confident that I have solved most of the major problems and have a pretty good idea on how to solve the remain ones. So now I'm going to promote this to it's own project page complete with a GitHub repository.
The first step is to find a decent bootloader that can be used on a range of ATMega chips (the ATMega8 and ATMega168 are obvious first targets but I'd like to support the ATMega48, ATMega88 and ATMega328 as well). I'm going to do some experiments with optiboot which seems to be nice and small.
Finally I need to make sure all of this integrates into the Arduino IDE easily - after that I can start looking at starter schematics to use for your own designs and breadboard modules.
I'm sticking with the name Babyduino, it seems to suit what I am trying to do and is kind of cute. A quick Google search shows that it's not used much which doesn't hurt either.
Stay tuned, this is a project that is going to grow.