TL; DR
Un sensor PIR se activa solo cuando se usa un temporizador para esperar 2 segundos después de que se active el sensor. Sin usar el temporizador para esperar, el sensor funciona como se esperaba.
Fondo y configuración
Tengo un sensor PIR conectado a un
ATMega328p .
El sensor PIR tiene tres pines; VCC
, GND
y AL
. El pin AL
usa el colector abierto para mostrar que el movimiento es
detectado
Lo que he hecho es que conecté el pin AL al pin PC0 en mi ATMega y configuré el pin como entrada con resistencia interna de extracción 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);
}
Luego tengo una función que comprueba cuando el PC0
pin es 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 todos los ciclos de mi ciclo principal:
int main()
{
setup_default_values();
blink(4);
for (;;) {
check_sensor();
}
return 0;
}
Problema encontrado
Todo funciona como se esperaba, el LED se ilumina cuando agito mi mano frente al sensor y no se dispara
sin movimiento El sensor establece el AL
pin LOW
durante aproximadamente 100 - 200 ms.
La cosa es que no quiero usar la señal durante 2 segundos después de que se haya detectado el movimiento. Así lo 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 haya dejado de contar y comience a aceptar señales de movimiento
Configuración problemática
Para usar este temporizador y la lógica de la bandera, agregué 2 LED, uno que muestra que el temporizador está activo y otro que muestra cuando la señal está 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, hago una nueva lógica a la función check_sensor
:
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 la primera vez, esto es lo que sucede:
- el LED que indica la señal de PIR está encendido
- 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 reinicia y se marca un indicador que indica que se detectó movimiento
Luego hay una nueva función que maneja la cuenta atrás:
#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 cuenta regresiva tiene se ha completado el temporizador que indica que el LED está apagado y se restablece el indicador de movimiento que indica que una nueva señal puede ser aceptada.
Cosas que he probado
Software rebote
He intentado agregar la funcionalidad software debounce
donde el movimiento solo se acepta si PC0
es LOW
para
Una cantidad definida de ciclos. Esto no cambió el comportamiento defectuoso.
Pulse el botón en lugar de PIR
He intentado quitar el PIR y agregar un botón que está LOW
al presionar hacia abajo. Al usar el botón pulsador
el circuito y la lógica funcionan como se esperaba.
Esquemas
Aquí están los esquemas para la fuente de alimentación. El circuito está conectado a una fuente de alimentación de CC estabilizada donde el riel de + 5V está alrededor de + 6.5V (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ánlosesquemasdelmicrocontrolador,losLEDyelsensorPIR.Algunospinesnosemuestranenlosesquemas:RESET
pinestáconectadoamiprogramador,lomismoconMOSI
,MISO
ySCK
.