Modulos RF 315 Mhz y micro 16f887

#1
He tratado realizar la comunicación de dos micros 16f887 mediante los módulos de RF y resulta que si conecto los dos micros con cable funciona todo muy bien, pero al poner los módulos RF no funciona.
Tengo un testigo para mirar que recibe y resulta que el led está parpadeando (otras señales o ruido).
No logro aún eliminar ese ruido. La idea es que al pulsar un botón el otro encienda un led y que al pusar otro botón se apague

PROGRAMA RECEPTOR
Código:
void main( void ){
 
//Declaración de variables.
char ARMADO;
 
//Configuración de puertos.
 
OSCCON = 0b01110110; //Oscilador interno a 4MHz
 
ANSEL = 0; //Configura portA como digital
ANSELH = 0; //configura los demas puertos como digitales
 
TRISA = 0xFF; // PORTA is input
TRISB = 0; // PORTB is output
TRISC = 0xFF; // PORTC is input
TRISD = 0xFF; // PORTD is input
 
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
 
//Configuración del puerto serial.
UART1_Init(9600);
 
do{ //Bucle infinito.
 
if(UART1_Data_Ready()==1){ //La sentencia if evalúa si un dato está listo para leer.
ARMADO = UART1_Read(); //Se lee el DATO del bufer.
 
if (ARMADO==30){
PORTB = 0B00001111;
Delay_ms(100); //tiempo de retardo
 
}
if (ARMADO==20){
PORTB = 0B00000000;
Delay_ms(100); //tiempo de retardo
}
}
if((PORTA.F7==0)&&(ARMADO==20)){ //Evalúa el estádo del pulsador por RA1, q se activado en bajo.
Delay_ms(2000); //tiempo de retardo
PORTB = 0B00001111;
}
} while(1);
}
PROGRAMA TRANSMISOR
Código:
void main( void ){
 
//Declaración de variables.
char ARMADO;
 
//Configuración de puertos.
 
OSCCON = 0b01110110; //Oscilador interno a 4MHz
 
ANSEL = 0; //Configura portA como digital
ANSELH = 0; //configura los demas puertos como digitales
 
TRISA = 0xFF; // PORTA is input
TRISB = 0; // PORTB is output
TRISC = 0xFF; // PORTC is input
TRISD = 0xFF; // PORTD is input
 
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
 
//Configuración del puerto serial.
UART1_Init(9600);
 
do{ //Bucle infinito.
 
if(UART1_Data_Ready()==1){ //La sentencia if evalúa si un dato está listo para leer.
ARMADO = UART1_Read(); //Se lee el DATO del bufer.
 
if (ARMADO==30){
PORTB = 0B00001111;
Delay_ms(100); //tiempo de retardo
 
}
if (ARMADO==20){
PORTB = 0B00000000;
Delay_ms(100); //tiempo de retardo
}
}
if((PORTA.F7==0)&&(ARMADO==20)){ //Evalúa el estádo del pulsador por RA1, q se activado en bajo.
Delay_ms(2000); //tiempo de retardo
PORTB = 0B00001111;
}
} while(1);
}
De ante mano muchas gracias por su ayuda. Trabajo en mikroC.
 
Última edición por un moderador:
#2
Esa frecuencia de 315Mhz es libre y usada por infinidad de aparatos por eso hay muchas señales por volando que puede detectar tu PIC he interpretarlas como validas, para poder asegurar de que funcione bien debes implementar rutinas de verificación de datos, ademas no esta de mas poner un filtro "acorde a la frecuencia con la que envías datos" para evitar que ese molesto ruido generado por el receptor, pueda estar disparando a tu micro receptor sin necesidad. Si conectas la salida del receptor a un osciloscopio veras como se generan picos de tensión. Yo use la codificación manchester, creo que da buenos resultados, envíe 2 bits de inicio que siempre son 1 para detectar si lo que viene después es valido, luego envíe 4 bits para identificar al transmisor que esta "valga la redundancia" transmitiendo, y luego envíe el byte de datos luego un bit de parada que siempre es cero, solo para validar que el mensaje llego completo.

Esto reduce mucho el ancho de banda, pero después de todos estos módulos están pensados para trabajar en aplicaciones de on/off.
 
#3
Tenés que trabajar con tramas de datos y así descartar el ruido. Ejemplo, c/elemento es un byte:

PHP:
Código de mensaje | Dir. Destino | Dir. Origen | .... Datos .... | Check-sum
Entonces para tomar un dato válido, solo deberías esperar un código de mensaje válido y verificar el check-sum.

A nivel de hard, te recomiendo invertir la salida de la uart, cuando está en reposo la uart está en 1 lógico, eso es poco práctico en RF, ya que estas transmitiendo todo el tiempo la portadora.
 
#4
entiendo que es una banda abierta y por tanto muchas mas señales interfieren y entiendo que debo lograr algún tipo de codificación, en realidad he buscado y no logro entenderlo bien la codificación en programación si no es muy atrevido de mi parte y me pueden permitir un código ejemplo con el cual guiarme les agradecería mucho.
 
#5
Tenés que hacerte dos funciones, una de recepción y otra de transmisión, ejemplo de los prototipos:

PHP:
int transmitir_trama_rf(u8 codigo_mensaje,u8 dir_destino,u8 dir_origen,u8 buffer_datos[],u8 tamanio);
Donde:

  • u8: es una variable del tipo unsigned char.
  • codigo_mensaje: un byte que indicará el tipo de mensaje, será un protocolo que vos definas.
  • dir_destino: dirección con el equipo que te vas a comunicar.
  • dir_origen: el equipo que envió el mensaje.
  • buffer_datos: será un vector del tipo unsigned char donde estarán los datos del mensaje.
  • tamanio: el tamaño del vector de datos.
  • Internamente se deberá generar un check_sum, es decir ir sumando en una variable todos los datos que se envían.
  • En caso de que la transmisión no tuvo inconvenientes, devolverá un 1, caso contrario -1 y se deberán tomar las medidas adecuadas en la rutina que llamo a la función.

Por el lado del receptor, luego de recibir el 1er byte del código de mensaje con un switch, tomás la decisión usando una función de este tipo:

PHP:
int recibir_trama_rf(u8 mi_dir,u8 *dir_origen,u8 buffer_datos_recibidos[],u8 tamanio);
Donde:

  • mi_dir: será la dirección propia del equipo, verificará que el mensaje recibido sea para él.
  • *dir_origen: es una variable que la pasas por referencia por si resulta útil saber que equipo envió el mensaje (para un ACK a futuro).
  • buffer_datos_recibidos: un vector de datos adecuado según el mensaje a recibir, previamente pactado por el código de mensaje.
  • tamanio: el equipo que envió el mensaje.
  • Internamente se deberá generar un check_sum, es decir ir sumando en una variable todos los datos que se reciben y compararlo con el byte de check-sum que envió el transmisor.
  • En caso de que la transmisión no tuvo inconvenientes, devolverá un 1, caso contrario -1 y se deberán tomar las medidas adecuadas en la rutina que llamo a la función.

Las funciones son bastante sencillas de realizar, solo es enviar/recibir todos esos datos por una uart y verificar que dichos datos sean correctos.
 
#7
Tenés que trabajar con tramas de datos y así descartar el ruido. Ejemplo, c/elemento es un byte:

PHP:
Código de mensaje | Dir. Destino | Dir. Origen | .... Datos .... | Check-sum
Entonces para tomar un dato válido, solo deberías esperar un código de mensaje válido y verificar el check-sum.

A nivel de hard, te recomiendo invertir la salida de la uart, cuando está en reposo la uart está en 1 lógico, eso es poco práctico en RF, ya que estas transmitiendo todo el tiempo la portadora.


trate de simplificar un poco para hacer pruebas solo envio bit de inicio/dato/bit de fin resulta que no logro que se comuniquen ni conectados, si me puedes ayudar en algo adjunto los codigos de igual manera sigo trabajando en ellos, muchas gracias
 

Adjuntos

#9
Ok, no esta mal lo que intentas hacer, pero corregiría un par de cosas:

- Sacá los "Delay_ms (100)" del transmisor, directamente enviá la trama de una, es importante que los bytes lleguen juntos, que es cuando te "aislas" del ruido por la presencia de la portadora y no enviar bytes en forma esporádica en presencia de ruido.

- En el receptor el "if(temp = 0x0E)" está de más y no permite que recibas los datos. La correción sería esta:


PHP:
                  do{
                           temp = Man_Receive(&error);             // Intento recibir byte
                           if (error) {                            // si hay error
                           ErrorCount++;                           // aumento ErrorCount
                             if (ErrorCount > 20) {                // si el error es mayor a 20
                             temp = Man_Synchro();                 //Intente sincronizar nuevamente
                             //Man_Receive_Init();                 //Intento inicializar el receptor nuevamente
                             ErrorCount = 0;                       // Reset error
                             }
                           }
                           else {
                           
                                    if (temp==30){
                                    PORTB = 0B00001111;
                                    
                                    }
                                    
                                    if (temp==20){
                                    PORTB = 0B00000000;
                                    
                                    }

                                    if((PORTA.F7==0)&&(temp==20)){              //Evalúa el estádo del pulsador por RA1, q se activado en bajo.
                                    
                                    PORTB = 0B00001111;
                                    }
                            
                            
                           }
                       

                          
                          }while (temp != 0x0E);       //hacer hasta recibir "fin"
El foro levanto medio desprolijo el código, pero creo que se entiende, es solo anular ese if y los delay.

Esos módulos yo los usé con velocidades de 2400bps, a menor velocidad mejor sensibilidad hacia el ruido.
 
Última edición:
#10
muchas gracias por su ayuda, el programa ya ha mejorado mucho ya logro que en ocasiones se active por el pulso que yo mando y estan en comunicación constante los pic, ya es cuestión de mejorar para que siempre se active al pulso enviado.
Recibo sugerencias de como puedo mejorar esto
 
Última edición:
#12
Justamente trabajo en algo similar.
Lo que mejoraría y mucho la comunicación, es una retransmisión de las tramas, de esa forma le das al receptor más oportunidades de recibir una trama válida.
Creo que no es mala idea enviar 2 o 3 tramas para cada mensaje, si una trama recibida no es correcta las otras dos podrían ser las correctas habrá menos probabilidad de error.
 
#13
Justamente trabajo en algo similar.


Creo que no es mala idea enviar 2 o 3 tramas para cada mensaje, si una trama recibida no es correcta las otras dos podrían ser las correctas habrá menos probabilidad de error.

creo haberles entendido he hice lo siguiente en el codigo agregar 2 envios mas aun asi persiste el hecho de que en ocasiones se activa y en otras no, adjunto los códigos, y muchas gracias por sus sugerencias y ayuda
 

Adjuntos

#14
¡No seas cabezón! :eek:

¡Usá un for/while! y repetilo 5 o incluso 10 veces. Para darte una idea, el encoder HT12e envía 4 veces la trama de bits (no bytes, bits) y solo hablamos de 1 nibble datos con un byte de dirección.

Lo malo de estos módulos que es que necesitas 2 pares para realizar una comunicación con acuse de recibo, eso es lo que hacía yo, luego de no recibir ese ACK durante un tiempo aleatorio, volvía a enviar el dato.
 
#15
¡No seas cabezón! :eek:

¡Usá un for/while! y repetilo 5 o incluso 10 veces. Para darte una idea, el encoder HT12e envía 4 veces la trama de bits (no bytes, bits) y solo hablamos de 1 nibble datos con un byte de dirección.

Lo malo de estos módulos que es que necesitas 2 pares para realizar una comunicación con acuse de recibo, eso es lo que hacía yo, luego de no recibir ese ACK durante un tiempo aleatorio, volvía a enviar el dato.
ok muchas gracias ya lo corrijo y agrego el for, lo pondre po ahora que lo mande 5 veces muchas gracias (y)
 
#16
cosmefulanito04 sus propuestas han sido un exito y me han ayudado bastante, al igual que las demas sugerencias ahora me encuentro como todo en la electronica con un problema en montaje que al igual considero puede ser solucionado con el codigo en C y es que trabaja todo muy bn pero si me alejo lo suficiente para que el control no transmita resulta q el receptor se deja afectar por otras señales, me hago entender si el control (transmisor) esta cerca al receptor todo muy bien pero si alejo el control o le quito la alimentación el receptor se ve afectado por otras señales. alguana sugerencia como eliminar este factor de antemano muchas gracias
 
#17
¿A que frecuencia de reloj trabaja el micro? Leí que con estos módulos RF es preferible usar un clock < 4Mhz para que el propio uc no añada ruido en exceso al RX.
¿Le colocaste antena a los módulos? una antena de ~ 23 cm mejoraría la reccepcción, si nada de eso funciona como dice un mensaje más arriba habrá que filtrar o limitar el ancho de banda del receptor... podría ser con un circuito tanque.
 
Última edición:
#18
...es que trabaja todo muy bn pero si me alejo lo suficiente para que el control no transmita resulta q el receptor se deja afectar por otras señales, me hago entender si el control (transmisor) esta cerca al receptor todo muy bien pero si alejo el control o le quito la alimentación el receptor se ve afectado por otras señales. alguana sugerencia como eliminar este factor de antemano muchas gracias
A ver, tenés varios problemas por lo que comentas:

  1. Distancia entre Tx y Rx no muy grande.
  2. Señales que intervienen en la comunicación.

El primer problema lo podés atacar de la siguiente forma:
  • Usar buenas antenas en ambos lados, en este tipo de transmisores la antena debe presentar una impedancia de 50Ohms. Por experiencia te puedo decir que un cable coaxil funciona bastante bien.
  • Usar la máxima tensión de fuente permitida en el transmisor. En los que yo usé la tensión de alimentación podías llevarla a 12v, esto requiere hacer un cambio de nivel de tensión a 12v en el la uart del transmisor.
  • Como mencioné antes, la uart en estado de reposo deja el bit de transmisión en un "1" lógico, esto implica que reposo tu módulo de transmisión está todo el tiempo enviando la portadora, esto es un problema ya que estas contaminando el espectro en esa frecuencia impidiendo que otro transmisor pueda trabajar. En otras palabras, si todos los transmisores están en "1" lógico, todos se interfieren, mala idea para múltiples puntos de transmisión. Esto se soluciona con el cambio de nivel explicado en el punto anterior.
  • Reducir la velocidad de la uart.
  • Mejorar el PCB lo máximo posible, separando bien las masas de alta frecuencia del transmisor/receptor con las masas digitales.

Con todo eso, yo usando unos módulos de 433MHz, conseguí una distancia máxima de 30mts indoor a 2400bps, mucho más no le podes pedir a esos módulos.

Sobre el segundo problema:

Siempre vas a estar recibiendo datos, ya sean válidos o no. Tu objetivo en el receptor es diferenciar bien cual es un dato válido de uno que no lo es, para eso usaste las tramas que te mencioné. Mientras más complejas sean esas tramas, menos probabilidad de tomar un dato inválido como válido.

En tu caso, como usas 3 bytes para diferenciar dato válido de dato inválido, dándote una probabilidad de tomar un dato inválido como válido de:

P(error en el descarte)=1/256*2/256*1/256*100=0,00001 %

O sea, probabilidad de tomar una trama inválida como válida es bastante baja.

Ahora el problema que tiene tu protocolo de comunicación es que no distingue el transmisor/receptor que se verá involucrado en la comunicación, esto es válido si solo tenes un transmisor y un receptor, pero obviamente deja de ser útil cuando hay múltiples transmisores/receptores.
 
#19
voy a intentar las soluciones que me plantean, lo de la antena y aumentar el voltaje en el transmisor. de igual manera adjunto imágenes del circuito como lo tengo montado y tratare de mejorar la trama. muchas gracias
 

Adjuntos

#20
La trama modificala solo si vas a trabajar con múltiples transmisores/receptores. De lo contrario, dejala así.

¿Qué módulos usas, podes subir su hoja de datos?

Del esquemático que vi, salvo que los módulos recomienden eso, colocar un capacitor de 100nF a derivación en la salida/entrada de la antena es muuuuuuy raro, más si ese capacitor (idealmente) presenta una impedancia de 5mOhms a 315MHz :unsure:.

Si me parece correcto colocar ese capacitor de 100nF entre Vcc del módulo y GND.
 

Temas similares

Arriba