Aller au contenu


transistance

Inscrit(e) (le) 19 nov. 2006
Déconnecté Dernière activité sept. 20 2015 10:21
*****

Sujets que j'ai initiés

SUPRA

24 mars 2015 - 07:58

Je vous présente SUPRA, mon projet robotique actuel !
 
Ce robot est une plateforme d'essai pour mettre en pratique les asservissements. Pour l'instant c'est un simple prototype, peu de soin à été apporté à l'esthétique. Si les essais sont concluants je ferais quelque-chose de correct.
 
Depuis que j'arrive à faire des robots pas trop naze j'ai eu l'envie de comprendre comment ce genre d'algorithme fonctionne parceque mine de rien, maintenir un cap ou une vitesse c'est quasi indispensable quand on cherche à faire de la navigation avec ses robots !
 
Objectifs:

  • Me familiariser avec différents asservissements (vitesse, position, polaire).
  • Faire connaissance avec les AVR.

Mécanique:
Comme je le disais, la partie mécanique de ce projet est trés rudimentaire et c'est totalement voulu. J'ai pas perdu de temps pour aller à l'essentiel de ce projet.
 
Electronique:
Pour ce projet qui est destiné à tester plusieurs configurations, j'ai décidé d'opter pour une architecture carte fond de panier + cartes filles enfichables.
Une carte est dédiée à la gestion de l'asservissement tandis qu'une autre (pas encore réalisée) sera dédiée à commander le robot.
 
Informatique:
Ce n'est pas mon domaine de prédilection et pourtant c'est 90% du travail sur ce projet... aoutch!
J'ai commencé par coder un asservissement en vitesse pour un seul moteur.
Actuellement je travail sur un asservissement polaire (angle et distance) qui semble bien marcher mais qui nécessite encore pas mal de travail. Je compte y adjoindre l'asservissement en vitesse précedemment développé.
 
 
Voici la bestiole sans son électronique:
chassis_filig.jpg
 
... et avec :
supra_tq1.jpg
 
supra_tq2.jpg
 
supra_top.jpg


Asservissement polaire

08 mars 2015 - 07:15

Après m'être fait la main sur un asservissement en vitesse d'un moteur, je m'attaque à l'asservissement polaire. J'aurai ainsi une consigne de distance et une consigne d'angle qui prend en compte l'ensemble des 2 moteurs.

Au début j'ai lu pas mal de pages internet sur le sujet, j'ai griffoné pas mal de schémas bloc, je me suis demandé comment j'allais traduire ça en code et puis, petit à petit, je suis arrivé à un truc qui semble tenir la route.
Il n'y a plus que deux points que je n'arrive pas à comprendre et dont je n'ai pas trouvé les réponses en cherchant moi même. C'est la raison de ce post.   

Premier point:
Dans mon asservissement en vitesse je commence par mesurer la vitesse de rotation de la roue grâce aux nombre de "tick" compté par les encodeurs. Les "tick" sont ensuite remis à 0 pour l'échantillon suivant.
Pour l'exemple, un extrait de ma fonction d'asser en vitesse:

// affectation des compteurs de PID et reset des compteurs sur interruption
        compteurD = tickD;
        tickD = 0;
        mesure_vit_d = (freq_ech*compteurD)/tick_trm/reduction;    // vitesse mesurée en tr/s    

Maintenant je part du principe que dans un asservissement polaire, le but étant de parcourir une certaine distance (par exemple 1000 tick), je ne suis pas censé remettre à 0 le compteur de tick n'est-ce pas ?

 

 

Second point:
Contrairement à un asser en vitesse, la fonction d'asservissement polaire doit gérer le sens de rotation des moteurs (si j'ai bien compris). C'est là que je bloque car je vois pas comment faire ça.

Je poste ici la fonction d'asservissement que j'ai réalisé jusque là:

//---------------------------------------------------------------------------
//                             INTERRUPTIONS EXTERNES                             -
//---------------------------------------------------------------------------
ISR(INT0_vect)        
{
    // Le sens de rotation des moteur est décodé en hardware et sert à incrémenter ou décrémenter les compteur de tick sur interruption.
    // si EncodDSens = 0 (on avance) alors incrémenter TickD sinon décrémenter
    if ( bit_is_clear(EncodDSens_portE, EncodDSens_broche))
    {
        tickD++;
    }
        else
        {
            tickD--;
        }    
}

ISR(INT1_vect)
{
    // si EncodGSens = 0 (on avance) alors décrémenter TickG sinon incrémenter (car cet encodeur est inversé)
    if ( bit_is_clear(EncodGSens_portE, EncodGSens_broche))
    {
        tickG--;
    }
        else
        {
            tickG++;
        }
}

//---------------------------------------------------------------------------
//                     FONCTION ASSERVISSEMENT PID Polaire                     -
//---------------------------------------------------------------------------
void pid(float ConsigneDist, float ConsigneOrient)
{
    float compteurD;
    float compteurG;
    float mesure_dist;
    float mesure_orient;
    float cmd_dist;
    float cmd_orient;

        // affectation des compteurs de PID et reset des compteurs sur interruption
        //compteurD = tickD;
        //compteurG = tickG;
        //tickD = 0;
        //tickG = 0;
        
        // mesure distance et orientation
        mesure_dist = (tickD + tickG)/2;
        mesure_orient = tickD - tickG;
    
        // Calcul des erreurs de distance
        erreur_dist = ConsigneDist - mesure_dist;
        somme_erreur_dist += erreur_dist;
        delta_erreur_dist = erreur_dist - erreur_prec_dist;
        // mise à jour de l'erreur précédente
        erreur_prec_dist = erreur_dist;
      
        // Calcul des erreurs d'orientation
        erreur_orient = ConsigneOrient - mesure_orient;
        somme_erreur_orient += erreur_orient;
        delta_erreur_orient = erreur_orient - erreur_prec_orient;
        // mise à jour de l'erreur précédente
        erreur_prec_orient = erreur_orient;
    
        // calcul des commandes
        cmd_dist = ((kp_dist * erreur_dist) + (ki_dist * somme_erreur_dist) + (kd_dist * delta_erreur_dist));    // PID distance
        cmd_orient = ((kp_orient * erreur_orient) + (ki_orient * somme_erreur_orient) + (kd_orient * delta_erreur_orient)); // PID orientation
        
        // appliquer les commandes aux moteur
        PWMG = cmd_dist - cmd_orient;        // ça ne doit surement pas fonctionner de cette façon
        PWMD = cmd_dist + cmd_orient;
        
        // Normalisation des commandes PWM de sortie (le moteur ne bouge pas avec un pwm < 240)
        if (PWMD < 240) {PWMD = 240;}
            else if (PWMD > 1023) {PWMD = 1023;}
        if (PWMG < 240) {PWMG = 240;}
            else if (PWMG > 1023) {PWMG = 1023;}
}

et la fonction principale:

int main (void)
{

    Ports_Init();                // initialisations E/S
    Init();                        // initialisation avant démarrage
    
    Consigne_Dist = 0;
    Consigne_Orient = 0;
    somme_erreur_dist = 0;
    somme_erreur_orient = 0;
    erreur_prec_dist = Consigne_Dist;         // initialisation sur consigne de depart
    erreur_prec_orient = Consigne_Orient;
    
    _delay_ms(1000);

    Consigne_Dist = 18000;                    // 18000 ticks = 1 tour de roue
    while (1)
    {
        pid(Consigne_Dist, Consigne_Orient);        
        _delay_ms(20);                        // PID à 50Hz (F=1/t)
    }
    
    return 1;
}

En vous remerciant !


Vitesse régulée par un PID

06 mars 2015 - 05:33

Je suis en train de réaliser un premier algorithme d'asservissement de vitesse par PID, le but étant de faire rouler droit le robot en question.

 

J'ai commencé par implémenter un PID à 50Hz sur un seul des deux moteurs et ça semblait bien marcher. Du coup j'ai testé ce que ça donne à 100Hz pour voir. Et là j'ai constaté que le moteur allait plus vite... ce qui n'est pas normal si ?

 

Je me suis basé sur cette page. Comme je ne travaille pas sur arduino j'ai adapté le code à mon besoin.

Pour déboguer et régler l'asservissement j'utilise la même méthode. D'ailleurs, bien que visuellement la roue semble tourner plus vite, les valeurs retournées de celles-ci sont similaires.

 

Infos utiles : Je programme en C sur un AVR atmega328p cadencé à 20Mhz. Celui-ci est totalement dédié à l'asservissement des 2 moteurs du robot. Les codeurs sont lu sur interruption.

 

La routine principale qui appel le pid 50 fois par seconde:

while (1) 
	{
	
		pid(consigne);		// consigne = nombre de tr/sec
		_delay_ms(20);		// PID à 50Hz (F=1/t)
	}

La fonctione d'asservissement:

void pid(float ConsigneVit)
{
	float compteurD;
	float mesure_vit_d;

	// affectation des compteurs de PID et reset des compteurs sur interruption
	compteurD = tickD;
	tickD = 0;
		
	mesure_vit_d = (50*compteurD)/tick_trm/reduction;		// vitesse mesurée en tr/s
		
	//calcul des erreurs
  	erreur_d = ConsigneVit - mesure_vit_d;	
	somme_erreur_d += erreur_d;
	delta_erreur_d = erreur_d - erreur_prec_d;
		
	// calcul de la commande
        PWMD += ((kp * erreur_d) + (ki * somme_erreur_d) + (kd * delta_erreur_d));
	
	// Normalisation des commandes PWM de sortie (le moteur ne bouge pas avec un pwm < 240)
	if (PWMD < 240) {PWMD = 240;}
		else if (PWMD > 1023) {PWMD = 1023;}
		
	// mise à jour de l'erreur précédente
		erreur_prec_d = erreur_d;
	
	//EnvoiFloat((PWMD/100));			
	EnvoiFloat(mesure_vit_d);               // envoie la valeur via uart
	EnvoiChaine("\r\n"); 			// retour a la ligne
}

Quelqu'un pourrait m'aider à comprendre ?

 

Merci.


Dédale le robot

07 juin 2014 - 04:22

Bonjour,

Cela fait quelques temps que je poursuis mon projet de robot d'exploration. Alors oui ça progresse toujours bien mais, comme c'est un projet de grande envergure, c'est long et pas toujours très amusant.

Ayant envie d'un projet robotique moins conséquent et plus léger, j'ai profité d'une commande de composants destinée à finir ma balise de base de recharge pour commander une paire de petits moteurs et un Picaxe.

Je vous présente donc Dédale, mon dernier robot. Le but était en premier lieu de faire un petit robot simple pour m'amuser avec sans me prendre la tête. Je suis assez content du résultat et il y a de quoi faire avec.

Il ne s'appel pas Dédale par hasard puisqu'il passera son temps à se balader dans son petit labyrinthe et chercher, pourquoi pas, le chemin de la sortie :)/>/>/>/>

J'en vois d'ici qui font déjà le rapprochement avec les concours micromouse. Il y a de ça, c'est vrai, mais le côté labyrinthique est bien le seul point commun puisque je ne cherche pas à me plier aux rêgles de ce tournoi (c'est pas demain la veille que je vais implémenter un A* dans Dédale). En effet, ça ne collerait pas avec ma démarche.

A présent j'aimerai donner un retour sur les moteurs pas à pas que j'ai utilisé (voir la page dédiée à Dédale sur mon site). Ils sont vraiment bien, a voir leur données techniques sur le site de Gotronic ça en faisait les candidats idéaux pour ce projet et ils ont tenu leur promesse. Seul bémol, ils sont pas bien rapide mais on peut pas trop leurs en vouloir vu la précision et le couple qu'ils offrent à 5V.
Le picaxe40x2 aussi me donne entière satisfaction, je m'étonne encore que si peu de gens ne l'emploi pas dans leurs projets.


J'espère en tout cas que Dédale vous à fait bonne impression et, pourquoi pas, donnera des idées à certains amateurs de robotique!

Batterie forte capacitée

20 février 2014 - 06:23

Bonjour,

Je cherche un pack d'accus forte capacitée. Dans l'idéal: NiMh 12V 10Ah (entre 6ah et 10Ah).

J'en ai trouvé sur robotmarketplace.com mais comme je n'ai jamais commandé à l'étranger je suis frileu.

L'un de vous a déjà commandé sur robotmarketplace ?
Si oui, comment procéder pour le paiement et quels sont les délais de livraison?

Au pire, où se procurer ce genre d'accu en france (par correspondance) ?

Merci.