Entra

View Full Version : [C++] funzione di CRC e calcoli errati in parte...


DomusP45
12-04-2012, 17:24
Salve a tutti, ho implementato questa funzione per il calcolo del CRC16 su un vettore di unsigned char,

typedef unsigned short UInt16;
typedef unsigned char UInt8;

UInt16 CRC16(UInt16 crc, UInt8 data)
{
const UInt16 tbl[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};

return ((crc & 0xFF00) >> 8) ^ tbl[(crc & 0x00FF) ^ (data & 0x00FF)];
}


la vado a richiamare in questo modo all'interno del programma:

UInt16 CalcolaCRC(UInt8 d[ ] ){
UInt16 crc=0;
UInt16 COD;
for(int i=0;i<sizeof(d);i++)
{
COD=CRC16(crc,d[i]);
crc=COD;
}

return COD;
}

se gli passo alcuni vettori, mi calcola il giusto crc, ad esempio richiamandola così:

UInt8 grup[1]={0x05};
UInt8 dlencmd[2]={0x01,0x92};
UInt8 buf[4];
buf[0]=grup[0];
buf[1]=IDPinza; <--questo è un intero
buf[2]=dlencmd[0];
buf[3]=dlencmd[1];

UInt16 crc=CalcolaCRC(buf);

UInt8 buffer[6];
for (int i=0;i<sizeof(buffer);i++){
buffer[i]=buf[i];
}
int sd=SendBuf(Pnum,buffer,6);

quello che mi viene inviato sulla porta seriale è il vettore più il crc che è corretto, cioè mi ritrovo {0x05,0x0C,0x01,0x92,0x40,0xF2}

dove gli ultimi due sono il CRC16 calcolato. Ma usando lo stesso sistema per richiamarla su altri vettori, tipo :

UInt8 grup[1]={0x05};
UInt8 par[2]={0x01,0x91};
UInt8 bf[4];
bf[0]=grup[0];
bf[1]=IDPinza;
bf[2]=par[0];
bf[3]=par[1];
CalcolaCRC(bf);
UInt8 bufer[6];
for (int i=0;i<sizeof(bufer);i++){
bufer[i]=bf[i];
}
int sd=SendBuf(Pnum,bufer,6); <--- Questa serve ad inviare sulla porta seriale

beh, in questo caso me lo ritorna sbagliato. Dovrebbe essere {0x05,0x0C,0x01,0x91,0x00,0xF3} invece mi ritorna {0x05,0x0C,0x01,0x91,0x05,0x01}

e così anche per altri vettori...eppure il sistema per richiamarla è lo stesso...dove sbaglio? Apparentemente sono vettori identici tranne che per alcuni valori...perchè mi dà simili errori? C'è un modo migliore per richiamarla?

Aiutatemi..

lorenzo001
12-04-2012, 20:24
Il codice non è chiarissimo ma mi sembra che il risultato di questa linea

UInt16 crc=CalcolaCRC(buf);

non la utilizzi nel buffer finale.

DomusP45
12-04-2012, 21:26
perchè mi ritorna due unsigned int e non so come assegnarli separatamente nelle due posizioni diverse.

Fatto sta che non so come mai, ma la cosa la fa automaticamente nei casi in cui funziona...cioè me li ritrovo divisi in modo corretto come ho indicato...

nessuno mi sa aiutare?

lorenzo001
12-04-2012, 22:48
perchè mi ritorna due unsigned int e non so come assegnarli separatamente nelle due posizioni diverse.

Veramente ritorna un solo unsigned int. E semmai devi assegnare i singoli byte.

Fatto sta che non so come mai, ma la cosa la fa automaticamente nei casi in cui funziona...cioè me li ritrovo divisi in modo corretto come ho indicato...

No ... non lo fa affatto automaticamente ma per caso. Si corrompe lo stack e a volte i valori vanno a finire al posto giusto. Ma è sbagliato ... il codice da correggere è questo


unsigned short int crc=CalcolaCRC(buf);
unsigned char buffer[6];
for (int i=0; i<sizeof(buf); i++)
buffer[i]=buf[i];
buffer[4]=crc & 0xFF;
buffer[5]=crc>>8;


Occhio alle modifiche che ho apportato rispetto al tuo codice ...

DomusP45
12-04-2012, 23:19
Veramente ritorna un solo unsigned int. E semmai devi assegnare i singoli byte.



No ... non lo fa affatto automaticamente ma per caso. Si corrompe lo stack e a volte i valori vanno a finire al posto giusto. Ma è sbagliato ... il codice da correggere è questo


unsigned short int crc=CalcolaCRC(buf);
unsigned char buffer[6];
for (int i=0; i<sizeof(buf); i++)
buffer[i]=buf[i];
buffer[4]=crc & 0xFF;
buffer[5]=crc>>8;


Occhio alle modifiche che ho apportato rispetto al tuo codice ...

Domani provo e ti aggiorno. Ora sto crollando dal sonno...grazie mille per la disponibilità...t aggiorno domani!

EDIT: anche introducendo tale modifica, il CRC calcolato cmq non corrisponde a quell che dovrebbe, solo in alcune funzioni. Con la modifica da te segnalata almeno sono sicuro di assegnarlo bene al vettore...però il problema sui calcoli con talune funzioni rimane...e non riesco a capire perchè...

lorenzo001
16-04-2012, 13:31
Dicci quali sono i casi che non vanno ...

DomusP45
16-04-2012, 16:26
Dicci quali sono i casi che non vanno ...

Ti posto le funzioni con le modifiche fatte, e ti dico l'output:

La funzione di CRC16 è quella postata sopra, poi c'è questa che la richiama

UInt16 CalcolaCRC(UInt8 d[])
{
UInt16 crc=0;
UInt16 COD;
for(int i=0;i<sizeof(d);i++)
{
COD=CRC16(crc,d[i]);
crc=COD;
}

return COD;


e la funzione di preparazione del buffer su cui calcolare il CRC che è questa:

void PreparaBuffer(UInt8 *par,UInt8 *dat, UInt8 *bufer)
{
if (par[0]==(0x05))
{
UInt8 grup[1]={0x05};
UInt8 buf[8];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
UInt16 crc=CalcolaCRC(buf);
for (int i=0;i<sizeof(buf);i++){
bufer[i]=buf[i];
}
bufer[8]=crc & 0xFF;
bufer[9]=crc>>8;
}
else if(par[0]==(0x01))
{
UInt8 grup[1]={0x05};
UInt8 buf[4];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
UInt16 crc=CalcolaCRC(buf);
for (int i=0;i<sizeof(buf);i++){
bufer[i]=buf[i];
}
bufer[4]=crc & 0xFF;
bufer[5]=crc >> 8;
}

}

che è divisa in due tipologie perchè la prima è quella in cui all'utente si chiede il parametro (float) in mm a cui spostare la pinza, il secondo pezzo invece è per mandare comandi senza parametri (buffer più corto).

nel main la cosa avviene così:

UInt8 dlencmd[2]={0x01,0x8B};
UInt8 bufer[6];
PreparaBuffer(dlencmd,0,bufer);
int i=SendBuf(Pnum,bufer,6);

che nel caso di funzioni di posizionamento, cambia in

int Posiziona(float param)
UInt8 dlencmd[2]={0x05,0xB0};
UInt8 bufer[10];
UInt8 *pr=(unsigned char *)&param;
PreparaBuffer(dlencmd,pr,bufer);
int sd=SendBuf(Pnum,bufer,10);

dove param è il parametro immesso da utente (millimetri).

Ora, ad esempio: se faccio una funzione di ACK, che ha dlencmd come indicato sopra, il buffer inviato risultante è corretto:

dal vettore 0x05,0x0C,0x01,0x8B mi invia quello completo di CRC corretto, che è

0x05 0x0C 0x01 0x8B 0x81 0x38.

Un'altra funzione simile che è questa

UInt8 dlencmd[2]={0x01,0x91};
UInt8 buffer[6];
PreparaBuffer(dlencmd,0,buffer);
int sd=SendBuf(Pnum,buffer,6);

che come vedi richiamo in modo identico, dal vettore

0x05 0x0C 0x01 0x91 dovrebbe dare 0x05 0x0C 0x01 0x91 0x00 0xF3 invece mi restituisce 0x05 0x0C 0x01 0x91 "00 AC" che se la lancio di nuovo diventa "00 B6" e ancora se la lancio diventa "00 F3"...insomma, non è corretto sto fatto che cambia...ed al terzo tentativo diventa corretta, poi se la lancio ancora, di nuovo 00 00 ...

Lo stesso per la funzione di posizionamento, immettendo 10 dovrebbe darmi

0x05 0x0C 0x05 0xB0 0x00 0x00 0x20 0x41 0x94 0x40

dove 0x00 0x00 0x20 0x41 è 10 (float) convertito. Invece, immettendo 10 quello che ottengo è

0x05 0x0C 0x05 0xB0 0x00 0x00 0xE3 0xAC 0x00 0x2B e la parte che dovrebbe rappresentare il 10 è sbagliata e cambia di volta in volta richiamando la funzione sempre con 10 come input.

Ecco i problemi quali sono...come posso risolvere??

DomusP45
18-04-2012, 12:00
allora, nessuno mi sa dire dove potrebbe essere l'errore?

DomusP45
19-04-2012, 10:11
up

lorenzo001
19-04-2012, 22:06
0x05 0x0C 0x01 0x91 dovrebbe dare 0x05 0x0C 0x01 0x91 0x00 0xF3

E a me restituisce proprio i valori corretti in grassetto...

Purtroppo, se non fornisci un codice preciso di prova (da copiare e incollare) non so dirti dove sbagli.

Ovvero, non scrivere "una funzione simile" ma fornisci esattamente il codice che stai provando (con i valori precisi ... ad esempio, non so mai quanto valga IDPinza per le prove ...)

DomusP45
20-04-2012, 00:52
E a me restituisce proprio i valori corretti in grassetto...

Purtroppo, se non fornisci un codice preciso di prova (da copiare e incollare) non so dirti dove sbagli.

Ovvero, non scrivere "una funzione simile" ma fornisci esattamente il codice che stai provando (con i valori precisi ... ad esempio, non so mai quanto valga IDPinza per le prove ...)

IDPinza vale 12...lo capisci dalla traduzione che vedi (0C) nell'array di byte. Facciamo così, domani mattina ti posto tutti i pezzi di codici per intero (che ora è tardi e non ce la faccio) e appena puoi mi rispondi..grazie ancora per la disponibilità!

DomusP45
20-04-2012, 10:50
ecco qua i vari pezzi e come li richiamo. Calcola che io sto creando una classe per la gestione di tale pinza, quindi ci sono 3 file Prova.h, Prova.cpp e main.cpp.

Ora, ti elenco le varie cose nell'ordine:

la definizione dei tipi

typedef unsigned short UInt16;
typedef unsigned char UInt8

funzione di richiamo calcolo CRC

Int16 Prova::CalcolaCRC(UInt8 d[]){
UInt16 crc=0;
UInt16 COD;
for(int i=0;i<sizeof(d);i++)
{
COD=CRC16(crc,d[i]);
crc=COD;
}

return COD;
}

Questa funzione mi prepara il buffer per l'invio a seconda del valore della prima posizione del parametro "par" che gli viene passato e gli altri parametri che vedi (dat,velo,acc) sono quelli chiesti all'utente che vengono presi "float" e convertiti come vedrai più avanti

void Prova::PreparaBuffer(UInt8 *par,UInt8 *dat,UInt8 *velo, UInt8 *acc, UInt8 *bufer)
{
//se arriva un posizionamento semplice
if (par[0]==(0x05))
{
UInt8 grup[1]={0x05};
UInt8 buf[8];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
UInt16 crc=CalcolaCRC(buf);
for (int i=0;i<sizeof(buf);i++){
bufer[i]=buf[i];
}
bufer[8]=crc & 0xFF;
bufer[9]=crc >> 8;
}
//se arriva una istruzione di comando
else if(par[0]==(0x01))
{
UInt8 grup[1]={0x05};
UInt8 buf[4];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
UInt16 crc=CalcolaCRC(buf);
for (int i=0;i<sizeof(buf);i++){
bufer[i]=buf[i];
}
bufer[4]=crc & 0xFF;
bufer[5]=crc >> 8;
}
//se arriva un posizionamento complesso
else if(par[0]==(0x09)){
UInt8 grup[1]={0x05};
UInt8 buf[14];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
buf[8]=velo[0];
buf[9]=velo[1];
buf[10]=velo[2];
buf[11]=velo[3];
UInt16 crc=CalcolaCRC(buf);
for (int i=0;i<sizeof(buf);i++){
bufer[i]=buf[i];
}
bufer[12]=crc & 0xFF;
bufer[13]=crc >> 8;
}
else if(par[0]==(0x0D)){
UInt8 grup[1]={0x05};
UInt8 buf[18];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
buf[8]=velo[0];
buf[9]=velo[1];
buf[10]=velo[2];
buf[11]=velo[3];
buf[12]=acc[0];
buf[13]=acc[1];
buf[14]=acc[2];
buf[15]=acc[3];
UInt16 crc=CalcolaCRC(buf);
for (int i=0;i<sizeof(buf);i++){
bufer[i]=buf[i];
}
bufer[16]=crc & 0xFF;
bufer[17]=crc>>8;
}
if (par[0]==(0x06))
{
UInt8 grup[1]={0x05};
UInt8 buf[9];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=(0x00);
buf[5]=(0x00);
buf[6]=(0x00);
buf[7]=(0x00);
buf[8]=(0x07);
UInt16 crc=CalcolaCRC(buf);
for (int i=0;i<sizeof(buf);i++){
bufer[i]=buf[i];
}
bufer[9]=crc & 0xFF;
bufer[10]=crc >> 8;
}
}

Questa è la funzione di posizionamento, che si occupa di richiamare prepara buffer, e di inviare poi il comando. In tale funzione converto i parametri che gli vengono passati da float a unsigned char...e la cosa però in output sulla porta non è fatta in modo corretto purtroppo e non riesco a capire perchè, visto che quello è il sistema.

int Prova::Posiziona(float pos, float vel, float corr)
{
OpenComport(Pnum, BDRATE);
//se velocità e corrente non sono state specificate
if ((vel==0)&&(corr==0)){
UInt8 dlencmd[2]={0x09,0xB0};
UInt8 bufer[14];
float veloc=10;
UInt8 *ps=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &veloc;
PreparaBuffer(dlencmd,ps,v,0,bufer);
int sd=SendBuf(Pnum,bufer,10);
return sd;
}
//se posizionamento in accelerazione
else if((vel!=0)&&(corr==0)){
UInt8 dlencmd[2]={0x09,0xB0};
UInt8 bufer[14];
UInt8 *pr=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &vel;
PreparaBuffer(dlencmd,pr,v,0,bufer);
int sd=SendBuf(Pnum,bufer,14);
return sd;
}
else if((vel!=0)&&(corr!=0)){
UInt8 dlencmd[2]={0x0D,0xB0};
UInt8 bufer[18];
UInt8 *pr=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &vel;
UInt8 *ac=(UInt8 *) &corr;
PreparaBuffer(dlencmd,pr,v,ac,bufer);
int sd=SendBuf(Pnum,bufer,18);
return sd;
}

}


Questa è la funzione che non riesce a darmi il CRC corretto, nonostante sia fatta identica ad altre che invece danno il risultato corretto.

int Prova::Stopper()
{
OpenComport(Pnum, BDRATE);
UInt8 dlencmd[2]={0x01,0x91};
UInt8 buffer[6];
PreparaBuffer(dlencmd,0,0,0,buffer);
int sd=SendBuf(Pnum,buffer,6);
return sd; //indicherà l'avvenuta trasmissione o -1 se errore
}

Questa è la funzione di calcolo vero e proprio del CRC, che viene richiamata ricorsivamente.

UInt16 Prova::CRC16(UInt16 crc, UInt8 data)
{
const UInt16 tbl[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};

return ((crc & 0xFF00) >> 8) ^ tbl[(crc & 0x00FF) ^ (data & 0x00FF)];
}


ed un altra funzione che lo stesso mi crea problemi di output è questa:

int Prova::GetState() //richiesta stato della pinza
{
OpenComport(Pnum, BDRATE);
UInt8 dlencmd[2]={0x06,0x95};
UInt8 bufer[11];
PreparaBuffer(dlencmd,0,0,0,bufer);
int i=SendBuf(Pnum,bufer,11);
return i;
}

Perchè quando viene messa in output non ha 00 00 00 00 ma altro, e vista com'è fatta PreparaBuffer, non riesco a capire come fa a non metterci in quelle posizioni quello che ho indicato per "par[0]=0x06" (che è riferito a questa funzione).

Ora passiamo al main , le cose le richiamo così:

Per controllo sui parametri inseriti all'inizio ho fatto così:

cout<<"Immetti l'ID della pinza (intero): ";
cin.getline(IDE,4);
ID = atoi(IDE);
if (ID<=0){
cout<<"Hai immesso parametri sbagliati.Riprova."<<endl;
exit(0);
}
else if(ID>0){
cout<<endl<<"Immetti il numero della porta seriale da aprire (intero): ";
cin.getline(NUMERO,4);
NUM = atoi(NUMERO);
if (NUM<=0){
cout<<"Mi dispiace hai immesso parametri sbagliati.Riprova."<<endl;
exit(0);
}
}

E non mi crea nessun problema tale conversione. Il numero IDPinza che interessa è 12.

Per il posizionamento, all'utente lo chiedo così:

void pos(Prova pinza)
{

cout<<endl<<"Immetti i parametri di posizionamento (mm): ";
//raccolta parametri
cin>>par;
cout<<endl<<"Immetti la velocità: (immetti 0 per velocità standar 10mm/s): ";
cin>>vel;
cout<<endl<<"Immetti l'accelerazione: (immetti 0 per accelerazione default: ";
cin>>ac;
int i=pinza.Posiziona(par,vel,ac);

}

La funzione Stopper, la richiamo così:

int i=pinza.Stopper();


Ebbene,
- Stopper non produce il risultato corretto come ti ho indicato nei post precedenti (e non capisco perchè)., anzichè 0x05 0x0C 0x01 0x91 0x00 0xF3 porta inzialmente 0x00 0x00 al posto degli ultimi due, poi dopo 3 "lanci" 0x00 0xF3 poi di nuovo 0x00 0x00...

- Posiziona non produce la conversione giusta dei parametri da float a unsigned e nemmeno il calcolo del CRC corretto.Es. Se immetto 10 come parametro posizione e 8 come velocità , 0 come acceler, deve passare (10, 8, 0) , e quindi quello che deve produrmi è 0x05 0x0C 0x09 0xB0 0x00 0x00 0x20 0x41 0x00 0x00 0x00 0x41 0x2D 0xEB, dove 00 00 20 41 è "10" convertito, 00 00 00 41 è 8, ed 2D EB è il crc, invece mi viene fuori: 05 0C 09 B0 00 00 20 41 00 EF 8A 41 C7 2B (crc sbagliato e conversione sbagliata, che cambia di volta in volta) e se invece immetto solo 10 (dovrebbe poi passare 10, 10 ,0) passa solo un 10 ed è sbagliata la lunghezza del buffer...

- GetState al posto di avere
buf[4]=(0x00);
buf[5]=(0x00);
buf[6]=(0x00);
buf[7]=(0x00);
buf[8]=(0x07);

in queste posizioni ha valori diversi da 0 e il calcolo del CRC ovviamente è sbagliato, dovrebbe venire fuori 0x05 0x0C 0x06 0x95 0x00 0x00 0x00 0x00 0x07 0x05 0xC2, dove 05 e C2 è il crc corretto. E invece non viene fuori così.

Più dettagliato di così non so essere. Spero che mi riuscirai a dare una mano!! Grazie!!

ESSE-EFFE
20-04-2012, 11:14
Int16 Prova::CalcolaCRC(UInt8 d[])
{
UInt16 crc=0;
UInt16 COD;
for(int i=0;i<sizeof(d);i++)
{
COD=CRC16(crc,d[i]);
crc=COD;
}

return COD;
}


Prova a controllare cosa restituisce sizeof(d)...

DomusP45
20-04-2012, 11:19
Prova a controllare cosa restituisce sizeof(d)...

deve restituire la grandezza del vettore che gli passo. Perchè?

ESSE-EFFE
20-04-2012, 11:27
deve restituire la grandezza del vettore che gli passo. Perchè?

E hai controllato che sia proprio così?

DomusP45
20-04-2012, 11:34
E hai controllato che sia proprio così?

beh, tutte le altre funzioni che ci sono diverse da stopper, vengono richiamate uguali. E per tutte le altre funziona perfettamente il calcolo del CRC. Tra parentesi molte delle altre sono identiche come grandezza a Stopper, differiscono per un solo parametro in pratica al posto 0x91 c'è un altro valore. Pertanto, se calcola bene tutte le altre, perchè dovrebbe sbagliare proprio questa? e perchè è l'unica che se ripeto il lancio più volte, cambia il crc, mentre per le altre questo non accade?

lorenzo001
20-04-2012, 12:24
Quella sizeof che ti è stata indicata restituisce *sempre* 4 perché la sizeof, in quel caso, restituisce la "grandezza" del puntatore e non il suo numero di elementi (un puntatore da 32 bit è sempre 4 byte ...).

Quindi, funzionerà (anche se per caso) solo per buffer grandi 4 byte e non per buffer di grandezza diversa.

Per cui cambia la


UInt16 CalcolaCRC(UInt8 d[], int lenbuffer){
UInt16 crc=0;
UInt16 COD;
for(int i=0;i<lenbuffer;i++)
{
COD=CRC16(crc,d[i]);
crc=COD;
}

return COD;
}


e chiamala sempre con


UInt16 crc=CalcolaCRC(buf, sizeof(buf));


a patto che buf non sia a sua volta un puntatore passato dall'esterno.

DomusP45
20-04-2012, 12:31
beh, buf come hai visto è il risultato di "PreparaBuffer"...questa cosa può quindi creare problemi? Ora faccio la modifica che mi hai consigliato...e ti aggiorno...

EDIT: Non funziona lo stesso...la prima volta che chiamo stopper, lo da corretto, poi sempre sbagliato...GetState succede la stessa cosa...e Posiziona mi converte male i valori...

DomusP45
20-04-2012, 13:10
beh, buf come hai visto è il risultato di "PreparaBuffer"...questa cosa può quindi creare problemi? Ora faccio la modifica che mi hai consigliato...e ti aggiorno...

EDIT: Non funziona lo stesso...la prima volta che chiamo stopper, lo da corretto, poi sempre sbagliato...GetState succede la stessa cosa...e Posiziona mi converte male i valori...

lorenzo001
20-04-2012, 13:25
EDIT: Non funziona lo stesso...la prima volta che chiamo stopper, lo da corretto, poi sempre sbagliato...GetState succede la stessa cosa...e Posiziona mi converte male i valori...

In che senso "la prima volta" e in che senso "poi" ...?

Se hai fatto una modifica al codice, mostra la parte modificata e il main o il codice con cui provi il nuovo codice.

E mostra i dati ottenuti, quelli corretti e quelli sbagliati ...!

DomusP45
20-04-2012, 14:01
Sono 25 funzioni, se te le voglio postare tutte facciamo notte! Ti posto la modifica che mi hai consigliato dove l'ho fatta, e come richiamo la cosa.

Queste stanno in prova.cpp

UInt16 Prova::CalcolaCRC(UInt8 d[], int leng){
UInt16 crc=0;
UInt16 COD;
for(int i=0;i<leng;i++)
{
COD=CRC16(crc,d[i]);
crc=COD;
}

return COD;
}

void Prova::PreparaBuffer(UInt8 *par,UInt8 *dat,UInt8 *velo, UInt8 *acc, UInt8 *bufer)
{
//se arriva un posizionamento semplice
if (par[0]==(0x05))
{
UInt8 grup[1]={0x05};
UInt8 buf[8];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
UInt16 crc=CalcolaCRC(buf,sizeof(buf));
for (int i=0;i<8;i++){
bufer[i]=buf[i];
}
bufer[8]=crc & 0xFF;
bufer[9]=crc >> 8;
}
//se arriva una istruzione di comando
else if(par[0]==(0x01))
{
UInt8 grup[1]={0x05};
UInt8 buf[4];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
UInt16 crc=CalcolaCRC(buf,sizeof(buf));
for (int i=0;i<4;i++){
bufer[i]=buf[i];
}
bufer[4]=crc & 0xFF;
bufer[5]=crc >> 8;
}
//se arriva un posizionamento complesso
else if(par[0]==(0x09)){
UInt8 grup[1]={0x05};
UInt8 buf[12];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
buf[8]=velo[0];
buf[9]=velo[1];
buf[10]=velo[2];
buf[11]=velo[3];
UInt16 crc=CalcolaCRC(buf,12);
for (int i=0;i<12;i++){
bufer[i]=buf[i];
}
bufer[12]=crc & 0xFF;
bufer[13]=crc >> 8;
}
else if(par[0]==(0x0D)){
UInt8 grup[1]={0x05};
UInt8 buf[16];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
buf[8]=velo[0];
buf[9]=velo[1];
buf[10]=velo[2];
buf[11]=velo[3];
buf[12]=acc[0];
buf[13]=acc[1];
buf[14]=acc[2];
buf[15]=acc[3];
UInt16 crc=CalcolaCRC(buf,16);
for (int i=0;i<16;i++){
bufer[i]=buf[i];
}
bufer[16]=crc & 0xFF;
bufer[17]=crc >> 8;
}
if (par[0]==(0x06))
{
UInt8 grup[1]={0x05};
UInt8 buf[9];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=par[2];
buf[5]=par[3];
buf[6]=par[4];
buf[7]=par[5];
buf[8]=par[6];
UInt16 crc=CalcolaCRC(buf,9);
for (int i=0;i<9;i++){
bufer[i]=buf[i];
}
bufer[9]=crc & 0xFF;
bufer[10]=crc >> 8;
}
}



int Prova::Posiziona(float pos, float vel,float corr) //param è il vettore parametri immesso da utente
{
OpenComport(Pnum, BDRATE);
//se velocità e corrente non sono state specificate
if ((vel==0)&&(corr==0)){
UInt8 dlencmd[2]={0x09,0xB0};
UInt8 bufer[14];
float veloc=10;
UInt8 *ps=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &veloc;
PreparaBuffer(dlencmd,ps,v,0,bufer);
int sd=SendBuf(Pnum,bufer,14);
return sd;
}
//se posizionamento in accelerazione
else if((vel!=0)&&(corr==0)){
UInt8 dlencmd[2]={0x09,0xB0};
UInt8 bufer[14];
UInt8 *pr=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &vel;
PreparaBuffer(dlencmd,pr,v,0,bufer);
int sd=SendBuf(Pnum,bufer,14);
return sd;
}
else if((vel!=0)&&(corr!=0)){
UInt8 dlencmd[2]={0x0D,0xB0};
UInt8 bufer[18];
UInt8 *pr=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &vel;
UInt8 *ac=(UInt8 *) &corr;
PreparaBuffer(dlencmd,pr,v,ac,bufer);
int sd=SendBuf(Pnum,bufer,18);
return sd;
}

}

int Prova::Stopper()
{
OpenComport(Pnum, BDRATE);
UInt8 dlencmd[2]={0x01,0x91};
UInt8 buffer[6];
PreparaBuffer(dlencmd,0,0,0,buffer);
int sd=SendBuf(Pnum,buffer,6);
return sd; //indicherà l'avvenuta trasmissione o -1 se errore
}


int Prova::CmdGetState() //richiesta stato della pinza
{
OpenComport(Pnum, BDRATE);
UInt8 dlencmd[7]={0x06,0x95,0x00,0x00,0x00,0x00,0x07}; //parametro stop di emergenza
UInt8 bufer[11];
PreparaBuffer(dlencmd,0,0,0,bufer);
int i=SendBuf(Pnum,bufer,11);
return i;
}

questo invece è la parte di main:

//funzione di richiamo posizionamento con richiesta parametri all'utente

void pos(Prova pinza)
{
float par,vel,ac;
cout<<endl<<"Immetti i parametri di posizionamento (mm): ";
//raccolta parametri
cin>>par;
cout<<endl<<"Immetti la velocità: (immetti 0 per velocità standar 10mm/s): ";
cin>>vel;
cout<<endl<<"Immetti l'accelerazione: (immetti 0 per accelerazione default: ";
cin>>ac;
int i=pinza.Posiziona(par,vel,ac,ritorno);
}


void st(Prova pinza)
{
int i=pinza.Stopper();

}

void gstate(Prova pinza){
int i=pinza.CmdGetState();//

Ora, la situazione è questa: le funzioni possono essere richiamate anche più volte, perchè all'inizio del programma faccio comparire un menù con la scelta, ed in base alla scelta viene avviata la funzione corrispondente.

I risultati sbagliati e corretti li ho già postati sopra nel post precedente...quelli aspettati e quelli sbagliati...

La funzione Stopper è l'unica che crea quel problema (cioè che ogni volta che la lancio il CRC è diverso, mentre per le altre (molto simili) la cosa non accade.

Invece, quelle di posizionamento, che ho postato, non mi fanno la conversione giusta da float a unsigned char...

ESEMPIO:

- GetState dovrebbe restituire 05 0C 06 95 00 00 00 00 07 05 C2 invece mi restituisce:
- la prima volta che la richiamo 05 0C 06 95 00 00 00 93 9E 00 68
- se la richiamo una seconda volta 05 0C 06 95 00 00 9E 00 F8

altro esempio:

Funzione stopper, dovrebbe 05 0C 01 91 00 F3 e invece ritorna:
- prima chiamata 05 0C 01 91 00 00
- seconda chiamata 05 0C 01 91 00 00
- terza chiamata 05 0C 01 91 00 9E

ecc...

Invece, per il posizionamento, introducendo da tastiera 10, 8 , 0 (alle tre richieste) ottengo:
05 0C 09 B0 00 9E 00 68 8A 9E 09 0F 2D EB, che è sbagliato visto che dovrei avere quello che ho indicato nell'altro post...

lorenzo001
20-04-2012, 15:50
A me non servono le 25 funzioni ... infatti ti avevi chiesto

mostra la parte modificata e il main o il codice con cui provi il nuovo codice

In ogni caso, ho provato la stopper più volte e ottengo sempre lo stesso risultato.

L'unica cosa che posso dirti è di preparare un sorgente di prova, senza la parte di comunicazione e con le sole funzioni di calcolo del CRC e le funzioni che non danno il risultato voluto, con un main "minimo" in cui si verifica quello che dici.

In pratica, scrivi un main con la Stopper e poco altro, fai uno zip del progetto e fammelo scaricare.

DomusP45
20-04-2012, 16:04
A me non servono le 25 funzioni ... infatti ti avevi chiesto

mostra la parte modificata e il main o il codice con cui provi il nuovo codice

In ogni caso, ho provato la stopper più volte e ottengo sempre lo stesso risultato.

L'unica cosa che posso dirti è di preparare un sorgente di prova, senza la parte di comunicazione e con le sole funzioni di calcolo del CRC e le funzioni che non danno il risultato voluto, con un main "minimo" in cui si verifica quello che dici.

In pratica, scrivi un main con la Stopper e poco altro, fai uno zip del progetto e fammelo scaricare.

OK lorenzo. Facciamo così, alleggerisco questo progetto e se per te va bene, te lo mando via mail...ci tolgo tutto quello che funziona, e lascio quello che non va...però non ti so dire quando lo faccio perchè proprio ora sto per partire e tornare a casa (sono fuorisede) e il materiale resta qua. Se tutto va bene massimo per lun/mar te lo faccio avere.

Io comunque penso che sia una questione di come gli passo i parametri alle funzioni...non so se fare la conversione float -->unsigned char in quel modo e poi passargli l'array come glielo passo crei il problema delle funzioni di posizionamento...ho questo dubbio però...solo che, in che altro modo potrei farla sta cosa? per avere un unsigned da un float immesso da tastiera, da inserire in quell'array, l'unico modo che conosco è quello...infatti fatto singolarmente in un altro programma funzionava perfettamente...messo così non va...

Per quanto riguarda stopper è un mistero: è identica a tutte le altre, che in pratica variano solo per il valore diverso di 0x91 (che ne so, in altre è 0xB1, 0x90, 0x88, ecc) ma nonostante ciò è l'unica che mi dà quel problema, nonostante sia richiamata esattamente come le altre. Mah...

Se ti venisse l'illuminazione prima su "da cosa potrebbe dipendere" un problema del genere, fammelo sapere...ti ringrazio ancora tanto per la disponibilità.

lorenzo001
20-04-2012, 16:14
se per te va bene, te lo mando via mail...ci tolgo tutto quello che funziona, e lascio quello che non va...però non ti so dire quando lo faccio perchè proprio ora sto per partire e tornare a casa (sono fuorisede) e il materiale resta qua. Se tutto va bene massimo per lun/mar te lo faccio avere.

Non ho fretta ... :D ... magari mi dai un link da cui scaricare lo zip del progetto di prova ...

Io comunque penso che sia una questione di come

Ma hai detto che il problema era solo nella Stopper e lì non ci sono float ...

Per quanto riguarda stopper è un mistero

Dato che la prima volta funziona, il problema sta nel modo con cui la richiami, ovvero nel modo con cui prepari i dati nel ciclo successivo ...

DomusP45
20-04-2012, 16:17
Ma hai detto che il problema era solo nella Stopper e lì non ci sono float ...



della stopper mi calcola il CRC sbagliato come ho indicato.
Di posiziona invece mi sbaglia le conversioni, l'ho scritto nel post...per quello ti ho incollato tutta quella roba c'è anche la funzione posiziona che non da l'output che dovrebbe..il CRC poi viene sbagliato perchè i byte all'interno sono sbagliati..

lorenzo001
20-04-2012, 18:09
No, il passaggio dei float sembra corretto. Il problema dovrebbe essere nella PreparaBuffer perché la riga

UInt8 buf[14];

dovrebbe essere

UInt8 buf[12];

e la riga

UInt8 buf[18];

dovrebbe essere

UInt8 buf[16];

DomusP45
24-04-2012, 10:56
Ecco qua i vari file:

Prova.h

#ifndef PROVA_H
#define PROVA_H

//definizione dei tipi per CRC16

typedef unsigned short UInt16;
typedef unsigned char UInt8;


class Prova
{

public:
//costruttore della classe
Prova(int P, int BD, int ID, float TOUT);

/*distruttore*/
~Prova();

UInt16 CalcolaCRC(UInt8 [], int);//richiama CRC16 ciclicamente byte per byte
int Posiziona(float pos, float vel,float corr);
int CmdGetState();
int Stoppe();

private:

//funzione calcolo CRC16
UInt16 CRC16(UInt16, UInt8);

//funzione che prepara il buffer per l'invio
void PreparaBuffer(UInt8 *par,UInt8 *dat, UInt8 *velo, UInt8 *acc, UInt8 *bufer);



//variabili della classe
bool p_aperta; //flag di porta aperta/chiusa
int Pnum; //indicatore del numero di porta seriale da aprire
int BDRATE; //baudrate della porta
float TimeOut; //timeout della porta
int IDPinza; //ID della pinza
};

#endif /* PROVA_H */

Prova.cpp

#include "rs232.h"
#include "prova.h"
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <iomanip>
#include <iostream>
#include <time.h>
#include <ctime>

//definizione dei tipi per CRC

typedef unsigned short UInt16;
typedef unsigned char UInt8;


//Costruttore della classe

Prova::Prova(int P, int BD, int ID, float TOUT)
{
p_aperta = false;
Pnum=P;
IDPinza=ID;
BDRATE=BD;
TimeOut=TOUT;

}

//distruttore della classe, chiude la connessione

Prova::~Prova()
{
p_aperta=false;
//manda il segnale di blocco alla pinza


//chiude la porta
CloseComport(Pnum);
}




UInt16 Prova::CalcolaCRC(UInt8 d[], int leng){
UInt16 crc=0;
UInt16 COD;
for(int i=0;i<leng;i++)
{
COD=CRC16(crc,d[i]);
crc=COD;
}

return COD;
}


void Prova::PreparaBuffer(UInt8 *par,UInt8 *dat,UInt8 *velo, UInt8 *acc, UInt8 *bufer)
{
//se arriva un posizionamento semplice
if (par[0]==(0x05))
{
UInt8 grup[1]={0x05};
UInt8 buf[8];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
UInt16 crc=CalcolaCRC(buf,8);
for (int i=0;i<8;i++){
bufer[i]=buf[i];
}
bufer[8]=crc & 0xFF;
bufer[9]=crc >> 8;
}
//se arriva una istruzione di comando
else if(par[0]==(0x01))
{
UInt8 grup[1]={0x05};
UInt8 buf[4];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
UInt16 crc=CalcolaCRC(buf,4);
for (int i=0;i<4;i++){
bufer[i]=buf[i];
}

bufer[4]=crc & 0xFF;
bufer[5]=crc >> 8;
}
//se arriva un posizionamento complesso
else if(par[0]==(0x09)){
UInt8 grup[1]={0x05};
UInt8 buf[12];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
buf[8]=velo[0];
buf[9]=velo[1];
buf[10]=velo[2];
buf[11]=velo[3];
UInt16 crc=CalcolaCRC(buf,12);
for (int i=0;i<12;i++){
bufer[i]=buf[i];
}
bufer[12]=crc & 0xFF;
bufer[13]=crc >> 8;
}
else if(par[0]==(0x0D)){
UInt8 grup[1]={0x05};
UInt8 buf[16];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=dat[0];
buf[5]=dat[1];
buf[6]=dat[2];
buf[7]=dat[3];
buf[8]=velo[0];
buf[9]=velo[1];
buf[10]=velo[2];
buf[11]=velo[3];
buf[12]=acc[0];
buf[13]=acc[1];
buf[14]=acc[2];
buf[15]=acc[3];
UInt16 crc=CalcolaCRC(buf,16);
for (int i=0;i<16;i++){
bufer[i]=buf[i];
}
bufer[16]=crc & 0xFF;
bufer[17]=crc >> 8;
}
if (par[0]==(0x06))
{
UInt8 grup[1]={0x05};
UInt8 buf[9];
buf[0]=grup[0];
buf[1]=IDPinza;
buf[2]=par[0];
buf[3]=par[1];
buf[4]=0;
buf[5]=0;
buf[6]=0;
buf[7]=0;
buf[8]=7;
UInt16 crc=CalcolaCRC(buf,9);
for (int i=0;i<9;i++){
bufer[i]=buf[i];
}
bufer[9]=crc & 0xFF;
bufer[10]=crc >> 8;
}
}


//funzione di posizionamento in mmm
int Prova::Posiziona(float pos, float vel,float corr) //param è il vettore parametri immesso da utente
{
OpenComport(Pnum, BDRATE);
//se velocità e corrente non sono state specificate
if ((vel==0)&&(corr==0)){
UInt8 dlencmd[2]={0x09,0xB0};
UInt8 bufer[14];
float veloc=10;//assegno velocità standard
UInt8 *ps=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &veloc;
PreparaBuffer(dlencmd,ps,v,0,bufer);
int sd=SendBuf(Pnum,bufer,14);
return sd;
}
//se posizionamento in accelerazione (corr diverso da zero)
else if((vel!=0)&&(corr==0)){
UInt8 dlencmd[2]={0x09,0xB0};
UInt8 bufer[14];
UInt8 *pr=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &vel;//assegno velocità immessa da utente
PreparaBuffer(dlencmd,pr,v,0,bufer);
int sd=SendBuf(Pnum,bufer,14);
return sd;
}
else if((vel!=0)&&(corr!=0)){
UInt8 dlencmd[2]={0x0D,0xB0};
UInt8 bufer[18];
UInt8 *pr=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &vel;
UInt8 *ac=(UInt8 *) &corr;
PreparaBuffer(dlencmd,pr,v,ac,bufer);
int sd=SendBuf(Pnum,bufer,18);
return sd;
}

}

//funzione di stop nella posizione corrente

int Prova::Stoppe()
{
OpenComport(Pnum, BDRATE);
UInt8 dlencmd[2]={0x01,0x91};
UInt8 bufer[6];
PreparaBuffer(dlencmd,0,0,0,bufer);
int sd=SendBuf(Pnum,bufer,6);
return sd; //indicherà l'avvenuta trasmissione o -1 se errore
}


//richiede stato
int Prova::CmdGetState() //richiesta stato della pinza
{
OpenComport(Pnum, BDRATE);
UInt8 dlencmd[2]={0x06,0x95};
UInt8 bufer[11];
PreparaBuffer(dlencmd,0,0,0,bufer);
int i=SendBuf(Pnum,bufer,11);
return i;
}



//funzione di calcolo CRC

UInt16 Prova::CRC16(UInt16 crc, UInt8 data)
{
const UInt16 tbl[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};

return ((crc & 0xFF00) >> 8) ^ tbl[(crc & 0x00FF) ^ (data & 0x00FF)];
}



MAIN.CPP


#include <cstdlib>
#include <cstring>
#include <iostream>
#include "prova.h"
#include "rs232.h"
#include <stdio.h>
#include <stdlib.h>
#include <iomanip>
#include <ctime>

using namespace std;

//dichiarazione delle variabili del main

int scelto, ID, NUM;
char NUMERO[4];
char IDE[4];
float par,vel,ac;//data sono i parametri chiesti all'utente

//dichiarazione delle funzioni

void pos(Prova);//posizionamento in mm
void st(Prova);//stop pos.corrente
void gstate(Prova);//getstate




//parte di richiesta primi parametri all'utente (omessa perchè funziona)

Prova pinza(NUM,9600,ID,3); //costruttore con i parametri chiesti (OK)


//qua c'è il menù con la domanda all'utente su quale funzione vuole chiamare (ciclo while/switch) omesso perchè funziona.Richiama a seconda della scelta dell'utente le funzioni sotto.

//parte finale main

cout<<endl<<endl<<"Chiusura comunicazione porta seriale..."<<endl;
pinza.Stoppe();
pinza.~Prova();

//funzione prova posizionamento

void pos(Prova pinza)
{
//float par;//data sono i parametri chiesti all'utente
cout<<endl<<"Immetti i parametri di posizionamento (mm): ";
//raccolta parametri
cin>>par;
cout<<endl<<"Immetti la velocità: (immetti 0 per velocità standar 10mm/s): ";
cin>>vel;
cout<<endl<<"Immetti l'accelerazione: (immetti 0 per accelerazione default: ";
cin>>ac;
int i=pinza.Posiziona(par,vel,ac);
}

//funzione prova stoppe

void st(Prova pinza)
{
int i=pinza.Stoppe();

}


//funzione prova gstate

void gstate(Prova pinza){
int i=pinza.CmdGetState();

}



Dimmi tu cosa c'è che non va. Le funzioni che ho lasciato sono quelle che non vanno della classe.

- Stoppe non da in output quello che dovrebbe, cioè 05 0C 01 91 00 F3, restituisce invece 05 0C 01 91 00 00

- GetState dovrebbe dare, 05 0C 06 95 00 00 00 00 07 05 C2, invece mi sbaglia dal 5° byte in poi

- La funzione di posizionamento, "posiziona" mi sbaglia la trasposizione in unsigned char dei valori float immessi da utente...anzichè "10" ad esempio che dovrebbe essere 00 00 20 41, mi riporta altro, tipo 00 BC 04 41.

Fai delle prove e ti prego, dimmi come posso risolvere!!

lorenzo001
25-04-2012, 13:40
Dimmi tu cosa c'è che non va.

Devi solo fare molta attenzione e un po' di debugging.

Stoppe non da quello che dovrebbe, cioè 05 0C 01 92 00 F3

Nel codice che hai mostrato, nella Stoppe hai scritto tu

UInt8 dlencmd[2]={0x01,0x91};

e non 01 92 come dici dovrebbe essere.

- GetState dovrebbe dare, 05 0C 06 95 00 00 00 00 07 05 C2

Per questa funzione utilizzi un valore

07

che nel codice non c'è. Forse deve essere

buf[8]=7; e non buf[8]=0;

- La funzione di posizionamento mi sbaglia la trasposizione in unsigned char dei valori float...anzichè 10--> 00 00 20 41, mi riporta altro.

Quale funzione? Spiegati meglio.

DomusP45
25-04-2012, 13:48
Nel codice che hai mostrato, nella Stoppe hai scritto tu

UInt8 dlencmd[2]={0x01,0x91};

e non 01 92 come dici dovrebbe essere.

Quello che ti ho indicato p l'output...sono byte, pertanto si scrivono così ma in uscita, sulla seriale, saranno senza "0x"....



Per questa funzione utilizzi un valore

07

che nel codice non c'è. Forse deve essere

buf[8]=7; e non buf[8]=0;

Si infatti...ma l'output è sbagliato comunque...al posto degli zeri escono altri valori in output sulla seriale (usando gtkterm con un cavo loopback sto facendo diversi test, e sono arrivato a tali risultati.


Quale funzione? Spiegati meglio.

Quella che si chiama Posiziona, scorrendo il codice la trovi, e che prepara buffer fa in funzione di "0x09" oppure "0x0D"...

lorenzo001
25-04-2012, 19:50
Quello che ti ho indicato p l'output...sono byte, pertanto si scrivono così ma in uscita, sulla seriale, saranno senza "0x"....

Questo lo so Domus, non è questo il punto. Quello che volevo farti notare è la differenza di valori

91 e 92

Si infatti...ma l'output è sbagliato comunque...al posto degli zeri escono altri valori in output sulla seriale (usando gtkterm con un cavo loopback sto facendo diversi test, e sono arrivato a tali risultati.

Scusa ma cosa c'entra l'output? Stiamo parlando della preparazione dei valori ... il 7 di cui parli non c'è ... Forse mi perdo qualcosa o tu non ti spieghi.

fa in funzione di "0x09" oppure "0x0D"...

Dammi spiegazioni più precise o non so neanche cosa testare.

DomusP45
25-04-2012, 20:16
Ok, ho modificato il codice, non ci sono più gli errori di cui parli.

Ora, i problemi sono quelli indicati là, cioè :

- Stoppe non da in output sulla seriale quello che dovrebbe, cioè dovrebbe 05 0C 01 91 00 F3, invece restituisce 05 0C 01 91 00 00 e dopo varie "chiamate" della stessa, 00 00 diventano altri valori, 00 B0, D2 00, ecc.

- GetState dovrebbe dare 05 0C 06 95 00 00 00 00 07 05 C2, invece mi sbaglia dal 5° byte in poi, del tipo che esce 05 0C 06 95 00 0F 4B 99 88 DD FF...

- La funzione di posizionamento, "Posiziona" mi sbaglia la trasposizione in unsigned char dei valori float immessi da utente...anzichè "10" (immesso dal main quando il programma si avvia con CIN) ad esempio che dovrebbe essere "00 00 20 41", mi riporta altro, tipo 05 0C 09 B0 00 BC 04 41 00 FF 00 C2 FF 44, sbagliando anche la parte in blu che invece è preassegnata da me a "10" (vedi codice)..primo pezzo di Posiziona:

if ((vel==0)&&(corr==0)){
UInt8 dlencmd[2]={0x09,0xB0};
UInt8 bufer[14];
float veloc=10;//assegno velocità standard
UInt8 *ps=(UInt8 *) &pos;
UInt8 *v=(UInt8 *) &veloc;
PreparaBuffer(dlencmd,ps,v,0,bufer);
int sd=SendBuf(Pnum,bufer,14);
return sd;
}

quella segnata in rosso nell'inviare sulla seriale comunque viene sbagliata: non è 10 nei 4 butes che dovrebbe rappresentarlo, cioè 00 00 20 41. Ed ogni volta cambia...ci sono sempre bytes diversi...

Spero di essere stato più chiaro.

Ora la domanda è questa: ma da che può dipendere un comportamento del genere? Se i valori addirittura sono preassegnati (come il caso getstate) perchè li sbaglia?

lorenzo001
25-04-2012, 20:39
- Stoppe non da in output sulla seriale quello che dovrebbe, cioè dovrebbe 05 0C 01 91 00 F3, invece ...

Ho provato l'ultimo codice che hai inviato e il valore del buffer per la Stoppe è sempre quello corretto (termina con 00 F3). Non so che dirti.


- GetState dovrebbe dare 05 0C 06 95 00 00 00 00 07 05 C2

E a me fornisce sempre questo risultato, non ho i problemi che hai descritto. Sempre con questo codice che sto provando (e non potrebbe essere diversamente dato che il codice non varia).

- La funzione di posizionamento, "Posiziona" mi sbaglia la trasposizione in unsigned char

No ... questo non succede ... il risultato della chiamata - sempre con il codice che hai fornito - è

05 0c 09 b0 00 00 00 00 00 00 20 41 0f 44

Ora la domanda è questa

Il codice che continuo a provare è un po' confuso (e quindi migliorabile) ma non ci sono gli errori che mi hai descritto.

Quindi il problema è da qualche altra parte del codice che hai tu e che io non ho visto.
Probabilmente è uno "sforamento" in memoria di codice che va a sporcare il contenuto dei vari buffer.

Ma non avendo TUTTO (e intendo tutto) il codice che stai utilizzando, non posso dirti altro.

DomusP45
25-04-2012, 20:44
nel codice completo non c'è niente di più che le altre funzioni simili a "stoppe", ed il ciclo while-switch per la scelta di quale funzione chiamare (che sta nel main).

Sono sempre più confuso a questo punto...grazie della disponibilità ma non se ne riesce a venire a capo. Tu hai provato usando la libreria seriale o solo verificando il contenuto degli array? Perchè a questo punto l'unico dubbio che mi viene è se il problema sta nell'invio, nella funzione SendBuf....

come posso fare per avere un output a video del contenuto del vettore che faccio inviare a Sendbuf prima di inviarlo? tu come fai?

lorenzo001
25-04-2012, 21:14
Evidentemente tutta la parte della seriale la commento ... altrimenti non potrei provare nulla.

Non so se il problema è nella parte della gestione della seriale (potrebbe anche essere).

I dati in uscita li vedo direttamente in memoria in debugging.

Ma se scrivi due righe con un ciclo e una printf li vedi a video.

DomusP45
26-04-2012, 10:12
infatti usando la printf subito prima di SendBuf, gli array sono corretti anche a me e sempre gli stessi...quindi il calcolo del CRC è corretto, Prepara buffer è corretta, e la conversione float ad unsigned è corretta....

a questo punto mi chiedo dove sta il problema, l'istruzione successiva è SendBuf...

lorenzo001
26-04-2012, 11:17
E quindi il problema sarà nella SendBuf ...