Archive for February, 2011

More error correction, aka the attiny reference voltage sucks.

Posted in attiny, avr, electronics on February 9, 2011 by makingthingswork

After much curve fitting and data analysis, I decided that the fluctuations in the readings were too much, and i had to find another way of fixing things.

I had previously made up my mind that the attiny board i made was the source of the error, not the scale itself. After working on it one evening, I saw the readings move quickly, then stabilize after i put the unit back in the garage (in the cold) from the nice warm house. The scale stayed out there the whole time.

So i figured it was the resistors changing and affecting the gain on the amplifier.

I ran some calculations and determined that the gain should not have changed anywhere near what it did in reaction to the temperature fluctuations, and the changes in resistance that might bring. So that leaves one thing: the ADC unit on the attiny85 itself.

I have been using the 1.1V reference voltage on the attiny as the basis for the readings. It’s a ‘bandgap’ based thing, which sounds fancy and accurate, but let’s give it a test. To test it, i got a 5k potentiometer and put the end pins on +5v and GND, and the wiper was set so it read about 1 volt. I connected the 1volt output to a spare pin on the attiny, and started taking readings to see if it would exhibit the same pattern as the scale.

About a day later, i’m pleased to report that the constant voltage varies EXACTLY the same way the scale does.

Here’s a picture:

After some analysis and curve-fitting, the coefficient is -1.0, which means that the error in the voltage reading is exactly the same as the scale reading, just opposite (which is to be expected, since i am storing the scale reading as 1024 – raw_reading). So it’s basically a matter of adding them together then subtracting an offset.

As you can see, it works really well, and the total range is just 2 ticks!

Also note that I was able to use a potentiometer (could easily have been 2 resistors) as a MUCH more effective temperature sensor than the internal temperature sensor of the attiny itself. That is somewhat sad.

For extra accuracy, i may someday try using an external VREF input, and see if it’s the ADC itself or if it’s the bandgap voltage moving around. For now, this is good enough.


More useful curve fitting – temperature compensation

Posted in Linux, math is fun on February 1, 2011 by makingthingswork

One of my current projects involves making a USB bathroom scale (I’ll post details later).

So as part of the process, I’ve been collecting the data and graphing it to make sure it gives a stable reading. It’s currently sitting in the garage with a 30lb bag of concrete on it, and the readings are not stable — they vary with temperature. Good to know, but how to fix it?

Here’s a day’s worth of data:

Since the weight is constant, the only variation (i’m assuming) is due to the fluctuations in temperature. It looks like a pretty close correlation. OK so far so good.

I exported the datapoints into a text file, looking like this:

258 158
258 157.269
258 157

Then loaded up gnuplot.

First I plotted them against each other, to see if there was a strong linear correlation

gnuplot> plot './tmpwght.txt' using 1:2 with points

It seems pretty linear.. (see the combined graph below). The temperature sensor in the attiny85 has only 1C increments, and the datapoints seem to land on ‘even’ numbers more often than not, creating groups of vertical points on the graph.

I then need to find the slope of the line that best fits the curve. I’m expecting a straight line of best fit, eg y=mx+b style, so i feed that into gnuplot’s “FIT” routines

gnuplot> f(x)=a*x+b
gnuplot> fit f(x) './tmpwght.txt' via a,b
Final set of parameters
a = 1.20761
b = -152.923

so it appears theres about a 1.2:1 correlation between temperature and weight reading (‘a’ from the curve fit). Let’s check the graph

gnuplot> f(x)=a*x+b
gnuplot> a=1.20761
gnuplot> b=-152.923
gnuplot> plot './tmpwght.txt' using 1:2 with points, f(x)

The fit looks good enough to try out. Let’s see if it does what we want.

Now, to adjust the weight reading to compensate for temperature fluctuations.

Since the ratio is based on the raw reading of temperature, we need to multiply the 2 together before we do any shifting: 1.20761 * temperature. Then, we need to make the temperature reading move the opposite way, so when the temp goes up, the number goes down. This is done by subtracting it from another number. I picked 325. This should give us a value that exactly contradicts the effect the temperature had on the weight measurement.

In equation form:
offset = 325 - (1.20761 * temperature)

Then we add that offset to the weight measurement, and we should get a straight line. Let’s see:

Looks pretty straight to me. The parts that aren’t straight can probably be attributed to poor temperature sensor data, which i will try and fix, either by adding a better temp sensor, or polling more frequently and averaging results.

I like math