cherche aide pour codage PID sur arduino !

  • Auteur de la discussion Doctor_itchy
  • Date de début
M

moissan

Compagnon
j'ai le même doute que toi , car il faut un circuit bien special pour faire compteur decompteur avec des signaux en quadrature

mais les codeur avec signaux en quadrature sont un truc si classique ... et la doc des microcontroleur est si longue que ça ne metonnerait pas que certain microcontroleur ai des compteur adaptable aux compteur en quadrature

et si le pic32 a 80MHz que je viens de citer n'a pas de compteur utilisable directement , et qu'il doit faire une interuption a chaque coup du codeur , il sera au moins plus rapide et poura faire plus de travail entre les interuption

attention aussi aux interuption sur un signal de codeur : le signal peut osciller rapidement autour d'un seul front : si le micro fait une interuption a chaque fois il n'a plus le temps de rien faire d'autre : il faut trouver un moyen de filtrer : quand le signal A a bougé , il ne faut plus faire d'interuption si le signal A bouge encore , car ce ne serais qu'une oscillation sur le même quart de pas : quand le signal A a bougé , il faut autoriser uniquement une interuption par le signal B : quand le signal B bougera il sera temps de lire le signal A pour savoir dans quel sens ça avance , inutile de savoir combien de fois ça a oscillé sur le même quart de pas

et bien sur quand le programe traite l'interuption sur B , il desactive l'intruption sur B et active A ...
 
E

erolhc

Guest
Il existe effectivement de micro avec des entrées spécifiques pour signaux en quadrature, j'en ai vu sur des PIC et des arm mais ceux-ci avaient la possibilité d'avoir 1 ou 2 encodeur et à coté de cela plétore d'autres I/O : trop d'I/O inutiles par rapport au faible nombre d'encodeurs possible pour les rares occasions ou j'aurais pu me servir de ces micro : donc circuits spécialisés ou des mini micro et communication avec le micro principal en I²C/SPI
Pour ce qui est du filtrage là encore j'ai un doute : en faisant ainsi tu diminues la résolution de positionnement par 2.(?) Bref c'est inutile de compter les "ticks" en résolution x4 pour en final se servir que de la résolution x2
Par ailleurs il me semble qu'a moins d'avoir un PID réglé à la perfection (parfait de chez parfait) un moteur-encodeur oscille toujours entre 2 "ticks"
 
R

roboba

Ouvrier
hello

je viens de tester la librairie "digitalWriteFast" pour l'arduino c'est deja mieux !
j'ai fait le test avec une manivelle electronique sortie TTL avec graduation de 0-99 sur les entrées interupt de l'arduino
je n'ais pas de perte de postion meme en tournant le plus vite possible (environ 3 tr/s soit 3X (100 X 4)=1200 cycles je pense )

il faut que je test sur les entrées " digital standard " voir si la lecture peux se faire aussi rapidement sans utiliser d’interruption
 
D

Doctor_itchy

Compagnon
oui il faut passer sur digitalfastwrite , sinon ça ne va pas , mais la nano as deux entrée "fast" que j'utilise pour l'encodeur

actuellement j'en suis pas plus loin que la derniere fois , ça fonctionne , mais quelque perte de pas vu qu'il n'y as pas de pid donc pas de corection de pas raté , juste immobilisation de l'axe

quand j'aurais un peu plus de temps je me remetrais as tout ça
 
M

moissan

Compagnon
ma façon de desactiver l'interuption de A quand on atend que B bouge , n'interdit pas de tenir compte de l'etat de A pour avoir les quart de pas , mais simplement en lisant son etat par la boucle de programme qui fait l'asservissement

oui le nombre d'entré pour codeur incremental des pic est limité ... donc pas moyen de faire 3 axe

je j'espere qu'avec un micro puissant comme le pic 32 on peut faire mieux

autre solution partager le travail : un micro qui fait le chef et remplace le PC et envoie des signaux step/dir pour chaque axe comme si c'etait des pas a pas , et un autre micro pour chaque axe qui recoit les step dir , et gere un seul asservissement , et un seul codeur incremental cablé sur son entré specifique compteur incremental

la solution d'un micro très puissant qui fait tout reduit le prix , mais bonjours les embrouille quand il y a des situation rare ou il n'y a pas le temps de tout faire
 
N

nopxor

Compagnon
Bonjour,

Pendant le déroulement d'un programme d'un microprocesseur RISC, comme les AVR ou les PIC, on a grosso-modo une instruction éxécutée par cycle d'horloge.

Soit pour un micro à 16 MHz par exemple, une instruction toutes les 62,5 ns.
Supposons que l'on ai un codeur incrémental avec 200 créneaux par tour sur un moteur tournant à 3000 Tr/mn.
On a donc 600000 impulsions par mn:
Soit une fréquence d'interruption de 10kHz à gérer.
(L'interprétation du sens de rotation se faisant par lecture de l'autre canal durant le sous programme d'IT.)

0,1ms / 62,5ns = 1600

On a donc le temps d'éxécuter 1600 instructions (moins les instructions de l'IT) entre chaque interruptions... C'est assez confortable.


Apréhender les grandeurs temporelles et le fractionnement d'une seconde par plusieurs millions (1 MIPS/ MHz) n'est pas forcément naturel.
Mais c'est important pour programmer.
Surtout les IT.
 
L

Louviau123

Apprenti
Bonsoir
Sans vouloir dénigrer ce qui a été déjà dit, as-tu posé ton problème sur le site d'Arduino ?
http://arduino.cc/forum/
A+
 
Dernière édition par un modérateur:
M

moissan

Compagnon
je suis bien d'accord que quand un codeur tourne a sa vitesse maximum il y a largement de quoi traiter les interuption

le probleme c'est a l'arret quand par malheur on est juste juste sur un seuil de commutation et que ça bagote avec les parasite : ça peut provoquer trop d'interuption

il y a des moyen analogique d'eviter le probleme : filtrage pour limiter la frequence maxi , ou hysteresis

1600 instruction c'est beaucoup , mais il faut combien d'instruction pour traiter uen interuption ? sauvegarder la tache en cours , traiter l'interruption proprement dite , remettre en marche la tache precedente ?

limiter la frequence de commutation par filtrage analogique est une difficulté , si frequence trop basse le signal utile ne passe pas ... si trop haute on peut surcharger le micro ... surtout si il y a plusieur axe a gerer

en autorisant l'interuption uniquement sur le bon signal on resoud le probleme sans avoir de parametre analogique a choisir
 
N

nopxor

Compagnon
Le signal du codeur est généralement propre (issu d'un trigger de Schmitt).
Il faut déclencher l'IT sur seuil, pas sur front.
Le "bagotage à l'arrêt" se détecte par l'inversion du canal sens.
De plus on peut supposer que 1/200 de tour du moteur est amorti par l'ensemble mécanique en aval.
Pourquoi filtrer analogiquement un signal numérique si on peut traiter de façon numérique le problème ?

moissan a dit:
1600 instruction c'est beaucoup , mais il faut combien d'instruction pour traiter uen interuption ? sauvegarder la tache en cours , traiter l'interruption proprement dite , remettre en marche la tache precedente ?
Par définition un sous-programme d'IT se doit d'être court. (Les calculs se font dans le corps du programme.)
Quelques lignes de code au plus.
Il s'agit généralement d'incréments de compteurs, de lecture d'un timer etc...
le traitement de l'IT (gestion du pointeur de pile) est optimisé par le compilateur.Moins de 10 instructions...
 
M

moissan

Compagnon
donc tout va bien pour gerer un codeur qui fait jusqu'a 10kHz , ce qui parait suffisant pour une machine moyenne

le probleme se pose quand on veut a la fois grande resolution et grande vitesse

dans le genre couper les centieme en 4 et avancer a 1m/s

1000mm/s / 0,0025mm = 400 000 Hz ... et la ça devient plus difficile a suivre que 10kHz ... mais reste possible
 
D

Doctor_itchy

Compagnon
je tient a expliquer un truc sur mon montage

il y as une arduino nano par axe , et en position "arret" ça ne bouge pas et cela sans pid de programmé ! , les déplacement sont rapide et fluide , et chaque arret est stable !

le seul problème du code c'est d'y intégré un pid automatique les entrée son ok , la vitesse d'encodage est ok c'est un nano V2 avec un uc plus rapide que la version nano de base , et un port usb sur la carte qui facilite les programmation in situ

donc pas besoin d'un uc plus rapide celui çi est très suffisant
 
N

nopxor

Compagnon
Gérer un signal de 400 kHz est à la portée de pas mal de processeurs.
Par contre, contrôler une machine qui coupe les cheveux en 40 se positionne au 1/4 de centième avec des déplacements de 1 m/s n'est pas une mince affaire...
Il faut (entre autre) prendre en compte le Jerk (dérivée de l'accélération) et le Yank (produit de la masse par le Jerk).
 
E

erolhc

Guest
Doc : il y a une librairie qui gere l'auto tune pour l'arduino (lien déjà donné plus haut)

Moissan : 1m/s c'est déjà la limite que les règles optiques habituelles sont capable d'encaisser si on parle de codeurs linéaire.

Par ailleurs quand l'encodeur à une résolution trop importante/vitesse trop rapide inutile de prendre des micro de course, il faut juste peaufiner la la fréquence de l'encodeur, et le coder le résultat pour l'envoyer en protocole série sur le micro processeur. De toute façon au delà de 500kHz ça fait une réponse de2 µS pour gérer le moteur ce qui à mon avis doit être délicat avec les inerties etc ... et cela doit être des applications particulières si jamais cela existe
Les drivers de servo sont passés d'une bande passante d’environ 600kHz quand l'envoi des données était en quadrature (2500x4 à 3600 tr/min) à quelques kHz quand le codage s'est fait en série (1.6kHz sur les yaskawa serie V) avec des codeurs sur 17-20 bits.

Sans compter que c'est bien beau de décoder à haute vitesse/haute résolution mais dans le cas de servo il faut aussi envoyer les dir/step à ces fréquences et pour une CNC d'usinage je suis pas sur que cela soit utile
 
M

moissan

Compagnon
bien sur qu'il est rarement utile d'avoir a la fois la grande precision et la grande vitesse , sauf que quand une machine qui a besoin d'une grande precision a faible vitesse a aussi besoin de vitesse rapide , il faut bien que ça suive

mais par chance , a grande vitesse il n'y a pas besoin de suivre les quadrature ! on sait dans quel sens ça tourne donc on peut changer de programme au dessus d'une certaine vitesse

pour un asservissement il faut une resolution suffisament superieur a la precision pour que l'asservissement puisse corriger avant de sortir de la precision demandé

c'est une difference entre pas a pas et asservissement avec codeur : en pas a pas la resolution utile est egale a un pas , ou meme moins avec les micro pas : en asservissement il faut une resolution du codeur superieur a la resolution souhaité pour que l'asservissement fasse sont travail : donc frequence du codeur superieure a la frequence d'un pas a pas pour la même fonction

et pour un micro generer une frequence est plus facile que de suivre une frequence exterieure sans rien perdre

donc le travail de l'asservissement est plus difficile a tous les niveaux que la commande d'un pas a pas ... mais j'ai commandé des pic32 olimex ... et je pense qu'il y a de quoi faire

le calcul de frequence en divisant vitesse par resolution est valable quelle que soit la realisation ... regle lineaire ou codeur rotatif sur le moteur

pour la stabilité de l'asservissement il faut de toute façon un codeur directement sur le moteur ... celui qui veut un codeur lineaire pour une meilleure precision doit faire une double boucle d'asservicement
 
D

Doctor_itchy

Compagnon
le code je le connais j'ai fouiller ça , mais c'est asservisement en vitesse la , ideal pour une broche ou moteur de robot simple , mais pas du tout en position :/
 
N

nopxor

Compagnon
Il faut un double asservissement vitesse et position avec rampe d'accélération et décélération.
L'asservissement en position se programme comme pour la vitesse, c'est lui qui détermine la consigne vitesse.

voir ce document p11 et code en p14:
http://www.totofweb.net/projets/pid/rapport.pdf
 
Dernière édition par un modérateur:
D

Doctor_itchy

Compagnon
hello

bon alors apres un long moment j'ai repris le codage de mon set arduino nano et drivers dc

ettttt j'ai repris le code depuis le début , avec passage forçer au code arduino :D

j'ai avec l'aide du net , de bout de code , refait mon code servo qui fonctionne :D

plus de perte de pas

reste as réglé le pid correctement car la vitesse n'est pas optimale (25khz en entrée et le moteur tourne au 1/3 de sa vitesse nominale ) et le "zero" n'est pas parfait , reglage de l'integral et dérivée as faire encore

je met le code

"/*

ce programme sert as controler un moteur DC en boucle fermer avec PID
le mouvement est detecter par un encodeur as quadrature en mode X4
deux entree nommee STEP et DIR permete le controle du moteur avec un
controleur classique de cnc
le code as ete cree pour un arduino nano avec port usb !
le port serie affiche la position courante de l'axe toute les secondes
ce code as ete fait avec l'aide de la communauter arduino et de ses librairie libre
toute utilisation de ce code ne peu etre commerciale .

pin utilisee:
entree Digitale D2 et D8 pour l'encodeur AB
entree Digitale D3 pour le STEP
entree Analogique A0 pour le DIR
sortie Digitale 9 et 10 pour le pont en H
sortie Digitale 4 pour l'activation du pont en H , possible mise as jour avec gestion
courant max moteur , entree enable securiter diverse


ATTENTION les valeur Kp, Ki, Kd, doivent etre ajustee selon votre moteur/encodeur/charge sur l'axe
en tant que tel il ne pourrais pas fonctionner correctement

Doctor_itchy
*/
#include "Arduino.h"
#include <PinChangeInt.h>
#include <PinChangeIntConfig.h>
#include <PID_v1.h>
#define encoder0PinA 8 // encodeur A
#define encoder0PinB 2 // encodeur B
#define M1 9 // sortie pwm moteur A
#define M2 10 // sortie pwm moteur B
#define enable 4 // activation pont en H

double kp=2,ki=0,kd=0;
double input=80, output=0, setpoint=180;
PID myPID(&input, &output, &setpoint,kp,ki,kd, DIRECT);

volatile long encoder0Pos = 0;

long previousMillis = 0; // enregistre la derniere position

long target1=0;

//pour le controle via ramps 1.4
bool newStep = false;
bool oldStep = false;
bool dir = false;

void setup() {
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
pinMode(enable, OUTPUT);
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
digitalWrite(enable, HIGH);
PCintPort::attachInterrupt(encoder0PinB,doEncoderMotor0,CHANGE); // permet l'utilisation du mode 4x de l'encodeur as desactiver si besoin
//attachInterrupt(0, doEncoderMotor0, CHANGE); // pin de l'encodeur sur l'interruption 0 pin 2 as désactiver si le mode 4* est utiliser )
attachInterrupt(1, countStep, RISING); //entree step sur pin 3
TCCR1B = TCCR1B & B11111000 | B00000001; // frequence pwm pour la sortie , as changer si moteur bruyant


Serial.begin (115200);

//configuration du pid
myPID.SetMode(AUTOMATIC);
myPID.SetSampleTime(1);
myPID.SetOutputLimits(-255,255);
}

void loop(){
input = encoder0Pos;
setpoint=target1;
myPID.Compute();
pwmOut(output);
if(millis() > previousMillis+1000 ) {Serial.print(encoder0Pos); Serial.print("->"); Serial.println(target1); previousMillis=millis(); }
if(Serial.available()) target1=Serial.parseInt();

}

void pwmOut(int out) {
if(out<0) { analogWrite(M1,0); analogWrite(M2,abs(out)); }
else { analogWrite(M2,0); analogWrite(M1,abs(out)); }
}


void doEncoderMotor0(){
if (((PIND&B0000100)>>2) == HIGH) {
if ((PINB&B0000001) == LOW) {
encoder0Pos-- ;
}
else {
encoder0Pos++ ;
}
}
else
{
if ((PINB&B0000001) == LOW) {

encoder0Pos++ ;
}
else {
encoder0Pos-- ;
}
}
}

void countStep(){
if (PINC&B0000001) target1++;
else target1--;
}

"

voila si l'un d'entre vous as une idée d'amélioration ou cherche un code pour leur cnc
 
D

Doctor_itchy

Compagnon
j'ai modifier le code , j'ai omis de désactiver une interuption en mode 4* et cela buggais ^la c'est impecable , il faut juste bien régler le pid pour votre moteur

perf pas mal , on tourne as 3000t/min au moteur départ arreté quasiment instantané répétabilité parfaite , stabilité du pid nikel (apres réglage du pid )

prochaine etape , config d'une pin d'etat du drivers ( error/initialitation/ok )

puis apres mode autopid pour ceux qui ne veulent pas passer 2 heure as réglé le pid ^^

personne pour se faire un drivers servo dc maison ?
 
D

ducran lapoigne

Compagnon
bonsoir doc

je suis ton post depuis le début (en silence ....)

j' ai récupéré quelques servos DC d' imprimantes IBM (30v 80w codeur 900 imp/tour)
a ton avis, avec l' arduino et un driver genre L298, cela va le faire ou bien je vais dans le mur ?

ton servo sera pour ta dernière cnc ?

++ sur le fofo
Antoine
 
D

Doctor_itchy

Compagnon
l298 ça doit tourné mais c'est pour 2 moteur de 2ampere 30volt

je te conseil le l6203 4ampere jusque 5 si tres bien refroidit mon code as ete fait pour 2 sortie pwm de commande et une sortie enable

j'ai un lot de ses composant il sont assez solide j'en suis content

oui c'est prévu pour ma cnc
 
D

Doctor_itchy

Compagnon
nouvelles modification du code

/*

ce programme sert as controler un moteur DC en boucle fermer avec PID
le mouvement est detecter par un encodeur as quadrature en mode X4
deux entree nommee STEP et DIR permete le controle du moteur avec un
controleur classique de cnc
le code as ete cree pour un arduino nano avec port usb !
le port serie affiche la position courante de l'axe toute les secondes
ce code as ete fait avec l'aide de la communauter arduino et de ses librairie libre
toute utilisation de ce code ne peu etre commerciale .

pin utilisee:
entree Digitale D2 et D8 pour l'encodeur AB
entree Digitale D3 pour le STEP
entree Analogique A0 pour le DIR
sortie Digitale 9 et 10 pour le pont en H
sortie Digitale 4 pour l'activation du pont en H , possible mise as jour avec gestion
courant max moteur , entree enable securiter diverse


ATTENTION les valeur Kp, Ki, Kd, doivent etre ajustee selon votre moteur/encodeur/charge sur l'axe
en tant que tel il ne pourrais pas fonctionner correctement

Doctor_itchy
*/
#include <digitalWriteFast.h>
#include "Arduino.h"
//#include <PinChangeInt.h>
//#include <PinChangeIntConfig.h>
#include <PID_v1.h>
#define encoder0PinA 8 // encodeur A
#define encoder0PinB 2 // encodeur B
#define M1 9 // sortie pwm moteur A
#define M2 10 // sortie pwm moteur B
#define enable 4 // activation pont en H


double kp=5.2,ki=200,kd=0.010000;


//double kp=2.25,ki=0.25,kd=0;

double input=80, output=0, setpoint=180;
PID myPID(&input, &output, &setpoint,kp,ki,kd, DIRECT);

volatile long encoder0Pos = 0;

long previousMillis = 0; // enregistre la derniere position

long target1=0;

//pour le controle via ramps 1.4
bool newStep = false;
bool oldStep = false;
bool dir = false;

void setup() {
pinModeFast(encoder0PinA, INPUT);
pinModeFast(encoder0PinB, INPUT);
pinModeFast(3,INPUT);
digitalWrite(encoder0PinA,LOW);
digitalWrite(encoder0PinB,LOW);
digitalWrite(3,LOW);
pinModeFast(enable, OUTPUT);
pinModeFast(M1, OUTPUT);
pinModeFast(M2, OUTPUT);
digitalWrite(enable, HIGH);
//PCintPort::attachInterrupt(encoder0PinB,doEncoderMotor0,CHANGE); // permet l'utilisation du mode 4x de l'encodeur as desactiver si besoin mais demande une freq 4 x superieur 125hz
attachInterrupt(0, doEncoderMotor0, CHANGE); // pin de l'encodeur sur l'interruption 0 pin 2 (desactiver si le mode4x est activer!)
attachInterrupt(1, countStep, RISING); //entree step sur pin 3
TCCR1B = TCCR1B & B11111000 | B00000001; // frequence pwm pour la sortie , as changer si moteur bruyant


Serial.begin (115200);

//configuration du pid
myPID.SetMode(AUTOMATIC);
myPID.SetSampleTime(1); // code 2 si pcintport couper , code 1 si activer
myPID.SetOutputLimits(-255,255);
}

void loop(){
input = encoder0Pos;
setpoint=target1;
myPID.Compute();
pwmOut(output);
if(millis() > previousMillis+250 ) {Serial.print(encoder0Pos); Serial.print("->"); Serial.println(target1); previousMillis=millis(); }
if(Serial.available()) target1=Serial.parseInt();





}

void pwmOut(int out) {
if(out<0) { analogWrite(M1,0); analogWrite(M2,abs(out)); }
else { analogWrite(M2,0); analogWrite(M1,abs(out)); }
}


void doEncoderMotor0(){
if (((PIND&B0000100)>>2) == HIGH) {
if ((PINB&B0000001) == LOW) {
encoder0Pos-- ;
}
else {
encoder0Pos++ ;
}
}
else
{
if ((PINB&B0000001) == LOW) {

encoder0Pos++ ;
}
else {
encoder0Pos-- ;
}
}
}

void countStep(){
if (PINC&B0000001) target1++;
else target1--;
}

j'ai viré le pinchange qui devait théoriquement multiplier la résolution , ça bug trop il y as une perte de quelque pas , que je n'ai pas en mode classique ( qui offre quand meme 1000pas par tour avec un codeur 500pas

en mode console cela fonctionne tres tres bien (code "cr" suivis du nombre de pas , et code LF pour retour au zero ! ) et pas de perte de pas ! , par contre en mode step dir , il me perd toujours quelque pas quand je lui demande de grand déplacement , donc soit ma carte hycnc déconne ,soit le cablage entre les deux as des parasite, soit l'arduino ne suis pas as grande vitesse ! ( et en mode fastwrite pour les entrée ça ne change rien ! )

donc il me reste as revoir cette partie du code , mais bizzarement je n'avais pas constaté cette perte de pas en mode step dir la derniere fois ? , allez comprendre ^^
 
D

Doctor_itchy

Compagnon
probleme de perte de pas résolu , j'ai mal parametré un code de base


/*

ce programme sert as controler un moteur DC en boucle fermer avec PID
le mouvement est detecter par un encodeur as quadrature en mode X4
deux entree nommee STEP et DIR permete le controle du moteur avec un
controleur classique de cnc
le code as ete cree pour un arduino nano avec port usb !
le port serie affiche la position courante de l'axe toute les secondes
ce code as ete fait avec l'aide de la communauter arduino et de ses librairie libre
toute utilisation de ce code ne peu etre commerciale .

pin utilisee:
entree Digitale D2 et D8 pour l'encodeur AB
entree Digitale D3 pour le STEP
entree Analogique A0 pour le DIR
sortie Digitale 9 et 10 pour le pont en H
sortie Digitale 4 pour l'activation du pont en H , possible mise as jour avec gestion
courant max moteur , entree enable securiter diverse


ATTENTION les valeur Kp, Ki, Kd, doivent etre ajustee selon votre moteur/encodeur/charge sur l'axe
en tant que tel il ne pourrais pas fonctionner correctement

Doctor_itchy
*/
#include <digitalWriteFast.h>
#include "Arduino.h"
//#include <PinChangeInt.h>
//#include <PinChangeIntConfig.h>
#include <PID_v1.h>
#define encoder0PinA 8 // encodeur A
#define encoder0PinB 2 // encodeur B
#define M1 9 // sortie pwm moteur A
#define M2 10 // sortie pwm moteur B
#define enable 4 // activation pont en H


double kp=5.2,ki=200,kd=0.010000;


//double kp=2.25,ki=0.25,kd=0;

double input=80, output=50, setpoint=180;
PID myPID(&input, &output, &setpoint,kp,ki,kd, DIRECT);

volatile long encoder0Pos = 0;

long previousMillis = 0; // enregistre la derniere position

long target1=0;

//pour le controle via ramps 1.4
bool newStep = false;
bool oldStep = false;
bool dir = false;

void setup() {
pinModeFast(encoder0PinA, INPUT);
pinModeFast(encoder0PinB, INPUT);
pinModeFast(3,INPUT);
digitalWrite(encoder0PinA,LOW);
digitalWrite(encoder0PinB,LOW);
digitalWrite(3,LOW);
pinModeFast(enable, OUTPUT);
pinModeFast(M1, OUTPUT);
pinModeFast(M2, OUTPUT);
digitalWrite(enable, HIGH);
//PCintPort::attachInterrupt(encoder0PinB,doEncoderMotor0,CHANGE); // permet l'utilisation du mode 4x de l'encodeur as desactiver si besoin mais demande une freq 4 x superieur 125hz
attachInterrupt(0, doEncoderMotor0, CHANGE); // pin de l'encodeur sur l'interruption 0 pin 2 (desactiver si le mode4x est activer!)
//attachInterrupt(1, countStep, RISING); //entree step sur pin 3
attachInterrupt(1, countStep, FALLING);
TCCR1B = TCCR1B & B11111000 | B00000001; // frequence pwm pour la sortie , as changer si moteur bruyant


Serial.begin (115200);

//configuration du pid
myPID.SetMode(AUTOMATIC);
myPID.SetSampleTime(1); // code 2 si pcintport couper , code 1 si activer
myPID.SetOutputLimits(-255,255);
}

void loop(){
input = encoder0Pos;
setpoint=target1;
myPID.Compute();
pwmOut(output);
if(millis() > previousMillis+250 ) {Serial.print(encoder0Pos); Serial.print("->"); Serial.println(target1); previousMillis=millis(); }
if(Serial.available()) target1=Serial.parseInt();





}

void pwmOut(int out) {
if(out<0) { analogWrite(M1,0); analogWrite(M2,abs(out)); }
else { analogWrite(M2,0); analogWrite(M1,abs(out)); }
}


void doEncoderMotor0(){
if (((PIND&B0000100)>>2) == HIGH) {
if ((PINB&B0000001) == LOW) {
encoder0Pos-- ;
}
else {
encoder0Pos++ ;
}
}
else
{
if ((PINB&B0000001) == LOW) {

encoder0Pos++ ;
}
else {
encoder0Pos-- ;
}
}
}

void countStep(){
if (PINC&B0000001) target1++;
else target1--;
}

la mnt c'est impec mouvement moteur précis au tick pret peu importe la vitesse et la distance parcourue , reste as coder en 4x l'encodeur , mais je doit utilisé deux intruption sur l'arduino et j'ai peur que cela fonctionne moins bien , vu que la deuxiemme sert pour l'entrée step ! , as moins de trouver une autre astuce ^^

apres c'est l'autopid (car faut le dire en manuel c'est galere ! ou alors je doit trouver un moyen d'afficher la courbe de réponse de position sur le pc via l'usb de l'arduino et la on vois tout de suite ce que l'on doit modifier
 
Y

Yakov TOPRAK

Compagnon
Bonsoir,
je suis tombé la dessus par hasard car j'ai des problèmes de perte de pas sur une moteur hybride.
Beau boulot.
Tu as réussi à coder en 4x l'encodeur ?
 
D

Doctor_itchy

Compagnon
ha un projet similaire , j'aime bien

alors non le code est en 2 x , car j'utilise une entrée du signal codeur pour le "pulse" et l'autre pour le "sens" je peu le faire en 4 x mais la vitesse sera réduite par 2 ! je doit encore travaillé le code pour changer ça il y as surement un truc simple que j'ai zapper mais comme je ne suis pas un pro du code ...

de plus je vais recodé en "pur" C et programé differement comme j'ai fait pour grbl ça permet de soulager le cpu qui doit calculé plus avec le code arduino donc en théorie on devrais gagner en vitesse de rotation et en temps de réactiviter

mais plus de temps libre actuellement donc de coter
 

Sujets similaires

D
Réponses
9
Affichages
599
Doctor_itchy
D
V
Réponses
214
Affichages
77 254
roboba
R
D
Réponses
9
Affichages
3 449
David80
D
Réponses
4
Affichages
4 828
taratata
D
Réponses
15
Affichages
6 115
Doctor_itchy
D
Réponses
31
Affichages
7 955
adriboss
Réponses
41
Affichages
22 038
stef1204
D
Réponses
13
Affichages
4 977
******
?
V
Réponses
37
Affichages
8 400
v tec
V