One of the things I tell my students is that it is GOOD to ask questions. And when you don’t know the answer to one posed to you, it is OK to say “I don’t know.”
On that note, I have been scratching my head over formulating a proper response to David’s question and thought “why don’t I ask our readers?” You all give great feedback and I am sure that there is someone out there that can help. If you think you have an answer, post in the comments section, and I will compile a response based on the feedback we receive!
David asks:
What is the best path if you want to progress from Arduino to bare AVRs? There seems to be a range of toolchains of varying currency around so google requires a lot of digging to find if what you have is actually current. Ditto some ICSPs seem to have no windows 7 support which can be a trap if that’s your OS of choice. Another way to word the question would be ‘what is the easiest way to work with AVRs while still being able to use things like the internal oscilator and timer interupts’?
Thanks everyone and I look forward to your responses!
Don’t forget, everyone is invited to ask a question!
“Ask an Educator” questions are answered by Adam Kemp, a high school teacher who has been teaching courses in Energy Systems, Systems Engineering, Robotics and Prototyping since 2005.
Adafruit publishes a wide range of writing and video content, including interviews and reporting on the maker market and the wider technology world. Our standards page is intended as a guide to best practices that Adafruit uses, as well as an outline of the ethical standards Adafruit aspires to. While Adafruit is not an independent journalistic institution, Adafruit strives to be a fair, informative, and positive voice within the community – check it out here: adafruit.com/editorialstandards
Stop breadboarding and soldering – start making immediately! Adafruit’s Circuit Playground is jam-packed with LEDs, sensors, buttons, alligator clip pads and more. Build projects with Circuit Playground in a few minutes with the drag-and-drop MakeCode programming site, learn computer science using the CS Discoveries class on code.org, jump into CircuitPython to learn Python and hardware together, TinyGO, or even use the Arduino IDE. Circuit Playground Express is the newest and best Circuit Playground board, with support for CircuitPython, MakeCode, and Arduino. It has a powerful processor, 10 NeoPixels, mini speaker, InfraRed receive and transmit, two buttons, a switch, 14 alligator clip pads, and lots of sensors: capacitive touch, IR proximity, temperature, light, motion and sound. A whole wide world of electronics and coding is waiting for you, and it fits in the palm of your hand.
Have an amazing project to share? The Electronics Show and Tell is every Wednesday at 7:30pm ET! To join, head over to YouTube and check out the show’s live chat and our Discord!
Python for Microcontrollers – Adafruit Daily — Python on Microcontrollers Newsletter: Diving into the Raspberry Pi RP2350, Python Survey Results and more! #CircuitPython #Python #micropython @ThePSF @Raspberry_Pi
EYE on NPI – Adafruit Daily — EYE on NPI Maxim’s Himalaya uSLIC Step-Down Power Module #EyeOnNPI @maximintegrated @digikey
First, a quick note. Any Arduino (or compatible – with the right chip and bootloader) can run pure embedded by replacing main() with init(). I just did that for my radar detector interface. You need a trivial sketch (which is never executed), but “init” is called as the first thing from the Arduino environment’s “main()”, so if you just don’t return, you can set all the registers as if you were doing a makefile and C programs. There are a few gotchas and I may not have found all cases (mainly I needed to declare things volatile if the interrupt would modify them and the main routine would read them – this is technically correct but I didn’t have to do it with the command-line direct install tools).
The AVR “Dragon” available from Digikey and other places works with the AVR studio environment as well as with avrdude (the programmer under Arduino). It can do ISP, JTAG, dW, serial or parallel high-voltage programming, I use jumpers and have added a ZIF socket
I just use GCC – the whole, full AVR toolchain supporting all the chips as far as I know is in one of the directories under the Arduino install directory. You need to set the paths and learn how to use Makefiles.
I have this one set to do high-voltage programming for ATtiny85s on the left side of the ZIF (so I don’t need a resonator), and ATtiny4313 on the right (for prototyping I solder the resonators onto the chips, but I can also attach one via the breakout area).
This explains how to hook up nearly any mode for any chip
There are a few things which aren’t supported – ISP for the Xmega series, though JTAG works (but you need ISP to flip the JTAG bit). The AVR Studio can update the Dragon firmware.
I go bare bones. You can find some of my projects at harleyhacking.blogspot.com and github.com/tz1 but I use Linux as a development environment, most distros let you install the avr toolchain so I use the command line. But as I noted, the Arduino includes it as part of their downloadable install.
I’d say that’s a good question to take over to avrfreaks.net. There are several very helpful and very knowledgeable AVR developers over there who could help you with this, and you’ll want to get familiar with those forums anyway as you get deeper into the mysteries of your future AVR projects. Browse the FAQs in the forum for a while and if you don’t feel like your question was fully answered, introduce yourself and ask away. Here’s a good jumping off point, I think:
There is no such thing as a best path… but the one I use seems pretty nice and easy, because it allows to use Arduino software as if nothing has changed (but the pin numbers, heh), and you don’t use any software other than you current Arduino SW:
1. Load ArduinoISP sketch onto your Arduino, then disconnect it from the PC. Connect 4 wires according to ArduinoISP sketch comments plus 2 wires to 5V and GND. You may use three diodes for state, I used RGB led: red – error (8), green – ready/heartbeat (9), blue – programming (7).
2. Start simple: put ATmega328 (does not have to have bootloader) into breadboard, connect 16MHz oscillator between (9) and (10) plus two 22pF caps to gnd (9-8 and 10-8); wire vcc (7) and avcc (20) together, connect gnds (8-22) together. You may want to put pull-up resistor between vcc (7) and reset (1), 100nF cap between gnd (8) and vcc (7). Consult Arduino schematics if you are not sure about pin numbers. Consult ATmega328 datasheet (from Atmel www site) to check for pin numbers again, you will learn what to do with datasheets of your other (next) chips.
3. Connect Arduino to the ATmega328 on breadboard. You need reset (Arduino pin 10 to ATmega pin 1), +5V to 7, GND to 8, MOSI (Ard11) to 18, MISO (Ard12) to 17, SCK (Ard13) to 19.
4. Quit Arduino software on the PC, find boards.txt (make a copy just in case) and open it in notepad, copy one of the sections, preferably one starting from
uno.name=Arduino Uno
In whole section change “uno.” to “mybb.” or whatever codename you want, change “Arduino Uno” to whatever name you want your board to show in “Board” submenu. Change (or add) following parameters to:
mybb.upload.using=arduinoisp
mybb.upload.protocol=stk500v1
mybb.upload.speed=19200
With different chips (or with other/internal oscillator) you may change other parameters manually, esp. mcu (atmega/attiny type), fuses and f_cpu (cpu frequency).
Save, close the notepad.
5. On the breadboard connect resistor and led in series between gnd (22) and pin 15. These are for Blink sketch only.
6. Connect Arduino to PC. Open Arduino software. Select its COM port. Select your new board in the menu, use “Burn bootloader” -> “Using ArduinoISP”. You don’t need the bootloader (this method uses ICSP, not serial, for programming), but this is the easiest way to set fuses (read about them later in your chips datasheet – they differ from chip to chip, so proceed carefully). Fuses may be set from command line, too, just a little more digging into datasheets is required.
7. Load Blink sketch, change pin 13 to pin 9. Upload. Smile at the blinking LED 🙂 Check Arduino schematics and ATmega datasheet to know why pin 9 is 15 on the breadboard and for other pin mappings.
8. Disconnect Arduino from the PC and breadboard, connect 5V and GND to breadboard, watch the LED blink again. Don’t mistake polarity, you connect the power directly to chip, no protections.
Loose thoughts:
– I used ATmega328, ATmega8 (use ArduinoNG as a base) and ATtiny85 (different pinout on 8 pins, requires some rework in .h files) and they work, both with different oscillators and without (internal one).
– Fuses are dangerous, but if you cannot program a chip, connect external 4MHz oscillator like in the instruction in point 2… this is because if it needs the external it has it, but 4 is low enough that any useful voltage/fuse/etc. should run… but anyway chips are cheap as chips… if you know what I mean.
– Change mcu in boards.txt for different chips, f_cpu for their frequency (you may lie, but some dependent frequencies may be set wrong), you need to change fuses if you change voltages or oscillator types.
Oh, if it isn’t clear enough, when you have PC, Arduino and breadboard-ATmega chip connected and fuses are set properly, you can just upload next sketches just by clicking upload, upload, upload…
P.S. Chips have different capabilities, more or less timers, memory, pwm, etc. If they differ tangibly (like pinouts) you may need to adjust some source and header files (like with ATtiny85 I mentioned). If not, you may just need to remember which pins have which capabilities (datasheet is your friend) and use just the matching pins. Maximum flash memory can be adjusted by changing mybb.upload.maximum_size line in boards.txt.
The best way to learn coding is to copy working code that already exists. I know that smacks of rote memorization, but what you’re really doing is reducing the number of free variables.
Make a list of things the chip in question can do, then write simple programs in the Arduino environment to demonstrate those features in action. Have the students copy that code and run it so they have a baseline of code known to work.
Find every function supplied by the Arduino libraries, dig through the library source code to find the implementation for those functions, then have the students write a new version of the same program using code pulled from the implementations of the API functions, not the API functions themselves. Keep them poking around with it until they get it running, ideally in a way that satisfies a set of test conditions in the original code.
Explore the new code to see how it can be changed. See what works and what breaks. Once you’re satisfied with that version of the code, back out another layer of abstractions. Repeat the process until you have nothing but assembler code that the students feel comfortable writing and modifying.
Then move on to the next feature.
Move from working code to working code every step of the way. Don’t make the students search for solutions, give them a working solution and then make sure they understand it well enough that they can take it apart and rebuild it from scratch. They’ll learn to generalize the code as they work through the chip’s feature set and see familiar patterns cropping up over and over again.
One thing to be careful about – the fuses can be such that it will require a crystal or resonator when programming (or a clock input) instead of the internal oscillator. Sometimes on the breadboard you have it but if you have a socket on the Dragon or wherever and it doesn’t have a crystal, you will need to add one (I have a resonator on some short jumper leads).
Be careful of the fuse settings, lock bits and such.
First, a quick note. Any Arduino (or compatible – with the right chip and bootloader) can run pure embedded by replacing main() with init(). I just did that for my radar detector interface. You need a trivial sketch (which is never executed), but “init” is called as the first thing from the Arduino environment’s “main()”, so if you just don’t return, you can set all the registers as if you were doing a makefile and C programs. There are a few gotchas and I may not have found all cases (mainly I needed to declare things volatile if the interrupt would modify them and the main routine would read them – this is technically correct but I didn’t have to do it with the command-line direct install tools).
The AVR “Dragon” available from Digikey and other places works with the AVR studio environment as well as with avrdude (the programmer under Arduino). It can do ISP, JTAG, dW, serial or parallel high-voltage programming, I use jumpers and have added a ZIF socket
I just use GCC – the whole, full AVR toolchain supporting all the chips as far as I know is in one of the directories under the Arduino install directory. You need to set the paths and learn how to use Makefiles.
https://picasaweb.google.com/lh/photo/cKXV5pjC94fIXfdgTgeQqdMTjNZETYmyPJy0liipFm0?feat=directlink
I have this one set to do high-voltage programming for ATtiny85s on the left side of the ZIF (so I don’t need a resonator), and ATtiny4313 on the right (for prototyping I solder the resonators onto the chips, but I can also attach one via the breakout area).
This explains how to hook up nearly any mode for any chip
http://www.antratek.nl/pdf/avr_dragon.pdf
There are a few things which aren’t supported – ISP for the Xmega series, though JTAG works (but you need ISP to flip the JTAG bit). The AVR Studio can update the Dragon firmware.
I go bare bones. You can find some of my projects at harleyhacking.blogspot.com and github.com/tz1 but I use Linux as a development environment, most distros let you install the avr toolchain so I use the command line. But as I noted, the Arduino includes it as part of their downloadable install.
I’d say that’s a good question to take over to avrfreaks.net. There are several very helpful and very knowledgeable AVR developers over there who could help you with this, and you’ll want to get familiar with those forums anyway as you get deeper into the mysteries of your future AVR projects. Browse the FAQs in the forum for a while and if you don’t feel like your question was fully answered, introduce yourself and ask away. Here’s a good jumping off point, I think:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=70673
There is no such thing as a best path… but the one I use seems pretty nice and easy, because it allows to use Arduino software as if nothing has changed (but the pin numbers, heh), and you don’t use any software other than you current Arduino SW:
1. Load ArduinoISP sketch onto your Arduino, then disconnect it from the PC. Connect 4 wires according to ArduinoISP sketch comments plus 2 wires to 5V and GND. You may use three diodes for state, I used RGB led: red – error (8), green – ready/heartbeat (9), blue – programming (7).
2. Start simple: put ATmega328 (does not have to have bootloader) into breadboard, connect 16MHz oscillator between (9) and (10) plus two 22pF caps to gnd (9-8 and 10-8); wire vcc (7) and avcc (20) together, connect gnds (8-22) together. You may want to put pull-up resistor between vcc (7) and reset (1), 100nF cap between gnd (8) and vcc (7). Consult Arduino schematics if you are not sure about pin numbers. Consult ATmega328 datasheet (from Atmel www site) to check for pin numbers again, you will learn what to do with datasheets of your other (next) chips.
3. Connect Arduino to the ATmega328 on breadboard. You need reset (Arduino pin 10 to ATmega pin 1), +5V to 7, GND to 8, MOSI (Ard11) to 18, MISO (Ard12) to 17, SCK (Ard13) to 19.
4. Quit Arduino software on the PC, find boards.txt (make a copy just in case) and open it in notepad, copy one of the sections, preferably one starting from
uno.name=Arduino Uno
In whole section change “uno.” to “mybb.” or whatever codename you want, change “Arduino Uno” to whatever name you want your board to show in “Board” submenu. Change (or add) following parameters to:
mybb.upload.using=arduinoisp
mybb.upload.protocol=stk500v1
mybb.upload.speed=19200
With different chips (or with other/internal oscillator) you may change other parameters manually, esp. mcu (atmega/attiny type), fuses and f_cpu (cpu frequency).
Save, close the notepad.
5. On the breadboard connect resistor and led in series between gnd (22) and pin 15. These are for Blink sketch only.
6. Connect Arduino to PC. Open Arduino software. Select its COM port. Select your new board in the menu, use “Burn bootloader” -> “Using ArduinoISP”. You don’t need the bootloader (this method uses ICSP, not serial, for programming), but this is the easiest way to set fuses (read about them later in your chips datasheet – they differ from chip to chip, so proceed carefully). Fuses may be set from command line, too, just a little more digging into datasheets is required.
7. Load Blink sketch, change pin 13 to pin 9. Upload. Smile at the blinking LED 🙂 Check Arduino schematics and ATmega datasheet to know why pin 9 is 15 on the breadboard and for other pin mappings.
8. Disconnect Arduino from the PC and breadboard, connect 5V and GND to breadboard, watch the LED blink again. Don’t mistake polarity, you connect the power directly to chip, no protections.
Loose thoughts:
– I used ATmega328, ATmega8 (use ArduinoNG as a base) and ATtiny85 (different pinout on 8 pins, requires some rework in .h files) and they work, both with different oscillators and without (internal one).
– Fuses are dangerous, but if you cannot program a chip, connect external 4MHz oscillator like in the instruction in point 2… this is because if it needs the external it has it, but 4 is low enough that any useful voltage/fuse/etc. should run… but anyway chips are cheap as chips… if you know what I mean.
– Change mcu in boards.txt for different chips, f_cpu for their frequency (you may lie, but some dependent frequencies may be set wrong), you need to change fuses if you change voltages or oscillator types.
Good luck!
Oh, if it isn’t clear enough, when you have PC, Arduino and breadboard-ATmega chip connected and fuses are set properly, you can just upload next sketches just by clicking upload, upload, upload…
P.S. Chips have different capabilities, more or less timers, memory, pwm, etc. If they differ tangibly (like pinouts) you may need to adjust some source and header files (like with ATtiny85 I mentioned). If not, you may just need to remember which pins have which capabilities (datasheet is your friend) and use just the matching pins. Maximum flash memory can be adjusted by changing mybb.upload.maximum_size line in boards.txt.
The best way to learn coding is to copy working code that already exists. I know that smacks of rote memorization, but what you’re really doing is reducing the number of free variables.
Make a list of things the chip in question can do, then write simple programs in the Arduino environment to demonstrate those features in action. Have the students copy that code and run it so they have a baseline of code known to work.
Find every function supplied by the Arduino libraries, dig through the library source code to find the implementation for those functions, then have the students write a new version of the same program using code pulled from the implementations of the API functions, not the API functions themselves. Keep them poking around with it until they get it running, ideally in a way that satisfies a set of test conditions in the original code.
Explore the new code to see how it can be changed. See what works and what breaks. Once you’re satisfied with that version of the code, back out another layer of abstractions. Repeat the process until you have nothing but assembler code that the students feel comfortable writing and modifying.
Then move on to the next feature.
Move from working code to working code every step of the way. Don’t make the students search for solutions, give them a working solution and then make sure they understand it well enough that they can take it apart and rebuild it from scratch. They’ll learn to generalize the code as they work through the chip’s feature set and see familiar patterns cropping up over and over again.
Awesome everyone. Thank you for the assistance. I will compile the replies and make a post shortly!
One thing to be careful about – the fuses can be such that it will require a crystal or resonator when programming (or a clock input) instead of the internal oscillator. Sometimes on the breadboard you have it but if you have a socket on the Dragon or wherever and it doesn’t have a crystal, you will need to add one (I have a resonator on some short jumper leads).
Be careful of the fuse settings, lock bits and such.