- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.
--- L’équipe FantasPic ---
Modérateur : Jérémy
Je suis sur un PIC 18F et je rencontre un problème avec l'utilisation d'un servo moteur....
Quartz = 4MHz
J'utilise le Timer 0 et cherche donc à générer des impulsions de 1 => 2ms avec une période de 20ms.
Je l'ai configuré comme suis :
Code : Tout sélectionner
//TIMER 0
T0CON1bits.T0CS = 0b010; //FOSC/4
T0CON1bits.T0ASYNC = 0; //The input to the TMR0 counter is synchronized to FOSC/4
T0CON1bits.T0CKPS = 0b0000; //Préscaler 1:1
TMR0H = 200 ; //TIMER0 COUNT REGISTER
T0CON0bits.T0EN = 1; // The module is enabled and operating
T0CON0bits.T016BIT = 0; //TMR0 is an 8-bit timer
T0CON0bits.T0OUTPS = 0b0000; //1:1 Postscaler
PIE0bits.TMR0IE=1; //Timer 0 interrupt enable
/*INTERRUPTIONS*/
INTCONbits.GIEH=1; //Global Interrupt Enable bit
INTCONbits.PEIE=1; //Peripheral Interrupt Enable bit
INTCONbits.IPEN=0; //Interrupt Priority Enable bit
counterB = 10; // 2ms
Dans l'interruption :
Code : Tout sélectionner
if(PIR0bits.TMR0IF == 1) // Timer 0
{
counter = counter + 1;
if (counter == counterB)
{
TEST = 0;
}
if (counter == 100)
{
counter = 0;
TEST = 1;
}
PIR0bits.TMR0IF = 0;
}
4MHZ / 4 1µs
Pas de préscaler/post scaler
J'attends 200 cycles => 200µs puis encore 100 cycles 20ms.
En cours de route, counterB permet de monter ou baisser la pwm.
PS : si en parallèle je fais un bête DELAY de 2 secondes... mon délais réel fait presque 4 secondes... et cela m'étonne d'une si grande différence...
Résultat :
A l'oscilloscope, j'obtiens exactement ce que je souhaite en terme de forme de courbe.
Le servo se rends bien à la bonne position, MAIS il a ensuite la tremblote.
(dur a expliquer)
Une fois a la bonne position, le servo va faire trois petites secousses, une pause, puis recommencer. C'est quelque chose de périodique.
Cela fait la même chose sur n'importe quel servo.
Auriez vous des conseils ?
Merci par avance !!
Hoffmann
-
cyril13110
Confirmé- Messages : 740
- Âge : 41
- Enregistré en : avril 2016
- Localisation : 13
si le servo tremblote cest que ton signal n'est pas stable. Dans un post sur le forum, je ne sais plus qui a parlé de la sensibilité des servomoteurs, mais il me semble qu'un servo classique de memoire etait semsible a une variation de quelques dizaines de microsecondes.
as tu regardé à l'oscilloscope la stabilité du signal dans le temps et surtout au moment ou ca tremble?
apres au sujet de ton code, la partie interruption doit etre le plus petit possible.
teste aves seulement l'incrementation de ta variable.
le restr du code tu le mets dans le programme principal ou dans une sous fonction simple.
-
Jérémy
Administrateur du site- Messages : 2725
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
Il faudrait que nous indique un lien vers la DS de ton PIC : procédure
SAns quoi o nen peut pas verifier si les registres sont les bons.
Si déjà avec un delay de 2 secondes tu obtiens un temps de 4 secondes, tu auras forcement des problèmes ! fais clignoter une LED pour commencer et surtout vérifier que tout fonctionne correctement.
Les servos moteurs ne fonctionne pas tous pareils, je ne sais pas combien tu en as testé ? mais essaye de le mettre plutôt 1.8ms plutôt que 2ms . 2ms c'est peu être trop les servos peuvent arriver en buter.
Les alimentations sont-elles bien découplées ? le schéma du montage ?
Une photo de ton signal au scope ?
J'ai pris pour habitude de ne jamais vérifier une égalité parfaite dans une INT . Car si pour une raison ou une autre tu loupe cette égalite le programme part en vrille.
Code : Tout sélectionner
if (counter == counterB)
{
TEST = 0;
}
A remplacer par :
Code : Tout sélectionner
if (counter >= counterB)
{
TEST = 0;
}
Et il faudrait la partie qui gère aussi les impulsions de ton programme ? est ce la variable "TEST" ?
Essaye de nous amener le plus d'infos possibles car la c'est un peu juste, les raisons peuvent être multiples
Voici le lien vers la Datasheet
J'ai bien modifié le code de l'interruption
Code : Tout sélectionner
if(PIR0bits.TMR0IF == 1) // Timer 0
{
counter = counter + 1;
if (counter >= counterB)
{
TEST = 0; // Sortie PWM
}
if (counter == 100)
{
counter = 0;
TEST = 1; // Sortie PWM
}
PIR0bits.TMR0IF = 0;
}
J'ai testé sur 4 servo différents : même problème...
Le #define test correspond a D0.
TRISDbits.TRISD0 = 0; // TEST
#define TEST LATDbits.LATD0
Les delay pur et dur fonctionnent très bien quand le TMR0 n'est pas activé. Dès qu'il est activé, je double les temps sans le vouloir...
Les alimentations sont bien découplés. La mise en position initiale du servo se passe bien, mais je n'arrive pas a comprendre pourquoi, au bout de x secondes il se mets a rebouger, puis pause, puis recommence. Très périodique.....
-
Jérémy
Administrateur du site- Messages : 2725
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
tout d'abord, merci de suivre la procédure pour mettre la Data-sheet de ton PIC comme indiqué ici : procédure
Ainsi la DS apparaitras dans tous les posts, pas besoin de cherche le post où tu l'a mise. Cela arrange tout le monde
Ta DS donne plusieurs PIC lequel utilises tu ?
Je nz comprends rien à la configuration de ton Timer0 ! Je pense que tu as fait des copier coller non ? un PIC ca demande plus d'effort et d'amour qu'un Arduino !
par exemple :
Code : Tout sélectionner
PIR0bits.TMR0IF == 1
Le flag du Timer0 se tropuve dans le registre INTCONet pas PIR0. d'ailleur PIR0 n'existe pas ou je l'ai pas vu !
TOUTE ta configuration du timer0 est à refaire ! les registre n'existe même pas !
Code : Tout sélectionner
T0CON0bits.T016BIT = 0; //TMR0 is an 8-bit timer
Page 125 de la DS, on voit qu'il faut mettre le bit T08BIT à 1 pour avoir un compteur de 8bit ?
Soit c'est la mauvaise DS......soit c'est le mauvais PIC lol .
-
Jérémy
Administrateur du site- Messages : 2725
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
Il faudrait le programme en entier pour y voir plus clair !
regarde déjà ici pour vérifier la configuration de ton timer0: viewtopic.php?f=27&t=71
Ensuite fais clignoter une led toute les secondes avec ce timer0 ensuite se sera gagné .
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
Peux-tu montrer ton code en entier ...
avec XC8 est-ce que la fonction Delay utilise un timer ou interrupt ?
sinon ressaie de remplacer ta fonction Delay de 2sec par une boucle de comptage
Code : Tout sélectionner
void Delay_2sec() // 1.956 sec
{
unsigned long L1=110000;
while(L1>0) L1--;
}
pour etre plus precis , au lieu d'etre à +-200µS de resolution ,
tu pourrais utiliser le Timer0 en mode 16bits.
et augmenter FOSC de 4 à 16Mhz, 32 voir 64Mhz
Alors,
Je suis bien en 5V partout et l'alimentation semble tenir le coups !
Voici mon code de paramétrage des registres :
Code : Tout sélectionner
//TIMER 0
T0CON1bits.T0CS = 0b010; //FOSC/4
T0CON1bits.T0ASYNC = 0; //The input to the TMR0 counter is synchronized to FOSC/4
T0CON1bits.T0CKPS = 0b0000; //Préscaler 1:1
//TMR0H = 200 ; //TIMER0 COUNT REGISTER
T0CON0bits.T0EN = 0; // The module is enabled and operating
T0CON0bits.T016BIT = 0; //TMR0 is an 8-bit timer
T0CON0bits.T0OUTPS = 0b0000; //1:1 Postscaler
Voici l'interruption :
Code : Tout sélectionner
if(PIR0bits.TMR0IF == 1) // Timer 0
{
counter = counter + 1;
if (counter >= counterB)
{
TEST = 0; // Sortie PWM
}
if (counter == 75)
{
counter = 0;
TEST = 1; // Sortie PWM
}
PIR0bits.TMR0IF = 0;
}
et dans mon main :
Code : Tout sélectionner
counterB = 8; // ou 4
T0CON0bits.T0EN = 1;
Alors, aujourd'hui ça fonctionne :) Je ne sais trop guerre pourquoi. (Peut être parceque je ne renseigne plus le TMR0H = 200 ;) ?
Le servo est stable.
Par contre, je sens que toute la puissance de mon pic part dans cet interruption :(
Meilleur moyen de le savoir, la fonction qui ne fait rien que perdre du temps
=> Au lieu de perdre 1 seconde (normal), je perds environ 1,7 seconde...
J'en déduis que je passe presque 70% de mon temps dans cette interruption... :(
J'aimerai bien, moins déclencher l'interruption. Mais je pense que la vitesse de mon horloge à 4MHz est trop faible non ?
Qu'en pensez-vous ?
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 51 invités