Go Down

Topic: [Moteurs PAP] un code qui marche? (Read 9986 times) previous topic - next topic

B@tto

oui ou encore mieux la manipulation des port directement ;)
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

Super_Cinci

C'est exactement là-dessus que je travaille (enfin, pour l'instant, c'est une calvitie grandissante).

je définis une table de 8 pas (0001, 0011, 0010, 0110, 0100, 1100, 1000, 1001), et là-dessus, j'ai une int timer qui agit comme suit :

Code: [Select]

ISR(TIMER1_COMPA_vect){
  motor_step++;
  motor_step &= 0x07;
  PORTX &= 0xF0;
  PORTX |= table_step[motor_step];
}
Je ne pense pas qu'on puisse faire plus optimal. digitalWriteFast() m'oblige à faire pas mal de tests pour savoir sur quelle pin je mets false ou true. Et j'ai pour principe qu'un projet est dès le début bien pensé, donc le câblage ne changera jamais (il faut rêver dans la vie).

le truc, c'est que j'ai pas encore testé... et que je n'ai trouvé aucun code de ce genre déjà fait. (je ne vous ai pas mis les phases accélération, c'est juste pour poser les bases...)

B@tto

Je comprend pas cette ligne :
PORTX &= 0xF0;

D'une part, tu écrit sur tes sorties un état intermédiaire non voulu (toutes tes sorties passe à zéro). Ensuite, au pire pour corriger ça, il suffit de faire :

  PORTX &= 0xF0 | table_step[motor_step];

Mais la solution optimale c'est tout simplement :

PORTX &= table_step[motor_step];

Avec table_step[] directement rempli avec les bons bytes. Genre :

byte table_step[]={0b11110011,0b11110110,0b11111100,0b11111001};
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

Super_Cinci

Quote

Mais la solution optimale c'est tout simplement :

PORTX &= table_step[motor_step];
mais non...
exemple : étata initial de PORTX : xxxx0011
on devrait donc passer à l'état suivant (table[step] = 11110110 ), donc faire PORTX = xxxx0011 & 11110110 = xxxx0010 on en a raté un.

Dans un souci de rapidité, je suis obligé de le faire en deux coups.

le premier (PORTX &= 0xF0) met mes 4 bits de sortie (0 à 3) à 0,
le second (PORTX |= table[step]) met les sorties à 1 selon le masque contenu dans table[step].

un &= ne peut que mettre des bits à 0, |= ne peut que mettre des bits à 1. on ne peut pas faire autrement que d'utiliser les deux. La première opération ne devrait durer que 3 cycles d'horloge, soit 190ns. Je ne pense pas qu'une transition à 0 si courte passe à travers le driver du moteur, et encore moins influer sur le courant dans les bobines...

PORTX = PORTX & 0x0F | table[step]; serait peut-être mieux, si le compilateur décide de passer par une variable intermédiaire, en décomposant l'opération par :

Code: [Select]

byte temp = PORTX;
temp &= 0xF0;
temp |= table[step];
PORTX = temp;


Du moment que ça prend toujours le même temps d'exécution! :)

B@tto

Autant pour moi c'est un ou exclusif qu'il faut, et en plus tu n'as plus besoin que d'une valeur : 0101

A supposer état initial xxxx0011

1) xxxx0011 ^=00000101 ==> xxxx0110
2) xxxx0110^= 00000101<<1 ==> xxxx0110^= 00001010 ==> xxxx1100
3)  xxxx1100 ^=00000101 ==> xxxx1001
4) xxxx1001^= 00000101<<1 ==> xxxx1001^= 00001010 ==> xxxx0011




à travers le driver du moteur, et encore moins influer sur le courant dans les bobines...



Le problème c'est la coupure de courant et donc la décharge des bobines ...


Code: [Select]

byte temp = PORTX;
temp &= 0xF0;
temp |= table[step];
PORTX = temp;


Du moment que ça prend toujours le même temps d'exécution! :)


Oué mais plus de passage à zéro ;)
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

Super_Cinci

OK, d'ac. ça ne marche par contre que pour 4 pas... mais bon...

mes premiers tests pas très concluants : pas d'accélération, mon moteur est resté à 30Hz, fréquence minimale dans mon code.

je reprends tout à Z.

Super_Cinci

#21
Oct 26, 2013, 11:45 am Last Edit: Oct 26, 2013, 11:47 am by Super_Cinci Reason: 1
Bon, phase d'accélération réussie... en alimentant un PAP 24V en 12V et sans trop réfléchir au courant (bien sous-alimenté quoi!)(1), j'arrive sans souci à le faire monter à 6KHz à vide en demi-pas. Ca représente quand même une vitesse de courroie de 25,4 cm/s (10 pouces par seconde) pour une résolution est de 600DPI.

Sur un système à tige fileteé de 6mm directement sur le moteur, on aurait un déplacement de 1,5cm/s pour une résolution de 4000 ppcm (10 160 DPI).
Sur un système à tige fileteé de 8mm directement sur le moteur, on aurait un déplacement de 1,875cm/s pour une résolution de 3200 ppcm (8 128 DPI).

Pour mes tests, j'augmente la fréquence de 100Hz tous les 8 demi-pas, en partant de 30Hz. la vitesse max est donc atteinte au bout d'environ 500 pas (2 cm). peut-être un peu violent quand même...

Là où je suis content, c'est que le calcul de l'accélération et décélération se fait tout seul en fonction du nombre de pas à faire, et que si on demande 100 pas par exemple, l'accélération et décélération sont ajustées. j'appelle juste une fonction moteur_avance(int nombre_de_pas), la fonction déclenche un timer et rend la main tout de suite, ce qui permettrait de déclencher un autre moteur pendant que le premier fait son petit tour... le timer, lui, compte les pas et s'arrête quand il a atteint nombre_de_pas.

Tout se fait à partir de seulement deux données : le nombre de pas au bout duquel on augmente / diminue la fréquence (ici : 8 ), et la fréquence max (6000Hz). j'y suis presque...

désolé, je réfléchis un peu à voix haute... c'est une façon de garder des traces...

------------------------
(1) : en fait, le moteur est donné pour 3,9V / 1,41A, mais il est derrière un SLA7033M, driver qui régule le courant par PWM. D'origine, ce montage était alimenté en 24V dans un photocopieur et servait à faire avancer les originaux sur la vitre du scanner. Je n'ai rien mesuré, juste fait tourné la bestiole... J'imagine qu'alimenté en 24V, le moteur aurait plus de pêche (montée plus rapide du courant dans les bobines)

Super_Cinci

j'ai décidé de faire réfléchir mes outils à ma place.

Maintenant, je teste mon code avec ça :



En gros, un moteur pas-à-pas qui entraîne un charriot sur sa courroie. résolution : un pas = 600DPI, 1/2 pas = 1200 DPI, ça me convient.

Là, ça marche impec, accélération, décélération, marche, arrêt... Bon, j'ai pas non plus envie de tout casser (j'ai mis le charriot à la verticale, 3Kg dessus, le moteur le monte à 30Hz sans rien dire (en même temps, un moteur PAP, ça dit rien ou ça fait rien.)

Derrière, y'a ça :



rien de méchant, j'ai du bol, la platine en alu possède des glissières à écrous de 7mm partout, donc pratique! Pratique, oui, car du coup, j'ai mis un système de fin de course réglable (les flèches rouges), les deux extrémités coulissent, et (la flèche verte) un simple capteur fourche les vois, ou pas... un seul capteur est suffisant si on sait dans quel sens va le moteur. Je suis content, car c'est vraiment facile de déplacer les cales, j'espère pouvoir faire pareil avec les autres moteurs (le CNC prend vie je crois...)



les cales dans la fourche (désolé, c'est au mm, c'est bien caché!)



le capteur (collecteur ouvert) sort sur une entrée PCINT de mon nono. ben là, c'est le fourbi, car dès fois nono voit, des fois nono voit pas. j'ai mis des leds en témoin, mesuré le capteur (il sort 0,10V à vide, et 4,96V sur une fin de course, donc bon). L'interruption PCINT est bien lancée, mais la pin du capteur n'est pas toujours reconnue, du coup, dans un test où le charriot doit faires des AR entre les deux FDC, il va souvent plus loin, sans s'arrêter... (je fais pourtant attention au sens du moteur pour savoir de quel côté on est arrivé au bout!)

Un coup, mon charriot va faire 13 AR super, puis le 14ième, hop, il part dans le moteur! mais maintenant, le capteur n'est même plus reconnu, ça part dans les choux tout de suite!

BREF : quelqu'un a déjà essayé de jouer avec des capteurs fourche d'imprimante? (le mien est un shark S51, un grand classique). peut-être ai-je basoin d'un "debounce"?)

A par àa, j'ai joué avec ma lime (ben oui, j'ai pas de tour) et mes filières, j'ai réduit une tige filetée de 8 :



alors diamètre 8 parce que j'ai surtout des roulements de 8mm, et que niveau résolution finale, 12700 sonne mieux que 15875 DPI, et 6mm car la roue dentée qui va bien est en 6mm, avec un méplat bien sûr...



souis fier de moi là... mais bon, si j'arrive pas à gérer mes capteurs...

B@tto

Comme ça c'est un peu à diagnostiquer, une fourche IR logiquement ça pose pas vraiment de problème ... Tu l'as branchée comment ?
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

Super_Cinci

J'ai simplifié un peu mon interruption PCINT, car dans le principe, elle est appelée à chaque fois qu'il se passe quelque chose sur un capteur (il n'y en a qu'un pour l'instant, mais je risque d'en mettre 8 ). Donc je dois détecter les changements pour ne pas me prendre les pieds dans le tapis.

J'arrive donc maintenant à calibrer le déplacement à la mise en route.

Code: [Select]

  // calibration :
  if (x_capt) {  // le capteur est sur une fin de course
    pap_x_step(1200, true);  // avancer de 1 pouce
    wait_x;               // attendre que le moteur ait fini son déplacement
    if (x_capt) {  // on y est toujours? c'est qu'on doit être en butée haute
      pap_x_step(-2400, true);  // reculer de 2 pouces
      wait_x;              // attendre que le moteur ait fini son déplacement
    }
  }
      // on est en dehors des fin de courses
  pap_x_go(false, true);  // reculer à fond
  while (!x_BOT){}     // on attend le capteur de butée basse
  pap_x_stop;            // on est arrivé en buttée basse.
  x_abs = 0;               // position absolue = 0
  x_min = 0;              // position mini autorisée
 
  pap_x_go(true, true);  // on recherche la buttée haute, lancer le moteur en avant
  while (!x_TOP){}     // on attend le capteur de butée haute
  pap_x_stop;            // on est arrivé en buttée haute
  x_max = x_abs;      // position maxi autorisée
 
  pap_x_send(0, true);  // retour à l'origine
  wait_x;                        // attendre que le moteur ait fini son déplacement

Voilà, maintenant, on a défini la zone entre les deux butées : [x_min à x_max]. x_abs est la position absolue du charriot (par rapport à x_min) et est mise à jour pour chaque déplacement moteur..

mes fonctions implémentées sont :

pap_x_go(boolean sens, boolean acceleration) : lance le moteur en avant (sens = true) ou en arrière (sens = false). si acceleration = true, alors le moteur accélèrera jusqu'à sa vitesse max, sinon, il restera à vitesse min (30Hz par défaut). le moteur ne s'arrêtera jamais tout seul, il faut faire un pap_x_stop pour l'arrêter. (ne tient pas compte des capteurs)

pap_x_step(int n, boolean acceleration) : fait avancer le moteur de n pas. si acceleration = true, le moteur accélèrera au démarrage et décélèrera pour s'arrêter au bon endroit...

pap_x_send(int absolu, boolean acceleration) : envoie le moteur à une position absolue (en gros, fait pap_x_step(absolu - x_abs, acceleration); ).

Ces trois fonctions démarrent le timer du moteur, ce qui fait qu'une fois appelées, on peut faire autre chose pendant que le moteur fait son train-train (d'où la fonction wait_x par exemple, qui attend simplement que le moteur soit arrêté).

Côté capteurs, je crois qu'en fait, l'arrivée de ma plaque d'epoxy dans la fourche ne provoque pas une coupure franche du signal. du coup, il se peut que l'interruption soit appelée, mais qu'entre temps, le capteur ait encore changé, et du coup, la lecture de la in correspondante ne renvoie pas ce qu'il faut. je devrais peut-être essayer dans un premier temps avec un shmidt direct au cul du capteur.

le capteur est branché comme suit :

led alimentée à 20mA par une résistance de 220ohms (donnée à 50mA max)
phototransistor émetteur à la masse, et collecteur direct sur pin nono avec pull-up du nono.
le tout avec des fils de 50cm en l'air (mais ça ne joue pas trop.

B@tto

A voir avec une R de pull up plus faible sinon (typiquement 4.7k)
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

68tjs


A voir avec une R de pull up plus faible sinon (typiquement 4.7k)

+1
A trop faible courant de collecteur la bande passante d'un transistor, donc son temps de réponse, n'est jamais terrible.
C'est la bonne solution que de diminuer sa résistance de charge de collecteur.
C'est aussi une bonne assurance pour ne pas être gêné par les courants de fuites qui fluctuent avec la température.

Super_Cinci

J'avais mis une résistance de 4,7k, au début en plus de la pull-up, mais je ne saturais plus le transistor (j'avais 0,6V, soit environ 9,4mA). les capteurs fourche n'ont pas un gros coëf de transfert... (rectif : j'ai 16,4mA dans la led, je devrais peut-être augmenter le courant à 30mA (rappel : 50 max)? ) un transfert IC / IF = 0,57, pas terrible...



Avec des petites leds qui m'indiquent ce que mon interruption détecte, je visualise un peux mieux ce qu'il se passe. en fait, comme il n'y a qu'un seul capteur, c'est le sens du moteur au moment de l'interruption qui détermine si c'est la butée haute ou basse (et aussi l'état de la pin à ce moment). ce qu'il se passe :

Le moteur descend, le capteur passe sur la butée basse, interruption -> stop moteur.
le moteur remonte, mais on est encore sur la butée, en quittant la butée, le capteur sautille un peu jusqu'à complètement quitter l butée, il y a donc des fronts montants, comme si on arrivait sur une butée -> le moteur monte, donc c'est pris pour une butée haute.

voilà : comment se retrouver avec une zone de 10 points...

Mon capteur fourche a une fourche de 3mm, ce qui est assez grand pour de l'opto, mais avec une plaque de 1,6mm qui passe dedans, il faut au moins ça. Mais ma plaque n'est pas très jolie sur les bords, donc en passant, elle ne coupe pas le faisceau d'un coup, mais plus ou moins, jusqu'à ce qu'elle occulte complètement. d'où mon idée de trigger matériel, mais aussi soft. dans mon programme de calibration, j'ai résolu le problème ainsi :

1 - trouver la butée basse, (dès le premier cri du capteur, on sait qu'on y est!)
2 - désactiver le capteur,
3 - remonter un peu (1 pouce),
4 - réactiver le capteur.

Là, on est bien sorti de la zone de turbullences. Si mon programme est bon, normalement, les capteurs ne devraient servir qu'au calibrage, et les moteurs par la suite ne devraient pas s'en approcher, sauf en cas de perte de pas.

Mais je me demande si rien qu'au niveau soft, je ne perds pas un pas à chaque mouvement... faut que je regarde ça de plus près...

B@tto

Dans la plupart des firmwares CNC le déclenchement d'une butée implique forcément une intervention humaine (ce qui est logique : butée = pièce foirée). Après je sais pas à quoi tu destines ton plateau
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

Super_Cinci


Dans la plupart des firmwares CNC le déclenchement d'une butée implique forcément une intervention humaine (ce qui est logique : butée = pièce foirée). Après je sais pas à quoi tu destines ton plateau
C'est pour ça que je ne me formalise pas trop au final. on pourrait même mettre des fin de course en // sur une seule entrée, car comme tu le dis, si on arrive en butée, c'est qu'il y a eu une couille quelque part, le soft doit normalement gérer les débordements.

Pour l'instant, le système que j'ai monté ressemble fort à un axe Y de CNC, on imaginerait donc le plateau comme support de l'axe Z (la tige filetée que j'ai préparée).

Go Up