2

Asservissement.net

Comme l’a dit précédemment PAC, cette année, pour le robot métallique, tout passe par du .net. Ou plus précisément en microframework.

Tout passer en .net, ça passe également par une migration de l’asservissement en .net. A première vue, cela peut paraître dangereux, le microFramework n’étant pas un OS temps réel, cependant notre expérience positive de l’an dernier sur la partie IA, capteurs et actionneurs nous a pousser à tenter l’asservissement.

Voici déjà en introduction une petite vidéo de ce que nous avons déjà réussi à obtenir (il reste à régler les PID mais c’est un bon début).

Je passe tous les concepts classique sur les PID de robot que l’on trouve très bien présentés sur d’autres site comme le club elekRCVA ou ce très complet ppt également de RCVA. Mon objectif est de faire un asservissement en polaire donc avec un PID pour l’angle et un pour l’avance.

Pour point de départ, nous sommes partit de ce code trouvé sur codeprojet.net : http://www.codeproject.com/Articles/49548/Industrial-NET-PID-Controllers

C’était un bon point de départ avec tout de même quelques défauts (boucle infinie, tests bizares autour du terme I…)

Dans les bons points, on note l’utilisation de delegate (pointeurs sur fonction) pour passer les valeurs d’entrée et de sortie, ainsi on peut utiliser une même classe pour plusieurs PID (dans notre cas, un polaire et un en distance).

Vous trouverez le code complet ici : MLRobotic.Asserv

Voici donc la partie simplifié du code que nous avons réalisé pour le point de calcul du PID :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private void Compute()
{
// récupération la valeur réelle obtenue par les codeurs
double pv = readPV();
// récupérer la valeur désirée
double sp = readSP();

//calcul d'erreur
double err = sp - pv;

// P
double pTerm = err * kp;

double iTerm = 0.0f;
double dTerm = 0.0f;

errSum += err;
// I
iTerm = ki * errSum;

// D
dTerm = kd * (pv - lastPV);

lastPV = pv;

// Somme des valeures
double outReal = pTerm + iTerm + dTerm;

// écrétage des valeurs maximum
outReal = Clamp(outReal, outMin, outMax);
// Valur de sortie
writeOV(outReal);
}

 

Pour éviter la boucle infinie, rien ne vaut un timer : Microsoft fait le travail pour nous :

1
2
3
4
public static void Enable()
{
ti = new System.Threading.Timer(new TimerCallback(Tick), null, computeDelay, computeDelay);
}

et ensuite, on considère les deux PID à mettre en place (polaire et distance), on les mets donc en static, et on les « compute » a chaque Tick :

1
2
3
4
5
6
7
8
9
public static PID pidAvance;
public static PID pidAngle;
private static void Tick(object sender)
{
if (pidAvance != null)
pidAvance.Compute();
if (pidAngle != null)
pidAngle.Compute();
}

Il ne reste alors qu’a initialiser le PID : je le présenterais dans un prochain article. Toute les sources sont de toute façon disponible ici.

EDIT : La suite ici

  1. [...] propos 0Asservissement.net (part. 2)Posted on mars 3, 2012 by Paul Nous avons déjà vu la base de notre asservissement en .netVoici maintenant la suite : comment intégrer ce PID dans le cadre de notre Robot, avec un [...]

  2. [...] un nouveau composant permettant de compter les pas de nos codeurs et s’interfacant avec notre carte d’asservissement de 2012. Nous nous sommes naturellment tournés vers un autre composant de chez LSI/CSI, le LS7366.Les [...]