Sensor PIR activado por sí mismo cuando se usa el temporizador, funciona sin temporizador

TL;DR

Un sensor PIR se activa solo cuando se usa un temporizador para esperar 2 segundos después de que se activa el sensor. Sin usar el temporizador para esperar, el sensor funciona como se esperaba.

Antecedentes y configuración

Tengo un sensor PIR conectado a un ATMega328p . El sensor PIR tiene tres pines; VCC, GNDy AL. El ALpin usa un colector abierto para mostrar que se detecta movimiento.

Lo que hice es que conecté el pin AL al pin PC0 en mi ATMega y configuré el pin como entrada con una resistencia de extracción interna y un LED conectado a PC5 para mostrar cuando se detecta movimiento:

void setup_default_values()
{
        DDRC |= (1 << PC5);
        DDRC &= ~(1 << PC0);

        PORTC |= (1 << PC0);
}

Entonces tengo una función que comprueba cuándo PC0está el pin LOW:

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

Esta función enciende el LED cuando PC0es LOWy lo apaga cuando PC0es HIGH. Esta función se ejecuta en cada ciclo de mi bucle principal:

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

    for (;;) {
                check_sensor();
    }

    return 0;
}

Problema encontrado

Todo funciona como se esperaba, el LED se enciende cuando muevo la mano frente al sensor y no se activa sin movimiento. El sensor establece el ALpin LOWdurante aproximadamente 100 a 200 ms.

Lo que pasa es que no quiero usar la señal durante 2 segundos después de que se haya detectado movimiento. Así que implementé una lógica de temporizador y bandera que ignora la señal durante estos 2 segundos. El problema es que ahora el LED se enciende solo después de que el temporizador deja de contar y comienza a aceptar señales de movimiento.

Configuración problemática

Para usar esta lógica de temporizador y bandera, agregué 2 LED, uno que muestra que el temporizador está activo y otro que muestra cuándo se registra una señal:

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;
}

Entonces le doy nueva lógica a la check_sensorfunción:

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;
                }
        }
}

Cuando se detecta movimiento por primera vez, esto es lo que sucede:

  • LED que indica que la señal de PIR está encendida
  • LED que indica la aceptación de la señal parpadeó una vez
  • El LED que indica que el temporizador está activo está encendido
  • El temporizador se restablece y se detectó una bandera que indica que se detectó movimiento

Luego hay una nueva función que maneja la cuenta regresiva:

#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;
}

Esta función debe ignorarse a menos que se detecte un movimiento. Cuando se ha completado la cuenta regresiva, el LED indicador del temporizador se apaga y la bandera de movimiento se restablece, lo que indica que se puede aceptar una nueva señal.

cosas que he probado

Rebote de software

He intentado agregar software debouncefuncionalidad donde el movimiento solo se acepta si PC0es LOWpor una cantidad definida de ciclos. Esto no cambió el comportamiento defectuoso.

Pulsador en lugar de PIR

He intentado eliminar el PIR y agregar un botón que está LOWpresionado hacia abajo. Cuando se usa el botón pulsador, el circuito y la lógica funcionan como se esperaba.

esquemas

Aquí está el esquema de la fuente de alimentación. El circuito está conectado a una fuente de alimentación de CC estabilizada donde el riel de +5 V es en realidad alrededor de +6,5 V (no sé cómo editar el texto de un componente en gschem). VCCes lo que conecto a mi microcontrolador y sensor PIR, como verá en el segundo esquema.

Fuerza

Aquí está el esquema del microcontrolador, los LED y el sensor PIR. Algunos pines no se muestran en los esquemas: RESETel pin está conectado a mi programador, lo mismo con MOSI, MISOy SCK.

uControlador

¿La potencia del PIR está desacoplada del resto? Quizás una pequeña fluctuación en el voltaje se esté viendo como movimiento.
@BobbiBennett ¡Vea los esquemas en la edición! Solo estoy usando tapas de desacoplamiento en la fuente de alimentación. El microcontrolador y el sensor PIR utilizan el mismo VCC de la fuente de alimentación. Noté algo, la hoja de datos del sensor PIR dice que el voltaje de funcionamiento es de 12 V, pero la página de la tienda dice 5 V - 12 V, por eso estoy usando 5 V para el sensor PIR. ¿Podría ser un problema con ambos, el desacoplamiento necesario y un voltaje más alto?

Respuestas (1)

El voltaje de caída típico del 7805 es de 2,0 V, pero solo tiene una entrada de 6,5 V, por lo que el regulador no puede funcionar correctamente. Esto podría significar que cualquier pequeño pico de corriente en la demanda en el lado de la carga del regulador, por ejemplo, cuando se encienden los LED, daría lugar a fluctuaciones de voltaje, a pesar del capacitor de 10 uF, y los PIR son muy sensibles a las fluctuaciones de voltaje.

Recomendaría aumentar la entrada al 7805 a por lo menos 7,0 V y probablemente 8,0 V para permitir variaciones en el voltaje de caída (2,0 V aparece como típico, no como máximo), y agregar un filtro RC al suministro al PIR circuito. Sin embargo, debe dimensionar la R con cuidado para evitar reducir el suministro del circuito PIR a menos del mínimo especificado (tal vez un inductor sería más efectivo y con menos pérdidas). Otra opción sería usar dos 7805, uno para el micro y otro para el circuito PIR, con 0V común, lo que evitaría que el ruido del lado del micro entre tanto en el circuito PIR.

Subí el voltaje a 8V y ahora funciona como se esperaba. ¡Gracias, @Martin!