Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Estoy haciendo una red inalámbrica de micropics para trasmisión de datos en serie (a base de repetidores) de uno a otro hasta la base. ¿Sabéis algún protocolo en C ya hecho? no vaya a ser que esté reinventando la rueda.
El alcance de uno a otro lo estoy calculando en 400m
Creo se puede hacer algo con el CAN, pero no estoy seguro
El sistema a prueba de bombas es como está ahora y vá bien a pesar de las colisiones, me costaría un h... cambiarlo ahora.
La idea inicial es que el primer aparato vaya preguntando a todos por sus datos, incluso que pudiera programar la potencia RF para ajustar consumos. El protocolo de errores se complicó muchísimo pues había que avisar de los errores en un sentido y en otro y tener en cuenta toda la casuística de errores. Logré que funcionara pues el primer trasmisor mandaba un "trencito de datos" donde cada vagón era el sitio donde iba los datos de cada terminal e incluso lo integré con labview con la consola de errores donde podía ver odos ellos e incluso simular errores (casi me quedo calvo), pero al depurar todas las infinitas variantes de error, posibles colisiones, etc, opté por simplificarlo drásticamente. Ahora uso el mismo código para repetidores y sensores, es unidireccional y me dá la potencia rf de cada receptor y nivel de batería de cada uno cada cierto tiempo :), el problema es un exceso de colisiones pues en este caso necesito una alta tasa de trasmisión, además para ajustar la potencia RF de cada bicho hay que ir donde está instalado y programarlo a mano, pero me ahorro tal cantidad de problemas que lo prefiero de sobra.
Cada emisor/repetidor trasmite cada cierto tiempo que es distinto para cada uno de ellos, por lo que es imposible que coincidan dos de ellos entre sí.
El protocolo simplemente rechaza todos los paquetes erróneos.
Un pequeño problema es que los repetidores y los sensores más cercanos al puesto central están más "privilegiados" que los que pasan por nodos intermedios, es como en un restaurante donde los clientes más cercanos al lugar donde salen los camareros están mejor atendidos
Si no puedes cambiar el protocolo es complicado.
Podrías hacer un slot de tiempos, en que cada sensor tiene un tiempo fijado para enviar los paquetes que tenga acumulados, la sincronización la lleva el 1 y todos se sincronizan con él (si no ves el 1 sincronizas con el que ves que se supone que esta sincronizado con el 1).
Si tienes sensores que no se ven se complica un poco ya que cada paquete debería llevar un número de secuencia y un número de reintentos. Los intermedios reenviarían la info y restarían un reintento el número de secuencia sirve para no reenviar 2 veces el mismo paquete. Cuando el número de reintentos máximo se supera el paquete se elimina.
Ejemplo:
Sensores A, B, C, D, E, todos ven a A excepto B; C y D se ven entre ellos, E y B se ven respecto a ellos.
-> A envía a B
Slot1: A envía el paquete 238 a B con 0 reintentos --> lo reciben C, D, E
Slot2: B no tiene nada que enviar por lo que no hace nada.
Slot3: C envia sus paquetes y el paquete 238 (hacia B) con reintento 1 --> lo recibe D y A
Slot4: D envia sus paquetes y el paquete 238 (hacia B) con reintento 2 --> lo recibe C y A
Slot5: E envia sus paquetes y el paquete 238 (hacia B) con reintento 2 --> lo recibe B y A
Slot6: A no hace nada
Slot7: B ha recibido el paquete 238 y reenvia la respuesta hacia A.
Si en algún momento el paquete llega a 3 reintentos no se envia (máx 3 reintentos).
S2
Ranganok Schahzaman
En mi caso se simplifica pues no hay reintentos, no importa si pierdo una telemetría, pues tengo la siguiente muy poco tiempo después y que no debe ser muy distinta.
El problema que yo tenía es que a cada repetidor le llegaban paquetes que venía de la central por un lado y por el otro le llegan de otros repetidores y/o sensores, había que combinar los errores en ambos sentidos y mandarlos a la central, con posibilidades multiples ¿y si no llegan datos en alguno de los sentidos? ¿como pongo varios sensores mandando a un único repetidor? ¿y si quiero poner dos repetidores redundantes porque tengo problemas de hubicación?
Una de las veces pensé en "aislar" los dos sentidos: un micro recibía por un lado y emitía por el otro (desde la central a los sensores) y en el otro snetido había otro micro mandando desde los sensores hacia la central. Lo que me decidió al cambio drástico de estrategia (eliminar DEL TODO el tráfico desde la central hacia los sensores) fué al comprar las antenas yagui pues ví en las especificaciones que habían lóbulos laterales, o sea, que si un repetidor manda un paquete en un sentido "machaca" a ambos receptores del mismo repetidor, total que habría que poner los sensores trasmitiendo a una frecuencia y cada "nivel" de repetidor a otra frecuencia. Esto no quise hacerlo por dos motivos:
1. Pueden haber solapamientos
2. A lo mejor tengo que pedir autorización, mejor pedirla para una frecuencia que para dos o tres.
Me he dado cuenta que la forma de obtener el checksum puede mejorarse. Normalmente el checksum de un vector v se halla empleando la función exclusive or de la siguiente forma:
typedef unsigned char byte;
void ponechecksum(byte *u)
{
byte checksum=0;
int i;
for (i=0;i<LON1;i++)
{
checksum=checksum^u;
}
u[LON1]=checksum;
}
Me he dado cuanta que si en el vector produzco un bit erróneo en uno de sus elementos y luego otro bit erróneo en la misma posición pero en otro elemento del vector, el checksum coincide.
Se me ocurre que es mucho mejor emplear la suma:
typedef unsigned char byte;
void ponechecksum(byte *u)
{
byte checksum=0;
int i;
for (i=0;i<LON1;i++)
{
checksum=checksum+u;
}
u[LON1]=checksum;
}
Me parece que es muchísimo mejor pues aunque se cambien dos bits en la misma posición en dos vectores, gracias a que al sumar se produce a veces el acarreo, se afecta a los bits de la izquierda. Lo malo es que el cambio se produzca justo en los bits de más a la izquierda.
No uses un checksum, actualmente te sobra potencia de microprocesador y puedes usar mejor un CRC.
El checksum es poco fiable, y menos en tue entorno en el que varios equipos van a transmitir datos a la vez a la misma velocidad y podrían superponerse. Por ejemplo el cambio de un bit en disintas palabras daría un checksum correcto.
Con el CRC, aunque sea uno sencillo de 8 bits, detectas siempre la paridad y muchos otros cambios e bit. Bueno, depende del polinomio que uses...
Yo he usado este código para generar CRC de 8 bits en el LaserGame y va perfectamente:
/*
(c) Heli Tejedor, Junio 2011, http://heli.xbot.es, helitp@arrakis.es
Este Software se distribuye bajo licencia
Creative Commons 3.0 Reconocimiento, No Comercial, Compartir Igual (CC BY-NC-SA 3.0)
http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es_ES
http://creativecommons.org/licenses/by-nc-sa/3.0/
Para usos comerciales contactar con el autor en helitp@arrakis.es
Este fichero contiene las rutinas de DOW CRC8 X8 + X5 + X4 + 1
usado por MAXIM en los IButtons, optimizadas para PIC con CCS
También sirven para el PC con Builder 6
Para compartir entre LaserGame.hex y LaserGame.exe
*/
byte IniCrc=0; // Valor inicial del CRC
/* ========================================================================*/
// 10001100 = 0x8C
// 01234567 Bit X^8 no se pone
#define CRC8_POLY 0x8C // X^8 + X^5 + X^4 + X^0 bit reversed
byte ActualizaCRC8 (byte Dato, byte CRC8)
{
byte Cont;
for (Cont = 0; Cont < 8; Cont++)
{
if ((CRC8 ^ Dato) & 0x01) CRC8 = (CRC8 >> 1 ) ^ CRC8_POLY;
else CRC8 >>= 1;
Dato >>= 1;
}
return CRC8;
}
/* ========================================================================*/
// Termina de preparar la transmision y calcula CRC
byte CalculaCRC8 (byte *Buf)
{
byte Cont, CRC8; // Uso su propia posicion como teporal
CRC8=IniCrc; // Valor al inicio para CRC8
// Calcula el CRC de todo menos A_CRC
for (Cont=A_STX; Cont<A_CRC; Cont++)
CRC8 = ActualizaCRC8 (Buf[Cont], CRC8);
return CRC8;
}
Para tu aplicación mejor usa otro polinomio como el CRC-8-CCITT x8 + x2 + x + 1
Mas soficticado y consumiendo mas potencia de CPU puedes usar un código PCH como este, usado en los buscapersonas (protocolo POCSAG). Es muy robusto y te permite corregir muchos de los errores y detectar otros:
http://www.piclist.com/techref/method/error/bch3121.c " onclick="window.open(this.href);return false;
Algo mas complejo este usado en telefonía movil:
http://www.piclist.com/techref/method/error/bch4836.c " onclick="window.open(this.href);return false;