-
Hola
Tengo un control remoto de dos botones con un HT6P20B (Holtek) y en el pic 887 tengo conectado directamente en el RB0 la salida digital de receptor RLP434, necesito leer lo que me llega y decodificar la señal por que el HT6P20X no tiene par decodificador, según Holtek, hay que hacerlo por soft.
Estuve capturando los datos como indica Holtek, con un timer que salta a 120 uSeg y capturando el estado de RB0 en la int, pero no logro comprender los datos. También hice una captura a 320 uSeg (sug por Holtek) para capturar el array indicador de comienzo del paquete y nunca obtuve una muestra coherente, mucho menos una trama que se repitiera.
¿Alguien me ayuda con esto?
Muchísimas gracias.
Darío.-
-
Trama recibida:
(http://img382.imageshack.us/img382/3156/ejeme.jpg)
No se puede recibir el pulso de 1/3 bit por medio de RB0, esperar 2 1/2 clock. Y a partir de ahí empezar a recibir la Dirección y después el dato. Osea:
Espero 2 1/2 clock y testeo DOUT --> Si esta en 1 el bit es 0, y si DOUT=0 entonces el bit es 1.
Espero 3 clock y testeo nuevamente....
-
Hola Suky
Disculpa por retomar lo que no entiendo:
¿Como sería eso de 2 1/2 clock y 3 clock? Holtek en ese mismo datasheet habla de 320 uSeg para detectr la trama inicial y después pasar a 120 uSeg para detectar el paquete. No entiendo que debería cambiar en el timer.
No encuentro en ningún lado la duración en uSeg de cada clock del receptor, por lo tanto no se como calcularlo.
Muchas gracias por la respuesta y por la paciencia.
Darío.-
-
Claro, en el datasheet dice que a Vdd=12V el valor típico de Fosc es de 3kHz. Igual creo que con un osciloscopio podría medirse. En este caso un clock sería de 333 us.
Lo de 2 1/2 y 3 Clock trato de explicarlo en la siguiente figura, es una idea mirando como llega la trama de datos:
(http://img407.imageshack.us/img407/7048/1131i.jpg)
Se recibe el pulso de 1/3 bit por medio de RB0, esperar 2 1/2 clock. Y a partir de ahí empezar a recibir la Dirección y después el dato. Entonces:
Espero 2 1/2 clock y testeo DOUT --> Si esta en 1 el bit es 0, y si DOUT=0 entonces el bit es 1.
Espero 3 clock y testeo nuevamente....
Espero 3 clock y testeo nuevamente....
.
.
.
-
Hola
Gracias Suky por la explicación... aunque sigo duro de entendedera :(
según este gráfico...
(http://img382.imageshack.us/img382/3156/ejeme.jpg)
...y según lo que me explicaste del clock y de que si recibo 1 lo tomo como 0 y viceversa, debería contar 23 ciclos para tomar lo siguiente como datos, o sea: 23 unos con pausa de 333 uSeg y a continuación, los datos, cerrados por 0 1 0 1 donde 0 = es un clock alto (bajo recibido) y dos clocks bajos (recibo alto) y un 1 son dos altos recibidos y un bajo recibido, todo a ritmo de clock.
Si hasta acá voy bien, te cuento que ni a palos recibo 23 altos por RB0 como inicio de trama, bajos recibo a montones, muchísimos más de 23.
Lo que entendí es que un bit de la trama de datos comprende 3 clocks :-/ una la pegue!!
¿Voy bien? ¿En qué me equivoco?
Lamento complicarla tanto.
Muchisimas gracias por las explicaciones.
Darío.-
-
Pero en los primeros 23 clock de fosc, Dout se mantiene a nivel bajo, no es ni un 1 ni un 0. Por eso que para comenzar a recibir la trama me centro en el primer pulso de 1/3 de bit (remarcado en rojo). Lo que yo haría sería con interrupción por RB0 detectar este pulso, recibir todos los datos hasta el anti-code y después salir de la interrupción.
-
Hola
Suky, disculpa que me ponga pesado y duro de entender con este tema.
Decís que detectes con una int en RB0, la llegada del primer pulso marcado en rojo y después interprete la trama, pero tengo varios inconvenientes a la hora de implementar esa solución.
Sin presionar ninguno de los botones del control remoto, cuando el receptor está en "reposo", sin recibir ninguna señal, a RB0 llega ruido, una sucesión de 1 y 0 con duración variable. En este momento, lanzo TMR1 con varios tiempos (probé con 332, 300, 290, 280 y 270 uSeg) cuento la cantidad de 0 que llegan, y cuando cuento 23 y a continuación, un 1, espero la trama, pero resulta que sin presionar ningún botón del emisor, indica que recibí 23 0 y a continuación un 1
Llevé el receptor a un oscilador y los picos del ruido en "reposo" superan los 2 volt, lo que hace que RB0 lo tome como un 1
Probé con 332, 300, 290, 280 y 270 uSeg, por que cuando medí el pulso de inicio de trama en el oscilador me marcó 280 uSeg, a pesar de que Holtek dice que cada clock dura 332 uSeg
Hasta llegué a dudar de mis cálculos...
Clock = 3 Khz = 3000 Hz
Instrucción 887 a 4Mhz = 1.000.000
1.000.000 / 3000 = 333.3333 uSeg
Muchas gracias por la paciencia y las explicaciones
Darío.-
-
Realmente yo no tengo como ver como se comporta la señal enviada por el HT6P20X, pero habría que solucionar el tema del ruido, sino va a ser complicado. Y con respecto a la frecuencia yo lo dejaría en 280us, porque es lo que se mide en el osciloscopio! Porque la diferencia de 50us en 60 clock de la trama va a traer problemas al decodificarlo.
Sin presionar el botón se reciben los 23 clock a nivel bajo + el pulso positivo? Eso si es raro...
-
Hola
Sin presionar el botón se reciben los 23 clock a nivel bajo + el pulso positivo? Eso si es raro...
Por lo aleatorio del ruido, de hecho también recibo xxx bajos y un positivo, la cantidad de bajos antes de un positivo varía.
Saludos
Gracias por la respuesta
Apenas tenga avances, te los comunico
Darío
-
Que tal Nicolas,
Encontré este link en donde realizan la decodificacion del HT6P20B para el arduino. Pero analizando el codigo y el algorimo se puede implementar en cualquier microcontrolador.
Aqui el link:
https://acturcato.wordpress.com/2014/01/04/decoder-for-ht6p20b-encoder-on-arduino-board-english/
Espero te sirva.
Elreypic.
-
Hola
Sin presionar el botón se reciben los 23 clock a nivel bajo + el pulso positivo? Eso si es raro...
Por lo aleatorio del ruido, de hecho también recibo xxx bajos y un positivo, la cantidad de bajos antes de un positivo varía.
Saludos
Gracias por la respuesta
Apenas tenga avances, te los comunico
Darío
Pudiste avanzar algo en esto? quiero decodificar la misma trama para hacer un comando a distancia.
hola nicolasbosio,
lo resolvi conectando tanto el emisor como el receptor al usart, transmito como si fuera serial cableado a 9600 y uso el rf como canal, me resultó lo más simple de implementar y se consigue un buen alcance
saludos
-
Hola LucasBols, que interesante esto ! !
Yo estaba necesitando implementar algo así con el serial, y usar los módulos de 433MHz para transmitir... y tenía mis dudas de que funcione...
Una consulta, envías algún bite inicial para sincronizar?
Gracias / Saludos
-
Hola LucasBols, que interesante esto ! !
Yo estaba necesitando implementar algo así con el serial, y usar los módulos de 433MHz para transmitir... y tenía mis dudas de que funcione...
Una consulta, envías algún bite inicial para sincronizar?
Gracias / Saludos
Hola delirio, yo también uso los de 433,
transmito igual que con una conexión cableada, lo único que implemento es un checksum de cada paquete que lo transmito al final del paquete y si no coincide o no se puede recuperar omito el envío del ack del número de paquete correspondiente, el emisor, si no se recibe el ack reenvía el paquete al final de la transmisión
por ahí leí que aumentándole el voltaje al emisor, llevándolo al voltaje máximo, se consiguen tasas de error mucho menores, pero no lo probé
saludos
-
Que tal delirio y LucasBols,
Me gustaría dar mi opinión con respecto a usar esos módulos de RF. En mi experiencia simplemente usar un serial tal cual sin codificación no es muy efectivo ni eficiente. Si bien se puede usar un serial, este tiene que ser de forma invertida y no true, usar una codificación de datos como la del circuito en cuestión o como en mi caso, usar manchester.
En el siguiente link esta una discución con respecto a este tema y el cómo lo he implementado. Espero que les sirva para que puedan implementarlo de una manera fácil y eficaz.
Link sobre RF (http://www.todopic.com.ar/foros/index.php?topic=40735.0)
Saludos.
Elreypic
-
Al principio, esto me parecía imposible, ya que había que calcular con precisión el tema tiempos, frecuencia interna que depende a su vez de la tensión de una batería, la cual también es variable, por ende Lambda también. Así que se me ocurrió medir ese Lambda cada vez que se manda el código. Los resultados fueron óptimos.
Luego de un tiempito de renegar, finalmente pude con él, filtrando o eliminando aquellos paquetes que no corresponden. Sin más preámbulos, les paso el código en CCS. Lo hice para un PIC16F628 (con su memoria EEPROM se pueden almacenar hasta 30 llaveros y controlar diferentes dispositivos o lo que ustedes quieran).
#include <16f628a.h>
#fuses INTRC_IO, NOWDT, BROWNOUT, NOPROTECT, MCLR
#use delay (internal = 4M)
#use fast_io (B)
#define Margen (int16)40
#define RX PIN_B4
#define LCD_RS_PIN PIN_A7 ////
#define LCD_RW_PIN PIN_A4 ////
#define LCD_ENABLE_PIN PIN_A6 ////
#define LCD_DATA4 PIN_A0 ////
#define LCD_DATA5 PIN_A1 ////
#define LCD_DATA6 PIN_A2 ////
#define LCD_DATA7 PIN_A3 ////
#include <lcd.c>
int32 Datos;
int32 Verif;
char contador_bits;
int16 Lambda;
int16 L;
int16 H;
enum {
Lambda_1=0,
Lambda_2,
Obtener_datos,
Datos_correctos,
Datos_incorrectos,
Paquete_obtenido,
Mostrar_resultados,
Paquete_fallido
};
Struct Supervisor {
int Tarea;
int Resultado;
}Supervisor;
void display();
#INT_RB
void int_rb_sir (){
switch (Supervisor.Tarea){
case Lambda_1:
if(input(RX)){
Lambda = 0;
L = 0;
H = 0;
set_timer0(0);
clear_interrupt(int_timer0);
enable_interrupts(int_timer0);
set_timer1(0);
Supervisor.Tarea = Lambda_2;
}
break;
case Lambda_2: //Se obtiene el valor de Lambda
if(!input(RX)){
Lambda = get_timer1();
L = 0;
H = 0;
contador_bits = 0;
set_timer0(0);
set_timer1(0);
Supervisor.Tarea = Obtener_datos;
}
break;
case Obtener_datos: //Comienza a medirse la duración del pulso bajo
if(input(RX)){
set_timer0(0);
L = get_timer1();
set_timer1(0);
}
else { //Comienza a medirse la duración del pulso alto
set_timer0(0);
H = get_timer1();
set_timer1(0);
}
if (H>0 && L>0){
if(L>((2*Lambda)+Margen)){
disable_interrupts(global);
Supervisor.Resultado = Datos_incorrectos;
}
else if(L<(Lambda-Margen)){
disable_interrupts(global);
Supervisor.Resultado = Datos_incorrectos;
}
else if(H>((2*Lambda)+Margen)){
disable_interrupts(global);
Supervisor.Resultado = Datos_incorrectos;
}
else if(H<(Lambda-Margen)){
disable_interrupts(global);
Supervisor.Resultado = Datos_incorrectos;
}
else {
if (L>H){
bit_set(Datos,contador_bits);
}
else if (L<H){
bit_clear(Datos,contador_bits);
}
L = 0;
H = 0;
contador_bits++;
Supervisor.Tarea = Obtener_datos;
}
}
break;
case Paquete_obtenido:
break;
case Mostrar_resultados:
break;
case Paquete_fallido:
break;
default:
clear_interrupt(int_timer0);
clear_interrupt(int_rb);
enable_interrupts(int_rb);
enable_interrupts(int_timer0);
enable_interrupts(global);
break;
}
}
#int_timer0
void interr_timer0(int32) {
clear_interrupt (int_timer0);
disable_interrupts (GLOBAL);
Supervisor.Tarea = Paquete_fallido;
}
void main () {
disable_interrupts(global);
set_tris_B (0x14); // RB4 = 1, RB2 = 1
setup_timer_0 (RTCC_DIV_4 | RTCC_INTERNAL);
setup_timer_1 (T1_DIV_BY_1 | T1_INTERNAL);
setup_oscillator(OSC_4MHZ);
setup_ccp1 (CCP_OFF);
enable_interrupts (INT_RB);
lcd_init();
Datos = 0;
contador_bits = 0;
Lambda = 0;
H = 0;
L = 0;
Supervisor.Tarea = Lambda_1;
Supervisor.Resultado = Datos_correctos;
enable_interrupts (GLOBAL);
while (true) {
switch(Supervisor.Tarea){
case Lambda_1:
break;
case Lambda_2:
break;
case Obtener_datos:
if(contador_bits < 28){
Supervisor.Tarea = Obtener_datos;
}
else {
Verif = Datos & 0x0A000000;
if(Verif == 0x0A000000){
Supervisor.Tarea = Mostrar_resultados;
Supervisor.Resultado = Datos_correctos;
}
else{
Supervisor.Tarea = Paquete_fallido;
Supervisor.Resultado = Datos_incorrectos;
}
}
break;
case Paquete_obtenido:
if(Supervisor.Resultado == Datos_correctos){
Supervisor.Tarea = Mostrar_resultados;
}
else{
Supervisor.Tarea = Paquete_fallido;
}
break;
case Mostrar_resultados:
display();
case Paquete_fallido:
disable_interrupts(int_timer0);
default:
Datos = 0;
Supervisor.Resultado = Datos_correctos;
Supervisor.Tarea = Lambda_1;
contador_bits = 0;
Lambda = 0;
L = 0;
H = 0;
clear_interrupt(int_rb);
clear_interrupt(int_timer0);
enable_interrupts(global);
break;
}
}
}
void display(){
contador_bits = 0;
lcd_gotoxy(1,1);
printf(lcd_putc,"%LX",Datos);
delay_ms(500);
}
También agrego el circuito de prueba para que puedan comprobar su funcionamiento.
-
Ignorar este mensaje. El mío propio de mi. Jejejeje.
Perdón por la confusión.
-
Ignorar ese mensaje.
¿El mío?
-
Ignorar este mensaje. El mío propio de mi. Jejejeje.
Perdón por la confusión.
No problema! Ya me parecía que no era para mí. ¿Han probado el código o llegué demasiado tarde con mi aporte?