Category Archives: technical

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:

towards a good night’s rest

Throughout college, suffice to say, I didn’t sleep much. If you know me well, you probably know the myriad reasons for this.

Nowadays, artificial lighting can cause the Dim-Light Melatonin Offset to be pushed back. Anyone who has lived on a farm or near a construction site knows that until recently, the light of the sun was the only light by which we could work, and our bodies adjusted accordingly.

It’s not much of a surprise, then, that staring into the bright light known as a “monitor” can impact some people’s sleep schedule vastly. It’s supplanted by the fact that for many people, night time frees them from the distractions of the day – people and the world outside in general.

amber on mac

I was fortunate enough to find an application for my Mac called Nocturne (from the makers of Quicksilver, in fact). It inverts the colors and can even tint a monochromed version of the inverted image – think green or amber terminal. An amber tint removes the blue light that is known to principally inhibit the production of melatonin, setting your monitor to this amber-on-black setting in the evening may help things out.

amber on linux

Compiz provides many of the shiny effects on Ubuntu. The CompizConfig Settings Manager (not installed by default – check apt) has a color filter plugin available primarily for those with colorblindness. However, negative and negative-green options are provided for low-light computing. Green is a nice choice, but amber will give us the best results. Unfortunately, there’s no easy way to set the tint from CompizConfig.

doing things the linux way

or, an adventure in OpenGL ARB fragment programs.

The filter configurations are hidden away in the

/usr/share/compiz/filters

folder. let’s check out the source for negative-green:

!!ARBfp1.0
TEMP temp, neg;
TEX temp, fragment.texcoord[0], texture[0], RECT;
RCP neg.a, temp.a;
MAD temp.rgb, -neg.a, temp, 1.0;
MUL temp.rgb, temp.a, temp;
MUL temp, fragment.color, temp;
SUB temp.rb, temp, temp;
MOV result.color, temp;
END

This is no GLSL, folks. This is the real deal: ARB OpenGL Assembly Language – specifically, a fragment program. It probably looks somewhat familiar if you’ve seen x86 or RISC assembly before.

I won’t say the approach used to invert the pixels is trivial, but we can eventually spot where the green tint is being applied:

SUB temp.rb, temp, temp;

This line takes the vector temp, subtracts temp (yielding the zero vector), and stores it in the .rb component of temp. Because temp is a color vector, the r and b stand for red and blue, leaving only the green component and alpha component intact.

Converting this to be a pure-red filter is simple enough – we’ll just subtract green instead of red and be set:

SUB temp.gb, temp, temp;

This makes a very nice red tinted inverted filter.

inevitable last 2% difficulty

Next, of course, I wanted it a bit dimmer – 100% red is still fairly blinding in the dark. Easy, except for the catch with open source:

Modifying someone else’s code is one thing. Writing your own is different.

I honestly had no idea what I was doing in ARB, but RenderGuild kindly provides an ARB assembly quick reference. Multiplying the .r component of my color seemed like the right thing to do, and to an extent, I was right. I also now believe that the alpha component (.a) has to be dimmed. Based on those two needs, I came up with these two instructions:

MUL tempColor.a, 0.6, tempColor.a;
MUL tempColor.r, 0.6, tempColor.r;

Perhaps there needs to only be one or the other, and perhaps they could be combined into a single instruction. It does, however, work to my liking.

notes on writing shaders

Mac OS X’s OpenGL Shader Builder was invaluable to checking the compilation of my sloppy coding and, more importantly, hinting at why it was wrong.

notes on Compiz filter switching

While I was working on the shader, I had some strange things such as near-all-red and near-all-black displays happen, with fading at the corners. I’m unsure why this happens, and may be a bug. Cycling back through again usually puts you back where you expect to be.

the grand results

Here’s the source to my fragment shader. It can be downloaded here.

!!ARBfp1.0
TEMP tempColor, negColor;
TEX tempColor, fragment.texcoord[0], texture[0], RECT;
RCP negColor.a, tempColor.a;
MAD tempColor.rgb, -negColor.a, tempColor, 1.0;
MUL tempColor.rgb, tempColor.a, tempColor;
MUL tempColor, fragment.color, tempColor;
SUB tempColor.gb, tempColor, tempColor;
# here is where we will dim.
MUL tempColor.a, .6, tempColor.a;
MUL tempColor.r, 0.6, tempColor.r;
MOV result.color, tempColor;
END

endnotes

I experimented with this kind of filtering during college starting at about 22h00 with a regular bedtime between 00h00 and 01h00. Now that I need to be sleeping sooner, I’ll likely push that back to… whenever sunset is.

This isn’t the solve-all for my sleep problems. Waking is still difficult to predict – blackout drapes are necessary for me to sleep, and therefore the natural light cues are absent for waking. With an alarm, I wake up to a dark vacuous room, which isn’t hugely motivating. I’ll be experimenting with an iPhone app (Climate) and perhaps building a gradual-wake LED light with my Arduino.

However, it has helped, and hopefully it can help someone else too.