TL;DR
Un sensor PIR se activa por sí mismo cuando se utiliza un temporizador para esperar 2 segundos después de que el sensor se activa. Sin usar el temporizador para esperar el sensor funciona como se esperaba.
De fondo y de instalación
Tengo un PIR sensor conectado a un
ATMega328p.
El sensor PIR tiene tres pines; VCC
, GND
y AL
. El AL
pin de usos de colector abierto para mostrar que el movimiento es
detectado.
Lo que he hecho es que he conectado AL pin a PC0 pin en mi ATMega y configurar el pin como entrada con internas de pull up resistor y un LED conectado a PC5 a mostrar cuando el movimiento es detectado:
void setup_default_values()
{
DDRC |= (1 << PC5);
DDRC &= ~(1 << PC0);
PORTC |= (1 << PC0);
}
Entonces tengo una función que verifica cuando el PC0
pin es LOW
:
void check_sensor()
{
if (PINC & (1 << PC0)) {
PORTC &= ~(1 << PC5);
}else{
PORTC |= (1 << PC5);
}
}
Esta función se enciende el LED cuando PC0
es LOW
y la apaga cuando PC0
es HIGH
.
Esta función se ejecuta cada ciclo de mi bucle principal:
int main()
{
setup_default_values();
blink(4);
for (;;) {
check_sensor();
}
return 0;
}
Problema encontrado
Todo funciona como se espera, el LED se ilumina cuando yo de la onda de mi mano delante del sensor y no se activa
sin movimiento. El sensor se establece el AL
pin LOW
de alrededor de 100 - 200 ms.
La cosa es que no quiero usar la señal de 2 segundos después de que se ha detectado movimiento. Por lo que he implementado un temporizador y la bandera de la lógica, que ignora la señal durante estos 2 segundos. El problema es que ahora el LED se enciende por sí mismo después de que el temporizador ha dejar de contar y empezar a aceptar señales de movimiento
Problemática de instalación
Para utilizar el temporizador y la bandera de la lógica he añadido 2 LEDs, uno que muestra que el temporizador está activo y que muestra cuando un la señal es registrada:
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;
}
Luego supe que la lógica de la check_sensor
función de:
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 el movimiento de la primera vez, esto es lo que sucede:
- LED que indica la señal de PIR se ilumina
- LED indicador de señal de aceptación parpadeó una vez
- LED que indica que el temporizador está activo se ilumina
- Se restablece el temporizador y la bandera se detectó el movimiento
A continuación, hay una nueva función que se encarga de 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 ser ignorado a menos que haya un movimiento detectado. Cuando la cuenta regresiva ha completado temporizador que indica el LED se apaga y el movimiento de la bandera es restablecer lo que indica que una nueva señal puede ser aceptado.
Cosas que he intentado
Software de rebote
He intentado añadir software debounce
funcionalidad donde el movimiento es aceptado solamente si PC0
es LOW
de
una cantidad definida de ciclos. Esto no cambia el comportamiento deficiente.
Empuje el botón en lugar de PIR
He intentado eliminar el PIR y agregue un botón de comando, que es LOW
en empujar hacia abajo. Cuando se utiliza el botón pulsador
el circuito y la lógica funciona como se esperaba.
Esquemas
Aquí está el esquema de la fuente de alimentación. El circuito está conectado a un Estabilizado la fuente de alimentación de CC, donde el riel de +5V es en realidad alrededor de +6.5 V (no sé cómo modificar el texto de un componente en gschem). VCC
es lo que me puedo conectar a mi microcontrolador y sensor PIR -, como se verá en el segundo esquema.
Aquí está el esquema para el microcontrolador, el Led y el sensor PIR -. Algunos de estos pines no se muestra en el esquema: RESET
pin está conectado a mi programador, con el mismo MOSI
, MISO
y SCK
.