Outils pour utilisateurs

Outils du site


cppu_moteur

Ceci est une ancienne révision du document !


Emplacement et horaire

Salle Objets Connectés, département GEII de l'IUT de Toulouse 3

8-12h le matin

13h30-17h30 l'après midi

Achat de matériel

Alimentation de laboratoire 10A (prévoir cable pour distribution 5V): https://www.amazon.fr/Alimentation-Laboratoire-KAIWEETS-stabilis%C3%A9e-Commutation/dp/B085S34NNW/ref=sr_1_3_sspa?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=alimentation+laboratoire&qid=1600841001&sr=8-3-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUFVUzNISUhVTlRYVE4mZW5jcnlwdGVkSWQ9QTAyMzY4NzQzTzJOU09RT0VYQUJUJmVuY3J5cHRlZEFkSWQ9QTA0NzEwNzdRMUNGTFBFU0lRWlkmd2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl

2x Carte shield motor L293D (16euros les 5): https://www.amazon.fr/AZDelivery-L293D-4-Channel-Diecimila-Duemilanove/dp/B07YWX7S9T/ref=pd_day0_107_6/259-9773987-6397531?_encoding=UTF8&pd_rd_i=B07YWX6N8B&pd_rd_r=09fb95fc-47a3-4712-9977-1d5df52c6ae9&pd_rd_w=Eyhez&pd_rd_wg=atieP&pf_rd_p=95f2fa2e-1e8f-4cae-bf89-355fdf5bbe96&pf_rd_r=BRJ769C5N9Q23VS6Y1ZJ&refRID=BRJ769C5N9Q23VS6Y1ZJ&th=1

3x Potentiomètre rotatif linéaire 10KOhm (7 euros les 5, en prendre 2 par manip): https://www.amazon.fr/potentiom%C3%A8tre-Arduino-Raspberry-dautres-projets/dp/B07B2TSDVF/ref=sr_1_8?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=arduino+potentiometre&qid=1600845741&sr=8-8

alternativement: https://www.sparkfun.com/products/9939

1x moteur avec réducteur (13 euros les 8) : https://www.amazon.fr/Gebildet-DC3V-6V-Voiture-motrices-robotique/dp/B07Z4PYJY4/ref=sr_1_16?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=arduino+motor&qid=1600845585&sr=8-16

1x moteur avec réducteur + roues (7.6 euros les 4) : https://www.amazon.fr/Nrpfell-Arduino-Intelligente-Plastique-Motoreducteur/dp/B07LGYTM57/ref=pd_sbs_60_5/260-0495266-0214753?_encoding=UTF8&pd_rd_i=B07LGYTM57&pd_rd_r=87808a76-98a5-4d65-be1b-011ed5a578e0&pd_rd_w=4KoNy&pd_rd_wg=qElsb&pf_rd_p=5df3b724-4d3e-4605-89d0-6cb31bf88ddc&pf_rd_r=YT9XJBA5JFAPWW2B31SJ&psc=1&refRID=YT9XJBA5JFAPWW2B31SJ

1x jeu de fils dupont (6euros les 3*40pièces): https://www.amazon.fr/AZDelivery-Jumper-Cavalier-C%C3%A2ble-Arduino/dp/B074P726ZR/ref=sr_1_7?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=dupont+wire&qid=1601414268&s=industrial&sr=1-7

1x petite centrale inertielle (18euros pièce): https://www.amazon.fr/MPI9250-CJMCU-117-dattitude-pr%C3%A9cision-communication/dp/B08289XC6V/ref=sr_1_2?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=CJMCU+117&qid=1601414477&sr=8-2

1x module récepteur GPS (7euros pièce): https://www.amazon.fr/Semoic-navigateur-positionnement-Satellite-Remplacement/dp/B07MZJSGKN/ref=sr_1_5?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=GPS+ATGM336H&qid=1601414739&sr=8-5

bobine de pla 1.75mm 1kg (18euros) : https://www.amazon.fr/AmazonBasics-Filament-pour-imprimante-Bobine/dp/B07T2R1BQJ/ref=sr_1_1_sspa?__mk_fr_FR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&dchild=1&keywords=pla&qid=1601414577&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzQzZVRFlSNFQ2QUc3JmVuY3J5cHRlZElkPUEwOTUzNTc5WldIVVhIS1o0TlJPJmVuY3J5cHRlZEFkSWQ9QTAyMzI4OTUyR01JMVlOU0QzQzEyJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==

La manip

Prérequis Initiation programmation et E/S arduino

Prérequis carte E/S

Présentation Servomoteur

Présenter le servomoteur et expliquer comment il se pilote: https://www.tutorialspoint.com/arduino/arduino_servo_motor.htm

Dire qu'on en construit un sur la base d'un moteur DC réducté avec asservissement numérique.

Réalisation du Servomoteur

vidéo de la manip en fonctionnement: https://www.youtube.com/watch?v=3goxHKO2iuE

Controle du moteur en vitesse et en sens

homepages.laas.fr_bvandepo_files_cppu_img_20200918_002851_crop_resize.jpg

Controle du moteur en position

homepages.laas.fr_bvandepo_files_cppu_img_20200924_130008_crop_resize.jpg

Installation de la librarie pour le shield moteur

Schéma du shield

Asservissement PID

Mettre ici des liens sur les fonctions de librairies Arduino à utiliser

CODE DE TEST Bertrand

motor_shield.ino
//B. Vandeportaele 09/2020
 
//done: gestion du temps pour que l'asservissement ait des paramètres fixes/ contenu du programme
 
#include <AFMotor.h>  
//Servo myservo;
 
   #include <Wire.h>
    //adresses codées sur 7bits
#define SLAVE_ADDR_8574_A 0x38+6
#define SLAVE_ADDR_8574_B 0x38+7
 
 
//AF_DCMotor motor(3,MOTOR34_1KHZ);//, MOTOR12_8KHZ);
AF_DCMotor motor(1,MOTOR12_1KHZ);//, MOTOR12_8KHZ);
 
int led = 13; //numéro de la broche Arduino pilotant la LED sur le shield PERIPH
 
//////////////////////////////////////////
char readPort8574(char addr, char * ptr_value)
/*addr, l'adresse du PCF8574
ptr_value, pointeur pour renvoyer la valeur lue sur le port
retourne -1 si échec 0 sinon*/
{
    Wire.requestFrom((byte)addr, (byte)1);// demande la lecture d'1 octet depuis l'adresse du pérpiphérique
    if (Wire.available()==1) //si l'octet est disponible
    {
        (* ptr_value) = Wire.read(); // lire l'octet
        return 0;
    }
    else
    {
        (* ptr_value) =0; //valeur par défaut si le composant n'a pas acquité
        return -1;
    }
}
//////////////////////////////////////////
char writePort8574(char addr, char value)
/*addr, l'adresse du PCF8574
value, la valeur à écrire sur le port
retourne -1 si échec 0 sinon */
{
    Wire.beginTransmission(addr);//démarre la transmission avec l'adresse du pérpiphérique
    Wire.write((byte)value);     //envoie la donnée
    if (Wire.endTransmission()==0)      //stoppe la transmission
        return 0;
    else
        return -1;
}
//////////////////////////////////////////
 
 
 #define TAB_SIZE 10
 int16_t erreur_tab[TAB_SIZE];
 uint8_t ind_ecr_erreur_tab=0;
 int16_t integrale_erreur=0;
 int16_t derivee_erreur=0;
 
void update_tab_erreur(int16_t new_erreur)
{
  //calcul intégrale
 integrale_erreur=integrale_erreur-erreur_tab[ind_ecr_erreur_tab];
 integrale_erreur=integrale_erreur+new_erreur;
//calcul dérivée
uint8_t ind_lec_erreur_tab=ind_ecr_erreur_tab+5;
if (ind_lec_erreur_tab>=TAB_SIZE )  //gestion modulo
  ind_lec_erreur_tab-=TAB_SIZE;
derivee_erreur=new_erreur-erreur_tab[ind_lec_erreur_tab];
//maj tableau 
 erreur_tab[ind_ecr_erreur_tab]=new_erreur;
 ind_ecr_erreur_tab++;
 if (ind_ecr_erreur_tab>=TAB_SIZE)
    ind_ecr_erreur_tab=0;  
 }
 //////////////////////////////////////////
void setup() 
{ 
// myservo.attach(9);   
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);   
       Serial.begin(115200);  // start serial port at 9600 bps:
       // Serial.print("Bonjour");
 
        Wire.begin();        // joindre le bus i2c en tant que maître
        writePort8574( SLAVE_ADDR_8574_B , 0xff); //configure le composant B en entrée
        writePort8574(SLAVE_ADDR_8574_A,~0); //eteind les leds
 
for (int i=0;i<TAB_SIZE;i++)
erreur_tab[i]=0;
 
}
 
//unité en milliseconde 
uint32_t cadence_it=3;
uint32_t time_next_it=0;
 
 
 
void loop()  
{
  if (millis()>=time_next_it)
  {
  time_next_it=time_next_it+cadence_it;
  controleur()  ;  
  //test si  la cadence peut etre tenue
    if (millis()>=time_next_it)
       writePort8574(SLAVE_ADDR_8574_A,~0xFF);
  }
}
 
 
void controleur()  
{  
 
/*
  digitalWrite(led, HIGH);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);   
 
  */
 
     //Serial.write('X');
//     delay(100); 
//motor.setSpeed(255);
 
/*delay(1000); 
motor.run(BACKWARD);      
delay(1000);  
motor.run(RELEASE);       
delay(1000); 
*/
static uint8_t vitesse=100;
static double t=0;
t=t+0.01;
 
 
 
//vitesse+=155+(100*sin(t));
//Serial.println(vitesse);
vitesse=vitesse+1;
if (vitesse==255)
  vitesse=100;
 
 
  byte port_in;
  readPort8574(SLAVE_ADDR_8574_B,(char*)&port_in);
//writePort8574(SLAVE_ADDR_8574_A,~port_in);
 
 
int16_t sens;
 
uint16_t consigne_position;
if ((port_in&1)!=0)
{
//lecture consigne sur potentiomètre
consigne_position=  analogRead(A0);
}else{
//génération échelons périodiques
unsigned long time;
  time = millis();
  if(((time/1000)%2)==0)
    consigne_position=512-250;
  else
    consigne_position=512+250;
}
 
 
uint16_t position=  analogRead(A1);
 
int16_t erreur=position-consigne_position;
 
 
 
update_tab_erreur(erreur);
 
/*
//type commande toute simple en proportionnel avec valeur min pour vaincre les frottements
int16_t commande_min=60; //pour vaincre les frottements
int16_t commande=abs(erreur)+commande_min;
int16_t commande_max=250;
if (commande>commande_max)
  commande=commande_max;
*/
 
int16_t Kd=10;  //de 0 à 50
int16_t Ki=2;  
int16_t Kp=1;
 
//erreur=erreur+4*derivee_erreur+integrale_erreur/8;
if ((port_in&2)!=0)
{
  erreur=erreur*Kp;
}
if ((port_in&4)!=0)
{
erreur+=Kd*derivee_erreur; //quand l'erreur diminue, ce terme est négatif et permet d'éviter le dépassement
}
if ((port_in&8)!=0)
{
  erreur+=(Ki*integrale_erreur)/TAB_SIZE;
}
int16_t commande=abs(erreur);
int16_t commande_max=250;
if (commande>commande_max)
  commande=commande_max;
 
 
 
 
 
if (abs(erreur)<3)
{
    motor.run(RELEASE);
motor.setSpeed(0);
sens=0;
}
else
if (erreur<0)
{
  motor.run(FORWARD);       
  motor.setSpeed(commande);
  sens=-1;
}
else
{
  motor.run(BACKWARD);       
 motor.setSpeed(commande);
   sens=1;
} 
/*
 
Serial.print("consigne_position: ");
Serial.print(consigne_position,DEC);
Serial.print("   position: ");
Serial.print(position,DEC);
Serial.print("   erreur: ");
Serial.print(erreur,DEC);
Serial.print("   commande: ");
Serial.print(commande,DEC);
 
Serial.print("   sens: ");
Serial.print(sens,DEC);
 
Serial.println("");
*/
 
 
 
 
Serial.print(consigne_position,DEC);
Serial.print("\t");
Serial.print(position,DEC);
Serial.print("\t");
 
Serial.print(erreur,DEC);
Serial.print("\t");
 
 
 
Serial.print(0,DEC);
Serial.print("\t");
Serial.print(1024,DEC);
Serial.print("\t");
 
/*Serial.print(erreur,DEC);
Serial.print("\t");
Serial.print(commande,DEC);
Serial.print("\t");
Serial.print(sens,DEC);
*/
Serial.println("");
//delay(10);
 
 
 
/*
  motor.run(BACKWARD);       
 motor.setSpeed(120);
 
/*
uint16_t adc=  analogRead(A0);
if (adc>=512)
  {
    if (adc>1023) adc=1022;
    vitesse=(adc-512)/2;
    motor.run(FORWARD);       
    motor.setSpeed(vitesse);
  }
  else
  {
        if (adc<2) adc=2;
     vitesse=(512-adc)/2;
    motor.run(BACKWARD);       
    motor.setSpeed(vitesse);
  }
/*
  vitesse=analogRead(A0)/4;
 
   motor.run(FORWARD);       
motor.setSpeed(vitesse);
Serial.println(vitesse);
*/
 
/*
    char  val;
if (readPort8574(SLAVE_ADDR_8574_B,&val)==0)
    {
      Serial.print("lecture  8574  OK, ");
        if (writePort8574(SLAVE_ADDR_8574_A,val)==0)
              Serial.println("ecriture 8574  OK");
        else
        Serial.println("ecriture 8574 NOK");
        }
        else
      Serial.println("lecture  8574 NOK,");    
*/      
    //writePort8574(SLAVE_ADDR_8574_A,~vitesse);
 
 
} 

Modèles des pièces 3D

connecteur_moteur_potar_2.scad
 
//B. Vandeportaele 09/2020
//jeu=0.5; //pour connecteur
jeu=0.3; //pour chape
 
/////////////////////////////
module tige_biseau(){
difference(){        
cylinder(h=20,d=5.5+jeu,$fn=120);
        //3.8mm en elevant les 2 biseaux  5.5-2*biseau=3.8=> biseau=0.85
        for (i=[0:1]){ //2 biseaux
            echo(i);
            rotate([0,0,i*180])
             translate([((5.5/2)-0.85)+jeu/2,-5,-1])
                cube([10,10,25]);
        }
    }
}
 
/////////////////////////////
 module tige_biseau2(){
difference(){        
cylinder(h=20,d=6+jeu,$fn=120);
        //4.5mm en elevant le  biseau
             translate([1.5+jeu/2,-5,-1])
                cube([10,10,25]);        
    }
}
/////////////////////////////
module connecteur(){
difference(){
cylinder(h=20,d=13,$fn=120);
    translate([0,0,-10])
    tige_biseau2();
    //#cylinder(h=20,d=6,$fn=120);
     translate([0,0,+12])
        tige_biseau();
}
}
/////////////////////////////
module chape(ep=3,long=30){
difference(){
hull()
{
cylinder(h=3,d=10,$fn=120);
  translate([long,0,0])
cylinder(h=3,d=4,$fn=120);
}
translate([0,0,-10])
tige_biseau();
translate([long,0,-10])
cylinder(h=20,d=2,$fn=120);
}
}
/////////////////////////////
 
 
module equerre(){
//distance entre axe vis fixation et potar=22mm
eps=0.01;
h=21.4;
ep=2;
entraxe=11;
diamvis=2.8;
hauteur=36.5;
union(){
    difference(){
            translate([-eps,-h/2,0])        
                cube([16,h,ep]);
            for (i=[-1:2:1]){
                translate([13.5,i*entraxe/2,-5])        
                #cylinder(h=10,d=diamvis,$fn=30);                
            }
            translate([2,0,-5])        
              #cylinder(h=10,d=4.5,$fn=30);                
    }
    translate([0,-h/2,ep-eps])     
        cube([ep,h,hauteur]);
    translate([-22+ep,-h/2,ep+hauteur-eps-eps])     
        difference(){
            cube([22,h,ep]);
             translate([33.5-22,h/2,-50])        
                 #cylinder(h=100,d=8,$fn=180);       
        }
}
}
/////////////////////////////
//tige_biseau2();
//connecteur();
//chape();
rotate([90,0,0])
equerre();
cppu_moteur.1601452389.txt.gz · Dernière modification : 2020/09/30 09:53 de bvandepo