No lado do sensor vou usar um Arduino com dois sensores: um sensor de temperatura DS18B20 ligado ao pino D8 e um sensor de efeito Hall A1120 ligado ao pino D7. A minha primeira ideia era usar o sensor LM35, mas ele não funciona com 3V inviabilizando o meu próximo passo. O rádio é ligado da mesmo forma que o meu teste anterior.
O software no Arduino transmitirá em duas situações:
- De 10 em 10 minutos.
- Quando detectar mudança no sensor de efeito Hall (indicando que um imã foi colocado ou retirado da frente dele).
- Dois bytes com a leitura do sensor de temperatura (temperatura em décimo de graus centígrados)
- Um byte contendo 0 ou 1 conforme o sensor de efeito Hall estiver acionado.
// Exemplo de sensor enviando dados através do nRF24L01+
// Daniel Quadros, 13/10/15
#include <SPI.h>
#include <RF24.h>
// Conexoes
const int pinLED = 6;
const int pinHall = 7;
const int pinDS18B20 = 8;
const int pinCE = 9;
const int pinCSN = 10;
// Este objeto encapsula o acesso ao nRF24L01+
RF24 radio(pinCE, pinCSN);
// Endereços
byte addrLogger[6] = "DLogr";
// Estado anterior do sensor de efeito Hall
const uint8_t hallOFF = '0';
const uint8_t hallON = '1';
const uint8_t hallUNDEF = 'X';
uint8_t hallAnt = hallUNDEF;
// Tempo em minutos entre transmissões periodicas
const unsigned long tempoTx = 10;
// Próximo envio automático
unsigned long proxEnvio;
void setup()
{
// Serial para debug
Serial.begin(9600);
Serial.println("Sensor com nRF24L01+");
// Iniciacao dos pinos de LED e sensores
pinMode (pinLED, OUTPUT);
pinMode (pinHall, INPUT);
digitalWrite (pinHall, HIGH);
setDQ(HIGH);
// Inicia o rádio
radio.begin();
radio.setPayloadSize(3);
radio.openWritingPipe(addrLogger);
// Primeiro envio
proxEnvio = millis() + tempoTx * 60000UL;
}
void loop()
{
uint8_t hall;
uint8_t msg[3];
uint16_t temp;
hall = digitalRead(pinHall);
if (hall == LOW)
{
hall = hallON;
}
else
{
hall = hallOFF;
}
if ((hall != hallAnt) || (millis() >= proxEnvio))
{
// Salva estado do sensor hall
hallAnt = hall;
// Indica transmissão
digitalWrite (pinLED, HIGH);
// Le a temperatura
temp = leDS18B20();
// Monta mensagem a enviar
msg[0] = temp >> 8;
msg[1]= temp & 0xFF;
msg[2] = hall;
// Envia
Serial.print ("Transmitindo (");
Serial.print (temp);
Serial.print (' ');
Serial.print ((char) hall);
Serial.print ("): ");
if (radio.write(msg, 3))
Serial.println ("Ok");
else
Serial.println ("Erro");
if (millis() >= proxEnvio)
{
// Programa próxima transmissão
proxEnvio = millis() + tempoTx * 60000UL;
}
// Indica fim da transmissão
digitalWrite (pinLED, LOW);
}
}
// Leitura da temperatura
// Retorna temperatura em décimos de grau
// Considera que temos apenas um sensor conectado
// e ele está com a configuração padrão
// Ref: AN162 da Maxim
uint16_t leDS18B20()
{
uint16_t valor;
if (!OW_Reset())
Serial.println("Nao achou sensor");
OW_WriteByte (0xCC); // Skip ROM
OW_WriteByte (0x44); // Start conversion
delay(750); // aguarda fim da conversao
OW_Reset();
OW_WriteByte (0xCC); // Skip ROM
OW_WriteByte (0xBE); // Read ScratchPAD
valor = OW_ReadByte(); // LSB
valor = (OW_ReadByte() << 8) + valor; // MSB
OW_Reset(); // Nao queremos o restp
valor = (valor * 100) / 16;
return (valor+5)/10;
}
// OneWire reset
// Retorna true se tem um sensor conectado
uint8_t OW_Reset(void)
{
uint8_t resposta;
setDQ(LOW);
delayMicroseconds(480); // comanda reset
setDQ(HIGH);
delayMicroseconds(70); // aguarda sensor responder
resposta = digitalRead(pinDS18B20); // le a resposta
delayMicroseconds(240); // aguarda fim da resposta
return resposta == LOW;
}
// OneWire Read Byte
uint8_t OW_ReadByte(void)
{
uint8_t i, resp;
for (i = 0; i < 8; i++)
{
// Pulso de 1uS abre janela para resposta
setDQ(LOW);
delayMicroseconds(1);
setDQ(HIGH);
// Dá um tempo para sensor colocar a resposta e a lê
delayMicroseconds(10);
resp = resp >> 1;
if (digitalRead(pinDS18B20))
{
resp = resp | 0x80;
}
// Aguarda o final da janela
delayMicroseconds(50);
}
return resp;
}
// OneWire Write Byte
void OW_WriteByte(uint8_t valor)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
// Low inicia a janela
setDQ(LOW);
delayMicroseconds(1);
if (valor & 0x01)
{
// Volta o nivel alto se for "1"
setDQ(HIGH);
}
// Manter o bit até o final da janela
delayMicroseconds(80);
// Voltar ao repouso
setDQ(HIGH);
// Passar para o próximo bit
valor = valor >> 1;
}
// Tempo de recuperação entre bytes
delayMicroseconds(1);
}
// Controle da linha DQ do DS18B20
void setDQ(uint8_t state)
{
if (state == LOW)
{
// LOW deve ser forçadp
pinMode (pinDS18B20, OUTPUT);
digitalWrite (pinDS18B20, LOW);
}
else
{
// HIGH é gerado pelo pullup interno
pinMode (pinDS18B20, INPUT);
digitalWrite (pinDS18B20, HIGH);
}
}
No lado do Raspberry Pi, a ligação do rádio continua a mesma. A aplicação abaixo recebe os pacotes, decodifica e grava em um arquivo:from nrf24 import NRF24
import time
import datetime
addrRx = "DLogr"
radio = NRF24()
radio.begin(0,0,25,24)
radio.setPayloadSize(3)
radio.openReadingPipe(1,addrRx)
radio.startListening()
radio.printDetails()
try:
while True:
pipe = [0]
if radio.available(pipe, False):
dado = []
radio.read(dado)
agora = datetime.datetime.now().strftime("%d/%m/%y %H:%M:%S ")
temperatura = ((dado[0]*256.0) + dado[1]) / 10.0
linha = "{0} {1:c} {2:.1f}".format(agora, dado[2], temperatura)
print linha
log = open("dado.log", 'a')
log.write(linha)
log.write('\n')
log.close()
time.sleep(0.1)
except KeyboardInterrupt:
sys.exit(0)
O meu próximo passo vai ser substituir o Arduino por um MSP430 e ver que performance eu consigo operando com uma bateria de 3V.
4 comentários:
Boa tarde Daniel... primeiramente gostaria de parabeniza-lo pelo poste e pelo otimo trabalho que foi feito. No entanto apesar de esta muito bem feito eu tenho duvidas.
1- eu preciso fazer alguma configuração nos pinos SPI do Raspberry?
2-Voce poderia dizer qual pino do módulo foi conectado em qual pino do RPI?
Grato.
Ailton, dê uma olhada na Parte 1: http://dqsoft.blogspot.com.br/2015/10/usando-o-nrf24l01-com-o-raspberry-pi-um.html. Aqui no blog tem também mais informações sobre o nRF24L01, dê uma olhada nos post antigos,
Ola Daniel... Depois de muito penar conseguir com a ajuda de seu post fazer o codigo ser executado. Porem estou usando um raspberry pi 2 e na impressao dos detalhes do modulo esta todos os endereços zerados, vc saberia como devo conectar o mudulo a esse raspi? ja olhei em varios sites e sempre fica zerado.
Grato.
Em princípio a conexão é a mesma em todos os modelo. Eu fiz o teste com um B+.
Postar um comentário