14.0 Overview

14.1.1 Hardware

Scheme

The components for measuring voltages are minimal: a voltage divider that reduces the
input voltage and feeds the divided voltage to the ADC3 input pin. With this configuration
voltages of up to 20.5 V can be measured. The resistor 56k2 is selected to ensure
a short sampling time of the ADC: if the feed resistance is too large, the sampling
time is prolonged from 1.5 to two clock cycles of the ADC.

Components

To the left is the resistor of 56.2 kΩ, to the right the 1 MΩ.
If you use other values, you will have to change the constants on top of the source
code. With that change you can use any resistor combination.

14.1.2 Measuring range, measure/calculation/display issues

Measuring range

The ADC is programmed to use the internally generated reference voltage of 1.1 V,
to be independant from the operating voltage of the ATtiny13. The voltage on the
ADC3 pin is UADC3 = UInput * 56.2 / (1000 + 56.2) = 1.1 [V].
The maximum measurable voltage therefore is
UInput = 1.1 * (1000 + 56.2) / 56.2 = 20.673 [V]. Per ADC bit the resolution
is 0.02 V.

Measuring conditions

The software is built on the following conditions:

The source pin for the ADC is ADC3, which is written to the MUX port of the
ATtiny24. As no other channels have to be measured in this version, this does not
change.

As reference for the ADC the internal 1.1 V is used, the results are
not depending from the operating voltage.

The measurements are averaged over 64 single measurements. This results in
a measurement/display frequency of 119&nbsl;cs/s.

Calculations

In the conversion of the ADC results to the displayed voltage the following parameters
play a role:

the relation of the two resistors, with Rel = (1M+56k2)/56k2,

at a reference voltage of 1.1 V the 10 bit ADC delivers 1,023, so the
measurement result is NADC = Upin * 1024 / 1.1,

by summing up 64 measurements the ADC yields 64 * NADC as sum value,

to display the voltage a resolution of 0.01 V makes sense because this is
the the ADC resolution of the 10 bit ADC.

From that the following formula for the display applies:

U (0,01V) = (1M+56k2)/56k2 * 1.1 / 1024 * 100 / 64 * NSum-ADC

The first parameters, by which the measured sum has to be muliplied is

U (0.01V) = 0.03154442 * NSum-ADC

To be independant from a floating point math lib, we multiply 0.0315442 with 65,536 and
skip the last two bytes of the result (dividing by 65,536). So we come to

U (0.01V) = 2067 * NSum-ADC / 65536

The calculation therefore is a 16-by-16 bit multiplication, with a 32 bit result.

By changing this constant we can accomodate to any other divider relation.

Display

The result of the multiplication and the dividing by 65,536 yields values at maximum
slightly above 2,000. For converting the binary to ASCII it is sufficient to start with
thousands. Suppressing leading zeros shall only apply to 1,000s, to make sure that at
least one digit before the descimal point is displayed. The decimal point
is to be displayed after the hundreds.

14.1.4 Example

When measuring currents it is crucial to have a as-low-as-possible input resistance to
avoid distortions by the measurement. We here use a very special feature of the ADC in
newer tiny devices that helps us with that.

14.2.1 Hardware

Scheme

The current is measured via the voltage drop over the resistor of 0.1 Ω. The
fuse that is in series with that resistor limits it to 2 A and protects the
resistor and the controller input pin ADC2 against short circuitting. The input ADC1
serves as differential input and is grounded. Measured is the differential voltage
between ADC2 and ADC1, and this difference is gained by a factor of 20.

Components

This here is a usual 0.1 Ω resistor. This wire resistor is specified for
5 Watts thermal power, while we would only need P = U * I = (I*R)*I = 4*0.1 =
0.4 W or the next higher rated (0.5 W). Unfortunately those resistors are
not sold, so we take what we get.

That is how the 2 A fuse looks like.

And this is a respective fuse holder. To fit to our breadboard we need to solder two
short wires to it.

To a fuse holder belongs a fuse holder cap. This is not necessary here because we only
measure low voltage DC. So see it rather as dust preventer.

14.2.2 Measuring range, measure/calculate/display issues

Measuring range

At full swing the ADC input reaches the reference voltage of 1.1 V, divided by
the differential gain of 20, which is 0.055 V. With a resistor of 0.1 Ω
this corresponds to a current of I = U / R = 0.055 / 0.1 = 0.55 A or 550 mA.
Per ADC bit this is a resolution of 0.53 mA. A display resolution of 0.1 mA
would be sufficient.

If we would not select a gain of 20 but of 1 (normal ADC input), our full range covers
currents of up to I = U / R = 1.1 / 0.1 = 11 A. To cover that whole range our
resistor should then have a power of P = I2 * R = 11 * 11 * 0.1 = 12.1 W.
Per ADC digit a resolution of around 11 mA would apply. The display should then
have a resolution of 0.01 A. And, of course, we need a higher-rated fuse.

Measuring

Measuring differential voltages involves just sending a different bit combination to
the ADMUX port. The device databook for the ATtiny24 says which MUX bits can be used
and lists all those combinations.

When measuring currents, we sum up 64 single values, just like in the previous chapter.

Display

The measured sum is a 16 bit binary, which is to be multiplied with the 16 bit binary
5,500. The lower two bytes of the result can be used to round the result in the upper
two bytes (division by 65,536). For conversion into the display format of 123.4 mA
first the thousands, then the hundreds and the tens are calculated. Following the hundreds
no suppression of leading zeros is needed any more, prior to the ones a decimal point
is to be displayed.

An alternative display format would be 1.234(5) A. That would require some changes
to the source code, but is possible and simple.

14.3.2 Measuring range, measuring, calculation and display

Temperatures below -40 and above +85 °C are unpractical and beyond the
operating range of the controller.

Measuring temperature

The temperature measurement is initiated by setting the ADC multiplexer to 8. This
is documented in the device databook and used in the source code.

Calculation

From the above listed values the ADC result is Nmeas = 1.1194 * t [°C]
+ 273.88. From that the temperature calculation is t [°C] = 0.89286 * Nmeas -
244.52. For 64 measurements Messungen and multiplied by 65,536 the following results:

Factually the parameter 245 is inaccurate and has to be adjusted. To determine this
parameter practically, the display of the measured temperature is in hex. This resulted
at 21°C in 0x013A, hence 35.8. The temperature was by 15°C too high, the parameter
245 had to be increased by 15.

Who wants it even more accurate has to determine the slope, too, by determining the
ADC result at two different temperatures and change the parameter cMultT in the source
code accordingly.

The current source code displays the temperature with a resolution of 1°C. For
displaying a resolution of 0.1°C has to change the math, e.g. the multiplicator
should be 9,143 and the subtractor 2.445 to arrive at tenth of degrees. As the physical
accuracy is only 0.89°C, the displayed tenth of degrees pretend a higher accuracy
than really is.

Display

The displayed temperature is an integer value. It can be positive or negative.

Two new instructions are used here. NEG register subtracts the content
of the register from 256 and stores the result in the register. This inverts negative
values (bit 7 is set) to their positive value (bit 7 is clear).

The instruction BRPL label branches to the label if the sign during the
last operation is cleared (the value was positive).