communication et synchro pc en C et arduino ?

bonjour à tous.

je découvre arduino avec grand plaisir, mais je rencontre quelques petits soucis quand à la partie communication série Arduino > l' api que je développe.

Cette dernière comprend beaucoup de routines, et notamment des procédures exécutées avec des timers ( 50° et 1/10° de sec).
Elle intègre déjà les drivers FTDI, car elle utilise des interfaces sur base FTDI.

J'utilise la classe CSerial pour récupérer les infos: http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c2503

Je n'ai aucun background sur la communication série, et du coup peut etre que je rate quelque chose:

-j'écoutes arduino sur port com en usb et suis sous windows
-je reçois les données d'arduino, mais les chaines semblent tronquées aléatoirement ( mes autres processus en cours ?)
-la routine d'écoute du port série est faite toutes les 50ème de secondes
-du coup je me demande si la communication en port com doit etre absolument continue ?

voilà, besoin d un avis éclairé et de vos conseils pour cerner la bete.
:smiley:

Si ta vitesse du port série est trop élevée, il peut y avoir trop d'octets dans le buffer donc tu n'as qu'une partie, car 20 ms c'est très long pour un microcontrôleur à 16 MHz.

  • Lis la datasheet pour savoir la taille du buffer
  • Compte combien de temps il faut pour remplir ce buffer
  • Fais des essais sans rien d'autre en plus
  • Utilise un outil comme Docklight pour vérifier ce qui passe sur la liaison

Je pense pouvoir peut-être aider sur ce coup : je développe en VB.NET mais j'ai eu ce problème. Je l'ai corrigé en utilisant la commande (en vb.net donc) mySerial.ReadLine(). En fait plutôt que de lire le buffer tu attends le signe de retour à la ligne, donc sur ton programme arduino il faut envoyer en Serial.println("...").

J'ai tout essayé rien ne marchait et maintenant ça marche nickel maintenant !!

Attention cependant : il faut aussi configurer le caractère de retour à la ligne avec mySerial.NewLine = Chr(13) + Chr(10)

bonjour B@tto.
merci de ta réponse, j utilise déjà println.
je suppose qu il vaudrait mieux envoyer d un seul coup ma chaine de données ( actuellement 13 dig ou 6 analo si changement d etat)
je voulais passer par les fonctions de concaténation mais String et les libs String.h et WString ne sont pas présentes dans Arduino 018. :frowning:

j ai une question bateau :
si j envoies un mot clé de mon app vers le COM, et que j attends directement la réponse en retour d arduino juste après le lancement est ce que ca fonctionne ?

ou bien passes tu par une fonction stockant les données entrantes dans un buffer à part, en tampon ?

@luj06: as tu un lien vers le datasheet ?

La lib Serial définit un buffer de 128 caractères ce qui est assez conséquent.

Si tu as peur d'avoir un débordement le mieux c'est d'utiliser dans ton appli la méthode available() qui indique la présence de caractères dans le buffer, de construire ta propre chaine et d'attendre l'indicateur de fin.
L'arduino ne disposant pas de beaucoup de mémoire le plus judicieux c'est d'interpréter la chaine au vol et de ne stocker que l'essentiel.

bonjour fdufnews.
au vol... ok donc je ne me plante a priori pas.

concernant libserial j ai essayé de l intégrer. je suis sous windows / compilo Mingw32 avec gcc3.4. Je n ai pas réussi à l intégrer, des include manquants et surtout des definitions manquantes, qui doivent servir sous Linux, mais ne fonctionnent pas avec mon compilo.
c est pour ca que je me suis retourné vers Cserial... du coup va falloir que je réecrives la roue :frowning:

à ton avis, concernant les infos, qu y a t il de plus judicieux: envoyer un mot clé avec le controle ( IO ou analog ) et sa valeur ( cad un println à chaque changement) , ou envoyer
une chaine de BYTES comprenant l etat de tous les capteurs ?

merci de ta réponse, j utilise déjà println.

Oui mais le soucis venait pas de l'arduino chez moi, mais du PC :wink:

Je n'ai pas d'explication logique à fournir, sur le terminal serial de l'API arduino ça fonctionne normalement, sur mon prog les valeurs (en print ou println) étaient tronquées souvent. J'avais beau mettre des delay partout (arduino et/ou PC), rien n'y faisait ...

ok.
j arrive à avoir quelque chose de plus stable et de moins tronqué en me limitant à une communication d'informations solos depuis arduino.
je suis conscient que c est du BA BA mais là je coince:
il m arrive de temps en temps de perdre une donnée ( je fais des tests avec les digital et parfois je n ai pas le relachement du bouton). La chose se produit dès que la chaine recue est tronquee. Celle ci au lieu d etre DIG/2=0/ par ex. peut etre IG/2=0/ ou encore 2=0/...

processus de mon application (cote PC):
-j'appelle ma lecture du port serie directement dans ma boucle principale, pas de timers.
-lecture du port serie si il est initialisé
-envoi de 5 bytes vers arduino pour déclencher l'envoi d une reponse par ce dernier, contenant l'état si modification entre le buffer précédent et l actuel
-lecture du port serie, si le nombre de bits sur ce dernier est >0 décryptage
-décryptage : sscanf(tmp_str,"DIG/%d=%d/\n",&num_dig,&val_dig);
(le \n est le caractere de retout et normalement je ne lis que le signal si il est complet : DIG/numdig=valeur/retourchariot
-puis report des valeurs dans le tableau qui y correspond
-nettoyage de la chaine de caracteres dans laquelle on ecrit les donnes recues en port serie

ici le code arduino:
:stuck_out_tongue:

//definitions du hardware en termes de nombre d'entrées
const int NBR_ANALOG=6;
const int NBR_DIGITAL=11;//(13-2 les premieres pins associées au tx rx en serial)

//création d'un tableau de définition pour les I/O 
bool digital_is_output[NBR_DIGITAL];

//tableaux de stockage des valeurs reçues en input
int buffer_analog[NBR_ANALOG];
int old_buffer_analog[NBR_ANALOG];
bool buffer_digital[NBR_DIGITAL];
bool old_buffer_digital[NBR_DIGITAL];

/////////////////////////////////////////////////////////////////
void aquire_arduino()
{
//digitales///////////////////
for(int i=2;i<NBR_DIGITAL+2;i++)//on zappe les états de TX RX
{
//si le digital est une entrée et pas les leds tx rx on lit et on stocke
if(digital_is_output[i]==0 )
  {
    old_buffer_digital[i]=buffer_digital[i];
    buffer_digital[i]= digitalRead(i);
    if(old_buffer_digital[i]!=buffer_digital[i])
    {
     Serial.print("DIG/");
     Serial.print(i); 
     Serial.print("="); 
     Serial.print(buffer_digital[i]);
     Serial.print("/");
     Serial.println("");
    }
  }
 }
}

/////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600);

//votre définition des pins à mettre en OUTPUT
digital_is_output[9]=1;
digital_is_output[10]=1;
digital_is_output[11]=1;

//INITIALISATION DES ON/OFF
for(int i=2; i<NBR_DIGITAL+2; i++)//on zappe les états de TX RX
{
if(digital_is_output[i]==1){pinMode(i,OUTPUT);}
else {pinMode(i,INPUT);}
}
}
/////////////////////////////////////////////////////////////////
void loop()
{
if (Serial.available() > 0) 
{
    aquire_arduino();
}
}

EDIT:
bon. j ai mis ma fonction lisant le port serie dans un timer, histoire de faire quelques essais. Même avec une lecture tous les 20ms, j ai ce tronquage de chaine de caracteres. et la perte du relachement ou de l'appui ou du relachement du bouton si je suis trop rapide dans mon mouvement.

EDIT 2:
@B@tto:
si dans mon code sur mon api, j'analyse la string danslaquelle jje recois les donnees de arduino et j attends un caractere de fin de ligne pour analyser, j ai moins de cas de chaines tronquées ( nettement moins), mais je continue à perdre encore un peu le relachement ou l appui d un bouton, et ce toujours sur réception de chaine tronquée. Me tromperais je dans le code arduino ?
any idea ? :frowning:

ok, tous mes soucis se sont réglés ! merci à tous.
Il y a certainement plus élégant, et je suis preneur de vos suggestions ! ;D

pour les prochains, voilà ce que j ai fais, mais c est pas forcemment le pérou:

Dans mon application PC, en utilisant la lib CSerial http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c2503

-ouverture du port

-dans un timer au 20eme de seconde ( pas plus rapide, sinon on a RE des soucis de tronquage de chaine (due à la vitesse d'Arduino ? pas trouvé de specs sur les cadences) ) la procedure de lecture:

-envoi d'un BYTE vers Arduino, avec une valeur précise arbitraire : 100

arduino voit que c est la bonne valeur, et scanne les ports et renvoi l info sous la forme d'une chaine avec 1 info:
DIG/4=1/
-lecture de la chaine recue sur le port série avec ReadData
-scan de la chaine jusqu à découverte d un caractere de type retour de ligne ( == '\0' )
-quand on trouve ce caractere: décodage avec sscanf
-report dans mon tableau
-envoi d'un byte vers arduino avec une valeur autre que 100 pour lui dire d'arreter d'émettre >> Arduino arrete d emettre car la condition a changé

dans arduino:

void loop()
{
if(Serial.available()>0)
{
inByte=Serial.read();
if(inByte==100)//valeur définie pour lire le data et renvoyer l info
{
aquire_data_and_send();
}
} 
}