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.
Tengo un sensor PIR conectado a un ATMega328p . El sensor PIR tiene tres pines; VCC
, GND
y AL
. El AL
pin 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 PC0
está el pin LOW
:
void check_sensor()
{
if (PINC & (1 << PC0)) {
PORTC &= ~(1 << PC5);
}else{
PORTC |= (1 << PC5);
}
}
Esta función enciende el LED cuando PC0
es LOW
y lo apaga cuando PC0
es 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;
}
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 AL
pin LOW
durante 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.
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_sensor
funció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:
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.
He intentado agregar software debounce
funcionalidad donde el movimiento solo se acepta si PC0
es LOW
por una cantidad definida de ciclos. Esto no cambió el comportamiento defectuoso.
He intentado eliminar el PIR y agregar un botón que está LOW
presionado hacia abajo. Cuando se usa el botón pulsador, el circuito y la lógica funcionan como se esperaba.
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). VCC
es lo que conecto a mi microcontrolador y sensor PIR, como verá en el segundo esquema.
Aquí está el esquema del microcontrolador, los LED y el sensor PIR. Algunos pines no se muestran en los esquemas: RESET
el pin está conectado a mi programador, lo mismo con MOSI
, MISO
y SCK
.
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.
bobbi bennett
rzetterberg