No artigo anterior foi explanado como os registradores do Atmega328p funcionam internamente e na programação em C/C++, e foi desenvolvido um código para piscar um LED utilizando o Atmel Studio 7, AVRDude e USBasp. Neste artigo será apresentado como programar um sensor PIR utilizando a mesma metodologia, e expandindo os conhecimentos na arquitetura AVR.
Para realizar este artigo de forma efetiva, é obrigatório a leitura do artigo anterior "Programando o Atmega328p com registradores", onde apresentamos correções de possíveis erros com o gravador USBasp, e teoria/prática das portas I/O do microcontrolador Atmega328p.
O sensor PIR DYP-ME003 ou de presença é utilizado principalmente para o acionamento de lâmpadas por meio de um relé. O sensor é ativado em nível alto (HIGH) quando uma pessoa, animal ou objeto passa em uma área de 5-7 metros de distância e em um ângulo de 100 graus. O sensor é desativado em nivel baixo (LOW) automaticamente por um delay próprio que pode ser ajustado pelo potenciômetro "Time" entre 5-300 segundos, e o potenciômetro "Sensitive" ajusta a sensibilidade de detecção do sensor PIR.
Montagem
Para este artigo utilize uma placa Arduino Uno ou um Arduino Standalone Atmega328p, ambos com conexão ICSP.
Este projeto podemos montar ele de duas formas, um com LED ou um módulo relé. Para isso separe a lista de materiais necessários abaixo.
Projeto principal
- 1 Arduino Uno ou Standalone Atmega328p.
- 1 Gravador AVR USBasp com cabo ICSP 10 pinos
- 1 Sensor PIR
- 1 Protoboard pequeno
- Fios jumpers
Projeto com LED
- 1 LED
- 1 Resistor de 220R
Projeto com módulo relé
- 1 Módulo relé de 1 canal ou Faça o seu próprio módulo relé agora!
Programando o Atmega328p
Abra o Atmel Studio 7 e crie um projeto com o nome de "SensorPir" e selecione o microcontrolador Atmega328p.
Copie e cole este código abaixo, compile e grave o código utilizando o gravador USBasp, em Tools/AVRDude USBasp.
/*
* SensorPir.cpp
*
* Created: 27/09/2019 16:55:40
* Author : tecdicas
*/
#define F_CPU 16000000UL // Cristal de 16MHz
#include <avr/io.h>
int main(void)
{
DDRD &= ~(1 << DDD3); // Configura o PD3 como INPUT (sensor PIR)
DDRD |= (1 << DDD4); // Configura o PD4 como OUTPUT (LED/Relé)
while (1)
{
bool pir = (PIND & (1 << PIND3)); // Ler o valor do PIR
if(pir == false)
{
PORTD &= ~(1 << PORTD4); // Desliga LED/Relé
}
else
{
PORTD |= (1 << PORTD4); // Liga LED/Relé
}
}
}
Se a compilação for bem sucedida..
Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
E se a gravação for bem sucedida..
avrdude.exe: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude.exe: Device signature = 0x1e950f
avrdude.exe: NOTE: FLASH memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude.exe: erasing chip
avrdude.exe: reading input file "D:\Projetos\AtmelStudio\SensorPir\SensorPir\Debug\SensorPir.hex"
avrdude.exe: writing flash (148 bytes):
Writing | ################################################## | 100% 0.07s
avrdude.exe: 148 bytes of flash written
avrdude.exe: verifying flash memory against D:\Projetos\AtmelStudio\SensorPir\SensorPir\Debug\SensorPir.hex:
avrdude.exe: load data flash data from input file D:\Projetos\AtmelStudio\SensorPir\SensorPir\Debug\SensorPir.hex:
avrdude.exe: input file D:\Projetos\AtmelStudio\SensorPir\SensorPir\Debug\SensorPir.hex contains 148 bytes
avrdude.exe: reading on-chip flash data:
Reading | ################################################## | 100% 0.05s
avrdude.exe: verifying ...
avrdude.exe: 148 bytes of flash verified
avrdude.exe: safemode: Fuses OK
avrdude.exe done. Thank you.
Ajuste os potenciômetros da forma que preferir, onde o LED ou relé irão ligar e desligar conforme a detecção do sensor PIR.
Analisando o código
Vamos analisar a forma em que os registradores foram utilizados na programação em C/C++.
Direções das portas
Dentro da estrutura int main() configuramos a porta PD3 como INPUT, utilizando o registrador DDRD, e o terceiro bit DDD3 setamos como 0/falso utilizando a técnica Bitwise de NAND. A porta PD4 foi configurada como OUTPUT, utilizando também o registrador DDRD, e o quarto bit DDD4 setamos como 1/verdadeiro, utilizando o mesmo método de bitwise, porém com a lógica OR.
DDRD &= ~(1 << DDD3); // Configura o PD3 como INPUT (sensor PIR)
DDRD |= (1 << DDD4); // Configura o PD4 como OUTPUT (LED/Relé)
O código equivalente utilizando a "linguagem Arduino" seria:
pinMode(3, INPUT);
pinMode(4, OUTPUT);
Leitura da porta input
Dentro da estrutura while (1) realizamos a leitura da porta PD3 setada como INPUT com o registrador PIND, e setamos o terceiro bit PIND3 como 1/verdadeiro. Fisicamente é a conexão com o sensor PIR, e guardamos o estado de false ou true dentro da variável do tipo bool pir.
bool pir = (PIND & (1 << PIND3)); // Ler o valor do PIR
O código equivalente utilizando a "linguagem Arduino" seria:
bool pir = digitalRead(3);
Estados da porta output
Com o valor obtido da porta PD3 e armazenado na variável pir, os estados da porta PD4 são definidos por uma estrutura condicional IF ELSE, se a variável pir for igual a false, desligamos o LED/Relé utilizando o registrador PORTD e o quarto bit como 0/falso utilizando o bitwise NAND. Então se a variável for igual a verdadeiro, ligamos o LED/Relé utilizando novamente o registrador PORTD com o quarto bit em 1/verdadeiro com o bitwise OR.
if(pir == false)
{
PORTD &= ~(1 << PORTD4); // Desliga LED/Relé
}
else
{
PORTD |= (1 << PORTD4); // Liga LED/Relé
}
O código equivalente utilizando a "linguagem Arduino" seria:
if(pir == false)
{
digitalWrite(4, LOW);
}
else
{
digitalWrite(4, HIGH);
}