Go Down

Topic: Arduino Direct Control (Read 1 time) previous topic - next topic

lordzeppo

Bonjour tous,j'ai une question pour vour.Je suis en train de construire une Desktop CNC a partir de 3 imprimantes jet d'encre (reste pas grand chose des imprimantes en fait) et j'suis en train de monter un programme en VB pour gerer la cnc et la question est:

Comment je fait pour que dans le loop du arduino il attende une ligne de code qui arriverais d emon programme ??

Ex:

J'utilise le Motor shield de ladyada;;

#include <AFMotor.h>


AF_Stepper motor(48, 2);


void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 Serial.println("Stepper test!");

 motor.setSpeed(10);  // 10 rpm  

 motor.step(100, FORWARD, SINGLE);
 motor.release();
 delay(1000);
}

void loop() {
 motor.step(100, FORWARD, SINGLE);
 motor.step(100, BACKWARD, SINGLE);
}


s'arranger pour que le programme envoi qlque chose genre exactement ca

 motor.step(100, FORWARD, SINGLE);

et que arduino l'utilise sans poser de question??


J'ai penser a;
envoyer un chiffre indiquant le nombre de steps et par une formule mathématique déterminer dans quel sens aller MAIS...ca gere qun stepper.

J'ai penser intégrer les différentes commandes dans arduino et les activer en sendant un ASCI mais ca limite la chose aux incréments déterminés

Ce que je vise comme but final ;

Un programme qui le controle;plus précisement une console dans laquelle on peut tapper x+500 et laxe x fait 500 steps,apres on met y-23 et etc.

des suggestions?
merci

Jean-François

Tu peux regarder comment celui-ci a fait, c'est en java :

slice & dice
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

lordzeppo

deja vu et pas tres fameux =\

Jean-François

#3
Jan 23, 2009, 04:33 pm Last Edit: Jan 23, 2009, 04:33 pm by jfs Reason: 1
Je ne dis pas qu'il est fameux... ou pas, mais c'est un point de départ et ça reste toujours intéressant de voir comment d'autres ont pensé faire ce que tu veux faire.

Je trouve intéressant par exemple que celui ci utilise une validation par CRC.

Il est à noter également qu'il traite l'interpolation linéaire / circulaire, peut-être pas de la façon dont tu voudrais le faire,mais lui l'a fait et c'est également intéressant...

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

lordzeppo

Je n'ai pas besoin que ce soit CNC, ou que ca utilise le CRC.

Ce que je demande c'est une facon basic de dire a arduino:

attend qu'on envoi une ligne de code
execute la 1 seule fois
attend de nouveau

Comme ca le software gere tout alors que larduino ne fait que relier le pc a la machine...de cette facon on est pas limité par les capacités de l'arduino.

Et secundo; j'ai préciser que j'utilisais un  Motor Shield de Ladyada pour controller els steppers,de fait..son raisonement m'est totalement inutile puisque tout ce que je cherche a accomplir c'Est:

void Loop()
Attend une commande
Execute la 1 fois
goto void loop()

et le software envoie une ligne de code comprenable pour arduino via le serial

ex:
motor.step(100, BACKWARD, SINGLE);

Luj06

#5
Jan 23, 2009, 11:40 pm Last Edit: Jan 23, 2009, 11:41 pm by julien@pobot.org Reason: 1
Voici ce qui correspond à ta demande (que j'ai trouvé très impolie au passage).

Code: [Select]


// pour stocker la chaine de caractère envoyée par la liaison série
byte commande[32];

// enregistre la chaine de caractère et indique le nombre de caractères lus
int readCommand()
{
 if(!Serial.available())
 {
   return 0;
 }
 int i = 0;
 // il faut lire chaque caractère 1 par 1
 while(Serial.available())
 {
   commande[i] = Serial.read();
   i++;
 }
 commande[i] = 0;  // toujours terminer par un 0
 return i;
}

void executeCommande()
{
 if (commande[0] == 'X')
 {
   motorX.step(commande[1], commande[2], commande[3]);
 }
 if (commande[0] == 'Y')
 {
   motorY.step(commande[1], commande[2], commande[3]);
 }
}

void loop()
{
 if (readCommande() != 0)
 {
   // si une commande complète est arrivée, on l'exécute
   executeCommande();
 }
}



lordzeppo

Merci bcp pour ton code..ca semble etre exactement ce que je cherche.
et desolé si ce que j'ecrit semble impolit,je suis militaire et de fait...j'utilise un ton impératif dans l'ensemble de mes activités,c'est qu'une habitude qui s'enleve pas tres facilement mais l'intention n'était point de faire du tord.

Pourrais-tu s'il te plait décrire le fonctionnement détaillé de ton code?
Je suis tres callé en Mécanique,
bien renseigné en électronique,
je me debrouille quand meme tres bien avec visual basic..
mais pour coder en C brute...j'ai de grandes lacunes.
merci 8-)

Luj06

#7
Jan 25, 2009, 10:08 am Last Edit: Jan 25, 2009, 10:09 am by julien@pobot.org Reason: 1
La différence entre ce code et le code "habituel" (i.e. celui qu'on trouve dans les exemples Arduino), c'est que celui-ci va construire une chaine de caractère complète avant de la traiter, alors que d'habitude on traite chaque octet au fur et à mesure.

Code: [Select]

// pour stocker la chaine de caractère envoyée par la liaison série
byte commande[32];

// enregistre la chaine de caractère et indique le nombre de caractères lus en retour
// pour savoir si on doit faire quelque chose ou pas
int readCommand()
{
 // s'il n'y a rien, on ne lit pas la liaison série
 if(!Serial.available())
 {
   return 0;
 }
 // on commence à compter
 int i = 0;
 // il faut lire chaque caractère 1 par 1
 while(Serial.available())
 {
   // stocke le caractère reçu dans le tableau de caractères
   commande[i] = Serial.read();
   i++;
 }
 commande[i] = 0;  // toujours terminer par un 0 la chaine
 // le nombre de caractères lus (pour vérifier que c'est bien ce qu'on attendait
 return i;
}

// traitement de la commande caractère par caractère,
// en supposant que l'on envoit des consignes composées de 4 caractères (exemple de ton post ci-dessus).
void executeCommande()
{
 if (commande[0] == 'X')
 {
   motorX.step(commande[1], commande[2], commande[3]);
 }
 if (commande[0] == 'Y')
 {
   motorY.step(commande[1], commande[2], commande[3]);
 }
}

// boucle Arduino principale, appelée en permanence
void loop()
{
 // traitement d'une éventuelle commande
 // si aucune commande n'a été reçue, la boucle continue
 if (readCommande() != 0)
 {
   // si une commande complète est arrivée, on l'exécute
   executeCommande();
 }
}

lordzeppo

merci énormément,ca ressemble exactement a ce que je cherchais.

Je me demandais...si au lieu d'avoir une partie de la commande écrite et de la compléter avec les caracteres lus,est-il possible qu'il en recoive une complete du style;

 if (commande[0] == 'K')
 {
   (commande[1], commande[2], commande[3],etc...);
 }

?

K étant le trigger pour une commande hors normes.


lordzeppo

au fait....j'ai tester et adapter ton code mai il semble manquer quelquechose....

Voici le code complet;

Code: [Select]
#include <AFMotor.h>


AF_Stepper motor(48, 2);
int commande[32];


void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 Serial.println("Stepper test!");

 motor.setSpeed(250);  // 10 rpm  
 motor.release();
 delay(1000);
}
int readCommande()
{
 // s'il n'y a rien, on ne lit pas la liaison série
 if(!Serial.available())
 {
   return 0;
 }
 // on commence à compter
 int i = 0;
 // il faut lire chaque caractère 1 par 1
 while(Serial.available())
 {
   // stocke le caractère reçu dans le tableau de caractères
   commande[i] = Serial.read();
   i++;
 }
 commande[i] = 0;  // toujours terminer par un 0 la chaine
 // le nombre de caractères lus (pour vérifier que c'est bien ce qu'on attendait
 return i;
}

void execCommande()
{
 if (commande[0] == 'x')
 {
   Serial.println("x has been detected");
   motor.step((commande[1] , commande[2] , commande[3] ),FORWARD, SINGLE);
   Serial.println("x has been moved");

 }
 if (commande[0] == 'y')
 {
   motor.step((commande[1], commande[2], commande[3]) ,BACKWARD, SINGLE);
 }
}
void loop()
{
 // traitement d'une éventuelle commande
 // si aucune commande n'a été reçue, la boucle continue
 if (readCommande() != 0)
 {
   // si une commande complète est arrivée, on l'exécute
   execCommande();
   Serial.println((commande[0] , commande[1], commande[2], commande[3]));
     motor.release();
   }
 }



-Il détecte sans probleme lorsque c'est x ou y le premier charactere
-Il effectue le mouvement
-Mais quand il me remontre les valeurs (supposons que je lui ai donner x150) il me redonne :

[ch9608]
[ch9608]
0

et ca..ca me pose probleme..parceque je suppose que la library du Mshield execute bien un move mais de [ch9608][ch9608] steps qui est a vrai dire rien. La varriable commande etait au depart en byte,j'ai esasiller en int et rien n'a changer.Des suggestions?

lordzeppo

#10
Jan 25, 2009, 11:02 pm Last Edit: Jan 25, 2009, 11:17 pm by lordzeppo Reason: 1
Bon..j'ai travailler comme un dingu pour tenter de trouver le probleme et je n'y arrive toujours pas...

voici le code;
Code: [Select]
#include <AFMotor.h>


AF_Stepper motor(48, 2);
byte commande[4];
int stp ;
int a;
int b;
int c;



void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 Serial.println("Stepper test!");

 motor.setSpeed(250);  // 10 rpm  
 stp = 0;
 motor.release();
 delay(1000);
}
int readCommande()
{
 // s'il n'y a rien, on ne lit pas la liaison série
 if(!Serial.available())
 {
   return 0;
 }
 // on commence à compter
 int i = 0;
 // il faut lire chaque caractère 1 par 1
 while(Serial.available())
 {
   // stocke le caractère reçu dans le tableau de caractères
   commande[i] = Serial.read();
   i++;
 }
 commande[i] = 0;  // toujours terminer par un 0 la chaine
 // le nombre de caractères lus (pour vérifier que c'est bien ce qu'on attendait
 return i;
}

void execCommande()
{
 if (commande[0] == 'x')
 {
   Serial.println("x has been detected showing variable values");
   a= (commande[1]);
       Serial.println(a);
   b=(commande[2]);
       Serial.println(b);
   c=(commande[3]);
       Serial.println(c);

   (stp = (a * 100) + (b * 10) + c);
   Serial.println("Valeure de steps");
   Serial.println(stp);
   motor.step((stp),FORWARD, SINGLE);
   Serial.println("x has been moved");

 }
 if (commande[0] == 'X')
 {
   Serial.println("-x has been detected");
   stp = (((commande[1])*100)+(commande[2])*10+(commande[3]));
   motor.step((stp),BACKWARD, SINGLE);
   Serial.println("-x has been moved");
 }
}
void loop()
{
 // traitement d'une éventuelle commande
 // si aucune commande n'a été reçue, la boucle continue
 if (readCommande() != 0)
 {
   // si une commande complète est arrivée, on l'exécute
   execCommande();
   motor.release();
   stp=0;
 }
}



le probleme est...(vous le verrez vous meme sans probleme si vous uploader ceci sur votre arduino et que vous le faite fonctionner...simplement enlever toute référence au motorshield et a ses commandes) que j'envoi par exemple;

x050
la premiere fois je recoit que des 0 dans la console et rien ne bouge

la 2eme fois que je le renvoi j'obtient;

x has been detected showing variable values
0
49
0
Valeure de steps
490
x has been moved

et le moteur bouge effectivement de 490 steps...mais je lui en ai demander 50...pas 490...

J'ai cru a un probleme de variable mais je n'arrive toujours pas a trouver le probleme...

merci d'y jeter un coup d'oeil

***EDIT***
je croit que la source du probleme est la conversion du chiffre qui est lu en chiffre utilisable par arduino...pourriez vous verifier?


Luj06

Je confirme que si tu envoies les valeurs depuis la console série, effectivement ça ne peut pas fonctionner.

Si tu envoies x050, la carte considère qu'elle a reçu 4 caractères : x puis 0 puis 5 puis 0.

Je regarderai ce soir le code à écrire pour faire la conversion.

lordzeppo


Luj06

Code: [Select]

char cmdChar;
int cmdValeur;

int flagNombre = false;

[...]

while (serialAvailable())
{
 cmdChar = Serial.read ();
 switch (cmdChar)
 {
 case 'x' :
 case 'y' :
 case 'z' :
   //
   if (flagNombre)
   {
      // rectifier i après le nombre qu'on vient d'accumuler
      // pour pouvoir enchainer "x 125 y 250" par exemple
      i++;      
   }
   // on indique qu'on n'est pas en train d'accumuler un nombre
   flagNombre = false;
   // stocke le caractère reçu dans le tableau de caractères
   commande[i] = cmdChar;
   i++;
   // remet à zéro l'accumulateur de nombre
   cmdValeur = 0;
   break;
 case '0' :
 case '1' :
 case '2' :
 case '3' :
 case '4' :
 case '5' :
 case '6' :
 case '7' :
 case '8' :
 case '9' :
   //
   flagNombre = true;
   // explication : les chiffres commencent à partir du caractère ASCII 48
   cmdValeur = cmdValeur * 10 + (cmdChar-48);
   // comme on ne sait pas quand on s'arrêtera, on met à jour la valeur dans notre tableau des commandes
   commande[i] = cmdValeur;
   // mais bien sûr on n'incrémente pas i car pour l'instant on reste
   break;
 default:
   Serial.print("> valeur non reconnue : ");
   Serial.println(cmdChar);
 }
}

if (flagNombre)
{
// rectifier le dernier i++ qui n'a pas été pris en compte
i++;  
}

[...]


lordzeppo

#14
Jan 27, 2009, 02:23 pm Last Edit: Jan 27, 2009, 02:26 pm by lordzeppo Reason: 1
j'vais etre honete avec toi sur ce point la...j'comprend absolument rien du code que ta écrit =\

J'ai tenter de l'intégrer dans mon code existant (posté ci-bas) mais je voit pas comment faire ca puisque je ne sais pas a quoi ca sert ligne par ligne.. y'aurais moyen de reposter le code,a l'endroit ou il va?

Aussi: j'avais réeussit a trouver pour le -48 et il ne faut aps oublier d'ajouter des condtions qui ramenent a 0 si ce n'est pas un chiffre qui est entré.

Code: [Select]
#include <AFMotor.h>


AF_Stepper motor(48, 2);
byte commande[4];
int stp ;
int a;
int b;
int c;



void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 Serial.println("Stepper test!");

 motor.setSpeed(250);  // 10 rpm  
 stp = 0;
 motor.release();
 delay(1000);
}
int readCommande()
{
 // s'il n'y a rien, on ne lit pas la liaison série
 if(!Serial.available())
 {
   return 0;
 }
 // on commence à compter
 int i = 0;
 // il faut lire chaque caractère 1 par 1
 while(Serial.available())
 {
   // stocke le caractère reçu dans le tableau de caractères
   commande[i] = Serial.read();
   i++;
 }
 commande[i] = 0;  // toujours terminer par un 0 la chaine
 // le nombre de caractères lus (pour vérifier que c'est bien ce qu'on attendait
 return i;
}

void execCommande()
{
 if (commande[0] == 'x')
 {
   Serial.println("x has been detected showing variable values");
   a= (commande[1] - 48);
   if (a <= 0) a=0;
   Serial.println(a);
   b=(commande[2] - 48);
   if (b <= 0) b=0;
   Serial.println(b);
   c=(commande[3] - 48);
   if (c <= 0) c=0;
   Serial.println(c);

   (stp = (a * 100) + (b * 10) + c);
   Serial.println("Valeure de steps");
   Serial.println(stp);
   motor.step((stp),FORWARD, SINGLE);
   Serial.println("x has been moved");

 }
 if (commande[0] == 'X')
 {
   Serial.println("-x has been detected");
   a= (commande[1] - 48);
   if (a <= 0) a=0;
   Serial.println(a);
   b=(commande[2] - 48);
   if (b <= 0) b=0;
   Serial.println(b);
   c=(commande[3] - 48);
   if (c <= 0) c=0;
   Serial.println(c);
  x stp = (((commande[1])*100)+(commande[2])*10+(commande[3]));
   motor.step((stp),BACKWARD, SINGLE);
   Serial.println("-x has been moved");
 }
}
void loop()
{
 // traitement d'une éventuelle commande
 // si aucune commande n'a été reçue, la boucle continue
 if (readCommande() != 0)
 {
   // si une commande complète est arrivée, on l'exécute
   execCommande();
   motor.release();
   stp=0;
 }
}



ps:avec ce code je suis en mesure de bouger de 1 step,5 steps,10 mais pas 100 et ils sont a délais..:

J'entre x0001-->rien se passe
j'entre x0005-->bouge de 1
J'entre x0010-->bouge de 5

J'ai l'impression qu'une etape nécéssaire est sautée lors du premier tour et ca l'empeche d'etre fonctionnel directement.

Go Up