I often see quite large scale projects online made with Arduinos, but as a person who has moved from AVRs to Arduino what I see doesn’t make a lot of sense. The arduino is essentially a prototyping device and while there is nothing really wrong with using it in a final design, much can be gained from moving away from it. Just to clarify: I understand that an arduino is built around an AVR, but the problem is that much of the power (and complexity) is abstracted away by the software. Perhaps it’s just me, but I like to know exactly what is going on inside my processor. On top of this, AVR Simulator is a godsend for hunting down that last bug.
The real reason behind this whole thing is price. From Little Bird, the cheapest Arduino is $17.50 while the sale is on, and that has no USB chip on it. The ones with the USB chip are >$40, not to mention the price of accessories. An Atmega88 at Futurlec is $3.80, a crystal is $1, caps are a few cents and so is the pullup resistor for reset (this will all be explained in a later post).
Development Environment
The basic tools I use for AVR development are:
- AVR Studio - A free IDE with AVR Simulator built in
- WinAVR – A free C compiler for AVRs (based on gcc) and other tools
- STK500 – There is a multitude of free or prebuilt development boards on the net
You won’t need any of these till the next tutorial; we are just going to talk about hardware for now.
AVR Hardware
You can find the datasheet for the Atmega88 here. Download it and save it somewhere safe or take it down to the print shop and get it bound; you are going to need to use it a lot. To start with today, let’s take a look at all the funky acronyms on the first page. Make sure you have it open in a different browser window or tab so you can follow along (a wikipedia tab can’t hurt either).
RISC stands for Reduced Instruction Set Computer. An instruction is exactly what you think it is; a piece of information passed to the CPU telling it to do something. Examples include MOV (Move), AND (Bitwise AND) and LEA (Load Effective Address). As you can see by the next line on the page, the AVR only has 131 instructions so after a bit of practice you can pretty much remember the whole set. As a point of comparison, the regular x86 architecture for PCs is a CISC architecture (Complex Instruction Set Computer) and has thousands of instructions. The beauty of a high level programming language like C is that you don’t need to remember any instructions; the compiler translates your code into the correct ones depending on the architecture you are compiling for.
The next line tells you that the mega88 has 32 8bit registers (the size of a C char). Registers act in a very similar way to memory, but they are located inside the CPU and thus are much, much faster to access. The “Fully Static Operation” bullet simply indicates that, as long as power is still applied, the AVR will maintain its current state if you take the clock source away and will pick up where it stopped once the clock is enabled again. 20 MIPS @ 20MHz means that it can process 20 million instructions per second when the clock source is 20MHz; pretty snappy!
You have 3 types of memory inside of an AVR: Flash, EEPROM and SRAM. The flash is where you store your code (the binary equivalent of all your instructions). Flash is non-volatile, meaning that it will not be erased if you take away the power. Whilst you can reprogram the flash memory while your code is running, it can cause all sorts of nasty things to happen so just assume that flash is read only unless you are using a device programmer or loading new code. So how do you store things between power cycles then? EEPROM (Electrically Erasable Programmable Read Only Memory) is also non-volatile, but you can read and write to it as much as you want (the name is kind of a misnomer). Just remember though, the EEPROM has a limited number of guaranteed erase cycles (100 000 for the mega88) so don’t go too nuts writing to it or it will wear down. SRAM is volatile (you will lose it between power cycles) but it is much faster than the other two types and doesn’t suffer from the wear down problem.
Bootloaders
Let’s take a quick jump back to Arduino land. If you’ve been paying attention, you should have been wondering why you can program an Arduino without a programming device, but you need one for every other AVR. This is the result of a magical little piece of software called the bootloader. A bootloader is a piece of software that retrieves new code from a non-standard location and loads it into the flash memory. In the Arduino, the bootloader retrieves the code over USB from the Arduino software. If you look in the memory section of the datasheet, you will see one of the bullets is “Optional Boot Code Section”; this is where the bootloader resides. When you click Upload in the Arduino software, the chip is put through a soft reset, after which the bootloader starts up and waits for data over the USB port. You can write a bootloader to load code from almost anywhere but you need a real device programmer to load the bootloader onto the chip the very first time and the maximum code size is often quite small so you will need to plan accordingly (you can’t perform RSA signature checking for example). An interesting point to note here is that the Arduino bootloader pretends to be an STK500 in order to leverage the already prevalent STK500 drivers.
Device Features
In a PC, all of these components we have been talking about are separated. The CPU is a different module to the RAM, which is a different module to the Southbridge, etc. The difference between a microprocessor and a microcontroller is that in the latter most of these components are already built in. You sacrifice some flexibility for simplicity but even then, certain AVRs have an external memory interface and almost all you can connect an external EEPROM to. Some of the modules that are built in to microcontrollers are not critical to their operation but simply provide an easier way to perform common tasks. If we look at the “Peripheral Features” section on the summary page, we can see what extra tasks this AVR can handle.
The mega88 three timers, two of which are 8 bit and one that is 16. This means that the modules can count to 255 (0xFF) and 65535 (0xFFFF) respectively. All three timers can be given a separate prescaler, meaning that for n cycles of the oscillator on the device with prescaler q, the clock will increase by the closest rounded down integer of n/q. Now that is a bit of a mouthful, so an example is probably in order: if you set the prescaler to 64, then the timer will increment every 64 clock cycles. Likewise, if you set the prescaler to 1024 then the timer will increment every 1024 cycles. The “Compare Mode” refers to the timer modules’ ability to trigger interrupts. I will talk about interrupts in more detail at a later time, but they are essentially events that tell the CPU to drop everything and handle this event immediately. The “Real Time Counter with Separate Oscillator” bullet refers to the fact that you can also have a counter that increments independently of the CPU clock cycles; you provide it with its own oscillator.
The next bullet down states that the mega88 has six PWM channels. PWM, or Pulse Width Modulation, is quite a complex topic (there are still a few bits I am hazy about) but for now, just pretend that it is a way of generating analog volatages in our digital environment. The six channels means that there are six pins on the device capable of PWM.
ADC (Analog to Digital Converter) allows you to read an analog voltage. So while a regular pin could only tell you whether it is +5v or 0v, an ADC pin could tell you that the voltage is currently +2.5v or +3.8v. The “10 bit” refers to the resolution of the module, or to how many decimal places it can be accurate. 10 bit means that it can tell you with an accuracy of 0 to 1023 (0×3FF). If this doesn’t make sense, don’t worry; more on this will come later. In the TQFP and QFN packages you get 8 pins that have these ADC modules attached, while in the PDIP package you get 6. TQFP (Tiny Quad Flat Pack, see image at the top of this post) and QFN (Quad Flat No leads) are chip packages used by soldering machines and expert solderers; you will most likely come accross PDIPs (Dual Inline Packages) in your electronics capers which are much larger and, unless you have the dexterity of a neurosurgeon, easier to deal with.
UART, SPI and I²C are all data transfer protocols; USART (Universal Synchronous/Asynchronous Receiver Transmitter) is the same one the COM port on your PC uses (although COM ports have been mainly phased out by now). SPI (Serial Peripheral Interface) is a special interface for talking to high speed devices like external EEPROMs or flash memory. Finally, I²C (Inter-Intergrated Circuit) is a protocol for connecting lots and lots of devices together. I²C is the protocol you will come accross the most in microcontroller-compatable chips; things like digital I/O, digital thermometers, external ADCs, real-time clocks (actual time clocks) and more. All of these have been abstracted by the underlying hardware to make them easier to use.
Although there is a lot more in this section, I am only going to talk about two more important parts now because let’s face it, this post is already long enough. The first is the external and internal interrupt sources. The AVR has many interrupts, from a timer match to a pin being pulled to +5v to a byte being received over I²C. They are very useful because they allow the AVR to become reactive as opposed to having to check for events over and over again (this makes the code much simpler as well). Finally, we have the 23 programmable I/O lines. If you look at page 2, “Pin Configurations”, you can see that most of the pins have P followed by a letter and then a number. This is a programmable I/O line that you can set to high or low. As an example, PC5 stands for Port C, pin 5. There are four ports on the mega88. The other labels in brackets refer to the modules we have been talking about previously and the pins that they can control.
In Conclusion
So concludes the basic introduction to AVR microcontrollers. Next time, we’ll go through a simple “Hello World” type application.
I would just like to say that I understand AVRs are complex. I never said that they weren’t. But if Arduinos are too expensive to include in your project or you would like to write your own libraries for them, learning about the underlying hardware is a must. Or perhaps, like me, you just like to know what is going on under the hood.
Thank you so much for the introduction and the information…
Thanks for thie, I hope you’ll go on
This is a very interesting article Jeremy. Please continue with your planned “Hello World” type application.
While it can be agreed that a good reason to move away from Arduino into lower level AVR code is for optimization, your argument about cost: “The real reason behind this whole thing is price” is a bit specious considering that the arduino code is free (ok open source) and you can use any of the supported AVR devices with pennies of hardware. Since you already have your own JTAG or bootloader setup (you can make your own for less than $10) you don’t need the USB port of the full kit Arduino brand board. In addition there are the Freeduino boards, and various other solutions that maybe hit double digit dollars.
So not arguing against making the leap into big-girl AVR programming – the closer to the iron you are the better you can make your app run (or screw it up). Its just focusing on cost like some big Cadillac fatcat lighting his cigars with $17 bills is not the only way to get into Ardiuno AVR.
Hi ernie!
I don’t quite get the Cadillac reference (I am Australian!) but I’m going to assume that you mean I am penny pinching like an overzealous MBA. And you would be correct but for a different reason: I am a poor student and penny pinching is what I have to do! Also the prices of some individual AVRs (with internal clocks) can be in the realm of cents, not dollars. This means for the price of a $22 arduino you could get 36 ATTiny11s or almost 8 ATMega88s. That’s 8 projects/experiments for the price of one. Sure you can use the cheaper options but you are still going to be paying for components that you don’t need. Also I should mention that back when I wrote this post there were few low cost arduino solutions I knew of. I’m not saying no-one should use arduinos, just that if you have the knowledge to move up in the hierarchy then there are a ton of benefits waiting for you (the most important of which is cost savings).
Jeremy,
I believe what Ernie was trying to say is that if you’re comfortable with Arduino, you can just buy a microcontroller and a programmer and load the bootloader on it yourself for free. Then you can stick to the familiar Arduino software and libraries. Of course I’m new to this whole thing, I’ve only had my Arduino for about a month.
I got my Duemilanove for $27 and now I’m looking for ways to make projects cheaper as well. My Arduino is tied up in a project right now and I’m trying to figure out a cheap solution to get it out so I can use it for other stuff! I’m considering moving to straight AVR, but I’m not a very good programmer and have very little microcontroller experience. I’m afraid it will be over my head or that I will “brick” it (I’ve seen some posts online about fuses and people bricking them).
In your response to Ernie, you spoke of paying for components you don’t need, are you referring to components specific to Arduino? Or the extra cost of purchasing a new Arduino board for every project?
Thank you for writing this! I found it very informative, now I’m going to read some of your other posts and see if they help me with my decision!
Hi Jeremy
This is exactly the kind of post I’ve been looking for for a while, since I am considering going AVR with one of my arduino projects. It can be a little intimidating though to find out where and how to start (I don’t have any experience with C for example, although I see this as a possibility to get more into it), and I was very much looking forward to your next post on the subject.
If you don’t intend to write about this again/anyway, would you happen to know a good primer on the subject?
Best regards,
Jakob
Hi Jakob,
I am still here! I no longer update this website as am in the process of moving everything over to a new server. Unfortunately, I quickly realised that after writing this post the sort of information I wanted to get across should not be done in blog post form.
I have been working on a longer guide to AVRs for some time, but unfortunately it is far from finished. I don’t know of any centralised sources of avr information, but you can probably find something at http://avrfreaks.net or in the relatively intimidating product datasheets.