Blog-Archive

Arduino (ATmega) mit Bewegungsmelder aufwecken

Vor kurzem hatte ich die Idee, eine Schaltung mit einem ATmega aufzubauen, die immer nur dann etwas macht, wenn jemand in der Nähe ist. Da die Schaltung mit Batterie betrieben werden sollte und eine möglichst lange Laufzeit aufweisen sollte, sollte der ATmega solange schlafen liegen, bis jemand in die Nähe kommt.
Ideen mit IR-Sensor oder Ultraschall Sensor wurden schnell wieder verworfen, das diese selbst zuviel Strom brauchen. Mechanische Schalter wollte ich auch nicht einsetzen und Induktionsspulen erschienen mir zu kompliziert und zu unempfindlich. Die Lösung brachte ein Pyroelektrischer Bewegungssensor. Bei eBay (Suchbgriff: PIR Motion Sensor) sind solche Sensoren für wenig Geld erhältlich. Vor allem der Standby Stromverbrauch von ca. 60uA (Datenblatt) fand ich fast schon nicht zu glauben. Aber schlauer ist man erst, wenn man es ausprobiert. Und heute war es dann soweit. Als erstes habe ich den Stromverbrauch gemessen, im Ruhemodus waren das ca. 70uA, die im aktiven Modus (Ausgang HIGH) dann auf ca. 170uA ansteigen.

CIMG4287bea

Für den ersten Aufbau musste ein Versuchsaufbau auf dem Steckbrett ausreichen. Der Arduino ist für Experimente im Sleep-Modus ungeeignet, da zwar der ATmega schlafen geht, aber andere Bauteile, wie der USB Wandler, der Spannungswandler und die LEDs weiterhin Strom verbrauchen.

Der PIR Sensor wird wie der ATmega mit 5V betrieben und gibt einen HIGH Pegel ab, wenn er Bewegung erkennt. Am ATmega hängt neben der Reset Beschaltung und dem Quarz nebst Kondensatoren ein LCD Display. Die Programmierung erfolgte über einen mySmartUSB light ISP.

Da der PIR-Sensor einen HIGH Pegel abgibt, der ATmega aber mit einem LOW Pegel geweckt werden will, wurde der Pegel mit einem BS170 invertiert. Zum Aufwecken wurde der INT0 am Eingang D2 genutzt, der mit einem externen Pullup auf HIGH gezogen wird. Die Programmierung erfolgte unter der Arduino IDE. Das LCD wird über D8 mit Strom versorgt und wird im Schlafmodus ebenfalls deaktiviert. Im LCD wird während der Aktivphase die Laufzeit in Sekunden und die Anzahl der Aufweckvorgänge angezeigt. Der Stromverbrauch liegt im Sleep-Modus bei ca. 450uA und im Aktiv-Modus bei 18mA.

#include <avr/sleep.h>
 #include <LiquidCrystal.h>
 #define LCD_POW 8
 #define INT2 2
 int toggle=0;
 // initialize the library with the numbers of the interface pins
 LiquidCrystal lcd(12, 11, 5, 4, 3, 6);
void wakeUpNow(){        // here the interrupt is handled after wakeup
 detachInterrupt(0);
 toggle = toggle++;
 }
void setup() {
 pinMode(INT2, INPUT);
 pinMode(LCD_POW, OUTPUT);
 digitalWrite(LCD_POW, HIGH);  // switch on power fpr LCD
 delay(100);  // wait for power to stabilize
 // set up the LCD's number of columns and rows:
 lcd.begin(16, 2);
 // Print a message to the LCD.
 lcd.print("hello, world!");
 }
void sleepNow(){
 pinMode(LCD_POW,INPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(12,INPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(11,INPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(5,INPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(4,INPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(3,INPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(6,INPUT);       // Ausgänge für Schlafen vorbereiten
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 sleep_enable();
 attachInterrupt(0,wakeUpNow, LOW);
 sleep_mode();
 // wakes up here
 sleep_disable();
 detachInterrupt(0);
 pinMode(12,OUTPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(11,OUTPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(5,OUTPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(4,OUTPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(3,OUTPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(6,OUTPUT);       // Ausgänge für Schlafen vorbereiten
 pinMode(LCD_POW, OUTPUT);
 digitalWrite(LCD_POW, HIGH);  // switch on power fpr LCD
 delay(100);  // wait for power to stabilize
 lcd.begin(16, 2);
 }
void loop() {
 // set the cursor to column 0, line 1
 // (note: line 1 is the second row, since counting begins with 0):
 lcd.setCursor(0, 1);
 // print the number of seconds since reset:
 lcd.print(millis()/1000);
 lcd.print(" ");
 lcd.print(toggle);
 if (digitalRead(INT2)) sleepNow(); // only if HIGH again
}

DSC01892

Werbeanzeigen