Category Archives: AVR

Taking Arduino to the next level with AVR-GCC: part 3

  • In part 1, we examined the architecture of the Arduino and AVR microcontroller.
  • In part 2, we set up the AVR-GCC toolchain and avrdude.

The Plan

This time, we will look at some more project-specific hardware buildup for a gradual-wake light clock.

This is meant to be at the “completely new to electronics design” level. If you know your way around parallel LEDs, you can probably build something better than I’ll build here.

Our Goal

Our regular alarm clock is pretty jarring, and it doesn’t really solve the problem of the room still being dark. How about we solve both of those at once by gradually lighting up the room?

Our little dream (or dream-interrupting) device.

Obviously the real thing will be nowhere near as pretty, but it gives us an idea of what hardware and software components we will need:

  • Timer – This will mostly be taken care of in software.
  • Bright light – We will use a bunch of LEDs (preferably white)
  • Time Display – We will display time until wake in hours + tenths of an hour
  • Digit Display Library – some kind of abstraction for display numbers
  • Status Light – Is the alarm on or off? (green = on, red = off)
  • Reset – turn it off.
  • Duration – increase the duration until wake within a set range, at the top it will simply loop back to the lowest value.
  • Holding the reset button and pressing the duration button will turn the alarm back on after it has been turned off.

the light module

We’ll start with the simplest part first: making a bright light. We’ll use a tiny breadboard, but perhaps if I had more LEDs I could fill a half-size breadboard and outshine the surface of the sun. If you’ve never worked with them or are a bit rusty on the details of the various kinds of breadboards, have a look at the Wikipedia Article.

So, with a bunch of LEDs in one hand and the breadboard in the other, we want to know whether a series or parallel circuit will be the brightest. For reasons you can find out in second-semester college physics (or through empirical observation), the parallel configuration will give us the most light.

light module schematic

Six LEDs connected in parallel to appropriate pins on the Arduino.
Here’s a handy-dandy schematic diagram (which I hope has the cathodes on the correct side), which we will soon find out is a vast oversimplification of the actual assembly:

I may be really unclever, but my plan was to plant the LEDs straddling the breadboard. Then, to establish the parallel bus, rather than connecting each LED to the one physically next to it, stagger the connections. (I don’t have any physical jumpers that are pre-cut to span adjacent pins.)

assembly – light module

This is a bit tough to describe in words, but luckily I have pictures instead!

  1. Insert LEDs such that the pins are inserted into the innermost (nearest the gap) points. IMPORTANT: make sure all of the anodes and cathodes are on the corresponding side of the gap. I skipped one row between each LED using 5mm dome LEDs.
    Pretty LEDs All In A Row. Notice the skipped rows.

    Pretty LEDs All In A Row, Part Deux: If you look closely at the inside of the LEDs, you can see the anode/cathode structure.
  2. Parallelize 3 sets of LEDs.
    • You’ll need 3 jumpers of the same length. In my case, I chose to make them span 7 pins – the distance between 3 LED anodes/cathodes. And of course, I chose red for the anodic side and green for the cathodic side.
      Top view. Parallel circuits for LEDs 1/4, 2/5, and 3/6 on the anode (left) and cathode (right) side.

      A different perspective on the progress so far.
    • Connect each set back to a bus row. Basically, we need each pair to connect back to one row, where we will actually connect the power and ground. Since there are only 4 columns available on my tiny board, some overlap was necessary. I used black wire to indicate bus connection wires.

      Bus wires added. Not pretty, but it forms a logical bus.
    • (optional) I chose to drag the bus down to the end of the board. The giant blur in the foreground is another larger white LED I had sitting around.

      Two wires pull the bus down to the last row. Out of focus: giant LED.

Yay, we’re done building the light module!

quick test

For our first run, we’ll actually try a failsafe way to test rather than loading up any software.

For our positive voltage, connect a jumper from the anodic (red) side bus row to the 3V3 pin towards the “bottom” of the Arduino. Connect a jumper from the cathodic (green) side bus row to one of the two nearby GND pins on the Arduino. Now, connect the Arduino to its power source – probably USB. All of the lamps should glow brightly – if a single lamp is out, you probably have the anode and cathode reversed; switching its orientation on the breadboard should fix it.

The 3V3 pin is meant as a reference voltage pin, so we probably don’t want to test its capacity by leaving the lights attached for too long – disconnect your power source first, then the light module.

fancier test: dimming

We want to be able to raise the light level of the light from nothing to bright over some amount of time. For now, we’ll just focus on fading from dark to bright.

This part is easiest done with the actual Arduino toolkit: it contains an example sketch that does exactly that – raise and lower the output voltage of Digital PWM Pin 9. To load the sketch, we’ll leave the light module disconnected and open the Arduino software and open the Fading sketch from the File menu as shown:

Select the Fading sketch from the Analog Examples (even though we're using digital trickery).

Once you have opened the Fading sketch, connect your Arduino to your computer (generally using USB), select the appropriate USB port in the Tools -> Serial Port menu, and click the “Upload” button highlighted below:

This will flash the Fading sketch to your Arduino.

Once the RX and TX lights have stopped blinking and the software proclaims “Done uploading,” disconnect your Arduino from USB before we reattach the light module.

Light module connected to Pin 9 and GND.

You can connect the cathodic side your light module to a GND pin on the bottom of the Arduino, or choose the one to the left of digital pin 13. The anodic side should be connected to our voltage source – Digital PWM Pin 9.

Shiny!

With both sides connected, you should now be able to reconnect your Arduino to a power source (USB) and see your many lights fading calmly.

And now, an excuse to use the HTML5 <video> tag!

the display module

Now that we have a light to light up, we need a way to show what duration remains before the “light alarm” goes off and whether or not the alarm is on.

Our digit display is clearly going to be two seven-segment LED displays; I’m using ones I picked up from the UNL EE shop – part number LSD5051, common cathode. The status light I chose is a combo RGB LED similar to this one. Be sure to notice that the forward voltages are not symmetric: while blue and green can handle 3.2V, red can only handle 2.0V and will burn up in a hurry if you’re not careful.

a new friend: the multiplexer

You may have noticed that there are a lot more pins coming off these display devices than we have left on our Arduino. Because LEDs are not instant on-off devices (though they’re darn close on a human time scale), we can use persistence of vision to our advantage and drive many more pins through a device called a multiplexer.

TI CD4067BE Multiplexer

In particular, I’m using the TI CD4067BE. That part may be a bit hard to find, but fortunately, it’s available cheaply online. If you have to wait on it, you can check out its datasheet and get some idea of how it works. We’ll dive deeper into that next time.

The beginnings of a display module. There will be wires, my friends.

Once you have those parts, you can assemble a display module on a half-size breadboard that looks something like this one:

Taking Arduino to the next level with avr-gcc: Part 2

Our AVR toolchain

For our example project, we will create two similar toolchains – one for Mac OS X and one for Linux.  Here’s a visual overview of how code will flow:

toolchain.png

If you’ve developed with C or C++ before, the diagram should look familiar. I’m assuming just one object here – if we had more, avr-ld works much the same as our traditional linker does. And, of course, we can write C++, tossing avr-g++ in for avr-gcc.

On the Linux side, I chose not to set up an IDE, but maybe my Mac approach will help you set one up. For Mac, I set up a Makefile-based Xcode project and run script to invoke these tools in order and provide the “pretty” Build Results screen. Someday, I hope to introduce gdb on-device debugging, but for now, it’s Build and Run only.

Toolchain Construction: Mac OS X

I’m assuming that if you’re reading this, you probably already have Xcode. If not, it’s not strictly necessary – you can follow the text editor + command line formula outlined for Linux equally well on OS X.

Our big helper here is MacPorts. If you have the latest version already installed, you can skip the next section.

Installing MacPorts

MacPorts is a great package management tool for Mac OS X, akin to ports on BSD and apt-get on Linux. A .pkg (standard OS X) installer is available here. Download the .dmg, mount it, and double click the Installer package. The usual installer semantics apply here.

Updating MacPorts

I neglected this step and it bit me hard.

Fire up Terminal.app and issue:

sudo port -v selfupdate

which will ask you for your password. Now, we can start the fun of actually installing the appropriate packages from the repository.

Installing Relevant Packages

We may not need all of these right away, but here’s our grocery list:

  • avr-binutils – tools for cross-platform development with AVR
  • avr-gcc – the bread and butter of our toolchain, obvious from its name.
  • avr-gdb – again, from the name, the GNU debugger for AVR.
  • avr-libc – some core C functions for use on the AVR platform. Without this, our programs probably won’t be very useful (or pretty).
  • avrdude – AVR flasher software.

To install them, again use Terminal.app, this time with the command:

sudo port install avr-binutils avr-gcc avr-gdb avr-libc avrdude

You may see some unrecognized packages floating by; these are likely dependencies of the packages we wish to install. It is normal for this process to take quite some time. Let’s all go to the kitchen and have ourselves a snack!

Test the new toys

After some time, everything will be built and ready to go. This is the moment of truth where we see if your PATH environment variable is set up to play nicely with MacPorts.

Create a new Terminal window and try running the command:

avr-gcc -v

The response should end with something like

gcc version 4.0.2

If that’s so, it looks like you’re ready to rock!

Toolchain Construction: Linux

For Ubuntu users, grab the following packages via apt-get or synaptic:

  • binutils-avr – tools for cross-platform development with AVR
  • gcc-avr – the bread and butter of our toolchain, obvious from its name.
  • gdb-avr – again, from the name, the GNU debugger for AVR.
  • avr-libc – some core C functions for use on the AVR platform. Without this, our programs probably won’t be very useful (or pretty).
  • avrdude – AVR flasher software.
  • avarice – If we need to do GDB over JTAG.
  • simulavr – Simulates AVR hardware for debugging and testing.

If you’re down with the terminal (and I hope you are), grab them all at once with the command:

apt-get install binutils-avr gcc-avr gdb-avr avr-libc avrdude avarice simulavr

Create a new Terminal window and try running the command:

avr-gcc -v

The response should end with something like

gcc version 4.3.4

If that’s so, it looks like you’re ready to rock!


UPDATE: Part III is available here.