Go Down

Topic: Problèmes de convertion (Read 2763 times) previous topic - next topic

fixair

Alors voila, je me suis lancé dans un projet, mais je ne maitrise pas le code Arduino. J'ai cherché mais je ne comprends pas.
Je reçois a l'entrée du port com de ma Uno des données sous la forme :
               "A10" ou "B25" ou "T1750" mais aussi "w-1000" et "s110"
il s'agit là de string, mon problème est de supprimer la lettre et de convertir le reste de la chaine en un entier (int).

Une fois converti en int, ces datas servirons a animer des servos et des moteurs pas à pas. Je souhaite utiliser la version 1.0.1 du logiciel d'Arduino. Le soft qui alimente le port com de la Uno est en c#.

Merci par avance.
FX ;op

Cordialement
@+ FX ;op

Super_Cinci

Si tu peux intervenir sur le soft émetteur, je te conseille d'abandonner les string, et d'envoyer des octets contenant directement les valeurs numériques et ou des codes. Regarde dans ce cas le tuto qu'à fait barbudor sur les protocoles série...

Le port série (que ce soit arduino ou PC) est trop souvent orienté texte, alors qu'il peut envoyer des octets purs et durs contenant chacun une valeur de 0 à 255... Pour info, envoyer la valeur 255 ne prend qu'un octet (8 bits), alors que la chaîne "255" en prend au moins 3, 5 si le caractère de fin de chaîne est inclus. je n'utilise le port série qu'avec des octets, et c'est bien plus rapide. l'arduino se limite très vite avec des chaines de caractères...

fixair

Merci pour ta réponse je vais regarder de ce côté.
Sinon est il possible de transmettre directement des datasheet sous forme integer ?
Ceci a titre d'infos ;op
FX
Cordialement
@+ FX ;op

Super_Cinci


Merci pour ta réponse je vais regarder de ce côté.
Sinon est il possible de transmettre directement des datasheet sous forme integer ?
Ceci a titre d'infos ;op
FX
Tu parles d'un fichier PDF de plusieurs Ko voire Mo? bien sûr que c'est possible, c'est même comme ça que marche le partage de fichier par port série entre PC (du temps où les cartes réseaux n'étaient pas accessibles à tous les portemonnaies...). le port série, à la base, sert à envoyer un octet de 8 bits de l'émetteur au récepteur. Mais tout de suite, les mecs, ils ont orienté ça en texte, mais un caractère reste un code sur 7 ou 8 bits, une valeur de 0 à 255 quoi!  XD ...

fixair

Oup's  :smiley-roll: j'ai glissé : non !!! maudit iphone qui corrige les mots sans le dire et que l'on ne pense pas a verifier (bref c'est pas la faute du tel ... lol  )
Bon il fallait lire datas  et non datasheets...

Pour info, mon projet c'est un simulateur hélico en double commandes avec les instruments réels re motorisés, mais si je me debrouille en mécanik et autre fer a souder, je suis un peu ,  beaucoup une quiche en programmation( il est loin le bon temps du basic sur ZX81... ;op )

Pour finir mes données sont donc des paramètres de vol : vitesse, altitude, vario, etc
D'ailleurs vous m'avez aiguillé sur le tuto magik de barbudor mais comment on extrait  le A dans "A1250" qui me sert d'index pour faire bouger le bon moteur ou servo ? A moins qu'il y ai une autre solution, j'ai d'ailleurs penser a transmettre un bloc complet de paramètre genre : AltiVitesseCapVz 2500110095-500 (2500 pieds ,110kt , 095°et -500 pieds/min) le hic c'est comment dispatcher les données au bon endroit sachant que ça peu être -2000 ft/min donc un zéro de plus. Ca me chiffonne le neurone...
Je sais suis un peu givré mais quand on aime et/ou on rêve...

Merci encore pour votre aide
FX
Cordialement
@+ FX ;op

fixair

#5
Aug 19, 2012, 02:15 pm Last Edit: Aug 19, 2012, 02:20 pm by fixair Reason: 1
Alors, pour vous permettre de voir un peu l'histoire voici quelques liens et autres bouts de code :





Le code si dessous fonctionne pour partie, quand je n'ai que 2 servos, c'est a peu près fluide, mais quand j'ajoute un moteur pap, c'est beaucoup moins fluide, voir même pas du tout genre 4 ou 5 fps.
Je rencontre aussi des problème de saturation de buffer, du moins je pense.
J'ai par ailleurs commencé la lecture du tuto cité plus, merci a son auteur (encore des mals de cranes en perspective mais ça vaut le coup...)

Voila, bienvenue dans l'univers d'un taré de l'aéro qui ne peu pas voler alors il mixe pc et hélico ;op
@++ FX ;op

Quote

#include <Servo.h> //Add's the servo library
Servo pitch; // Names the servo
Servo roll;
int j1; // Variable used by serial.read
String Pitchsp, Pitchold; // variables used for Pitch
String Rollsp, Rollold; // variables used for Roll

void setup() // the set up loop
{
 pitch.attach(8) ; // attaches the servo
 roll.attach(9); // attaches the servo
 Serial.begin(115200); // sets up the serial port
}

void loop() // the main loop where it all happens
{
  if (Serial.available() > 0) { // read the oldest byte in the serial buffer:
   j1 = Serial.read(); // Read a serial byte
   if (j1 == 'A'){ // Found the reading "Pitch"
             delay (11); // It seems to need a delay here
             Pitchsp = char(Serial.read()); // first digit of the data
             Pitchsp += char(Serial.read()); // Second digit and so-on
             Pitchsp += char(Serial.read());
             Pitchsp += char(Serial.read());
             Pitchsp += char(Serial.read());
             Pitchsp += char(Serial.read());
             if (Pitchsp != Pitchold){ // checks to see if its different to the "old" reading
                char carray[6]; //converting a string to number sequence
                Pitchsp.toCharArray(carray, sizeof(carray)); //converting string to number sequence
                int n = atoi(carray); //converting string to number sequence
              //  n= n * 10;                   //Makes the reading more "sensitive"
                if (n <= -25) n = -25 ;  if (n >= 25) n = 25; // Servo protec
                n = map(n, -90, 90, 2, 178); //Maps the readings to the servo
                pitch.write(n); //Sends the data to servo
                delay (11); // Probably not neccesary
                Pitchold = Pitchsp;// Writes the current reading to the "old" string.
                   }      // end of it's a different reading section
                  }      // end of "found A" section
                 
   if (j1 == 'B'){ // Found the reading "Roll"
             delay (11); // It seems to need a delay here
             Rollsp = char(Serial.read()); // first digit of the data
             Rollsp += char(Serial.read()); // Second digit and so-on
             Rollsp += char(Serial.read());
             Rollsp += char(Serial.read());
             Rollsp += char(Serial.read());
             Rollsp += char(Serial.read());
             if (Rollsp != Rollold){ // checks to see if its different to the "old" reading
                char carray[6]; //converting a string to number sequence
                Rollsp.toCharArray(carray, sizeof(carray)); //converting string to number sequence
                int n = atoi(carray); //converting string to number sequence
              //  n= n * 10;                   //Makes the reading more "sensitive"
                if (n <= -80) n = -80 ;  if (n >= 80) n = 80; // Servo protec
                n = map(n, -90, 90, 2, 178); //Maps the readings to the servo
                roll.write(n); //Sends the data to servo
                delay (11); // Probably not neccesary
                Rollold = Rollsp;          // Writes the current reading to the "old" string.
                  }     // end of "found B" section      
                  }
           }
}

             
             

Cordialement
@+ FX ;op

Super_Cinci


A moins qu'il y ai une autre solution, j'ai d'ailleurs penser a transmettre un bloc complet de paramètre genre : AltiVitesseCapVz 2500110095-500 (2500 pieds ,110kt , 095°et -500 pieds/min) le hic c'est comment (...)
tu auras beaucoup de mal à déchiffrer ta trame dans ce format : on peut y trouver aussi : 250 pieds, 011kt , 0095°et -500 pieds/min. Je te conseille d'envoyer ta trame dans ce format : "A2500;K110;C095;Z-500;". une lettre suivie d'une donnée numérique puis d'un ';' (séparateur).

Ainsi, pour décoder (c'est un début d'illustration du tuto du barbu) :

Code: [Select]

boolean moins1;
int data1;
byte j1, j2;

void loop(){
  while(!serial.available());  // boucler tant qu'il n'y a rien dans le port série
  j1 = Serial.read(); // lecture du premier octet
 
  while(!serial.available());  // boucler tant qu'il n'y a rien dans le port série
  j2 = serial.read(); // lecture octet suivant
  data1 = 0;
  moins1 = false;
  while (j2 != ';'){  // boucler tant qu'on n'a pas le séparateur
    if (j2 == '-'){
      moins = true;  // signe -
    } else if ((j2 == '.') || (j2 == ','){  // virgule ou point : partie décimale
      // ici le code de ton choix pour gérer les décimales...
    } else if ((j2 >= '0') &&(j2 <= '9')){  // chiffre
      data1 = (data1 * 10) + (j2 - '0');
    }
    while(!serial.available());  // boucler tant qu'il n'y a rien dans le port série
    j2 = serial.read(); // lecture octet suivant
  }
  // normalement, là, j2 = ';', bah on s'en fout, c'est un octet perdu, mais il nous aura servi à sortir de la boucle!
  if (moins1) data1 *= -1;  // signe négatif
  switch (j1){       // en fonction de la lettre d'identification de la commande, faire :
    case 'A':       // Altitude
      gerer_altitude(data1);
      break;
  }
    case 'K':         // Kt
      gerer_kt(data1);
      break;
  }
    case 'C':          // cap
      gerer_cap(data1);
      break;
  }
}

Avec ça, tu peux jouer tranquille. Je te laisse le soin de gérer la réception d'un nombre à virgule, mais si tu n'en utilises pas, alors tu peux virer ce if... Si tu es motivé, tu peux t'amuser à décoder des trames genre "A2500;K011;P12.5,21;C045;", où la donnée P est suivie de deux données (j'ai imaginé P comme position suivie de x puis y. sachant qu'en plus, x est un nombre à virgule... il faudra gérer des float, et prévoir data1, data2, data_n... Maintenant, tu peux rester simple avec "P12.5;Q21;", mais il peut être parfois intéressant de décoder en même temps plusieurs données pour les envoyer en même temps dans la fonction gerer_donnees_multiple(data1, data2).

Pour ce qui est du mélange servos / PAP, les librairies ne sont pas forcément compatibles entre elles. Si l'une paramètre une ressource (je pense surtout au un timer2...) et que l'autre modifie la même ressource pour ses propres besoins, ça fera tout du caca dans la première lib, mais ça, c'est le côté opensource...

fixair

ok, j'ai compris dans l'ensemble, merci pour ta réponse.
Maintenant, je me pose la question suivant : on sait que l'arduino ne gère pas le multitâches, est il envisageable d'appliquer la methode de Barbudor, a savoir :

Quote
Ainsi pour rentrer dans le "cadre" Arduinon chaque tâche doit fournir au moins une fonction de setup() pour l'initialisation et une fonction de loop(). Le code global de l'application peut ainsi s'écrire :

void setup()
{
  task1_setup();
  task2_setup();
  task3_setup();
}

void loop()
{
  task1_loop(); // réception datas
  task2_loop(); //K
  task3_loop();// C, etc...
}


Si j'ai bien compris je peux affecter une fonction pour la réception des datas et une par moteur ou servo, dans un souci de fluidité, pour être plus efficace.

D'autre part, je n'ai pas besoin de gérer des décimales,juste des entiers positif ou négatif donc ça devient plus simple.
A savoir aussi, qu'il y aura grosso modo un mixe de 10 servos et moteurs pap, donc environ 8 à 10 fonctions Max.

Mille merci encore pour votre aide précieuse.
FX ;op
Cordialement
@+ FX ;op

fixair

Bonsoir,
Ayé, problème de lag sur mes aiguilles résolu : en fait, il suffisait de donner la bonne côte au Timer1 que j'utilise sous visual C#.
Et la c'est fluide.D'autre pârt, j'ai appliqué la méthode :
Quote
Ainsi pour rentrer dans le "cadre" Arduinon chaque tâche doit fournir au moins une fonction de setup() pour l'initialisation et une fonction de loop(). Le code global de l'application peut ainsi s'écrire :

void setup()
{
  task1_setup();
  task2_setup();
  task3_setup();
}

void loop()
{
  task1_loop(); // réception datas
  task2_loop(); //K
  task3_loop();// C, etc...
}


en faisant un mix avec d'autres infos trouvées sur le net.  Voici un petit bout de l'histoire qui tourne sous Arduino 1.0.1 :
Quote

#include <Servo.h>

int n,j,JJ,j1,j2,vz,dA,nA,nR,nP;
int  jZ=0;
int Vert_A, Vert_P=0;
Servo pitch;
Servo roll;
String Pitchsp, Pitchold,Rollsp, Rollold;

void setup()

  pitch.attach(8);
  roll.attach(9);
  Serial.begin(115200);
}

void loop()
{
     while(Serial.available() > 0){
       j1 = Serial.read();
       if (j1 == 'A') Tangage();
       if (j1 == 'B') Roulis();                         
                                 }
}       
 
void Tangage() {
              delay (5);
              Pitchsp = "";
              Pitchsp += (char)Serial.read();
              Pitchsp += (char)Serial.read();
              Pitchsp += (char)Serial.read();
              Pitchsp += (char)Serial.read();
              Pitchsp += (char)Serial.read();
              Pitchsp += (char)Serial.read();
              if (Pitchsp != Pitchold){
                 char carray[6];
                 Pitchsp.toCharArray(carray, sizeof(carray));
                 nA = atoi(carray);
                 if (nA <= -25) nA = -25 ;  if (nA >= 25) nA = 25; //// butée de protection servo(course mécanique limitée)
                 nA = map(nA, -90, 90, 2, 178);
                 pitch.write(nA);
                 delay (11);
                 Pitchold = Pitchsp;
                                       }     
                   }
void Roulis(){
              delay (5);
              Rollsp = "";
              Rollsp += (char)Serial.read();
              Rollsp += (char)Serial.read();
              Rollsp += (char)Serial.read();
              Rollsp += (char)Serial.read();
              Rollsp += (char)Serial.read();
              Rollsp += (char)Serial.read();
              if (Rollsp != Rollold){
                 char carray[6];
                 Rollsp.toCharArray(carray, sizeof(carray));
                 int nB = atoi(carray);
                 if (nB <= -80) nB = -80 ;  if (nB >= 80) nB = 80; // butée de protection servo(course mécanique limitée)
                 nB = map(nB, -90, 90, 2, 178);
                 roll.write(nB);
                 delay (11);
                                       }     
                   }



Et voilà pour le moment ;op
@+ FX
Cordialement
@+ FX ;op

Go Up