Pages

Wednesday, July 4, 2012

Tutorial - ArduinoISP Duemilanove with Optiboot

Hey everyone,

This will be technically a few tutorials in one as I intend to not only teach you how to interface two Arduino's together for In-System-Programming but also how to upgrade and change the firmware built in (so it will probably turn out much longer than my Dosbox VGA Tutorial). This method does require a second Arduino board to act as our ISP Programmer but there is another method called Bit-Banging where you connect the 4 pins called the X3 header on the Duemilanove, usually located next to the FTDI chip and hook them to the ICSP pins on the same Arduino, since I won't be using that method in this tutorial feel free to check out this tutorial instead if you only have a single Arduino on hand. I may append the Bit-Bang method to this tutorial or make a new one in the future now that I have the necessary connectors on hand to do it but for now the link will suffice.

I remember reading somewhere on the internet about the overhead of having a boot-loader on your Arduino vs direct upload of a compiled program. The convenience of a boot loader is that it allows you to upload sketches to your Arduino using a USB serial interface while the only down side is less memory for your uploaded project due to the memory requirements of the boot-loader and a delayed start up time for the Arduino. The newer version of the Arduino called UNO comes with a much smaller and faster boot-loader called Optiboot which gives back around 1.5kb's of memory for your projects. Later on I'll teach you how to upgrade your older Diecimila or Duemilanove with this new boot-loader.

The First Part of this tutorial is to teach you how to connect an Arduino to another Arduino by using the In-System-Programming method or ISP for short. One of the Arduino's will be your programmer while the other is the slave that you will be modifying the firmware on. When I first learned how to do this I was using my Arduino Mega 1280 to reprogram my Arduino Duemilanove to both upload raw sketches without a boot loader as well as successfully install the Optiboot loader. After I had worked out all the kinks and solved some problems I decided that it might be beneficial to share my experience and teach others how to use this method too. At first I just had floating wires everywhere connecting the two together but I spent a good afternoon constructing a proper cable that is much more stable for connecting them which you can see here:

















For the time being you can simply connect everything with wires for this tutorial but feel free to use hook up wires with pins if you have any or even make your own cable. I didn't have any header pins available when I made this so I just used pieces of solid wire I cut from a spool which needed a little sanding to remove the outer cover since solder wasn't sticking to it. Depending on what Arduino you use changes which pins we will be using to connect the programmer to your slave board. The 4 main pins that we will be using are listed here:

Master-In-Slave-Out (MISO) = Pin 12 on Duemilanove and Pin 50 for Mega
Master-Out-Slave-In (MOSI) = Pin 11 on Duemilanove and Pin 51 for Mega
Serial Clock (SCK) = Pin 13 on Duemilanove and Pin 52 for Mega
Slave Select (SS) = Pin 10 on Duemilanove and Pin 53 for Mega

If your chosen programmer board is a Diecimila or Duemilanove then connect the wires like this: Connect Pin 10 of the programmer to the reset pin of your slave, connect Pin 11 to Pin 11 of your slave, connect Pin 12 to Pin 12 on your slave and then lastly connect Pin 13 to Pin 13 on your slave.

If your chosen programmer board is an Arduino Mega then connect the wires like this: Connect pin 53 to the reset pin of your slave, connect Pin 52 to Pin 13 of your slave, connect Pin 51 to Pin 11 of your slave and lastly connect Pin 50 to Pin 12 of your slave.

Feel free to check out this link if you need more help connecting them.

What we have done is connect the two boards together using the Serial Peripheral Interface (SPI). Since only the programmer will be connected to the computer we will need to make sure your slave has access to power as well. To do this simply connect a wire from the 5v pin of your programmer's power rail to your slave's 5v pin and another wire connecting your programmer's Ground pin to your slave's Ground pin.

Technically you could program any number of different Arduinos with this system; just look up the hardware page and find the 4 pins needed for SPI interfacing.



The Second Part will involve uploading a project called ArduinoISP (which comes with the Arduino software) to your programmer board which will allow us to reprogram another board connected through the SPI system. First you'll need to make sure you have installed the programming IDE for Arduino which you can download from here. Simply choose the correct version for the operating system you have then download and install it. Once it's installed open up the program and on the top menu click File, then mouse over Examples and finally click on the ArduinoISP project which will open up an instance of the code. Now attach your desired programmer board to the computer, click on Tools and open up boards, select the board you wish to use as your programmer; in my case I chose "Arduino Mega (ATmega1280)". Go back to tools and select the Port your programmer is attached to. Finally you can click the upload button at the top that looks like an arrow pointing right which will upload the ArduinoISP project onto your programmer.

Now you might have noticed that I have an LED display on my cable. This is related to the ArduinoISP software which uses Pin 7 to indicate that it's programming, Pin 8 to report any errors and Pin 9 which is the heartbeat that pulses to indicate that everything is good; this information can be found in the top comments section of the project code. Feel free to add these LED's to your setup so that you can know when things are working properly or have failed somewhere. If you are new to connecting LED's to Arduino's then I recommend this great tutorial by Lady Ada.

Awesome, now that we have your programmer board all set up and connected to the slave board that we wish to reprogram, we now need a way of uploading your new boot-loader to it. A good way of testing your programmer board is to burn the default boot-loader onto your slave board. To do this, make sure that the programmer is attached to your computer and that both boards have power. Open up the Arduino programming IDE that we recently installed, then under the Tools select the board that is your slave; in my case I selected "Arduino Duemilanove /w ATmega328". Then in the Tools menu go to Programmer, then select "Arduino as ISP", once that's selected go back to Tools and click on "Burn Bootloader" and you should see your programmer board upload the boot-loader to your slave board with the default blink sketch blinking the led on Pin 13; just like when you first bought the board from a reseller.

Alright, now that we can upload to your slave board successfully using your programmer there's lot of things we can try out. I'll show you how to upload your sketches without the need for a boot-loader as well as upgrading your older Arduino's with the latest Optiboot loader. To do this we will be using a program called AVRDude which comes with WinAVR. You can download the latest version from its source forge page here then install it. WinAVR's installer will register the AVRDude executable with Windows so it can be accessed via command prompt. You can access the command prompt in Windows a myriad of ways. I usually just press the Windows key and type "cmd" or "powershell" and hit enter in Windows 7 but for this tutorial I'll be using the power-shell as my preferred terminal. Alternatively you can open the command prompt via the start menu and click on run, then type "cmd" or "powershell" and hit enter. You can even shift + right click in any folder or on the desktop then click the new "Open command window here" option that appears. Once you have your terminal open type "avrdude" and hit enter, you should see a list of available options listed like I show here:

Command terminals on Windows default the starting location to the user's folder unless you used the "Open command window here" method which will inherit the folder you right clicked in. If this is the case then simply type "cd.." and hit enter, do this again and again until you are at the root drive and only see "C:\" in the command window. Here's an example:


This is simply to make uploading a Hex file to your board much easier since you would need to specify the directory that contains your file in full for AVRDude. Feel free to use a folder structure though if you prefer but since your project files are so small it's easy to use the root drive as a temporary folder for uploading. Hex files are the end result of a compile with the Arduino IDE and are encoded in Intel assembly; to learn more about the Arduino build process you can check out this link. In older versions of the IDE you could find the Hex file in your project's directory but the later versions now store the compiled code temporarily in the Windows temp folder which is hidden from the user by default located here:

C:\Users\USER_NAME_HERE\AppData\Local\Temp

This folder is specific to which operating system you are using, in my case I have Windows 7 but if you have a different OS then you can find where the IDE compiles to by initialising verbosity mode. Go to the top menu and click File then Preferences and in the preferences window you should see "Show verbose output during:". Select compile or both if you prefer then hit ok. Now when you click the Verify button you should see where the IDE is compiling the code to.

Lets prepare a project to upload to your slave board without a boot-loader installed. I like the blink project as it give you feedback of a successful upload via the blinking LED. With the Arduino IDE open, go to the top menu and click on "File" then go to Examples/01.Basics and click on Blink. You should now have a Blink project open, since we need the code compiled into a Hex file but we don't want the code uploaded to the board just yet, you can click on the Verify button (looks like a tick) which will compile your code and check for errors but it won't upload the code to the board which can be very useful. While the IDE is open and you have compiled your code, the Hex file can be found in the Temp folder I showed previously; projects in this folder usually start with the name "build" with a series of unique numbers like this "build1544573883262332201.tmp" and inside this folder will be your Hex file and in my case it was called "Blink.cpp.hex". Remember that your Hex file will usually be deleted the moment you close the IDE along with the temporary folder so it's best to find your Hex file and copy / paste it into your C:\ drive for uploading, feel free to rename it to whatever you like; for example: "Blink.hex".

Uploading Raw Sketches

Before we begin the upload, if you are worried about the fact that we will no longer have a boot-loader on the board, remember that you always have the "Burn Bootloader" option at your disposal in the Arduino IDE under Tools; this uploads the default boot-loader that comes with the board you have selected as your slave. Additionally if you go back to the default boot-loader and wish to upload projects to it like normal without a programming board, remember to change the IDE's programmer under Tools back to "AVRISP_II" and set the Board and Serial Port respectfully for the board you plan to upload to.

Alright, now that we have successfully compiled a project and have our Hex file ready to go I can now teach you how to use AVRDude to upload it to your slave board. There's a number of parameters that we will need to pass to AVRDude in order to upload our sketch to the board, this will include the method we are using to upload with, the baud rate, what chip we are programming and where the sketch will be stored etc. Make sure you have a command prompt open and set to your C:\ drive like I showed above.

The First Parameter will be our uploading method; there's numerous options which you can see a full list of if you type "avrdude -c randomtext" since random text isn't an available option, AVRDude will list all the possible upload methods supported. Take note of the last option in the list called "Arduino" which means that an Arduino would be used for our programming method which is perfect for us since we are using one as an ISP programmer. Now that we know which programmer to use, lets move on to the next parameter.

The Second Parameter will be the chip we plan to upload to, if you type "avrdude -c arduino" and hit enter, AVRDude will display a list of supported micro controllers which can be specified with "-p" and then the name of the chip we are programming. If you are unsure of the chip on your board you can check out the Hardware page for your board at the Arduino website which will show the technical specifications that indicates what chip is used. In my case I was using an Arduino Duemilanove with an ATmega328 chip so I would choose "m328p" from the list.

The Third Parameter will be the name of our port that the Arduino programmer is attached to. The best way I find to work this out is to simply reference where the Arduino IDE says in "Tools/Serial Port". Alternatively you can go to your Device Manager and under "Ports (COM & LPT)" you should see a device listed with the port that it uses. You can pass a port to AVRDude by using the "-P" command and typing the port's name after that; in my case it was "-P com3".

The Fourth Parameter will be our desired baud rate which is how fast we will be sending data to our programmer. Since we are going to be using the ISP system we must use "19200" as our overriding baud rate which you can pass to AVRDude with the "-b" command. If this command is not passed you may receive issues with syncing the programmer board.

The Fifth Parameter will specify where in the micro controller's memory that the sketch will be uploaded to; in this case we will be using flash, additionally we will also specify that we wish to write to the memory which is specified with "w" between the colons. You use the "-U" command and then pass "flash:w:" then write the name of your Hex file "Blink.hex", in my case I wrote "-U flash:w:Blink.hex".

The whole command should look like this:
Once you've typed that in, hit enter and if everything goes well, you should see AVRDude uploading the Hex file to the board and verifying that everything was uploaded correctly as you can see here:



And now you should see your Arduino slave board blinking away, since there's no longer a boot loader on the Arduino if you reset the board you'll noticed almost no delay before the code starts again which can be extremely useful for projects that need as much up time as possible during self resets. Another useful feature of not using a boot-loader is that you have a lot more room for large sketches / projects.

Uploading Optiboot

Cool, now that we have successfully uploaded a raw Hex file to our board I'll now show you how to upload the more up to date boot-loader called Optiboot. Optiboot actually comes with your Arduino's IDE software; simply go to the folder you have placed the software in and go to this location:

(Arduino Installation Folder)\hardware\arduino\bootloaders\optiboot

And you should see a Hex file called "optiboot_atmega328.hex", copy and paste this file to your "C:\" drive so we can upload it to our slave board like before. The boot-loaders folder that we just went inside contains the Hex files that the Arduino IDE literally uploads to the board when you click on "Burn Bootloader". The association for each board's default boot-loader is defined inside the "boards.txt" file in the "hardware\arduino" folder, which I'll be talking about more in the bonus tutorial below.

Now inside your command prompt that was used to upload the Blink sketch, we will now upload the Optiboot Hex file. To do this, type exactly what was typed before but change "Blink.hex" to the name of the Optiboot Hex file "optiboot_atmega328.hex" then hit enter. This will take a few seconds longer to upload to the slave board than the Blink sketch since it is much larger file and just like before you should see this:
























The majority of the time that is taken for AVRDude is verifying every bit that was uploaded to your slave board, if you are confident in AVRDude's ability to upload without fault then feel free to pass the "-V" command which will omit the verification process and finalise the upload much quicker.

You should now have an Arduino Duemilanove with the latest Optiboot loader installed :) please note that this new boot-loader has a faster upload allowance and that you won't be able to upload your code using the Arduino IDE with Duemilanove set as your board. Additionally you shouldn't worry if the light is not blinking this time since the new boot-loader doesn't come with it by default. Duemilanoves use "57600" as their baud rate while the Optiboot loader uses "115200" which is two times faster so if you tried uploading sketches the normal way to your new board you'd receive a sync error. Since the Arduino UNO has the exact same chip and parameters as the Duemilanove, you can use the UNO as your uploading board. If you wish to learn more about how you could create a custom board definition for an Arduino Duemilanove with Optiboot then feel free to continue reading my bonus tutorial which will not only show you how to create a custom board but also introduce you to what fuses are all about.

Bonus Tutorial :)

I decided since this tutorial turned out so huge that another complemetary tutorial couldn't hurt and might be of some interest to a few people.

Since we have physically changed the boot-loader that was once on our Arduino to the new Optiboot that comes with Arduino Uno I thought it might be nice to show you how to add a custom board to the Arduino IDE that can represent an Arduino Duemilanove with Optiboot and allow uploading sketches.

To make a custom board that we can use with our new board, we'll need to modify the "boards.txt" file inside the "hardware\arduino" folder. Since the encoding of the file is extended beyond basic ASCII we will need a proper binary editor; Notepad won't be able to format the text correctly. The one I like to use is called Context which you can download here. There's also an editor called Notepad++ that should work. There are lots of editors out there so feel free to choose the one you like best.

Once you have installed an editor, open the "boards.txt" file inside it and you should see all the definitions of the boards currently supported by the Arduino IDE. We will be extending this list with a custom board definition that you can see here:

##############################################################

Duemilanove.name=Arduino Duemilanove w/ ATmega328 - Optiboot

Duemilanove.upload.protocol=arduino
Duemilanove.upload.maximum_size=32256
Duemilanove.upload.speed=115200

Duemilanove.bootloader.low_fuses=0xFF
Duemilanove.bootloader.high_fuses=0xDE
Duemilanove.bootloader.extended_fuses=0x05
Duemilanove.bootloader.path=optiboot
Duemilanove.bootloader.file=optiboot_atmega328.hex
Duemilanove.bootloader.unlock_bits=0x3F
Duemilanove.bootloader.lock_bits=0x0F

Duemilanove.build.mcu=atmega328p
Duemilanove.build.f_cpu=16000000L
Duemilanove.build.core=arduino
Duemilanove.build.variant=standard

##############################################################

Place this between the "Arduino Uno" definition and the "Arduino Duemilanove w/ ATmega328" one. As you can see there's a few differences from the original Duemilanove definition; there's a larger "maximum_size" that takes into account the new memory given back by the smaller bootloader and the baud rate has been doubled to support our new board for uploading. Additionally for those who are curious, the "bootloader.file=optiboot_atmega328.hex" line is actually what the IDE will consider the default boot-loader to upload to your board if you click the "Burn Bootloader" button while the "bootloader.path" specifies what folder inside the "hardware\arduino\bootloaders" folder that the Hex file exists in.

The name before every line must be unique from every other definition or it will not show up in the Arduino IDE. Since the definition for the original Duemilanove was "atmega328" I decided to call the new one "Duemilanove". If you close all instances of the Arduino IDE and re-open it you'll find the new board definition available which you can use to burn sketches to your hearts content. Just remember to change the programmer back to "AVRISP_II" since we won't need the programmer board now that we have a boot-loader.

Fuses are a bit of a misnomer since they don't have anything to do with protecting against power surges etc. In the microprocessor world fuses are simply switches that can be turned on and off to specify how the board should act. The fuses are non-volatile and will remain set even if you erase the board since they have their own flash memory that they are stored in. A word of caution though, you can damage your arduino beyond repair if these are set incorrectly and won't be able to reprogram it using ISP. The only way to recover a damaged chip is to use a high voltage programmer; here's a good example that's compatible with Arduinos.

Fuses are stored as hex values which if converted to binary will show you which switches are turned on and off. Each letter of the Hex value represents 4 bits and since we have two letters that's 8 bits in total or one byte. I'll give an example of the "0xDE" high fuse value of our board definition:

0xDE
or
11011110

To make life easier we can use a fuse calculator to derive the needed Hex values. The one I like to use is here. Simply choose the chip that you are programming; in my case it's "ATmega328P" then click select. You should see the interface expand showing the default settings that the chip has as a factory default. Further down the screen you can find the Hex values in the "Current Settings" area. Any changes you make to the above settings will change the Hex values appropriately. Never set "Reset Disabled" or "Disable ISP" to true unless you know what you are doing since you won't be able to reprogram the chip using the In-System-Programming method. If you accidentally did this and can no longer reprogram the chip just remember to get yourself or make a high voltage programmer: a good example of one can be found here and here. This calculator website kindly displays the commands needed to set the fuses of your board using AVRDude just to the right of the "Current Settings" area:

avrdude -c arduino -p m328p -P com3 -U lfuse:w:0xFF:m
avrdude -c arduino -p m328p -P com3 -U hfuse:w:0xDE:m
avrdude -c arduino -p m328p -P com3 -U efuse:w:0x05:m

After choosing the settings you desire, the Hex values will be calculated, then it's just a matter of passing the correct Hex value to the correct fuse using AVRDude: either Low, High or Extended. I recommend you double or even triple check the settings before uploading to the board just to be safe and don't forget to use your programmer with the ISP cable to code the new fuse settings to the slave.

Some of the settings that are of interest include:

Disabling the "Divide clock by 8" option which will increase the speed of your Arduino to maximum speed but uses more power. Or maybe your project doesn't require much speed and enabling the "Divide clock by 8" feature would lower power consumption which can be handy if your project is powered by a battery.

Turning on "Brownout Detection" if your project is dependant on using the EEPROM for storing information, the moment you go below the brownout power threshold the Arduino will shut down to shield the EEPROM from being erased or corrupted.

To compliment the "Brownout Detection" feature you can enable "Preserve EEPROM memory" which keeps the data stored in the EEPROM even after a chip erase since you may not want the information deleted.

That's all I can think of for now but I do hope this tutorial was helpful

Thanks for reading,
Ashton.

No comments:

Post a Comment