Born to be wired

 Youpi, testons les moteurs !

J’avais longuement expliqué dans cet article les étapes de fabrication d’un câble parallèle pour relier le robot Youpi à un PC standard.

Aujourd’hui je vais comme promis diffuser les quelques lignes de code permettant de tester l’ensemble des moteurs. Le programme est grandement inspiré de celui que l’on peut trouver sur le site du BTS-IRIS de Niort.

C’est un programme développé à la va-vite en C. Il pourra servir de base pour tous ceux qui comme moi souhaitent vérifier que tous les moteurs sont en bon état de fonctionnement.

Le code

robotest.c

/*
Youpi Robot Test program
------------------------

Author: AlphaK - www.alphak.net
Revision: 2010-07-16

This program has to be run as root
or with sufficient credentials (suid...)
*/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/io.h>

// Change this to your parallel port
#define LPT 0x378

// Defines the byte type
typedef unsigned char byte;

// Defines the time between each instruction
int tempo = 2000;

/*
This functions writes a byte to the parallel port
Do not use any other way to do it as the robot needs to pause
between each instruction.
*/
void writelpt(byte b) {
	outb(b, LPT);
	usleep(tempo);
}

/*
This is the main function
*/
int main() {

	//Variables
	int i,j;
	int steps = 600;

	//Welcome message
	printf("*** YOUPI ROBOT TEST PROGRAM ***\n");

	//Tries to access parallel port
	if(ioperm(LPT, 1, 1) != 0) {
		perror("ioperm");
		return 1;
	}

	//Initializes the robot
	printf(" * Initialization\n");
	writelpt(0x47);
	writelpt(0x00);

	//Orders earch motor to rotate
	for(j=0; j<6; j++) {
		printf(" * Test of motor %d\n", j);

		//...with the correct tempo value
		tempo = (j == 0) ? 2000:1500;

		//...into one direction
		writelpt(0x80);
		writelpt(0x00);
		for(i=0; i<steps; i++) {
			writelpt(0x40+j);
			writelpt(0x00+j);
		}

		//...into the opposite direction
		writelpt(0xBF);
		writelpt(0x3F);
		for(i=0; i<steps; i++) {
			writelpt(0x40+j);
			writelpt(0x00+j);
		}
	}

	return 0;
}

Et le Makefile qui va avec :

CC=gcc
CFLAGS=-W -Wall -O

all: robotest

robotest: robotest.c
	$(CC) $(CFLAGS) -o $@ $<

clean:
	rm robotest

Quelques explications

Le manuel indique une vitesse de rotation maximale de 40°/s pour tous les moteurs, avec une résolution maximale de 0.03° par 1/2 pas. Chaque 1/2 pas est effectué grâce à l’envoi de 2 instructions par le port parallèle. Pour faire avancer le robot à cette vitesse maximale, il est nécessaire d’espacer chaque instruction d’un temps T en secondes, calculé ci-dessous :

Il faut donc espacer chaque instruction de 1500 µs, ce qui explique les 1500 à la ligne 27 du code. Descendre en dessous de cette limite est susceptible de provoquer des catastrophes inconnues, donc si vous essayez, cela sera à vos risques et périls. Note : comme me l’a fait remarquer cosmos dans les commentaires, pour le moteur de la base ayant une résolution de 0.04° par 1/2 pas, ces espacements doivent monter à 2000µs selon cette même formule.

Bugs connus

Avec un sommeil de 1500 µs entre chaque instruction, le programme devrait théoriquement être terminé en approximativement 2+6*(2+600*2)*2*0.0015 = 22 secondes, en négligeant le temps nécessaires aux autres instructions. Hors j’obtiens en moyenne un temps d’exécution à 58 secondes.

Ce phénomène est expliqué en partie par le paragraphe suivant, tiré de la page man 3 de usleep :

La période de sommeil peut être allongée par  la  charge  système, par le temps passé à traiter l’appel de fonction, ou par la granularité des temporisations système.

En résumé, lors de mon test, la vitesse de rotation de chaque moteur n’est pour le moment pas optimale. J’avais fait d’autres essais en réduisant significativement cette temporisation à quelques µs, ou en utilisant nanosleep afin d’avoir une granularité plus fine, mais le temps d’exécution total n’est jamais descendu en dessous de ces 58 secondes. Je ne sais pas encore comment optimiser cette vitesse, cela fait appel à des notions d’architecture système et de programmation temps réel qui me manquent à l’heure actuelle. Dans tous les cas, même si la vitesse est à l’heure actuelle bridée, le programme est néanmoins capable de démontrer le fonctionnement correct de chaque moteur.

Informations complémentaires

J’en profite pour placer un rappel : au lieu de me contacter personnellement pour me demander de l’aide à propos de ce robot, merci d’effectuer cette démarche en laissant un commentaire sur ce site afin que les questions et réponses profitent à tout le monde.

NB : vous pourrez maintenant trouver en un seul clic tous les articles de ce site relatifs au robot Youpi grâce au tag Youpi.

Mise à jour du 18/04/2015

J’ai de bonnes raisons de penser que mon calcul de temporisation dont la formule est exposée ci dessus est faux. Mes nouveaux calculs indiquent que les instructions devraient être séparées de 375 µs (respectivement 500 µs pour le moteur de la base) au lieu des 1500 µs (respectivement 2000 µs). Si cela est exact, les vitesses d’exécution de robotest et de Youba pourraient être améliorées jusqu’à x4 ! D’autre part on peut envisager l’utilisation de l’instruction nanosleep qui serait susceptible de réduire le temps de sommeil « inutile » (c.f. explications ci-dessus). Je n’ai malheureusement pas la possibilité de tester ces changements actuellement, ne disposant pas du Youpi à mon domicile. Cela pourra néanmoins s’arranger dans les prochaines semaines. Je vous ferai part des améliorations disponibles dès que cela sera possible.

 Tags: , , , ,

 21 commentaires pour “Youpi, testons les moteurs !”

  1.  chocho

    Hey, attention, je raconte peut être pas mal de conneries, mais j’ai envie de balancer mes idées, on sait jamais si ca peux t’aider, tu y a déjà sans doute pensé, mais j’ai vraiment envie de savoir ce que tu vas faire de ce youpi ! 🙂

    Tu ne peux rien lire depuis le robot ? Genre sa position ?

    Que se passe t il si tu fais

    while (position_actuelle != position_a_atteindre) {
    writelpt(déplace_toi)
    position actuelle = readlpt(ou_es_tu_petit_robot)
    }

    ou alors

    nb_pas_a_faire = position_voulue – position_actuelle
    for (i=0;i<nb_pas_a_faire;i++) {
    writelpt(deplace_toi)
    }

    De mémoire de mes TP de premier cycle, on gros on leur disait vitesse maximale jusqu'à une position proche, puis vitesse lente pour arriver précisément la ou on voulait, au demi-pas près.

    Bref, pour optimiser ta relation avec ce robot, cherche ce que tu peux apprendre de lui, ce qu'il balance sur son port parallèle quoi 🙂

  2.  AlphaK

    j’ai vraiment envie de savoir ce que tu vas faire de ce youpi

    Moi aussi, j’aimerais tellement le savoir 🙂

    Tout d’abord merci pour tes idées.
    Je n’ai jamais essayé de lire le contenu du port parallèle. J’ai la vague impression que si je le fais, le contenu sera identique à celui que j’ai envoyé… J’essaierai à tout hasard, ça ne coûte rien 🙂

    Je m’explique : le youpi possède *en option* 6 capteurs de position qu’il est possible de lire (cool !). Je ne sais pas si le mien en est équipé, à priori non. Ces informations sont lisibles, si j’en crois la documentation en ma possession, sur des broches différentes de celles utilisées pour envoyer les commandes. Ce qui veut dire que si je cherche à lire l’info sur le même port parallèle, je vais probablement devoir l’adapter pour « fusionner » les signaux d’entrée et de sortie sur les mêmes broches côté PC, tout en protégeant le robot et le PC des court-circuits. Une simple paire de diodes par broche suffira probablement à protéger le robot, mais pas le PC. On commence à dépasser mes compétences en électronique…

    Autrement, je peux aussi conserver le montage actuel, et lire les informations des capteurs avec une autre source dans un premier temps (un oscillo par exemple). Le problème, c’est que le manuel d’origine ne détaille absolument pas comment interpréter l’information donnée par les capteurs. Il semble qu’il s’agisse juste d’une information binaire pour prévenir un mouvement hors-limites. L’information ne serait donc pas très pertinente en dehors de aspect didactique 🙂

    En ce qui me concerne, je comptais surtout, dans un programme de haut niveau, laisser la possibilité de calibrer la position de chaque bras du robot, laisser le programme mémoriser la position de chaque moteur tout au long de l’exécution, puis revenir en position calibrée au final (afin de passer optionnellement cette étape à la prochaine exécution). Compte tenu de la précision des moteurs, je pense que c’est une option réaliste. Il n’existe malheureusement pas de notion de vitesse par axe, la vitesse ne pouvant être gérée que par le temps d’espacement des instructions.

    Je pense que tu as dû travailler avec des robots plus récents que le mien 😉

  3.  cosmos

    Bonjour,

    Que pensez-vous de la cascade puredata>pduino>arduino?
    Serai-ce faisable?

    liens arduino:
    http://www.rhombus-tek.com/BC4Arduino.html
    http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236358622/4

    pduino:
    http://at.or.at/hans/pd/objects.html

    puredata (extended):
    http://puredata.info/downloads

    arduino:
    http://www.arduino.cc/

    C.

  4.  AlphaK

    Bonjour

    L’Arduino ne fait malheureusement pas partie de mon domaine de compétences, j’aurai donc beaucoup de mal à vous conseiller. L’interfaçage du robot avec un Arduino me semble tout à fait possible via ses lignes d’I/O. Pour ce qui est des couches applicatives supérieures, notamment la cascade puredata>pduino>arduino que vous proposez, je n’y connais rien.

  5.  cosmos

    Bonjour,

    J’ai fait tourner votre programme sur une debian.
    Le robot toutefois ne bouge pas d’un pouce.

    Je precise que je n’ai pas de mode spp dans le bios de mon portabe.

    Si cela marche avec d’autres modes du port parallelle, il y a t-il une configuration precise a faire sous debian?

    C.

  6.  cosmos

    Voila le retour d’un:

    dmesg | grep parport
    [ 12.288354] parport_pc 00:0b: reported by Plug and Play ACPI
    [ 12.288399] parport0: PC-style at 0x3bc, irq 7 [PCSPP]
    [ 23.582135] lp0: using parport0 (interrupt-driven).

    PCSPP=SPP?

    C.

  7.  AlphaK

    Bonjour,

    Avez-vous fabriqué le câble parallèle avec le brochage spécifique adapté au robot, comme expliqué dans cet article ?
    http://www.alphak.net/news/2009/05/on-a-retrouve-le-prototype-du-t-800/

    De plus le programme est conçu pour utiliser un port parallèle à l’adresse 0x378, est-ce bien le cas de votre portable ?

  8.  AlphaK

    D’après le résultat de dmesg votre port parallèle utilise l’adresse 0x3bc, est-ce bien celle qui est configurée à la ligne 16 du programme ?

    A priori l’usage du port en mode SSP ou EEP n’a pas d’importance car les broches de Data0-7 et Gnd sont à la même place, cf ce lien : http://www.beyondlogic.org/epp/epp.htm

  9.  cosmos

    Cool,
    tous les moteurs ronronnent maintenant.
    Il fallait bien changer l’addresse vers 0x3bc dans vtre code.

    Que veut dire « int steps = 600 » a la ligne 39?

  10.  cosmos

    Je suis en trai d’interfacer le robot avec une carte arduino pilotee depuis puredata.
    Comme vous l’avez demontre par vos calculs, j’ai prevu un delay de 1.5 milliseconde entre chaque instruction de 8 bits.

    cependant je ne saisis pas encore la valeur de « int steps = 600 ». Cela a t-il a voir avec la transmission des 8 bits?

  11.  AlphaK

    La variable steps représente un nombre de demi-pas à exécuter. Chaque demi-pas équivaut à 0.03°, donc dans ce programme afin de tester chaque axe, on commande 600 demi-pas dans un sens de rotation puis 600 demi-pas dans l’autre. Ce qui équivaut normalement à 18° aller/retour. C’est une valeur choisie arbitrairement afin que la rotation soit visible.

  12.  cosmos

    ok,

    donc si j’ai bien compris, pour le moteur n°1 par exemple (moteur de la base), le programme envoie 600 fois la validation de ba suvante:

    0 1 0 0 0 0 0 0, delay 15 millisec., 0 0 0 0 0 0 0 0, delay 15 millisec (0x40 en HEX et 64 en décimal)?

    Aussi ne vaut t-il pas plutôt mettre « int tempo = 2000 », un delai de 20 millisecondes entre chaque instruction?
    Le moteur n°1 semble avoir une résolution de 0.04 et non 0.03 comme les autres moteurs.

  13.  cosmos

    ou plus simplement en valeurs décimales:

    64, pause 15ms, 0, pause 15ms, x 600?

    Combien de temps met environ une écriture de 8 bits?

    C’est pour avoir une idée pour l’automatisation dans puredata des objets [metro] et [delay] avant de les envoyer vers la sortie digitale (8bits) de l’Arduino.

  14.  AlphaK

    64, pause 15ms, 0, pause 15ms, x 600?

    C’est ça, sauf pour la pause dont la durée est de 1.5ms

    Aussi ne vaut t-il pas plutôt mettre « int tempo = 2000″, un delai de 20 millisecondes entre chaque instruction?
    Le moteur n°1 semble avoir une résolution de 0.04 et non 0.03 comme les autres moteurs.

    Effectivement c’est bien vu, en toute rigueur il faudrait utiliser une tempo de 2ms (pas 20) pour le moteur n°1, avec int tempo = 2000

    Combien de temps met environ une écriture de 8 bits?

    Je ne sais pas. En conditions réelles il peut être intéressant de le tester à l’oscilloscope.

  15.  cosmos

    Oui en effet je me suis trompe d’une decimale: c’est bien 1.5ms et 2ms.

    Je prevois de faire des essais avec une carte arduino en utillisant les pins 2 (D0), 3 (D1), 4 (D2), 5 (D3), 6 (D4), 7 (D5), 8 (D6) et 9 (D7) en mode digital output depuis le script Pduino dans puredata.

    De cette maniere il sera possible d’intercaller differentes instructions avec un delay minimum de 2ms, de maniere a faire fonctionner plusieurs moteurs en meme temps, a l’aide de [bang( sur des objets [metro] et [delay] envoyant des instructions binaires en mode decimal.

    Dans une version plus elaboree, il est tout a fait possible d’envisager des mouvements qui coeerespondent a des « algorythmes biologiques », prenant en compte des accelerations et des ralentissements dans des mouvements fluides.

    L’enjeu technique reside dans la synchronisation de ces etapes ainsi que dans la definition de la position initiale du robot.

  16.  cosmos

    Une autre alternative consisterait a utilliser l’abstarction pyext dans puredata et d’envoyer les instructions directement du PC vers le robot a travers le port LPT sans passer par l’arduino. Pyext permet d’intervenir dans un script python depuis puredata.

    A quoi ressemblerait la version python de votre programme?

  17.  cosmos

    Plus simple encore:
    utilliser l’objet [lpt] de la librairie « flatspace » ou « zexy » dand pd-extended.

    Marche sur Windows et Linux.
    Pour windows telecharger:
    http://www.embeddedtronics.com/public/Electronics/minidaq/userport/

    Pour Linux, resoudre les permissions d’utillisation du port LPT.

  18.  AlphaK

    A quoi ressemblerait la version python de votre programme?

    J’envisageais de développer un backend envoyant des instructions au robot sur lequel pourrait se greffer n’importe quel frontend applicatif (afin de pouvoir piloter par clavier, joystick, web, réseau, etc), le tout à base de commandes de plus haut niveau reçues par socket… Et j’envisageais justement de faire ce backend en Python.
    Je posterai le code lorsque ce sera fait.

  19.  AlphaK

    En attendant, je viens de mettre à jour le programme ci-dessus pour gérer les 2ms nécessaires au moteur de base.

    Notez que je n’ai pas le robot sous la main, je n’ai donc pas testé les modifications (bien que minimes), j’ai simplement vérifié que la nouvelle version compile sans erreur.

  20.  Cocobello

    Bonjour,
    Je suis enseignant et un de mes groupe d’élèves travaille sur le robot YOUPI.
    Nous sommes à la recherche d’informations sur les caractéristiques de la motorisation de ce robot. Mis à part les quelques informations notées sur les moteurs d’origine, c’est le trou noir.
    – CROUZET Servo 82.971.005 R:5 ohms Step:1.8 P:10W (motorisation de tous les axes sauf la pince)
    – MAE offango HY200-173-040A6 R:17 ohms 040 Amp/phase n°4 fasi Italy (motorisation de la pince)
    – Carte de commande située dans la base, AUCUN SCHEMA ni autre document.
    Si vous possédez ce type d’informations, je suis intéressé car sans celles-ci, il sera difficile d’envisager la réalisation d’un programme en langage python pour commander ce vieux robot.

    Merci d’avance.

  21.  AlphaK

    Mise à jour du 18/04/2015 – c.f. bas de l’article

    J’ai de bonnes raisons de penser que mon calcul de temporisation dont la formule est exposée ci dessus est faux. Mes nouveaux calculs indiquent que les instructions devraient être séparées de 375 µs (respectivement 500 µs pour le moteur de la base) au lieu des 1500 µs (respectivement 2000 µs). Si cela est exact, les vitesses d’exécution de robotest et de Youba pourraient être améliorées jusqu’à x4 ! D’autre part on peut envisager l’utilisation de l’instruction nanosleep qui serait susceptible de réduire le temps de sommeil « inutile » (c.f. explications ci-dessus). Je n’ai malheureusement pas la possibilité de tester ces changements actuellement, ne disposant pas du Youpi à mon domicile. Cela pourra néanmoins s’arranger dans les prochaines semaines. Je vous ferai part des améliorations disponibles dès que cela sera possible.

 Laisser un commentaire