AdSense

Sonntag, 31. August 2014

Spannung überwachen am Arduino, ATmega oder ATtiny

(English version)
Wer seinen Arduino oder einen ATmega bzw. ATtiny über eine Batterie mit Spannung versorgt muss immer damit rechnen, dass die irgendwann einmal leer ist und dann der Mikrocontroller ohne Vorwarnung den Dienst einstellt. Hier ist es hilfreich, die Versorgungsspannung zu überwachen. Sollte sie unter einen bestimmten kritischen Wert fallen, kann man sich zum Beispiel durch anschalten einer LED warnen lassen.
Die Überwachung der Spannung kann ohne zusätzliche Hardware erfolgen. Möglich macht es der AD-Wandler. Dieser arbeitet ja bekannterweise nach folgender Formel:
WERT_ADC = V_EINGANG * 1023/V_REFERENZ
Nun könnte man natürlich meinen: "Ich lege einfach meine Versorgungsspannung an den Eingang des AD-Wandlers und kann diese so messen". Das funktioniert leider nicht, da die Referenzspannung des AD-Wandler ebenfalls die Versorgungsspannung ist. Der Wert des AD-Wandlers wäre als immer 1023.
Doch es gibt einen Trick: jeder Mikrocontroller erzeugt eine interne Referenzspannung, die so genannte "Bandgap Voltage" V_BG. Diese beträgt beim ATmega328, der im Arduino Uno zum Einsatz kommt, 1.1V.  Diese Spannung lässt sich auf den Eingang des AD-Wandlers legen. mit V_EINGANG = V_BG und V_REFERENZ = V_CC ergibt sich dann:
WERT_ADC = V_BG * 1023/V_CC
oder umgeformt:
V_CC = V_BG * 1023/WERT_ADC
Setzt man nun ein V_BG = 1100 (in mV) ergibt sich:
V_CC = 1100 * 1023/WERT_ADC
V_CC ist nun der Wert der Spannungsversorgung in mV

Umgesetzt in Code sieht das dann so aus:

int led = 13;  //Pin der LED
int adc_low, adc_high;  //Zwischenspeicher für die Ergebnisse des ADC
long adc_result;  //Gesamtergebnis der Messung des ADC
long vcc;  //Versorgungsspannung

void setup() {    
  pinMode(led, OUTPUT);  

  ADMUX |= (1<<REFS0); //VCC als Referenzspannung für den AD-Wandler
  ADMUX |= (1<<MUX3) | (1<<MUX2) | (1<<MUX1);  //1.1V Referenzspannung als Eingang für ADC 
  delay(10);  //warten bis sich die Referenzspannung eingestellt hat
  ADCSRA |= (1<<ADEN);   //ADC aktivieren
}

// the loop routine runs over and over again forever:
void loop() {    
  ADCSRA |= (1<<ADSC);  //Messung starten

  while (bitRead(ADCSRA, ADSC));  //warten bis Messung beendet ist
  //Ergebnisse des ADC zwischenspeichern. Wichtig: zuerst ADCL auslesen, dann ADCH
  adc_low = ADCL;
  adc_high = ADCH;

  adc_result = (adc_high<<8) | adc_low; //Gesamtergebniss der ADC-Messung 
  vcc = 1125300L / adc_result;  //Versorgungsspannung in mV berechnen (1100mV * 1023 = 1125300)

  //wenn Spannung kleiner als 5V 
  if (vcc < 5000)
  {
    digitalWrite(led, HIGH);  //schalte LED an
  }
  //wenn größer oder gleich 5V
  else 
  {
    digitalWrite(led, LOW);  //schalte LED aus
  }

  delay(500);
}


In der setup()-Funktion wird zuerst der AD-Wandler so eingestellt, dass zum einen die Versorgungsspannung V_CC als Referenz und zum anderen die Bandgap-Spannung V_BG als Eingang für den AD-Wandler dienen. Nach einer kurzen Wartezeit wird der AD-Wandler dann aktiviert.
In der loop() wird dann die Messung durch setzen des Bits ADSC gestartet. Ist die Messung beendet (ADSC ist wieder 0) wird das Ergebnis der Wandlung aus den Registern ADCL (die unteren 8 Bit) und ADCH (die oberen 2 Bit) ausgelesen und zu einem 10-Bit-Ergebnis zusammengesetzt. Aus diesem wird dann nach der obigen Formel die Versorgungsspannung bestimmt. Liegt sie unter 5V, wird eine LED eingeschaltet.

Diese Methode funktioniert prinzipiell mit allen ATmegas oder ATtinys. Je nach verwendetem µC müssen allerdings in den Registern des AD-Wandlers andere Bits gesetzt werden. Welche das genau sind, kann dem Datenblatt entnommen werden.

Mittwoch, 20. August 2014

ATmega - Bodenfeuchte von Zimmerpflanzen messen

(English version) Heute möchte ich vorstellen, wie man einen Feuchtigkeitssensor baut und ansteuert. Die Grundidee dahinter ist, zu messen wie feucht die Erde einer Pflanze ist und dann dementsprechend zu wissen wann man gießen muss.

Für den Bau des Sensors wird nicht viel benötigt. Ich habe ein kleines Stück Streifenrasterplatine, 2 Nägel und Stiftleisten benutzt. Der Sensor sieht dann so aus:
Nun misst man den Widerstand zwischen den zwei Nägeln (wenn der Sensor in der Erde steckt) und schon kann man Rückschlüsse auf die Bodenfeuchte ziehen. In der Schaltung sieht das dann folgendermaßen aus:
Bei feuchter Erde leiter der Sensor gut, also misst der ATmega eine hohe Spannung (zu interpretieren als Erde ist feucht). Bei trockener Erde steigt der Widerstand, daher sinkt die gemessene Spannung. Natürlich kann man jetzt noch überlegen welche Einheiten die Achsen bekommen und so weiter, ich denke jedoch es ist sinniger, einfach 0 bis 5 V aufzutragen (oder 0 bis 100%) und dann selbst zu überprüfen wann die Pflanze gegossen werden muss - dies ist dann der Wert bei dessen Unterschreitung eine rote Lampe an geht oder eine automatische E-Mail gesendet wird.