comunicazione arduino seriale

ciao a tutti avrei bisogno di qualche chiarimento sull’interfaccia arduino PC.
io ho un programma iin c++ che legge i dati inviati da arduino.ho letto che la comunicazione tra USB e arduino crea una seriale simulata in cui vado a scrivere una spece di file sul PC a cui accedo tramite un puntatore carattere per carattere.(è vero??)
il massimo numeri di caratteri che invio da arduino e lungo 17, perchè invio una stringa del tipo:
|1234 1234 12345<
alla fine imposto un ritardo di 10ms.
prima domanda: io cerco di inviare (17*8/0.01) bit/s giusto?? il che significa 14400bit/s.
seconda domanda: se imposto un baud rate di 9600 non ci sto dietro giusto?? tento di inviare un pacchetto troppo grande.
terza domanda: se imposto un baud rate di 38400 ho che spesso perdo la comunicazione e non riseco a leggere i dati come mai? se imposto un baud rate di 19200 invece va tutto alla perfezione e non perdo nulla, perchè??
può essere che ci sia un limite al baud per una seriale simulata su USB???

grazie ciao Confa

Ciao,

se ho capito bene tu "perdi" i dati in lettura nel tuo programma in C++?

Come hai impostato la porta seriale dal lato programma C++? Quale velocita'? Dovresti impostare la stessa velocita' nell'Arduino e nel programma C++ che risiede nel PC.

Puoi utilizzare un software per il serial port monitor per controllare cosa e come viene trasmesso.

Ciao, Marco.

Confa:
ciao a tutti avrei bisogno di qualche chiarimento sull’interfaccia arduino PC.
io ho un programma iin c++ che legge i dati inviati da arduino.ho letto che la comunicazione tra USB e arduino crea una seriale simulata in cui vado a scrivere una spece di file sul PC a cui accedo tramite un puntatore carattere per carattere.(è vero??)

che esista un file speciale è vero per i sistemi operativi unix-like (mac, linux, solaris)

Confa:
il massimo numeri di caratteri che invio da arduino e lungo 17, perchè invio una stringa del tipo:
|1234 1234 12345<
alla fine imposto un ritardo di 10ms.
prima domanda: io cerco di inviare (17*8/0.01) bit/s giusto?? il che significa 14400bit/s.

esatto

Confa:
seconda domanda: se imposto un baud rate di 9600 non ci sto dietro giusto?? tento di inviare un pacchetto troppo grande.

esatto, credo che la funzione Serial.write() ti blocca fino a quando non riesce di nuovo a trasmettere

Confa:
terza domanda: se imposto un baud rate di 38400 ho che spesso perdo la comunicazione e non riseco a leggere i dati come mai? se imposto un baud rate di 19200 invece va tutto alla perfezione e non perdo nulla, perchè??

non so, bug?

Confa:
può essere che ci sia un limite al baud per una seriale simulata su USB???

grazie ciao Confa

può essere, anche se mi sembra strano che un pc non riesca a elaborare un simile flusso di dati… bisognerebbe vedere che succede a livello di SO

in un’altro post ho già linkato i due programmi sia lato arduino che lato PC. cmq la velocità che imposto è la stessa da entrambe le parti, ora è 19200 perchè così non ho problemi, ma come dicevo se vado a 38400 ho che spesso perdo la comunicazione.
la comunicazione via USB la faccio richiamando le API di windows che vanno a creare un file dove simula la seriale, almeno così ho letto.
cmq per ora credo che lavorerò a questa velocità, se qualcuno ha voglia di fare qualche prova i file che linko sotto dovrebbero andare senza bisogno di header strani. grazie cmq delle conferme almeno qualcosa l’ho capita.
grazie Confa

// My_serial.cpp : Defines the entry point for the console application.
//
//#include “stdafx.h”
#include <windows.h>
#include <conio.h>
#include <stdio.h>
//#include “crc.h” //l’header per il controllo della correttezza dei dati tramite algoritmo CRC

FILE *stream, fopen(); //apro un file in cui vado a memorizzare i termini di interesse(es. i valori di arduino il CRC ecc.)
/
funzione che richiama le API e permette di aprire la porta USB
e scrivere i dati ricevuti in un file, in questo modo simulo
una comunicazione seriale */
BOOL setComm ( HANDLE hComm )
{
DCB dcb;
BOOL res;

FillMemory ( &dcb , sizeof ( dcb ), 0 );
res = GetCommState ( hComm , &dcb ); // get current DCB
if ( !res )
// Error in GetCommState
return FALSE;
printf ( “\nBaudRate %d ByteSize %d StopBits %d\n” , dcb.BaudRate , dcb.ByteSize , dcb.StopBits );
// Update DCB rate.
dcb.ByteSize = 8; // numero di bit
dcb.StopBits = ONESTOPBIT;
dcb.BaudRate = CBR_19200; // baudrate
dcb.Parity = NOPARITY; // nessun bit di parità
dcb.fAbortOnError = 0;

// Set new state.
res = SetCommState ( hComm , &dcb );

// Error in SetCommState. Possibly a problem with the communications
// port handle or a problem with the DCB structure itself.
if ( !res )
return FALSE;

DWORD err = GetLastError();
if ( err )
printf( “\n ERROR % d\n” , err );

return TRUE;
}

/* sinceramente non so a cosa serve */
void state ( HANDLE hComm )
{
DCB dcb;
BOOL res;

FillMemory ( &dcb , sizeof ( dcb ) , 0);
res = GetCommState( hComm , &dcb ); // get current DCB

DWORD err = GetLastError();
if ( err )
printf( “\n receive ERROR % d\n” , err );

SetLastError ( 0 );
}

/* funzione per la scrittura su seriale */
BOOL write ( HANDLE hComm , char * buf )
{
DWORD nNumberOfBytesToWrite = strlen ( buf );
DWORD NumberOfBytesWritten;
LPOVERLAPPED lpOverlapped = NULL;
BOOL res = WriteFile(
hComm, // handle to file to write to
buf, // pointer to data to write to file
nNumberOfBytesToWrite, // number of bytes to write
&NumberOfBytesWritten, // pointer to number of bytes written
lpOverlapped // pointer to structure for overlapped I/O
);

if ( res )
printf ( “\nwrite OK\n” );
else
{
DWORD err = GetLastError();
printf ( “\nwrite ERROR %d \n” , err );
}
return res;
}

/* definizione del main /
int main( int argc , char
argv )
{

/* vado ad aprire il file su cui vado a memorizzare i miei controlli */
stream = fopen( “prova.txt” , “w” );
if ( ( stream = fopen (“prova.txt”,“w”) ) == NULL )
{
printf ( “non posso aprire il file %s\n” , “prova.txt” );
}

char gszPort = “COM6”; // imposto quale porta USB aprire
HANDLE hComm;
hComm = CreateFile( gszPort,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0, // NO ! FILE_FLAG_OVERLAPPED,
0);

/* verifico che sono riuscito ad aprire la porta*/
if ( hComm == INVALID_HANDLE_VALUE )
{
printf( “error opening\n” );
// error opening port; abort
}

else // se ho aperto la porta COM
{

/* definisco i parametri della comunicazione */
char c;
DWORD nNumberOfBytesToRead = 1;
DWORD NumberOfBytesRead = 0;
LPOVERLAPPED lpOverlapped = NULL; // pointer to structure for data
BOOL bResult;

bResult = setComm ( hComm );

int ho = 0; // contatore dei cicli di lettura da seriale(definisco quante volte leggere)
const int LUNG_MAX = 30; // definisco la lunghezza massima della stringa in cui memorizzo i valori
int ax = 0, ay = 0, CRC_A = 0; // ax, ay = coordinata x e y CRC_A = CRC (valore di controllo correttezza del dato)
char str [ LUNG_MAX ]; // stringa in cui memorizzo il buffer della x e y
char buff [ 5 ]; // buffer dove memorizzo il valore esadecimale in formato ASCII di ax che uso per calcolare il CRC lato PC e che poi confronto con quello restituito dall’arduino
int yu = 0; // variabile di controllo di uscita dal ciclo della seriale (esco quando leggo una stringa valida)
int i = 0, j = 0; // i = contatore per scrivere nella stringa di lettura da seriale j = contatore dei cicli da seriale (quante volte vado a leggere il buffer della seriale a cui accedo con il puntatore *c)
int rec = 0; // variabile di controllo che mi dice se iniziare a memorizzare la stringa

for ( ho = 0 ; ho < 100 ; ho++ ) { // inizio il ciclo di lettura (vado a leggere 20000 volte dalla seriale)

/* inizializzo le variabili ogni volta che ho letto una stringa valida ( valida non vuol dire corretta, la corretteza la dice il CRC) */
ax = 0;
ay = 0;
CRC_A = 0;
yu = 0;
i = 0;
j = 0;
rec = 0;
buff[0] = ‘\0’;
str[0] = ‘\0’;

do // inizio a leggere un carattere per volta dal buffer della seriale fino a che non ho letto una stringa valida
{
nNumberOfBytesToRead = 1;
bResult = ReadFile(
hComm, // handle of file to read
&c, // pointer to buffer that receives data
nNumberOfBytesToRead, // number of bytes to read
&NumberOfBytesRead, // pointer to number of bytes read
lpOverlapped // pointer to structure for data
);

////////////////// stampo il ciclo j-esimo il carattere letto dal buffer che punta alla seriale prima in ASCII poi in Esadecimale //////////////////////
printf( " Ciclo : = %d\n", j++);

if(c == ‘|’) { //se leggo | inizio a memorizzare i valori nella stringa
rec = 1;
}

// Ricostruisco a stringa
if(rec == 1 && i < LUNG_MAX)
{
if(c == ‘|’) {} // non mi interessa nella ricostruzione della stringa quindi se la leggo non faccio nulla
else if(c != ‘<’) // se non ho letto il terminatore (<) memorizzo il valore perchè è interessante
{
str [ i++ ] = c;
}
else // se ho letto < metto il terminatore di stringa in fondo a str perchè ho letto tutto quello che mi serve
{
str [ i ] = ‘\0’;
yu = 1; // incremento yu e quindi esco dal ciclo do (notare che poi faccio controllo sul CRC, se non è soddisfatto riazzere yu e torno a leggere)
}
}

if (i > LUNG_MAX ) // se esco dalla lunghezza massima della stringa o se ho letto il terminatore faccio il controllo sul CRC e azzero le variabili del ciclo
{
sscanf ( str , “%d\t%d\t%d” , &ax, &ay, &CRC_A); //trasformo la stringa
itoa ( ax+ay, buff, 16); //trasformo il valore in esaASCII per fare il calcolo del CRC
crcInit(); //crea tabella per velocizzare il calcolo del CRC
// printf(" The crcFast() of %i is 0x%X, 0x%X\n", ax+ay, CRC_A, crcFast( buff, strlen(buff) ) ); //stampo a video il valore di interesse il CRC lato arduino e il CRC lato PC

/* faccio il controllo sul CRC confrontando quello calcolato sul PC con quello inviato da Arduino, salvo tutto in ogni caso ma metto ok se è corretto e NO se la stringa non è corretta */
// if( crcFast ( buff, strlen(buff)) == CRC_A ) fprintf ( stream, “ciclo = %2i|| OK ||x = %2i ||y = %2i ||somma = %2i ||CRC_arduino = 0x%i ||CRC_calc = 0x%X%\n”, ho, ax, ay, ax+ay, CRC_A, crcFast( buff, strlen(buff) ) );
// else
// {
// fprintf( stream, “ciclo = %2i|| NO ||x = %i ||y = %2i ||somma = %2i ||CRC_arduino = 0x%X ||CRC_calc = 0x%X%\n”, ho, ax, ay, ax+ay, CRC_A, crcFast(buff, strlen(buff) ) );
// yu = 0; // se la stringa non è corretta non devo uscire dal ciclo do quindi ricambio il valore di yu
// }

/* azzero le variabili che uso per la memorizzazione*/
rec = 0;
str [ 0 ] = ‘\0’;
i = 0;
j = 0;
}

/* se non ho beccato l’inizio di scrittura per più di 200 cicli do qualcosa non va provo a spegnere e riaccendere la COM, mi sa ma non va molto bene*/
if (j > 200)
{
fprintf( stream, “ciclo = %i ho perso contatto \n”, j );
CloseHandle ( hComm ); //chiudo la seriale
hComm = CreateFile( gszPort,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0, // NO ! FILE_FLAG_OVERLAPPED,
0);

rec = 0;
str [ 0 ] = ‘\0’;
i = 0;
j = 0;
}
} while( yu == 0 );// se yu è diverso da 0 esco dal ciclo id lettura dalla seriale perchè ho memorizzato in stringa il valore di x e y
}
fclose ( stream ); //chiudo il file
CloseHandle( hComm ); //chiudo la seriale
}
getch();
return 0;
}

/*

programma che ha in ingresso : somma—> valoro intero di cui voglio fare il CRC
mi manda in uscita il CRC
Cosa fa: converto il valore somma in un numero esadecimale in formato ASCII con la funzione itoAsciiEx
itoAsciiEx mi converte il valore di somma che viene memorizzato nella variabile hexa di typo byte e in più mi restituisce la lunghezza di hexa
hexa viene inviato alla funzione crc_1021 che mi restituiscwe il CRC.
Da notare che la stringa che contiene il numero in esadecimale è lunga al massimo 4(uno spazio è riservato a \0)

*/

char CheckSumC[5];
int somma=2300;
unsigned mC=0;

int ritardo = 10; // [ms] invece che definire la frequenza
int t_assest = 5; // [ms] tempo di assestamento ciruito RC

int Xp = 10; // pin X+
int Xn = 14; // pin X-
int Yp = 11; // pin Y+
int Yn = 15; // pin Y-

int ADC_X = 0;
int ADC_Y = 1;

int cella_1 = 3;
int cella_2 = 4;
int cella_3 = 5;

int Vx;
int Vy;

int Vf1;
int Vf2;
int Vf3;

int GetCRC(char crcCheckSumC[5])
{
// Common register
int aLen =0; // Length of the array that contains the base array
// End common register

// Register for the convert function from String HEX value to ascii
byte hexa[5];
int i =0; // Master index
// End of register for the convert function from String HEX value to ascii

// Register for the checksum convert the value to string
char strConvBuffer[40]; // Temporary buffer
long int crcCheckSumD; // Crc checksum that contain the decimal value of the checksum
int d =0;
unsigned short crcBuffer =0; // Temporary buffer for the checksum calc
String crcCheckSumS; // String that contain the HEX value of the checksum and is convertet to upper case
// End register for the checksum convert the value to string

aLen= itoAsciiEx(somma,hexa);
for (i=0; i < aLen; i++) // Convert function from String HEX value to ascii
{
// Serial.println(hexa*);*

  • }*

  • crcCheckSumD =crc_1021(crcBuffer,hexa, aLen); // Calc the crc checksum and convert the value to string and upper case*

  • //Serial.print(crcCheckSumD);*

  • // Serial.println(“bbbbbbbbbbbbb”);*

  • itoa (crcCheckSumD,strConvBuffer,16);*

  • for (d = 0; d < 4; d++)*

  • {*

  • crcCheckSumC[d] = strConvBuffer[d];*

  • crcCheckSumS = strConvBuffer;*

  • crcCheckSumS = crcCheckSumS.toUpperCase();*

  • crcCheckSumC[d] = crcCheckSumS[d];*

  • }*

  • return crcCheckSumD;*
    }
    unsigned short crc_1021(unsigned short crc, unsigned char const *buffer, int len)
    {

  • unsigned short cmpt;*

  • //For all char*

  • while (len–) {*
    _ crc = crc ^ *buffer++ << 8;_

  • //For All bit*

  • for (cmpt = 0; cmpt < 8; cmpt++) {*

  • if (crc & 0x8000)*

  • crc = crc << 1 ^ 0x1021;*

  • else*

  • crc = crc << 1;*

  • } //End bit*

  • } //Frame end*

  • return crc;*
    }
    //
    // controller touch screen resistivo a 4 fili, letture x, y , F1, F2, F3, senza opzione stand-by
    *void setup() *
    {

  • Serial.begin(19200);*
    }
    *void loop() *
    {

  • // step 1: alimento le X e leggo la Y*

  • pinMode(Yp, INPUT); // Hi-Z*

  • pinMode(Yn, INPUT); *

  • pinMode(Xp, OUTPUT); // inizializzazione alimentazione*

  • pinMode(Xn, OUTPUT);*

  • digitalWrite(Xp, LOW); // alimentazione*

  • digitalWrite(Xn, HIGH); *

  • delay(t_assest); // [ms] delay per rispettare il tempo di assestamento*

  • Vy = analogRead(ADC_Y); // lettura valore X*

  • //delay(ritardo);*

  • // step 2: alimento le Y e leggo la X*

  • pinMode(Xp, INPUT); // Hi-Z*

  • pinMode(Xn, INPUT); *

  • pinMode(Yp, OUTPUT); // inizializzazione alimentazione*

  • pinMode(Yn, OUTPUT);*

  • digitalWrite(Yp, LOW); // alimentazione*

  • digitalWrite(Yn, HIGH); *

  • delay(t_assest); // [ms] delay per rispettare il tempo di assestamento*

  • Vx = analogRead(ADC_X); // lettura valore Y*

  • somma = Vx + Vy;*

  • mC = GetCRC(CheckSumC);*

  • Serial.print("|");*

  • Serial.print(Vy);*

  • Serial.print("\t");*

  • Serial.print(Vx);*

  • Serial.print("\t");*

  • Serial.print(mC);*

  • Serial.print("<");*
    // Serial.println();

  • delay(ritardo);*
    }
    int itoAsciiEx(int val, byte *hexa)
    {

  • int n = 0;*

  • char stringa [5];*

  • itoa(val, stringa,16);*

  • while( stringa[n] != ‘\0’ )*

  • {*

  • hexa[n] = (byte)stringa[n];*

  • n++; *

  • }*

  • return n–;*
    }[/quote]