Ein PIR-Sensor wird von selbst ausgelöst, wenn ein Timer verwendet wird, um 2 Sekunden nach dem Auslösen des Sensors zu warten. Ohne Verwendung des Timers zum Warten funktioniert der Sensor wie erwartet.
Ich habe einen PIR-Sensor an einen ATMega328p angeschlossen . Der PIR-Sensor hat drei Stifte; VCC
, GND
und AL
. Der AL
Stift verwendet einen offenen Kollektor, um anzuzeigen, dass eine Bewegung erkannt wird.
Was ich getan habe, ist, dass ich den AL-Pin mit dem PC0-Pin meines ATMega verbunden und den Pin als Eingang mit internem Pull-up-Widerstand und einer an PC5 angeschlossenen LED eingerichtet habe, um anzuzeigen, wenn eine Bewegung erkannt wird:
void setup_default_values()
{
DDRC |= (1 << PC5);
DDRC &= ~(1 << PC0);
PORTC |= (1 << PC0);
}
Dann habe ich eine Funktion, die prüft, wann der PC0
Pin ist LOW
:
void check_sensor()
{
if (PINC & (1 << PC0)) {
PORTC &= ~(1 << PC5);
}else{
PORTC |= (1 << PC5);
}
}
Diese Funktion lässt die LED aufleuchten, wenn PC0
sie ist, LOW
und schaltet sie aus, wenn PC0
sie ist HIGH
. Diese Funktion wird in jedem Zyklus meiner Hauptschleife ausgeführt:
int main()
{
setup_default_values();
blink(4);
for (;;) {
check_sensor();
}
return 0;
}
Alles funktioniert wie erwartet, die LED leuchtet auf, wenn ich mit der Hand vor dem Sensor winke, und es löst nicht ohne Bewegung aus. Der Sensor setzt den AL
Pin LOW
für ca. 100 - 200 ms.
Die Sache ist, dass ich das Signal 2 Sekunden lang nicht verwenden möchte, nachdem eine Bewegung erkannt wurde. Also habe ich eine Timer- und Flag-Logik implementiert, die das Signal während dieser 2 Sekunden ignoriert. Das Problem ist, dass die LED jetzt von selbst aufleuchtet, nachdem der Timer aufgehört hat zu zählen und Bewegungssignale akzeptiert
Um diese Timer- und Flag-Logik zu verwenden, habe ich 2 LEDs hinzugefügt, eine, die anzeigt, dass der Timer aktiv ist, und eine, die anzeigt, wenn ein Signal registriert wird:
volatile bool motion_detected;
void setup_default_values()
{
DDRC |= (1 << PC5);
DDRC |= (1 << PC4);
DDRC |= (1 << PC3);
DDRC &= ~(1 << PC0);
PORTC |= (1 << PC0);
TCCR1B |= (1 << CS12); // Timer 1B set up to use a prescaler of 256
TCNT1 = 0; // Timer value set to 0
motion_detected = false;
}
Dann habe ich neue Logik für die check_sensor
Funktion:
void check_sensor()
{
if (PINC & (1 << PC0)) {
PORTC &= ~(1 << PC5);
}else{
PORTC |= (1 << PC5);
if (!motion_detected) {
PORTC |= (1 << PC3);
_delay_ms(50);
PORTC &= ~(1 << PC3);
PORTC |= (1 << PC4);
TCNT1 = 0;
motion_detected = true;
}
}
}
Wenn zum ersten Mal eine Bewegung erkannt wird, passiert Folgendes:
Dann gibt es eine neue Funktion, die den Countdown behandelt:
#define F_CPU 1000000UL
/*
* Timer increments per second
*
* This value represents how many increments the timer will do to the TCNT1 register
* per second.
*
* To produce this value you divide the clock frequency in hz with the prescaler amount.
* For example:
* 1000000 / 256 = 3906
*/
#define TMR_INC_PER_SEC 3906
void check_timer()
{
if (!motion_detected) return;
if (TCNT1 >= TMR_INC_PER_SEC * 3) {
PORTC &= ~(1 << PC4);
motion_detected = false;
}
}
int main()
{
setup_default_values();
blink(4);
for (;;) {
check_timer();
check_sensor();
}
return 0;
}
Diese Funktion sollte ignoriert werden, es sei denn, es wird eine Bewegung erkannt. Wenn der Countdown abgeschlossen ist, wird der Timer, der die LED anzeigt, ausgeschaltet und das Bewegungsflag wird zurückgesetzt, was anzeigt, dass ein neues Signal akzeptiert werden kann.
Ich habe versucht, software debounce
eine Funktionalität hinzuzufügen, bei der Bewegung nur akzeptiert wird, wenn PC0
sie LOW
für eine definierte Anzahl von Zyklen gilt. An dem fehlerhaften Verhalten änderte dies nichts.
Ich habe versucht, den PIR zu entfernen und einen Druckknopf hinzuzufügen, der LOW
gedrückt ist. Bei Verwendung des Tasters funktioniert die Schaltung und Logik wie erwartet.
Hier ist der Schaltplan für die Stromversorgung. Die Schaltung ist an eine stabilisierte Gleichstromversorgung angeschlossen, bei der die +5-V-Schiene tatsächlich etwa +6,5 V beträgt (ich weiß nicht, wie ich den Text einer Komponente in gschem bearbeiten soll). VCC
verbinde ich mit meinem Mikrocontroller und PIR-Sensor, wie Sie im zweiten Schema sehen werden.
Hier sind die Schaltpläne für den Mikrocontroller, die LEDs und den PIR-Sensor. Einige Pins werden in den Schaltplänen nicht angezeigt: RESET
Pin ist mit meinem Programmierer verbunden, dasselbe mit MOSI
, MISO
und SCK
.
Die typische Dropout-Spannung des 7805 beträgt 2,0 V, aber Sie haben nur 6,5 V Eingang, sodass der Regler nicht richtig funktionieren kann. Dies könnte bedeuten, dass kleine Stromspitzen auf der Lastseite des Reglers, z. B. beim Einschalten von LEDs, trotz des 10-uF-Kondensators zu Spannungswelligkeiten führen würden, und PIRs sind sehr empfindlich gegenüber Spannungswelligkeiten.
Ich würde empfehlen, den Eingang zum 7805 auf mindestens 7,0 V und wahrscheinlich 8,0 V zu erhöhen, um Schwankungen der Abfallspannung zu berücksichtigen (2,0 V ist als typisch aufgeführt, nicht als Maximum), und der Versorgung des PIR einen RC-Filter hinzuzufügen Schaltkreis. Sie müssen R jedoch sorgfältig dimensionieren, um zu vermeiden, dass die Versorgung der PIR-Schaltung auf weniger als das angegebene Minimum reduziert wird (möglicherweise wäre eine Induktivität effektiver und weniger verlustreich). Eine andere Möglichkeit wäre die Verwendung von zwei 7805, einen für den Mikro- und einen für den PIR-Kreis, mit gemeinsamen 0 V, was verhindern würde, dass Rauschen von der Mikroseite so stark in den PIR-Kreis gelangt.
Bobbi Bennett
rzetterberg