Saturday, December 14, 2013

ATTiny & 2.56 V A/D reference

If you google around, you see a lot of suggestions to use 6 as the analogReference parameter to select a 2.56 volt reference. And this is quite attractive - it means that the A/D units represent exactly 0.25 mV. This works spectacularly well for TRR, because the AD8495 outputs 5 mV per degree C, which gives a range of 0-512 degrees and a resolution of a half a degree, which is ideal. 

If you try, however, you'll find that what you actually get is the 1.1 volt reference. Why?

The value 6 comes from the ATTiny85 data sheet, table 17-3. But the problem is that the three REFSx bits are not adjacent to each other in the ADMUX register. The default code in wiring_analog.c will shift the lower two bits of the analogReference argument into the top two bits of ADMUX, but will throw away the REFS2 bit. 

The fix is to edit that line and or in 0x10 to ADMUX if analog_reference & 0x4 is not zero. 

Here's a patch:
--- wiring_analog.c.orig    2013-12-12 12:44:11.000000000 -0800
+++ wiring_analog.c 2013-12-12 12:16:16.000000000 -0800
@@ -66,7 +66,7 @@
    // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
    // to 0 (the default).
 #if defined(ADMUX)
-   ADMUX = (analog_reference << 6) | (pin & 0x07);
+   ADMUX = (analog_reference << 6) | (pin & 0x07) | ((analog_reference & 0x4)?0x10:0);

    // without a delay, we seem to read from the wrong channel
What the Arduino folks really ought to do is change all of the analogReference argument #define values to represent all four bits of the top nibble of ADMUX. That would allow custom, non-standard values to be passed into ADMUX at conversion start time. 

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.