Go Down

Topic: Serial libraries avec Processing >> Arduino (Read 2 times) previous topic - next topic

Jean-François

Apr 27, 2010, 10:11 pm Last Edit: Apr 27, 2010, 10:15 pm by jfs Reason: 1
J'essaie de faire une interface Processing pour configurer l'aéroquad.

Lorsque la carte reçoit un caractère, elle renvoie un string, Exemple :

Processing envoi "L", Arduino envoi 0.20,0.20,0.500

Si j'envoie un caractère en solo, pas de problème, par contre si j'envoie une série de caractère différents je devrais avoir ça :

Processing envoi "L", Arduino envoi 0.20,0.20,0.500
processing envoi "Q", Arduino envoi -1,-1,1,-525,-527,-757,0,0,0.00,0.00
Processing envoi "R", Arduino envoi -2,0,2,-426,-467,-679
et ainsi de suite....

Et ce n'est pas ce que j'obtiens... j'ai plutôt ça :

Code: [Select]
Q 0,0,0,-527,-529,-756,0,0,0.00,0
L .00

L 0.20,0.20,0.50,

Q -1,0,1,-523,-530,-756,0,0,0.00,0.00

L 0.20,0.20,0.50,

Q 0,-1,-1,-522,-531,-759,0,0,0.00,0.00

Q 0.20,0.20,0.50,

Q -1,0,-1,-526,-527,-758,0,0,0.00,0.00

Q 0.20,0.20,0.50,

L -1,-1,-1,-525,-530,-759,0,0,0.00,0.00

L 0.20,0.20,0.50,

L -1,-1,0,-522,-527,-755,0,0,0.00,0.00

L 0.20,0.20,0.50,

Q -1,-1,1,-525,-527,-757,0,0,0.00,0.00

Q 0.20,0.20


avec ce code test :

Code: [Select]

import processing.serial.*;
Serial myPort;
char send_char;
String portName;
void setup()
{
 size(490, 200);
 background(51);
 frame.setResizable(true);
 println(Serial.list());
 String portName = Serial.list()[3];
 myPort = new Serial(this, portName, 115200);
}

void draw()
{ myPort.clear();
 new Serial(this, portName, 115200);
 send_char='Q';
 myPort.write(send_char); // envoi un caractere a l'arduino
 while (myPort.available() > 0) {
   String inBuffer = myPort.readString();  
   if (inBuffer != null) {
     print (send_char+" ");
     println(inBuffer);
   }
   myPort.clear();
 }
new Serial(this, portName, 115200);
 send_char='L';
 myPort.write(send_char); // envoi un caractere a l'arduino
 while (myPort.available() > 0) {
   String inBuffer = myPort.readString();  
   if (inBuffer != null) {
     print (send_char+" ");
     println(inBuffer);
   }
   myPort.clear();
 }
}


(Serial libraries)

Comment est ce que je peux faire pour pouvoir changer de caractère et que ça match à chaque fois avec le string entrant ?
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

B@tto

Je connais pas très bien processing mais comme c'est à peu près la même histoire dans tous les languages : peut-être faut-il rajouter des delay le temps que l'arduino ait le temps de réagir ? Parce que la si je comprend bien ton code, tu envois le caractère et de suite après tu guettes le buffer d'entrée.
Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

Jean-François

J'ai essayé avec des delay et des boucles for et le problème persiste.
Le bout de code que j'ai mis est simplement un test, celui que j'ai pour le quadricoptère est un peu plus conséquent .

Lorsque je change de caractère avec des boutons-radios l'affichage de mes vumètres est figé pendant 10-15 secondes.
lorsque je change le caractère destiné à l'Arduino, il ne match pas immédiatement avec le string reçu.
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

Jean-François

#3
Apr 28, 2010, 03:25 pm Last Edit: Apr 28, 2010, 03:29 pm by jfs Reason: 1
J'ai fait des test en utilisant myPort.stop() et apparemment on ne peut réouvrir un port depuis la boucle draw(), donc a la deuxième lecture du port ça plante.

d'après ce que je constate , ce serait les buffers qui ne se vident pas assez vite et qui serait relu une deuxième fois.

comment faire pour être sur que le buffer est bien vide, j'ai déjà tester avec myPort.clear() et il n'y a pas de changement.
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

B@tto

Mais si je comprend tu ouvres et ferme ton port dans la boucle ?? Pourquoi ? Une fois que tu l'as ouvert dans ton setup tu n'as juste qu'à surveiller l'envoi et la réception dans le draw.
Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

Jean-François

Normalement je ne fais pas d'ouverture fermeture dans la boucle... là il se trouve que dans le code publié, je vide le buffer (myport.clear()), mai je ne le ferme jamais.
Par contre si je ne refais pas "new Serial(this, portName, 115200);" à chaque fois ça ne fonctionne pas du tout (dans cet exemple).

le port est ouvert dans le setup et ne peut pas être réouvert depuis la boucle draw() (d'après mes essais).
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

Jean-François

#6
Apr 28, 2010, 11:00 pm Last Edit: Apr 29, 2010, 07:10 am by jfs Reason: 1
Bon j'ai peut-être trouvé ce qui ne va pas.

Est ce possible de limiter la longueur d'un float en forçant à deux chiffres après la virgule, par exemple pour 0.234567, de le tronquer à 0.234 ?
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

B@tto

L'idée saugrenue  qui me vient comme ça : tu multiplis par 1 000 000 tu passes en integer, tu divises par 1 000, tu repasses en float et tu redivises par 1000.

Mais j'imagine qu'il doit bien y avoir une autre soluce mais la journée est longue aujourd'hui ...  ;D
Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

Jean-François

#8
Apr 29, 2010, 05:39 pm Last Edit: Apr 29, 2010, 06:21 pm by jfs Reason: 1
J'ai fait comme ça :

Code: [Select]
String []send_value_filter=new String[7];
     send_value_filter[0]=str(send_char);
     send_value_filter[1]=nf(gyro_Filter,1,2);  //%2.f,nombre
     send_value_filter[2]=";";
     send_value_filter[3]=nf(accel_Filter,1,2);
     send_value_filter[4]=";";
     send_value_filter[5]=nf(time_Filter,1,2);
     send_value_filter[6]=";";
     String joinedsend_value_filter=join(send_value_filter,"");
     String[]list=split (joinedsend_value_filter,',');
     
     myPort.write(list[0]+"."+list[1]+"."+list[2]+"."+list[3]);


parce qu'avec la fonction nf() ça me met une "," dans mon nombre et ça ne passe qu'avec un ".".... ::) et ce ne sont pas les floats avec plus de deux chiffres après la virgule qui me font foirer mon appli.... :P mais ce n'est pas le but de ce post.

J'aimerais tout de même trouver une solution pour que le buffer entrant match avec le caractère sortant.
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

Jean-François

#9
May 01, 2010, 03:03 pm Last Edit: May 01, 2010, 03:04 pm by jfs Reason: 1
Je fais au plus simple avec une incrémentation de A+1 pour comptabiliser le nombre de cycle, avec ce code :

Code: [Select]
void setup()
{
 size(490, 200);
 background(51);
 frame.setResizable(true);

 println(Serial.list());
 String portName = Serial.list()[3];
 myPort = new Serial(this, portName, 115200);
}

void draw()
{
 frame.setSize(800, 500);
 smooth();
 strokeWeight(2.0);
 stroke(0, 102, 153);
 background(150);
receive_value_filter();
println(A+"sortie "+gyro+" "+accel+" "+time);
send_value_filter();
A++;
}


void receive_value_filter()
{


   for(int a=0; a<=20;a=a+1){
     myPort.write(str('L')); // envoi un caractere a l'arduino
     while (myPort.available() > 0) {
       String inBuffer = myPort.readString();
       if (inBuffer != null) {
         String[] nums = split(inBuffer, ',');
         if((nums.length)==3){  // 6 pour'R"
           for (int i = 0; i <=2; i = i+1) {
             filtre_value[i] = nums[i];
           }
           myPort.clear();
           gyro_Filter=float(filtre_value[0]+"f");
             accel_Filter=float( filtre_value[1]+"f");
             time_Filter=float( filtre_value[2]+"f");
           gyro=float(filtre_value[0]);
           accel=float(filtre_value[1]);
           time=float(filtre_value[2]);
        }
       }
     }
 }
 
}


void send_value_filter()
{
     gyro_Send=0.2;
     accel_Send=0.3;
     time_Send=0.4;
 String send=('K'+str(gyro_Send)+';'+str(accel_Send)+';'+str(time_Send)+';'+';');
     for(int a=0; a<=40;a=a+1){
     myPort.write(send); // envoi un caractere a l'arduino
     }
     myPort.clear();
}


Le premier nombre affiché avant sortie est le nombre de cycle pour que l'arduino commence à afficher les valeurs que je lui envoi :

Code: [Select]
30.0sortie 0.2 0.2 0.5
31.0sortie 0.2 0.2 0.5
32.0sortie 0.2 0.2 0.5
33.0sortie 0.2 0.2 0.5
34.0sortie 0.2 0.3 0.4
35.0sortie 0.2 0.3 0.4
36.0sortie 0.2 0.3 0.4


Donc 34 boucles avec chaque fois 40 envois pour que mes valeurs passent  :o

J'ai du faire une erreurs  quelque part, alors si quelqu'un vois un truc qui cloche... ou bien aurait une piste à explorer  ;)
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

Jean-François

#10
May 01, 2010, 10:57 pm Last Edit: May 01, 2010, 10:57 pm by jfs Reason: 1
Je fais des essais avec serialEvent()

On dirait que ça marche pas trop mal. Je vais creuser un peu  ;)
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

Jean-François

Avec une liaison série en continu, le chip Ftdi a tendance  à chauffer, je lui ai rajouté un radiateur.
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

Jean-François

#12
May 03, 2010, 09:13 pm Last Edit: May 03, 2010, 10:29 pm by jfs Reason: 1
Voici une petite vidéo de ce que donnent mes essais de liaisons série :

http://www.youtube.com/watch?v=7j02DZ83OnU


lors du lancement de l'application, les valeurs contenues dans la carte sont lues et les sliders sont alignés par rapports à ces dernières.
Ensuite, les valeurs sélectionnées par les sliders sont envoyées à l'arduino, tant que les valeurs de la carte ne sont pas égales aux sliders, le point reste rouge et les valeurs des sliders sont renvoyées à l'Arduino.

Lorsque les valeurs sont équivalentes entre la carte et les sliders, le point devient vert. Tant que l'équivalence est avérée seule une lecture de la carte 2-3 fois par seconde subsiste.

Voici mon code Processing :

Code: [Select]

import processing.serial.*;
import guicomponents.*;

GWSlider gyroSlider,accelSlider,timeSlider;
Serial myPort;
String portName;

PFont myFont;

float chrono=0;
float oldChrono=0;

float gyro=0;
float accel=0;
float time=0;

String []filtre_value = new String[4];
float gyro_Filter = 0;
float accel_Filter = 0;
float time_Filter = 0;

String inString;
float gyro_receive= 0;
float accel_receive = 0;
float time_receive = 0;

String send;
float gyro_Send= 0;
float accel_Send = 0;
float time_Send = 0;

float A=1;
float Z=1;

int B=1;
int M=0;
int lf = 10;

char send_char;

boolean OK=false;

void setup()
{
 size(490, 200);
 background(51);
 frame.setResizable(true);

 println(Serial.list());
 String portName = Serial.list()[3];
 myPort = new Serial(this, portName, 115200);

 gyro_Filter=float("1.5f");
 gyroSlider = new GWSlider(this,"blue18px",500,80,260);  //Gyro filter slider
// gyroSlider.setInertia(2);
 gyroSlider.setValueType(GWSlider.DECIMAL);
 gyroSlider.setLimits(1.5f, 0f, 3.0f);
 gyroSlider.setRenderValueLabel(true);

 accel_Filter=float("1.5f");
 accelSlider = new GWSlider(this,"blue18px",500,200,260);
// accelSlider.setInertia(2);
 accelSlider.setValueType(GWSlider.DECIMAL);
 accelSlider.setLimits(1.5f, 0f, 3.0f);
 accelSlider.setRenderValueLabel(true);

 time_Filter=float("1.5f");
 timeSlider = new GWSlider(this,"blue18px",500,320,260);
// timeSlider.setInertia(2);
 timeSlider.setValueType(GWSlider.DECIMAL);
 timeSlider.setLimits(1.5f, 0f, 3.0f);
 timeSlider.setRenderValueLabel(true);
 
 myPort.bufferUntil(lf);
}

void draw()
{
 frame.setSize(800, 500);
 smooth();
 strokeWeight(2.0);
 background(150);
 
 if (A==0){
   receive_value_filter();
   A=20;
  }
 
    if(B<=10){
      while (B<=8) {
   receive_value_filter();
   if (inString != null) {
   String[] nums = split(inString, ',');
   if((nums.length)==3){  // 6 pour'R"
     gyro  = float(nums[0]);
     accel = float(nums[1]);
     time  = float(nums[2]);
   } B++;
 }set_slider_value();
 }
  B=20;}
 A--;
   if(OK==false){fill(240,30,0);
  ellipse(600, 40, 35, 35);}
  else{fill(0,240,100);
  ellipse(600, 40, 35, 35);}
  noFill();
  fill(80,80,80);
 text(Z+" valeurs reçues: " + inString, 200,50);
 text(str(OK), 200,80);
  text(Z+" valeurs envoyées: " + send, 200,110);

 if (inString != null) {
   String[] nums = split(inString, ',');
   if((nums.length)==3){  // 6 pour'R"
     gyro  = float(nums[0]);
     accel = float(nums[1]);
     time  = float(nums[2]);
   }
 }

 Z++;
  if((gyro!=gyro_Send)||(accel!=accel_Send)||(time!=time_Send)){
   OK=false;
   M++;
 }
 else{
    OK=true;
   M=0;
 }
 if(M>=10){
   OK=false;
   send_value_filter();
    M=0;
  }
 else{ return; }
}

void set_slider_value(){
 
 gyroSlider.setValue(gyro);

 accelSlider.setValue(accel);

 timeSlider.setValue(time);

 gyro_Filter =  gyro;
 accel_Filter = accel;
 time_Filter =  time;
}


void handleSliderEvents(GSlider slider) {

 if ((mouseY >65) && (mouseY< 95)){
   gyro_Filter = slider.getValuef();
 }  
 else if ((mouseY >185) && (mouseY< 215)){
   accel_Filter=slider.getValuef();
 }
 else if ((mouseY >305) && (mouseY< 335)){
   time_Filter=slider.getValuef();
 }  
 else{
   return;
 }
  slider.getValuef());
  gyro_Send=float(int(gyro_Filter*100))/100;
 accel_Send=float(int(accel_Filter*100))/100;
 time_Send=float(int(time_Filter*100))/100;
}


void receive_value_filter()
{
char send_char='L';
 myPort.write('L');
 myPort.clear();
}


void send_value_filter()
{
 gyro_Send=float(int(gyro_Filter*100))/100;
 accel_Send=float(int(accel_Filter*100))/100;
 time_Send=float(int(time_Filter*100))/100;
 send=('K'+str(gyro_Send)+';'+str(accel_Send)+';'+str(time_Send)+';'+';');
 for(int a=0; a<=40;a=a+1){
   myPort.write(send);
 }
 myPort.clear();
}


void serialEvent(Serial p)
{
 inString = p.readString();
 myPort.clear();
}


En l'état, ça ne fonctionne pas de façon très "stable", les valeurs ne sont pas enregistrées immédiatement dans la carte donc le point reste au rouge pendant de long moment et parfois la liaison est rapide et le point devient vert en 1-2 seconde.

Si quelqu'un à des corrections à me suggérer, c'est vraiment bien venu  ;)
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

Volta

bien que n'y connaissant rien , j'ai remarqué en regardant la vidéo que le temps de réaction été plus long lorsque tu diminues une valeur peut être que je me trompe :-/

Jean-François

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

Go Up