Bonjour à tous,
Je tiens déjà à remercier les futurs "lecteurs". Je vais essayer d'être clair et concis. J'ai fait un programme assez complet qui permet, à partir de la fréquence de deux sondes HALL de générer 4 signaux de commandes de rapport cyclique 25% et déphasés de 90°... Jusque là ... ok. Les fréquences sont comprises entre 15 et 150Hz (je n'ai pas utilisé le PWM pour la génération car ça me posait des problèmes, j'ai opté pour le timer1).
Le problème arrive!! Il faut désormais que je fasse un asservissement PID car il ne faut pas que je génère les commandes brutalement mais avec un certain délais, une certaine accélération. C'est pourquoi je fais appel à vous. J'ai gratté l'exemple sur MicroChip et différent sites internet (fribotte ..) mais ça me parait très compliqué et ils passent tous par le PWM. Voici ce que j'ai tenté de faire pour le moment mais je suis bloqué :
Il y a surement des erreurs, n'hésitez surtout pas. J'ai trouvé des cours sympathiques sur le PID sur internet et mes souvenirs de BTS resurgissent (un peu) mais j'arrive pas à traduire tout ça en programmation. S'il vous semble nécessaire d'avoir ma génération de signaux via le timer1 n'hésitez pas.Code:void MAINPid () { // Calcul du terme intégrale i16SumE = i16SumE + i8En0; // Addition des erreurs if (i16SumE > SUM_E_MAX) { // Test si SumE trop grand ... i16SumE = SUM_E_MAX; // Alors le fixer à la valeur max } if (i16SumE < SUM_E_MIN) { // Test si SumE trop petit ... i16SumE = SUM_E_MIN; // Alors le fixer à la valeur min } // Le terme intégral est (Ts/Ti) * SumE où Ti vaut Kp/Ki // et Ts est la période d'échantillonnage // L'équation actuelle utilisée pour calculer le terme intégral est // Ki*SumE / (Kp * Fs * X) où X est le facteur d'échelle inconnu // et Fs est le fréquence d'échantillonnage i16IntegralTerm = i16SumE / 256; // Divisé par la fréquence d'échantillonnage i16IntegralTerm = i16IntegralTerm * i1Ki; // Multiplié par Ki i16IntegralTerm = i16IntegralTerm / 16; // Combinaison du facteur d'échelle et de Kp // Calcul du terme dérivé i16DerivativeTerm = i8En0 -i8En3; if (i16DerivativeTerm > 120) { // Test si le terme dérivé est trop grand .. i16DerivativeTerm = 120; // Alors le fixer à 120 } if (i16DerivativeTerm < 120) { // Test sur le terme dérivé est trop petit ... i16DerivativeTerm = -120; // Alors le fixer à -120 } // Le calcul du terme dérivé est (Td/Ts)[E(n) - E(n-1)] // Où Td est Kd/Kp // L'équation actuellement utilisée est Kd(en0-en3)/(Kp*X*3*Ts) i16DerivativeTerm = i16DerivativeTerm * i1Kd; // Où X est le facteur d'échelle inconnu i16DerivativeTerm = i16DerivativeTerm >> 5; // Divisé par 32 précalculé Kp*X*3*Ts if (i16DerivativeTerm > 120) { i16DerivativeTerm = 120; } if (i16DerivativeTerm < 120) { i16DerivativeTerm = -120; } // C(n) = K(E(n) + (Ts/Ti)SumE + (Td/Ts)[E(n) - E(n-1)]) i16Cn = i8En0 + i16IntegralTerm + i16DerivativeTerm; // Addition des termes i16Cn = i16DerivativeTerm * i1Kp / 1024; // Multiplié par Kp après échelonnage }
NB : Les éternels râleurs de forum (he oui y'en à toujours!), pas la peine de me dire "google est ton amis" ou autre ... j'ai fait bon nombre de recherches sans pouvoir avancer. On est ici pour de l'entraide alors faites part de vos connaissances (et elles sont souvent utiles!), pas de vos blabla!
Merci à tous pour votre attention et/ou futures réponses.
Julien
-----