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
IMPRESIONANTE HELI, la he probado y es de lo mejor. Este es el resultado de comparar 4 checksums/crcs:
==============================================
Test Nº1, Exclusive OR:
Lanzados 200000 tests aleatorios, resultando erroneos 748: 1 cada 267.38
Lanzados 40 tests 1 bit, resultando erroneos 0: 1 cada 1.#INF
Lanzados 32 tests 2 bits 1 posicion, resultando erroneos 8: 1 cada 4
Lanzados 200000 tests 2 bits aleatorios, resultando erroneos 20006: 1 cada 9.997
Lanzados 200000 tests 3 bits aleatorios, resultando erroneos 0: 1 cada 1.#INF
==============================================
Test Nº2, SUMA sin carry:
Lanzados 200000 tests aleatorios, resultando erroneos 781: 1 cada 256.082
Lanzados 40 tests 1 bit, resultando erroneos 0: 1 cada 1.#INF
Lanzados 44 tests 2 bits 1 posicion, resultando erroneos 6: 1 cada 7.33333
Lanzados 200000 tests 2 bits aleatorios, resultando erroneos 8558: 1 cada 23.3699
Lanzados 200000 tests 3 bits aleatorios, resultando erroneos 1491: 1 cada 134.138
==============================================
Test Nº3, Uso de indices: (inventado o reinventado por mí)
Lanzados 200000 tests aleatorios, resultando erroneos 781: 1 cada 256.082
Lanzados 40 tests 1 bit, resultando erroneos 0: 1 cada 1.#INF
Lanzados 74 tests 2 bits 1 posicion, resultando erroneos 1: 1 cada 74
Lanzados 200000 tests 2 bits aleatorios, resultando erroneos 767: 1 cada 260.756
Lanzados 200000 tests 3 bits aleatorios, resultando erroneos 775: 1 cada 258.065
==============================================
Test Nº4, Rutina CRC8 de Heli:
Lanzados 200000 tests aleatorios, resultando erroneos 841: 1 cada 237.812
Lanzados 40 tests 1 bit, resultando erroneos 0: 1 cada 1.#INF
Lanzados 80 tests 2 bits 1 posicion, resultando erroneos 0: 1 cada 1.#INF
Lanzados 200000 tests 2 bits aleatorios, resultando erroneos 0: 1 cada 1.#INF
Lanzados 200000 tests 3 bits aleatorios, resultando erroneos 0: 1 cada 1.#INF
El uso de índices que he inventado o reinventado es la siguiente rutina:
byte alea[256]={193,35,160,0,58,115,27,61,82,44,55,241,66,57,83,235,179,166,168,45,129,15,186,153,224,
94,187,28,19,198,169,223,64,219,5,200,67,46,139,17,222,132,199,39,164,119,13,53,42,212,
184,221,150,182,70,59,60,163,137,133,214,18,118,203,85,154,80,238,188,120,237,253,192,
101,251,246,158,43,10,148,210,220,135,165,1,68,102,30,107,180,93,29,74,73,161,146,75,
175,145,157,228,38,20,96,254,121,24,190,185,114,99,78,100,128,152,12,171,195,14,159,37,
234,201,216,242,191,181,6,34,98,31,136,149,162,142,206,218,239,208,111,95,130,202,194,
2,205,226,71,110,156,155,126,151,230,183,240,56,81,172,177,88,215,232,26,32,124,50,122,
72,147,252,106,63,21,244,117,49,231,104,112,196,131,245,207,92,97,22,123,91,211,25,3,167,
189,143,213,116,217,65,90,229,33,247,125,178,8,89,84,51,77,173,41,236,9,255,140,204,243,
227,174,48,170,127,86,36,144,209,11,4,16,47,113,79,7,134,103,248,69,23,225,62,197,87,108,
52,40,109,249,54,176,76,250,233,138,105,141};
//LON1 es la longitud de u[] menos 1
byte hallachecksum(byte *u)
{
int i;
byte checksum=0;
for (i=0;i<LON1;i++)
{
// checksum=checksum^u;
// checksum=checksum+u;
// checksum=alea[(checksum+u)&0xFF];
checksum=ActualizaCRC8 (u, checksum);
}
return checksum;
}
void ponechecksum(byte *u)
{
u[LON1]=hallachecksum(u);
}
La tuya la he reescrito un poco:
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;
}
byte hallachecksum(byte *u)
{
int i;
byte checksum=0;
for (i=0;i<LON1;i++)
{
checksum=ActualizaCRC8 (u, checksum);
}
return checksum;
}
void ponechecksum(byte *u)
{
u[LON1]=hallachecksum(u);
}
Es curioso, que el uso de checksum de 16 bits exclusive or es el que he visto en todos los protocolos de la ESA que he visto tanto dentro de sus satélites como en sus comunicaciones con la Tierra.
No se si te lo habías planteado, pero puedes usar el algoritmo de detección y corrección de errores de Hamming: http://es.wikipedia.org/wiki/C%C3%B3digo_Hamming " onclick="window.open(this.href);return false; Te premite no sólo detectar errores de tranmisión sino corregirlos sin tener que volver a enviarlos.
Si, los CRC son muy robustos y es dificil que se den colisiones, aunque las hay.
Un CRC de 8 bit tiene 2^8 = 256 combinaciones. Una trama de 16 bytes tiene 128 bits que son 2^128 posibiles combinaciones. Verás que tiene que haber muchos otras tramas para los cuales exista el mismo CRC...
Lo bueno del CRC es que en su cálculo interviene el peso de los bits, de forma que para que dos ficheros tengan el mismo CRC han de ser tan distintos que es casi imposible que se hayan derivado el uno del otro por un error de transmisión.
Si usas uno de 16 bits entonces la seguridad aumenta. Para tramas cortas basta el de 8 bits, para mensajes mas largos es imprescindible el de 16 ó 32 bits. Ten en cuenta que en una comunicación se mandan millones de bytes a lo largo del tiempo y hay que intentar detectar todos los posibles fallos.
Lo que me comentas de la ESA es raro, puede ser que esten calculando un CRC de 16 bits usando tablas precalculadas y no identifiques el código. Es otra forma de calcular el CRC, necesita mas memoria ROM porque ha de almacenar una tabla, pero es mucho mas rápido de calcular, solo dos XOR y mantener un índice de 8 bit. Yo uso la forma primitiva de cálculo de CRC partiendo del polinomio porque, aunque es mas lenta y ocupa algo mas de código, en el PIC la tabla de 256 bytes necesaria ocupa demasiada memoria.
Esto es un CRC16 para el protocolo Modbus basado en tabla, la tabla esta separada en bytes HI/LO, pero puede hacerse igual con una tabla de enteros:
/* Table of CRC values for high-order byte */
static unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* Table of CRC values for low-order byte */
static char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
/* CRC16 calc on frame pointed by puchMsg and usDataLen lenght */
/* Pre-calc routine taken from http://www.modicon.com/techpubs/crc7.html site */
unsigned short CRC16(unsigned char *puchMsg, unsigned short usDataLen)
{
unsigned char uchCRCHi = 0xFF ; /* high CRC byte initialized */
unsigned char uchCRCLo = 0xFF ; /* low CRC byte initialized */
unsigned uIndex ; /* will index into CRC lookup table */
while (usDataLen--) /* pass through message buffer */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
Fusion, Heli, hay algo que no me cuadra.
Hasta donde yo se, Ranganok esta dando consejos acertados sobre el tema de evitar colisiones en el medio. Ya que la única solución (que yo conozco o me han explicado) que hay para evitarlas es utilizar técnicas de multiplexado FDMA, TDMA, CDMA/SSMA y SDMA, es decir multiplexacción en frecuencia, tiempo, código o ensanchado de espectro y espacial. A esto hay que añadir los protocolos de acceso múltiple y los mecanismos de control (que introducen múltiples variantes de las básicas descritas antes).
En cuanto a los CRC y ChecnkSum son códigos detectores de error (ojo no correctores) El Hamming como bien apunta sistemasorp si es un código corrector de errores.
Luego hay un tema muy interesante para la corrección y detección de errores a nivel de modulación digital, por ejemplo en la Q-PSK se pueden implementar igualadores de canal, filtros adaptativos, etc. Permitiendo implementar comunicaciones muy robustas. Pero esto es otro tema a parte.
Pero a lo que iba utilizando un código u otro podrás detectar más o menos errores o incluso corregirlos si utilizas un Hamming. Pero no veo la manera de utilizar un código detector de error para evitar colisiones.
Para mi que se ha cambiado algo en la simulación, yo al menos lo analizaría a fondo.
Saludos.
Ya, a mi tampoco me cuadra, ya que dice que usa paso de testigo, pero que tiene colisiones, lo cual es imposible. Así que me hago el loco 🙄