PIR-Sensor wird bei Verwendung des Timers von selbst ausgelöst, funktioniert ohne Timer

TL;DR

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.

Hintergrund und Aufbau

Ich habe einen PIR-Sensor an einen ATMega328p angeschlossen . Der PIR-Sensor hat drei Stifte; VCC, GNDund AL. Der ALStift 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 PC0Pin ist LOW:

void check_sensor()
{
        if (PINC & (1 << PC0)) {
                PORTC &= ~(1 << PC5);
        }else{
                PORTC |= (1 << PC5);
        }
}

Diese Funktion lässt die LED aufleuchten, wenn PC0sie ist, LOWund schaltet sie aus, wenn PC0sie ist HIGH. Diese Funktion wird in jedem Zyklus meiner Hauptschleife ausgeführt:

int main()
{
        setup_default_values();
        blink(4);

    for (;;) {
                check_sensor();
    }

    return 0;
}

Problem aufgetreten

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 ALPin LOWfü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

Problematische Einrichtung

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_sensorFunktion:

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:

  • LED-Anzeigesignal vom PIR leuchtet
  • LED zur Signalakzeptanz blinkte einmal
  • Die LED, die anzeigt, dass der Timer aktiv ist, leuchtet
  • Der Timer wird zurückgesetzt und das Flag zeigt an, dass eine Bewegung erkannt wurde

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.

Dinge, die ich ausprobiert habe

Software-Entprellen

Ich habe versucht, software debounceeine Funktionalität hinzuzufügen, bei der Bewegung nur akzeptiert wird, wenn PC0sie LOWfür eine definierte Anzahl von Zyklen gilt. An dem fehlerhaften Verhalten änderte dies nichts.

Taster statt PIR

Ich habe versucht, den PIR zu entfernen und einen Druckknopf hinzuzufügen, der LOWgedrückt ist. Bei Verwendung des Tasters funktioniert die Schaltung und Logik wie erwartet.

Schema

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). VCCverbinde ich mit meinem Mikrocontroller und PIR-Sensor, wie Sie im zweiten Schema sehen werden.

Leistung

Hier sind die Schaltpläne für den Mikrocontroller, die LEDs und den PIR-Sensor. Einige Pins werden in den Schaltplänen nicht angezeigt: RESETPin ist mit meinem Programmierer verbunden, dasselbe mit MOSI, MISOund SCK.

uController

Ist die PIR-Leistung vom Rest entkoppelt? Vielleicht wird eine kleine Spannungsschwankung als Bewegung gesehen.
@BobbiBennett Sehen Sie sich die Schaltpläne in der Bearbeitung an! Ich verwende nur Entkopplungskappen im Netzteil. Der Mikrocontroller und der PIR-Sensor verwenden denselben VCC von der Stromversorgung. Mir ist etwas aufgefallen, das Datenblatt für den PIR-Sensor sagt Betriebsspannung 12V, aber die Shop-Seite sagt 5V - 12V, deshalb verwende ich 5V für den PIR-Sensor. Könnte es ein Problem sowohl mit der erforderlichen Entkopplung als auch mit der höheren Spannung sein?

Antworten (1)

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.

Ich habe die Spannung auf 8V erhöht und jetzt funktioniert es wie erwartet. Danke, @Martin!