Saturday, June 28, 2014

Atmel AVR Toolchain 3.4.4

Since I started developing on AVR MCUs, I've used avr-gcc, which includes avr-libc.  A few months ago I found out Atmel maintains a version of avr-libc separate from the Savannah project.  It's part of the Atmel AVR Toolchain.  I've wanted install avr-gcc 4.8 on my CentOS server, however I could only find rpms for 4.7.  The Atmel toolchain version 3.4.4 includes avr-gcc 4.8.1, so I decided to try it out.

To download the binary package I had to out an annoying form, before I could get access to the direct download link.  The binary is distribution agnostic, and can be installed in a user directory without root access.  After downloading just run tar xzf to extract the files, then update your path.  For bash, I added the following two lines to my .bashrc:
PATH=$PATH:~/avr8-gnu-toolchain-linux_x86/bin
export PATH

The AVR toolchain consists of three main parts:

  1. Compiler (gcc)
  2. GNU binutils (objdump, ld, nm, ...)
  3. avr-libc (including headers for various AVR MCUs)
As of May 2014, when AVR toolchain version 3.4.4 was released, the latest version of the gcc 4.8 branch was 4.8.2.  The toolchain includes binutils 2.24, which is the latest version.  With avr-libc it gets a bit confusing.  The latest avr-libc release on savannah.gnu.org is 1.8.0 from December 2011.  In a discussion on AVRfreaks, I found out Atmel maintains a separate branch of avr-libc, which seems to be based on the latest avr-libc from savannah plus additional fixes and MCU headers.  I checked for avr-libc bug #41519, which I submitted on 2014/02/07 and was fixed on 2014/03/18.  The fix is included in the toolchain 3.4.4.

I've previously blogged about link-time optimization, so I wanted to check the code generated by the AVR toolchain.  I used the following test program:
#include <avr/io.h>
#include <util/delay.h>

void toggle(unsigned char pin)
{
    PINB = (1<<pin);
}

#define LEDPIN 1
void main()
{
  toggle(LEDPIN);
  while (1) {
    toggle(LEDPIN);
    _delay_ms(500);
  }
}

I compiled it with -Os and -flto.  As expected, the toggle function was inlined in main() when I looked at the code using avr-objdump -D:
0000004c <main>:
  4c:   82 e0           ldi     r24, 0x02       ; 2
  4e:   83 b9           out     0x03, r24       ; 3
  50:   83 b9           out     0x03, r24       ; 3
  52:   2f ef           ldi     r18, 0xFF       ; 255
  54:   34 e3           ldi     r19, 0x34       ; 52
  56:   9c e0           ldi     r25, 0x0C       ; 12
  58:   21 50           subi    r18, 0x01       ; 1
  5a:   30 40           sbci    r19, 0x00       ; 0
  5c:   90 40           sbci    r25, 0x00       ; 0
  5e:   e1 f7           brne    .-8             ; 0x58 <main+0xc>
  60:   00 c0           rjmp    .+0             ; 0x62 <main+0x16>
  62:   00 00           nop
  64:   f5 cf           rjmp    .-22            ; 0x50 <main+0x4>

However the toggle function was still included in the binary.  After trying different compiler options, I found that adding -fwhole-program will not included the unused toggle function.  When testing a gcc-4.8.0 MinGW, I didn't have to use the -fwhole-program option.  As well, the gcc docs state, "This option should not be used in combination with -flto. Instead relying on a linker plugin should provide safer and more precise information."  In the description of -flto it also says, "When the linker plugin is not available, -fwhole-program should be used..."

When I compared the build specs (gcc -dumpspecs) between the AVR toolchain build and the MinGW build, I found the following string in the AVR toolchain: "fuse-linker-plugin:    %e-fuse-linker-plugin is not supported in this configuration"  Although there doesn't seem to be anything wrong with using -fwhole-program instead of the linker plugin, at least for simplicity of build options, the linker plugin is better.

Friday, June 20, 2014

The Science of Cheap Beer

Most guys like beer, and many like to brew their own.  Unfortunately, in many countries, beer is heavily taxed.  In the part of Canada where I live, the cheapest beers cost $42 for 24 bottles.  There's a 10c refund for the empty bottles, so after you bring the bottles back the net cost is $39.60, or $1.65 per bottle.  Each bottle is 341ml, making the cost per liter $4.84.  With homebrew kits like Coopers, 23L of beer can be brewed for <$20, or about 1/5th the retail price.  With a little more work, it's even posible to make a brew with the same ingredients as a Coopers kit for about $10, or 1/10th of the retail beer price.

The Coopers kits require adding 1kg of fermentable sugar to the malt extract and water, and the brew shops recommend corn sugar aka dextrose aka glucose, which sells for $5 for a 2kg bag.  Dextrose has about 10% moisture content, so 1kg of fermentable dextrose costs about $2.80.  Cane sugar aka sucrose sells for $2 or less for a 2kg bag, so for my first beer kit brew I tried half dextrose and half glucose.  It turned out fine.

I decided to research some of the science behind the fermentation of different sugars.  I found a paper by Labatt Breweries which shows virtually no difference in the fermentation of glucose vs. sucrose.  Glucose may actually be worse than sucrose, since the paper shows high glucose suppresses fermentation of maltose (fig 4B).  Malt extract is 30-50% maltose, so using sucrose instead of glucose means fermentation will be finished sooner.

Malt extracts are much more expensive than sucrose - about $5/kg for liquid malt extract.  The fermentable sugars do not contribute to the taste, so using a malt with less fermentable solids allows you to use more sucrose while still maintaining flavor. The Coopers kits include 1.7kg of hopped LME and recommend adding 1kg of fermentable sugar.  Using 1.5kg of a darker malt (~$7.50) and a little more than 1kg of sucrose (~$1) should give a flavor profile almost the same as the Coopers kit assuming the same hops.

Dried hops costs about $30/kg, and depending on the recipie, a 23L batch will need 20-50g of hops.  This adds about a dollar to the cost of a batch of beer.  The cheapest source of hops is to grow your own.  One homebrewer I know had a couple varieties of hops growing up a trellis attached to his back deck.

Coopers ale yeast costs just under $2 for a 7g package, but you don't need one for every batch.  I bought a Coopers kit on sale that was missing the yeast pack, and just split a package between 2 batches.  Despite some people that say the amount of yeast you pitch is important, the biochemistry of yeast seems to indicate otherwise.  It might take a bit longer for the brew to ferment, but not that I could notice.   I used 3.5g of yeast for a batch of Cooper's ale, which I uncovered and stirred after a few hours for oxygenation. After three days at 23C there was a full cover of foam from the active yeast.  Yeast from one batch can be re-used multiple times, so is's feasible to use a single 7g package for up to 10 batches.

When it comes time for priming, a number of sources, including this one, say that using sucrose gives a cidery taste to beer.  I've used sucrose and didn't notice a cidery taste.  More likely explanations for a cidery taste in beer is oxidation or incomplete fermentation.  Since only 100 to 150g of priming sugar is needed for a batch, the choice of priming sugar doesn't affect the cost much.

So how do I come up with the $10/batch number I mentioned?  Here's the breakdown:
1.5kg dark LME: 7.50
1.25kg sucrose: 1.25
30g hops:       0.90
yeast:          0.25
total:         $9.90

If you want a lighter tasting beer like mainstream beer buyers (bud light is the top selling beer in the US), then 1kg of dark LME and 1.5kg of sugar should suffice.  If you grow your own hops, then your cost for a homebrew light beer could be as little as 10c per bottle!

Sunday, June 8, 2014

Cheap battery-powered micro-controller projects

Many MCU circuits use less than 25mA of power with a 3-5V supply, making battery-powered operation not only feasible, but often cheaper than using a dedicated power supply.  Although I'm using AVR MCUs, the same concepts apply to using a PIC or MSP430.  An Arduino UNO consumes > 30mA even when the MCU is in sleep mode, so powering it from a battery is not a great idea.  For an Arduino Pro Mini or bare MCU on a breadboard, long running time on a battery can be achieved.

Disposable or re-chargeable batteries?

For projects with average power consumption in the low micro-amps range, it's hard to beat the disposable CR2032 coin cells.  Sparkfun's Adventures in Low Power Land shows how how to run an ATMega328p off a single CR2032.  JeeLabs also has some info on running wireless sensor nodes on coin cells.  Quality cells such as Panasonic cost only 25c in small quantities.  Battery holders are about 10c, or wires can be soldered directly to the cells.  For wireless sensor nodes that use bursts of more than a few mA of power, a cheap electrolytic capacitor will extend battery life, particularly with lower-quality cells.

For projects that would use more than one CR2032 per year, a rechargeable LIR2032 coin cell is another option.  Although their capacity is about 1/5th of a disposable, they can sustain higher output currents than the disposable cells.  However they are much harder to find than disposable cells.  FastTech is one place I've found that sells them for about 50c ea.  Chargers are also difficult to find, though not to hard to build according to this Hack A Day post.

Powering circuits from a 9V battery has long been popular, often with a small 5V regulator such as the 78L05.  An alkaline 9V battery has a capacity of about 600mAh, but it might last not much longer than a 220mA CR2032.  Over it's usable life, the average output voltage will be close to 7.5V, which means a linear regulator will be 66% efficient, leaving about 400mAh.  Even in low-power mode, a microcontroller will use about 50% more power at 5V than it will at 3V, meaning 267mAh at 3V would give the same battery life as 400mAh at 5V.
Once the higher cost of a 9V battery is factored in (about $1.50), the 9V battery is clearly more expensive than a 3V coin cell.  However you may have a cheap source of 9V batteries - smoke detectors.  I've found my smoke detectors start beeping to replace the batteries when the open-circuit voltage is still above 8V.

I've re-used these batteries for RF transmitter projects.  The transmitter modules I use will work with 3-12V, with more voltage providing higher power transmission.  Instead of using a voltage regulator to power the AVR, I use a LED similar to what I did for my ATtiny85 NRF24l01+ project.  Instead of a red LED, I used a green LED with a forward voltage of 3V.  With the 9V battery putting out 7.9V under load, I measured 4.9V at the input of an ATtiny84a I used.  Besides being a bit cheaper than a regulator, the LED has the benefit of working as a power use indicator - when the AVR is consuming more power the LED glows brighter.

Update: David Cook has recently posted the battery life expectancy of his Attiny lofi device.  According to Energizer's Alkaline Handbook, at 25mA drain the capacity of an AA alkaline is over 2500mAh, and under 1mA drain the capacity approaches 3000mAh.  Once self-discharge of 2-3% per year is factored in, the 12-year life expectancy David calculated is about right.  With a cost of about 25c for AA cells and 20c for CR2032 cells, 12 years of use on CR2032's would cost about $2 vs. 50c for the AA cells.

A wireless sensor node using an Atmega328p with a 32.768khz watch crystal and a nrf24l01+ module could work for >12yrs with a CR2032.  The power-down current with timer2 running is 1uA, or about 9mAh per year.  The nrf module would need to be transmitting for 0.5ms to transmit 16 bytes at 250kbps, vs 53ms for an ASK/OOK module at 2400bps, and both consume 10-15mA at 3V.  Even consuming 15mA for 2ms every 5 minutes would equate to only 0.1uA average consumption.  Adding 0.25uA for self-discharge adds up to 12mAh per year, or 16 years of battery life!