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