Ich habe eine Möglichkeit gesucht, die Betriebsspannung des ATtiny85
ohne externe Kompenenten zu messen. Im Handbuch ist etwas versteckt
aufgeführt, dass man die interne Bandgap-Referenz auch als Eingang für
den ADC auswählen kann.
Wenn man diese Spannung mit VCC als Referenz misst, kann man indirekt
VCC messen. VCC berechnet sich dann zu:
Die Genauigkeit der Bandgap-Referenz wird mit +-10% angegeben. Wenn man
nach den Graphen im Datasheet geht, ist die Genauigkeit <+-3%, selbst
wenn man die Abhängigkeit der Bandgap-Spannung von VCC berücksichtigt.
Der ADC-Fehler beträgt 2 LSB, also +-0.4%. Der Fehler wird also von der
Bandgap-Referenz dominiert.
Die Genauigkeit sollte ausreichen, um z.B. eine Batteriespannung zu
überwachen.
Anwendung:
1 | uint16_t in;
|
2 | double vref;
|
3 |
|
4 | in=MeasureVCC();
|
5 | vref=1024*1.1f/(double)in;
|
6 |
|
7 | printf("ADC Value: %i VCC: %.2f V\n",in,vref);
|
Code:
1 | /*
|
2 | uint16_t MeasureVCC(void)
|
3 |
|
4 | Measures the supply voltage of an ATtiny85 internall using the ADC.
|
5 |
|
6 | Returns the ADC-value of the 1.1 band gap input measured with VCC as reference voltage.
|
7 | This value can be converted to the VCC voltage by using this equation:
|
8 |
|
9 | VCC=1024*1.1/ADC;
|
10 |
|
11 | cpldcpu@gmail.com - Nov 23, 2013
|
12 | */
|
13 |
|
14 | uint16_t MeasureVCC(void)
|
15 | {
|
16 | PRR &=~_BV(PRADC); // ADC power on
|
17 | ADCSRA =_BV(ADEN)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0); // Enable ADC, Set prescaler to 128
|
18 | ADMUX =_BV(REFS2) | 0x0c; // Use VCC as voltage reference, select bandgap reference as ADC input
|
19 | _delay_ms(1); // Settling time, see p.134 in ATtiny Datasheet
|
20 |
|
21 | ADCSRA |=_BV(ADSC); // Start conversion
|
22 | while (!(ADCSRA&_BV(ADIF))); //~100 us
|
23 | ADCSRA |=_BV(ADIF); // Clear ADIF
|
24 | return ADC;
|
25 | }
|