Ou melhor dizendo - Tentando desvendar Controle Remoto RF.

Depois que consegui fazer funcionar o Analisador Lógico com o Arduino, tenho feito várias verificações que sempre quis fazer. Fiz uma análise de controle remoto usando a Luz infravermelha e agora estou fazendo uma análise mais apurada de controle remoto que usa Rádio-frequência RF).

Tutorial - Analisador Lógico com Arduino:

http://labdegaragem.com/profiles/blogs/tutorial-analisador-l-gico-c...

Decodificando Controle Remoto infravermelho:

http://labdegaragem.com/profiles/blogs/6223006:BlogPost:315534

Já li em vários Blogs do Lab de Garagem, que muitos desejam usar o Controle Remoto RF com o Arduino.

Para a minha decepção e acredito que  muitos se decepcionarão também, os controles remotos atuais são criptografados.Por isso, alguns já tentaram usar e falharam.

Para entender melhor, fiz uma análise do Controle Remoto do fabricante Rossi. (aciona a abertura e fechamento de portões de garagem). Esse controle usa o chip HCS201 da Microchip:

http://ww1.microchip.com/downloads/en/DeviceDoc/41098c.pdf

Possui dois botões (chaves) S0 e S1. A frequência da portadora é de 433,92 MHz. Usa uma pilha de 12V.

O link da Rossi portões, com os circuitos de controle de portões:

http://www.rossiportoes.com.br/produtos/120-central-de-comando.html

Lendo o data sheet do chip HCS201 da Microchip, percebi que a tecnologia usada é bem segura.

Ele é bem versátil - cada chip tem um número de série programável de 28 bits e uma chave de criptografia de 64 bits (acredito que é impossível descobri-la) . Essas informações são gravadas pelo fabricante do controle remoto (no caso a Rossi).

Cada transmissão tem um código diferente, por isso, se o circuito receptor não souber a chave criptográfica do fabricante, não haverá rotina de decodificação que permita identificar qual código foi transmitido. Fiz vários testes e comprovei ! Pressionei várias vezes o botão S1 e a cada momento o trem de pulsos era de um formato diferente.

Seria possível usar o controle remoto, desde que usasse um chip programado pelo desenvolvedor.

Assim a rotina de decodificação usaria a chave gravada no chip.

Vejam que interessante as várias telas capturadas usando o Analisador Lógico com o Arduíno.

Minhas medições foram no saída TX OUT do chip HCS201. Alimentei o controle remoto com 5V para não danificar o Arduino.

Essa captura foi feita pressionando o botão S1 - taxa de amostragem de 5 KHz :

Vejam que tem 12 pulsos de preambulo para sincronização :

Taxa de amostragem de 10 Khz.

Os 12 pulsos de preambulo usam a largura de pulso de 780 us:

(taxa de amostragem 50 KHz) 

Para decodificar os bits 0 e bit 1 :

Esse é o formato do Bit 0 : (taxa de amostragem 50 KHz) 

E esse é o formato do Bit 1 : (taxa de amostragem 50 KHz) 

Exibições: 87434

Responder esta

Respostas a este tópico

Os sensores magnéticos da ECP comprados no ML chegaram ontem.

Após apanhar um pouco, descobri que o código, pelo menos para mim aqui com um arduino pro mini, não estava com o timing correto, estava atrasando, e assim perdendo muitas mensagens e outras vezes invertendo bits. Acho que isso é um problema também do transmissor da ECP que pode não ser muito preciso também.

Mas com um pequeno ajuste no código do Turcato, fazendo com que cada bit do endereço fosse lido em sequência (ao invés de ler um bit por chamada da função de leitura e do loop(), funcionou com maior exatidão. (basicamente troquei o "if" por um "while".

O problema é que o código calculava o lambda numa única chamada e depois quando lia o endereço só lia um bit e liberava a função loop().

O problema agora é o alcance, os sensores que coloquei na sala onde está o arduino com o receptor RF são lidos corretamente mas no quardo que fica bem ao lado e na cozinha não consegue ler nenhuma vez.

Tentei colocar uma antena linear de 17,3 mas não melhorou muito.

Será que a ligação na USB esta interferindo? Mas o programa que fiz depende da USB. A idéia é o arduino enviar via serial para um script no windows que tomaria algumas ações com base na informação de qual sensor foi ativado. Se for a usb terei que comprar mais um ESP8266 e liga-lo no arduino para transmitir por wifi. A maior desvantagem seria perder a alimentação por bateria (do netbook).

Alguém sabe se a antena helicoidal funciona melhor?

Uma vez fiz um teste com uma RFM69W em 433MHz e com uma antena helicoidal e conseguia transmitir de um lado a outro da casa usando a lib radiohead.

Pergunta, será que a diferença era a antena ou a potência do RFM69W?

Sugestões para melhorar o alcance? Ou alguma solução alternativa pra conseguir monitorar as janelas?

Acho que o programa do Turcato é assincrono. Isto é a largura dos pulsos pode variar um pouco. Portanto não acho que seja problema de sincronismo.

Quando eu fiz testes com os meus sensores funcionaram muito bem.

Sugiro que meça a tensão das pilhas dos sensores. Pilha fraca poderá interferir nas comunicações.

Não acredito que a USB possa estar interferindo. 

Tem wireless em casa ? Faça testes com o wireless desligado. 

Evite colocar celular próximo dos circuitos também.

Alterei para usar interrupção de forma a ficar assíncrono e agora não perde nenhum dado.

O programa dele é síncrono: isto é, ele faz a chamada para ler e aguarda o retorno. Se o arduino está rápido e não faz outra coisa a não ser decodificação simples, funciona perfeitamente. Se o arduino faz outras coisas (ex. manter o relógio, logging, etc), funciona mas não sempre gerando alguns erros, tornando o sistema "não confiável".

O problema é que o cálculo da duração da mudança de estado é feito entre o início da chamada pulseIn() e o retorno dela, sendo que uma aplicação pode fazer muita coisa antes e depois dessa chamada.

Pra conseguir compensar esse problema, ele deixou o programa bem tolerante a divergências. Ele considerou 1/2 ciclo a 1 e 1/2 ciclos em nivel alto como se fosse 1 (divergência de até 50% para ambos os lados) e 1,5 a 2,5 como se fosse 0. Dessa forma, em aplicações simples funciona;

No meu caso, dava 1 erro a cada 10 leituras em média (não fiz uma estatística formal - é um chute), o que pra mim não é confiável.

Quanto ao problema do alcance, acho que achei o problema.

Conectei o netbook na tomada e agora está conseguindo receber do quarto ao lado, da cozinha, do lavabo e outros, mas ainda tem dificuldade para receber do quarto que fica do outro lado do apartamento.

Conectei na USB do desktop e está funcionando com alcance similar.

Acredito que a falta de aterramento do netbook estivesse interferindo no arduino e no módulo RF via USB.

No Netbook fora da tomada o alcance estava até 3 metros sem parede com a antena linear. Com tomada ou no desktop já ta indo mais de 8 metros com parede.

Agora preciso tentar mexendo na antena, acho que ela está com um erro no comprimento (soldei com ela passando um pouco do furo, e eu acho que isso pode fazer diferença), e vou tentar uns formatos que andei achando pela internet além de tentar fazer uma helicoidal.

você tentou mostrar na serial quando detecta com erro? o programa estava apresentando que detectava a transmissão pq o sensor envia a mensagem várias vezes e sempre reconhecia a maioria mas uma dessas repetições quase sempre dava erro, como as outras davam certo, o programa ficou aceitável para a maioria dos usos.

a primeira versão que coloquei no arduino com a rotina de leitura exatamente igual a do Turcato as vezes armazenava 2 códigos de sensor de uma só vez na eeprom por que o programa estava errando 1 bit as vezes. (obs. fiz uma aplicação para armazenar/cadastrar os sensores na eeprom do pro mini e outro para monitorar e enviar mensagem pela serial em caso de detecção - assim não preciso de botões). Nesse caso, alterando o "if" por um"while" resolveu o problema já que a aplicação não faz quase nada a não ser ler o receptor RF.

Mas colocando outras coisas para o arduino fazer ao mesmo tempo, a quantidade de erros aumenta. No caso do programa de monitoração que faz muitas outras coisas, só funcionou usando interrupção e medindo o tempo entre as mudanças de nível e não medindo o tempo de espera de uma função.

Olá Clóvis!

Notei q vc tem testado exaustivamente o código q postei tempos atrás.

Muito legal! A ideia é exatamente essa: todos usarem e comentarem sobre possíveis melhorias.

No entanto, esses "erros" q vc mencionou não ocorreram/ocorrem aqui nos meus testes.

Como os equipamentos q estamos utilizando nos testes são diferentes, talvez aí esteja a explicação para a diferença nos resultados.

O comentário que o Murta fez faz todo sentido: a bateria do controle tem forte influência na qualidade do sinal.

Tempos atrás me pediram para alterar o código pra usar "interrupções". Cheguei até a fazer, mas como aumenta um pouco a complexidade no entendimento do mesmo, deixei disponível para a "comunidade" o mais simples e, portanto, mais fácil de entender.

Caso vc possa, poste tb o seu código para que possamos utilizar/testar...

T+

Este é o código ORIGINAL onde coloquei algumas instruções para armazenar as transmissões reconhecidas e também quando da erro nos anti-codes (não armazena os outros erros para não interferir muito reconhecimento).

Coloquei ainda no Loop para mostrar o resultado da monitoração após o recebimento de todas as repetições (aguarda 2 segundos sem receber transmissão).

Para mostrar o resultado, acrescentei um if e uma chamada à função millis() em todas as execuções da função loop. Isso simularia um pequeno overhead de processamento num programa real que faz alguma coisa além de simplesmente reconhecer código recebidos, as instruções dentro do if só são executadas quando não há transmissão.

#include <EEPROM.h>
#define DUMP
//# undef DUMP

const byte pinRF = 2; // Pin where RF Module is connected. If necessary, change this for your project

int lambda; // on pulse clock width (if fosc = 2KHz than lambda = 500 us)

struct rfControl //Struct for RF Remote Controls
{
unsigned long addr; //ADDRESS CODE
boolean btn1; //BUTTON 1
boolean btn2; //BUTTON 2
unsigned long milisecs; // quando terminou de reconhecer
};
#ifdef DUMP
// buffer para armazenar os reconhecimentos
unsigned int reg = 0;
struct rfControl rfs[30];
#endif

boolean ACT_HT6P20B_RX(struct rfControl &_rfControl){

static boolean startbit; //checks if start bit was identified
static int counter; //received bits counter: 22 of Address + 2 of Data + 4 of EndCode (Anti-Code)
static unsigned long buffer; //buffer for received data storage

int dur0, dur1; // pulses durations (auxiliary)

if (!startbit)
{// Check the PILOT CODE until START BIT;
dur0 = pulseIn(pinRF, LOW); //Check how long DOUT was "0" (ZERO) (refers to PILOT CODE)

//If time at "0" is between 9200 us (23 cycles of 400us) and 13800 us (23 cycles of 600 us).
if((dur0 > 9200) && (dur0 < 13800) && !startbit)
{
//calculate wave length - lambda
lambda = dur0 / 23;

//Reset variables
dur0 = 0;
buffer = 0;
counter = 0;

startbit = true;
}
}

//If Start Bit is OK, then starts measure os how long the signal is level "1" and check is value is into acceptable range.
// ********** trocar o IF abaixo por WHILE para que o código na função LOOP não interfira no reconhecimento.
// while (startbit && counter < 28)
if (startbit && counter < 28)
{
++counter;

dur1 = pulseIn(pinRF, HIGH);

if((dur1 > 0.5 * lambda) && (dur1 < (1.5 * lambda))) //If pulse width at "1" is between "0.5 and 1.5 lambda", means that pulse is only one lambda, so the data é "1".
{
buffer = (buffer 1) + 1; // add "1" on data buffer
}
else if((dur1 > 1.5 * lambda) && (dur1 < (2.5 * lambda))) //If pulse width at "1" is between "1.5 and 2.5 lambda", means that pulse is two lambdas, so the data é "0".
{
buffer = (buffer 1); // add "0" on data buffer
}
else
{
//Reset the loop
startbit = false;
}
}

//Check if all 28 bits were received (22 of Address + 2 of Data + 4 of Anti-Code)
if (counter==28)
{
// Check if Anti-Code is OK (last 4 bits of buffer equal "0101")
if ((bitRead(buffer, 0) == 1) && (bitRead(buffer, 1) == 0) && (bitRead(buffer, 2) == 1) && (bitRead(buffer, 3) == 0))
{
counter = 0;
startbit = false;

//Get ADDRESS CODE from Buffer
_rfControl.addr = buffer >> 6;

//Get Buttons from Buffer
_rfControl.btn1 = bitRead(buffer,4);
_rfControl.btn2 = bitRead(buffer,5);

#ifdef DUMP
// armazena para conferência
memcpy(&rfs[reg], &_rfControl, 10); // 4 + 1 + 1 + 4
rfs[reg++].milisecs = millis();
#endif

//If a valid data is received, return OK
return true;
}
else
{
//Reset the loop
startbit = false;
#ifdef DUMP
//Get ADDRESS CODE from Buffer
_rfControl.addr = buffer >> 6;

//Get Buttons from Buffer
_rfControl.btn1 = bitRead(buffer,4);
_rfControl.btn2 = bitRead(buffer,5);

// armazena para conferência
memcpy(&rfs[reg], &_rfControl, 10); // 4 + 1 + 1 + 4
rfs[reg++].milisecs = millis();
#endif
}
}

//If none valid data is received, return NULL and FALSE values
_rfControl.addr = NULL;
_rfControl.btn1 = NULL;
_rfControl.btn2 = NULL;

return false;
}

void setup(){
pinMode(pinRF, INPUT);
pinMode(13, OUTPUT);
reg = 0;
Serial.begin(9600);
}
unsigned long lastrecon = 0;
void loop(){
digitalWrite(13, digitalRead(pinRF)); //blink de onboard LED when receive something

struct rfControl rfControl_1; //Set variable rfControl_1 as rfControl type

if(ACT_HT6P20B_RX(rfControl_1))
{
lastrecon = millis();
//If a valid data is received, print ADDRESS CODE and Buttons values
Serial.print("Address: "); Serial.print(rfControl_1.addr, HEX);
Serial.print(" B1: "); Serial.print(rfControl_1.btn1, BIN);
Serial.print(" B2: "); Serial.println(rfControl_1.btn2, BIN);
}
// este trecho aproveita que não está reconhecendo nada no momento e mostra os dados dos erros
// além disso, inclui um pouco de overhead de processamento quando está reconhecendo algo (uma chamada a millis() e um if simples)
// no caso de trocar o if pelo while na rotina de reconhecimento, este overhead deixa de existir.
#ifdef DUMP
unsigned long now = millis();
if (now - lastrecon > 2000 && reg > 0) {
// passou mais de 2 segundos do último reconhecimento, então acabaram as repetições automáticas da transmissão do código
for (int i = 0; i < reg; i++) {
Serial.print(rfs[i].addr, HEX);
Serial.print(" ");
Serial.print(rfs[i].btn1, BIN);
Serial.print(rfs[i].btn2, BIN);
Serial.print(",");
Serial.print(rfs[i].milisecs);
Serial.println();
}
reg = 0;
}
#endif
}

Este é o resultado com o sensor a 10 cm do receptor rf.

Address: 22D091 B1: 0 B2: 1

Address: 22D091 B1: 0 B2: 1
Address: 22D091 B1: 0 B2: 1
Address: 22D091 B1: 0 B2: 1
Address: 22D091 B1: 0 B2: 1
Address: 22D091 B1: 0 B2: 1
Address: 22D091 B1: 0 B2: 1
Address: 22D091 B1: 0 B2: 1
Address: 22D091 B1: 0 B2: 1
Address: 22D091 B1: 0 B2: 1
22D091 01,10531371
22D091 01,10531475
22D091 01,10531580
22D091 01,10531685
22D091 01,10531790
22D091 01,10532052
22D091 01,10532157
22D091 01,10532630
0 00,10532943
22D091 01,10532998
22D091 01,10533154

O programa reconhece o sensor e mostra o resultado. Porém, como pode-se ver ocorre 1 erro de anti-code e há algumas repetições não reconhecidas (a diferença entre os momentos dos reconhecimentos que deveriam sempre ser entre 100 e 115). Só houveram 10 retransmissões reconhecidas corretamente.

Esse teste foi feito no NANO a 16MHz.

O problema piora no pro mini que roda a 8MHz.

Quando juntei com meu programa que usa a interrupção do RTC piora mais ainda.

Alterando o IF (tem um comentário no código) por um WHILE, fez com que o programa reconhecesse consistentemente 22 retransmissões por acionamento do sensor pois, com esse while, o arduino não perde tempo executando outras coisas (não resolve quando o arduino está conectado a outras interrupções).

Ok, reconhece na maioria das vezes e é por isso que  sensor envia várias vezes. Mas, não sei se por azar, no momento que estava gravando a eeprom reconheceu um bit errado que não era bit de anti-code e acabou gravando o código errado.

O problema maior ocorre quando juntamos com outras lógicas (não quero um arduino exclusivo para recenhecer transmissões e ter que usar outro para outras coisas).

Bom, alterando para WHILE resolve o problema se usado em programas que não executam lógica assincrona em paralelo.

Vou enviar neste e nos próximos 3 posts o código com interrupção (versão feita as pressas no domingo.

Para usar em produção no início do arquivo Ht6p20b.cpp deve-se alterar as linhas

#define DUMP
#define DEBUG

para 

//#/define DUMP
//#/define DEBUG

Comentando somente o define DEBUG vai funcionar mas vai ficar enviando prints pela serial.

Arquivo Ht6p20b.h

#ifndef HT6P20B_H
#define HT6P20B_H

#include <Arduino.h> //needed for Serial.println
class Ht6p20b{
private:
byte interruptPin = 0;
volatile int lambda = -1;
volatile unsigned long lastLevelChange = 0;
volatile unsigned long lowDuration = 0;
volatile unsigned long lastDetection = 0;
volatile unsigned short bitCount = 0;
volatile unsigned long value = 0;
volatile unsigned int state = 0;
public:
Ht6p20b (byte); // interrupt (0 or 1)
void signalChanged();
void attachInt();
unsigned long getCode();
unsigned int getState();
};
#endif

(para executar com detecção deve-se remover ou comentar as linhas #define).

Arquivo Ht6p20b.cpp

#include <Arduino.h> //needed for Serial.println
#include "Ht6p20b.h"

#define DUMP
#define DEBUG
#ifdef DEBUG
int num = 0;
#endif

// global
Ht6p20b * Ht6p20b_instance = NULL;
void Ht6p20b_signalChangedWrapper() {
if (Ht6p20b_instance) {
Ht6p20b_instance->signalChanged();
}
}

void Ht6p20b::signalChanged() {
digitalWrite(13, !digitalRead(13));
bool rising = digitalRead(2 + interruptPin) == HIGH; // int0 == pin2, int1 == pin3
unsigned long now = micros(); // micros não incrementa durante ISR
long dur0 = now - lastLevelChange; // quanto tempo ficou no nível anterior
switch (state) {
case 0 : // waiting for PILOT CODE
if (rising) {
// mudou pra HIGH então vamos ver quanto tempo demorou
//If time at "0" is between 9200 us (23 cycles of 400us) and 13800 us (23 cycles of 600 us).
if ((dur0 > 9200) && (dur0 < 13800)) {
//calculate wave length - lambda
lambda = dur0 / 23;
state = 1; // wait for LOW to start 3 cicles BIT
value = 0;
bitCount = 0;
} else {
// erro --- está lendo estática?
state = 0;
#ifdef DEBUG
num = 0;
#endif
}
} else {
// erro --- está lendo estática?
state = 0;
#ifdef DEBUG
num = 0;
#endif
}
break;
case 1 : // waiting for first cicle LOW
if (rising) {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
} else {
state = 2; // wait for HIGH
}
break;
case 2 : // waiting for the END of first cicle LOW
if (rising) {
lowDuration = dur0; // intervalo em que ficou em LOW.
state = 3; // wait for LOW
} else {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
}
break;
case 3 : // waiting for the END of the HIGH cicle, the END of the BIT
if (rising) {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
} else {
// dur0 tem intervalo em que ficou em HIGH.
if (lowDuration > dur0) {
// como ficou mais tempo em LOW, temos um BIT 1.
value = (value 1) + 1; // add "1" on data buffer
} else {
value = (value 1); // add "0" on data buffer
}
if (++bitCount < 24) {
state = 2; // wait for another bit. this is already the start of the BIT (the LOW cicle).
} else {
// read ANTI-CODE
state = 4;
}
}
break;
case 4 :
if (rising) {
lowDuration = dur0; // intervalo em que ficou em LOW.
state = 5; // wait for LOW
} else {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
}
break;
case 5 : // waiting for the END of the HIGH cicle, the END of the BIT 0
if (rising) {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
} else {
// dur0 tem intervalo em que ficou em HIGH.
if (lowDuration > dur0) {
// como ficou mais tempo em LOW, temos um BIT 1.
// então é erro, pois deveria ser 0
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
} else {
// como ficou mais tempo em HIGH, temos um BIT 0.
state = 6; // lets go read de second ANTI-CODE BIT
}
}
break;
case 6 :
if (rising) {
lowDuration = dur0; // intervalo em que ficou em LOW.
state = 7; // wait for LOW
} else {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
}
break;
case 7 : // waiting for the END of the HIGH cicle, the END of the BIT 2
if (rising) {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
} else {
// dur0 tem intervalo em que ficou em HIGH.
if (lowDuration > dur0) {
// como ficou mais tempo em LOW, temos um BIT 1.
state = 8; // lets go read the third ANTI-CODE BIT
} else {
// como ficou mais tempo em HIGH, temos um BIT 0.
// então é erro, pois deveria ser 1
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
Serial.println("????? deveria ser 1");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
}
}
break;
case 8 :
if (rising) {
lowDuration = dur0; // intervalo em que ficou em LOW.
state = 9; // wait for LOW
} else {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
}
break;
case 9 : // waiting for the END of the HIGH cicle, the END of the BIT 3
if (rising) {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
} else {
// dur0 tem intervalo em que ficou em HIGH.
if (lowDuration > dur0) {
// como ficou mais tempo em LOW, temos um BIT 1.
// então é erro, pois deveria ser 0
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
Serial.println("????? deveria ser 0");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
} else {
// como ficou mais tempo em HIGH, temos um BIT 0.
state = 10; // lets go read de last ANTI-CODE BIT
}
}
break;
case 10 :
if (rising) {
lowDuration = dur0; // intervalo em que ficou em LOW.
state = 11; // wait for LOW
} else {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
}
break;
case 11 : // waiting for the END of the HIGH cicle, the END of the BIT 4
if (rising) {
// erro --- nunca deveria entrar aqui, perdemos evento ou tem erro na lógica?
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
} else {
// dur0 tem intervalo em que ficou em HIGH.
if (lowDuration > dur0) {
// como ficou mais tempo em LOW, temos um BIT 1.
state = 12; // decoded!!!!!!!
#ifdef DUMP
#ifdef DEBUG
Serial.print(++num);
state = 0; // decoded!!!!!!!
#endif
Serial.println(" decoded");
#endif
lastDetection = now;
} else {
// como ficou mais tempo em HIGH, temos um BIT 0.
// então é erro, pois deveria ser 1
#ifdef DUMP
// não interfere pois só imprime quando da erro
Serial.print(state);
Serial.println("?????");
Serial.println("????? deveria ser 1");
#ifdef DEBUG
num = 0;
#endif
#endif
state = 0;
}
}
break;
case 12: // detected
// wait until main program deal with detection.
break;
default :
// invalid state!!!!! how could we possibly got here?
state = 0;
break;
}
lastLevelChange = now;
}
void Ht6p20b::attachInt() {
attachInterrupt(interruptPin, Ht6p20b_signalChangedWrapper, CHANGE);
}
unsigned long Ht6p20b::getCode() {
if (state == 12) {
state = 0;
return value;
} else {
return 0;
}
}
unsigned int Ht6p20b::getState() {
return state;
}
Ht6p20b::Ht6p20b(byte pin) {
interruptPin = pin;
Ht6p20b_instance = this;
}

Programa de teste da classe Ht6p20b.

Este programa mostra quando um sensor é acionado.

Quando o DEBUG e o DUMP estão habilitados no arquivo Ht6p20b.cpp o estado nunca vai para 12 e por isso não apresenta a detecção.

Em compensação com DEBUG vai mostrar na serial todas as transmissões detectadas.

#include <EEPROM.h>
#include "Ht6p20b.h"

Ht6p20b h(0); // pin 2
void setup() {
Serial.begin(9600);
h.attachInt();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2500);
unsigned long code = h.getCode();
if (code > 0) {
Serial.print("detectou ");
Serial.print(code, HEX);
Serial.print(", ");
Serial.print(code, BIN);
} else {
//Serial.println(h.getState());
}
}

postando novamente, parece que deu erro quando enviei a última mensagem....tomara que consiga escrever novamente

Este é o resultado da execução com DEBUG e DUMP habilitados:

1?????
1?????
2?????
1?????
1 decoded
2 decoded
3 decoded
4 decoded
5 decoded
6 decoded
7 decoded
8 decoded
9 decoded
10 decoded
11 decoded
12 decoded
13 decoded
14 decoded
15 decoded
16 decoded
17 decoded
18 decoded
19 decoded
20 decoded
21 decoded
22 decoded
23 decoded
24 decoded
25 decoded
26 decoded
27 decoded
28 decoded
29 decoded
30 decoded
31 decoded
32 decoded
33 decoded
34 decoded
35 decoded
36 decoded
37 decoded
38 decoded
39 decoded
40 decoded
9?????
????? deveria ser 0
1?????
1?????
3?????
3?????

Me parece que o sensor magnético ECP transmite 41 vezes sendo que a última sempre tem o anti-code errado (ou não transmitido). Executei umas 20x esse teste e o resultado sempre foi o mesmo. Como não há interrogações (??) entre as detecções significa que não houve detecção de erro após o início da transmissão do sensor.

Esta é a saída na serial quando desabilito DEBUG e DUMP.

detectou 8B4246, 100010110100001001000110

A mensagem se repete 2x por que deixei um delay de 2500 no loop() e acaba pegando a última retransmissão (como o código fazia outras coisas antes de limpar para enviar aqui, não persebi que estava repetindo).

observe que getCode() retorna o sensor detectado e zera os registros permitindo detectar novamente se o sensor ainda continuar transmitindo, vai detectar mais vezes o mesmo sensor (é o que ocorre no programa exemplo apenas 1x devido ao delay).

como foi feito na correria deve estar com vários bugs ainda.

Ah, sabia que faltou uma coisa que escrevi quando tentei postar a primeira vez.

Não separei os bits de dados entre endereço e botões. Está lendo tudo num long para simplificar.

Fiz isso por que não pretendo ler controles, quero ler apenas sensores e, caso leia controles, posso considerar cada botão como se fosse um controle diferente. Mas se quiser separar é fácil usando / e % ou >>.

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço