Pages: [1] 2 3 4   Go Down
Author Topic: lire des valeurs sur Arduino en c / c++  (Read 6350 times)
0 Members and 1 Guest are viewing this topic.
Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Je cherchais un moyen de lire des valeurs sur l'Arduino avec mon Mac depuis quelques temps...

En furetant sur le net j'ai trouvé ça :

How to talk to the USB Arduino board with your  C++ Code and Xcode  (Comment communiquer via USB avec Aduino en C++ et avec Xcode)


Le problème c'est que ce code montre bien comment envoyer des données à l'Arduino, mais pas comment les lire.


Ensuite j'ai trouvé ça :

Création d'une centrale interactive de capteurs

Projet dans lequel j'ai récupéré un bout de code pour modifier le premier.

Ce qui donne :

Code:
#include <iostream>
#include <stdio.h>
#include <fcntl.h>  
#include <termios.h>
#include <unistd.h> //write(), read()

using namespace std;



int fd;


/******************************************************************************************************************
      Setting the serial port up to talk to the Arduino board
******************************************************************************************************************/
void init_port(int *fd, unsigned int baud)
{
    struct termios options;
    tcgetattr(*fd,&options);
    switch(baud)
    {
       case 9600: cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
break;
       case 19200: cfsetispeed(&options,B19200);
cfsetospeed(&options,B19200);
break;
       case 38400: cfsetispeed(&options,B38400);
cfsetospeed(&options,B38400);
break;
  default:cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
break;
    }
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    tcsetattr(*fd,TCSANOW,&options);
}

/******************************************************************************************************************
      Main Function
******************************************************************************************************************/
int main()
{
      char USBPort[1000];
      
      cout << "what USB port is your Arduino Board pluged into?" << endl;
      cout << "Example:\n/dev/tty.usbserial-A70041zl\nor\n/dev/tty.usbserial-A1001N2Y" << endl;
      cin >> USBPort;
      
      fd = open(USBPort, O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd == -1)
      perror("open_port: unable to open port");
      
      init_port(&fd,9600);         //set serial port to 9600,8,n,1
      
      
    
      fcntl(fd, F_SETFL, 0);

      char readport();


      int Temp,Temp1,Temp2 = 0;
      
      char table[5]={0};
      
      read(fd,&Val,5);

      cout<<Val<< endl;
      cout<<Val[2]<<Val[3]<<Val[4]<< endl;
      cout<<Val[0]<<Val[1]<<endl;
      
      Temp1 = Val[2]-'0';       // convert ASCII
      Temp2 = Val[3]-'0';       // to
      Temp3 = Val[4]-'0';       //decimal
      
      Temp = Temp1*100 + Temp2*10 + Temp3 ;      


      cout<<endl<<Temp<<endl;

      close (fd)     //close USBPort
      
      return 0;
      
      
 
}





Ainsi cela me permet de lire des données en ASCII envoyée par l'Arduino par ce code :

Code:
int Test1 = 0;

void setup()
{

  Serial.begin(9600);
}

void loop () {

Temp1 =123;
Serial.print("ok");
Serial.println(Test1);
 
}


Et voilà ce qui sort à la console :

Code:
[Session started at 2008-03-21 19:49:38 +0100.]
what USB port is your Arduino Board pluged into?
Example:
/dev/tty.usbserial-A70041zl
or
/dev/tty.usbserial-A1001N2Y
/dev/tty.usbserial-A1001N2Y
ok123
123
ok

Executable “digit” has exited with status 123.


C'est peut-être rudimentaire, mais comme je ne connais pas le langage C (je commence à apprendre  smiley), c'est un grand pas pour moi.
« Last Edit: March 22, 2008, 05:00:06 am by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

J'ai un peu modifié mes codes sur l'Arduino :

Code:
int CaptPin05 = 5;

void setup()
{
pinMode(CaptPin05,INPUT);
  Serial.begin(9600);
}


void loop ()
{
Serial.print("ok");
Serial.println(analogRead(CaptPin05));
 
}


J'utilise un capteur de luminosité sur un pin analogique, donc je devrais avoir une valeur comprise entre 0 et 1023
à lire.

J'ai deux problèmes, le premier est que la lecture n'est pas régulière et de temps en temps un chiffre manque ou alors c'est une lettre du "ok" qui sort et je ne comprend pas pourquoi.

Le deuxième problème est qu'avec la méthode que j'ai utilisé pour convertir mes "lectures" d'Ascii à Décimal, lorsque je dois afficher des valeurs en dessous du millier, la valeur s'affiche, mais elle est suivie d'un ou plusieurs chiffres incohérent et je n'arrive pas à résoudre cela.
Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut,

a mon avis, ton probleme vient du fait que ton soft sur PC lit 5 caraecters puis s'arrete (je ne me trompe pas ? )
sauf que l'arduino, elle, crache en continue des choses sur son port série. si je regarde le code arduino, ca devrait ecrire :
'ok' suivi d'une valeur entre 0 et 1023, suivi d'un retour chariot.

une valeur entre 0 et 1023, ca correspond a 1, 2 3 ou 4 caracteres...

donc il faut que tu lises ton port serie juqu'a recevoir un retour chariot.

Ensuite, il y a des buffers sur la liaison serie, donc si tu lis systematiquement 5 caracteres, ben tu va avoir
un premier message plus le debut du suivant, puis a la lecture suivante, tu auras la fin du second message et le debut du 3eme, etc...
tous tes soucis viennent du fait que tu lis 5 caracteres, et non pas caracteres par caracteres en regardant si c'est le carac lu est le dernier d'un message...








Logged

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

OK Pascal, merci pour la réponse.


Donc si j'ai bien compris je suis obligé de lire le flux caractère par caractère jusqu'à trouver un \n ou \r ?

Est ce qu'en utilisant un fgets() à la place de read() cela marcherait, normalement le fgets devrait lire mon string en entier et s'arrêter à \n ?
Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

oui en theorie fgets doit suffire je pense...
« Last Edit: April 10, 2008, 01:41:58 pm by Skall » Logged

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

J'ai fait des essais avec fgets, mais ça ne renvoit aucune valeurs du flux.
La communication avec l'arduino n'est même pas amorcée, les leds Rx/Tx restent éteintes.

Voici la façon dont j'essaye de l'utiliser :
Code:
     

      fd = open(USBPort, O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd == -1)
      perror("open_port: unable to open port");

      init_port(&fd,9600);         //set serial port to 9600,8,n,1
      
    
      fcntl(fd, F_SETFL, 8);
      


      char readport();

      
      
      
      char table[100]={0};
            
      
      
      char fgets(table,99,fd);


      
« Last Edit: April 10, 2008, 03:19:46 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

pourquoi tu passes 8 comme argument a ton fcntl ?

autre chose : tu n'as pas besoin de mettre char readport();,
readport(); suffit, pareil pour le fgets...
fgets(able,99,fd); suffit.

« Last Edit: April 11, 2008, 04:55:45 am by Skall » Logged

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Je devrais mettre quoi pour F_SETFL ?


Si je ne mets pas les char ça plante , si j'ai de la chance ça me sort de l'application, autrement je suis obligé d'éteindre mon ordi de façon barbare... et j'ai la même chose lorsque la communication avec l'arduino est coupée au milieu d'un flux, je suis planté... planté.
Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

J'ai repris mes codes et j'ai essayé de rendre plus propre celui en C, j'ai rajouté une partie pour commencer la lecture et pour l'arrêter à la fin du string.
J'ai rajouté une ouverture de fenêtre (merci le site du zéro) pour avoir les valeurs imprimées dessus en parallèle à la console.
Le problème de la position des milliers, centaines et dizaines est traité directement sur l'arduino en ajoutant des "0" suivant l'échelle dans laquelle on se trouve, la lecture est ainsi stabilisée.
J'ai rajouter une fonction qui me permet de détecter le(s) port(s) USB utilisé(s), cela s'affiche dans la console.
L'application est toujours démarrée depuis la console.


Le main sur mon mac (Xcode) :

Code:
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL_ttf/SDL_ttf.h>



#include <fcntl.h>
#include <termios.h>  
//#include <memory.h>
#include <unistd.h> //write(), read()

using namespace std;

void Output();          // pour envoyer à l'arduino
void readport();        // pour recevoir de l'arduino
void init_port();       //initialise le portUSB
void Ouverture_port();  //ouvre le portUSB


char USBPort[1000];                  // pour le nom du portUSB
char temps[20] = "";            //pour déterminer le temps
char Temperature [5]={0};      //pour la valeur écrite dans la fenêtre
char table[7]={0};                  //pour les valeurs en sortie d'arduino

int fd = 0;
int continuer = 1;
long Temp,Temp1,Temp2,Temp3 ,Temp4,Temp5  = 0;




int main(int argc, char *argv[])
{
      /******************************************
      détection du port usb
      *******************************************/
      FILE* myPipe=NULL;
      char buffer[1000];
      myPipe = popen("ls /dev/tty.usbserial*", "r");
      if(myPipe==NULL){
            //errorstuff
      }
      while(fgets(buffer, 1000, myPipe)!=NULL){
            (void) printf("\n\nvotre usb est : %s \n", buffer);
      }      
      
      
      pclose(myPipe);
      
      /*******************************************
      fin de détection
      ********************************************/
                  

      
      cout << "what USB port is your Arduino Board pluged into?" << endl;
      cout << "Example:\n/dev/tty.usbserial-A70041zl\nor\n/dev/tty.usbserial-A1001N2Y" << endl;      
      
      cin >> USBPort;

      

    SDL_Surface *ecran = NULL, *texte = NULL;
    SDL_Rect position;
    SDL_Event event;
    TTF_Font *police = NULL;
    SDL_Color couleurNoire = {0, 0, 0}, couleurBlanche = {255, 255, 255};


    SDL_Init(SDL_INIT_VIDEO);
    TTF_Init();

    ecran = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
    SDL_WM_SetCaption("Mesure de luminosité", NULL);


    police = TTF_OpenFont("angelina.ttf", 65);

    tempsActuel = SDL_GetTicks();



    while (continuer)
            {
        SDL_PollEvent(&event);
        switch(event.type)
        {
            case SDL_QUIT:
                continuer = 0;
                        close(fd);
                break;
        }

        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));

            
      Ouverture_port();
      Output();
      readport();
      close(fd);
            

                  sprintf(Temperature, "%ld%ld%ld%ld", Temp1, Temp2, Temp3, Temp4);      
      
      cout<<table[0]<<table[1]<<Temperature<<endl;
            
            sprintf(temps, "Temp : %s", Temperature);
            SDL_FreeSurface(texte);
            texte = TTF_RenderText_Shaded(police, temps, couleurNoire, couleurBlanche);
          

        position.x = 180;
        position.y = 210;
        SDL_BlitSurface(texte, NULL, ecran, &position); /* Blit du texte contenant le temps */
        SDL_Flip(ecran);

            }
      
      
      
            TTF_CloseFont(police);
            TTF_Quit();

            SDL_FreeSurface(texte);
            SDL_Quit();


    return EXIT_SUCCESS;
      }




Les fonctions :

Code:
void init_port(int *fd, unsigned int baud)
      {
    struct termios options;
    tcgetattr(*fd,&options);
    switch(baud)
    {
       case 9600: cfsetispeed(&options,B9600);
      cfsetospeed(&options,B9600);
      break;
       case 19200: cfsetispeed(&options,B19200);
      cfsetospeed(&options,B19200);
      break;
       case 38400: cfsetispeed(&options,B38400);
      cfsetospeed(&options,B38400);
      break;
      default:cfsetispeed(&options,B9600);
      cfsetospeed(&options,B9600);
      break;
    }
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    tcsetattr(*fd,TCSANOW,&options);
      }
      
      
void Ouverture_port()
            {
            fd = open(USBPort, O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd == -1)
      perror("open_port: unable to open port");

      init_port(&fd,9600);         //set serial port to 9600,8,n,1
      fcntl(fd, F_SETFL,3);
      }


void Output()
      {
      
      write(fd,"&",1);
      }
            
      
void readport()
      {
      char table[7]={0};
      {      
      while(table[6]!='$')
      {
      read(fd,&table,sizeof(table));
      
      Temp1 = table[2]-'0';
      Temp2 = table[3]-'0';
      Temp3 = table[4]-'0';
      Temp4 = table[5]-'0';

      }
      }

      }


      
      
      



Ainsi j'obtiens un renouvellement de l'affichage des mesures environ toutes les secondes.

J'aimerais savoir si c'est possible de rendre cela plus rapide ?
« Last Edit: April 14, 2008, 06:31:34 am by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Le .pde sur l'Arduino

Code:
int CaptPin05 = 5;
//int Temp1 = 0;
char incoming = 0;
void setup()
{
pinMode(CaptPin05,INPUT);
  Serial.begin(9600);
}



void loop () {
//Temp1 = analogRead(CaptPin05);

//Temp1 =123;

incoming=Serial.read();
if (incoming = '&')
{
Serial.print("ok");
//Serial.print("yes");
/* mise à niveau des chiffres */
if(analogRead(CaptPin05)<1000)
{
  Serial.print("0");
}
if(analogRead(CaptPin05)<100)
{
  Serial.print("0");
}
if(analogRead(CaptPin05)<10)
{
  Serial.print("0");
}
/* fin de mise à niveau */

Serial.print(analogRead(CaptPin05));
Serial.print("$");
incoming = 0 ;
}
}



Ainsi j'obtiens un renouvellement de l'affichage des mesures environ toutes les secondes.

J'aimerais savoir si c'est possible de rendre cela plus rapide ?
« Last Edit: April 13, 2008, 12:21:46 pm by jfs » Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

oui, ca peut etre plus rapide,

Tout d'abord, tu peux augmenter la vitesse de ton port serie. Moi, je tourne en 19200.

Mais ca peut surtout etre plus efficace :

Perso, j'ai ajouté une condition  : je ne remonte la valeur au PC que si elle a changé.
Tu peux meme introduire une notion de seuil : ne remonter la valeur qui si elle a change de plus de XX%..
mais la, ca depend de ce que tu veux faire...
Logged

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci pour ces réponses, je vais tester ça...
Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Après essais ça ne change rien à la vitesse d'affichage des mesures.

Je pense que c'est le fait d'ouvrir et fermer le port usb à chaque boucle qui ralenti le tout.

Si je déplace la fonction d'ouverture et celle de fermeture ça plante.
Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geneva
Offline Offline
Faraday Member
**
Karma: 30
Posts: 3230
Yoplait... le pt'it suisse
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

En mettant la lecture du port dans un thread et l'affichage dans le main, je peux ouvrir le port en début d'application et le fermer à la fin de l'application.
Sans l'affichage graphique (affiché dans la console) la fréquence de mesure est de 130 par seconde, cette fréquence tombe à 50 par seconde avec l'affichage dans une fenêtre graphique.

Logged

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

la, ca devient un probleme de programmation mac...  :-X

tu dois surement avoir un mecanisme de synchro entre ta thread de lecture de l'arduino, et la partie graphique qui fait que ca ralentit... (mutexs, sections critique ou autre).
si tu veux plus de vitesse, va falloir que tu t'embringues dans des traitements asynchrones, et je te souhaite bien du plaisir....

tu as vraiment besoin de lire si vite ?
et si tu ne remontes la valeur que si elle change, ca ne resoud pas ton probleme ?

au fait, c'est quoi le but final de ton projet ? (si c'est pas indiscret)

bonne chance.
Logged

Pages: [1] 2 3 4   Go Up
Jump to: