position and speed dc motor regulator with real time software and trajectory generator

Dependencies:   NVIC_set_all_priorities QEI_hw SoftPWM mbed

/media/uploads/exarkun/wp_20171120_002-1-.jpg /media/uploads/exarkun/wp_20171030_004.jpg /media/uploads/exarkun/wp_20171030_002.jpg

position/time graph: /media/uploads/exarkun/wp_20171120_004.jpg

/media/uploads/exarkun/wp_20171128_001.jpg

un grand merci a Pierre Voiriot pour son aide .

rem: pour la modiffication hardware QEI voir ce lien

https://os.mbed.com/users/hexley/notebook/qei_hw-interface-implementation-notes/

Files at this revision

API Documentation at this revision

Comitter:
exarkun
Date:
Mon Nov 13 15:44:15 2017 +0000
Commit message:
position and speed motor dc control with lmd18200t with trajectory generator best project done up to now for dc motor i used hardware QEI; you sould make some hardware modification on mbed lpc1768 ; ; ; good end year 2017 ;-)

Changed in this revision

NVIC_set_all_priorities.lib Show annotated file Show diff for this revision Revisions of this file
QEI_hw.lib Show annotated file Show diff for this revision Revisions of this file
SoftPWM.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 6aa00967963c NVIC_set_all_priorities.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NVIC_set_all_priorities.lib	Mon Nov 13 15:44:15 2017 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/users/frankvnk/code/NVIC_set_all_priorities/#8acd3bf521ff
diff -r 000000000000 -r 6aa00967963c QEI_hw.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QEI_hw.lib	Mon Nov 13 15:44:15 2017 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/users/hexley/code/QEI_hw/#53f8ae2cf502
diff -r 000000000000 -r 6aa00967963c SoftPWM.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftPWM.lib	Mon Nov 13 15:44:15 2017 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/users/komaida424/code/SoftPWM/#7918ce37626c
diff -r 000000000000 -r 6aa00967963c main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Nov 13 15:44:15 2017 +0000
@@ -0,0 +1,416 @@
+#include "mbed.h"
+#include "qeihw.h"
+#include "NVIC_set_all_priorities.h"
+// déclaration du hardware
+Serial pc(USBTX, USBRX);//utilisation de la liaison usb 
+QEIHW qei(QEI_DIRINV_NONE, QEI_SIGNALMODE_QUAD, QEI_CAPMODE_4X, QEI_INVINX_NONE );
+Serial device(p9, p10);// tx, rx.//definition de la liaison rs232
+DigitalOut frein_moteur1(p15); //changement momentané pour le projet r2d de p5 a p15
+DigitalOut sens_rotation_moteur1(p13);  
+PwmOut PWM1(p21);
+ 
+// définition des timers.
+Timer timer1; 
+Timer timer2;
+
+// définition des sortie leds
+DigitalOut led1(LED1);
+DigitalOut led3(LED3);
+
+char c;
+int t ;
+
+float PI=3.141592653589793;
+
+//position codeur en pulses 2000pulses/rotation 
+int position_actuelle;//position du codeur
+int position_actuelle_n1;//position du codeur a n-1
+
+//données mecanique & moteur 
+float J=3.375*1e-5;//0.005;//inertie en kg.m²
+float K=0.05;//2;//constante de couple  N.m/v
+float R=5;//K;//resistance du moteur en Ohms
+float Umax=24;//tension max en volts
+
+//parametres reglage
+float dt_vit(5*1e-4);
+float Ki=10;//default value=10;
+float Kp;
+float Kv;
+float K_sw(K);
+float tau;
+float taud=(10*dt_vit);
+float r1=3;//default value=2.5;
+float r2=r1;//default value=2.5;
+
+//variables generateur de consigne///////////////////////////////////////////////////////////////////////////////////////////
+float Teta_debut, Teta_fin, Teta_diff;
+float delta_Teta;
+float consigne;//en pulse 
+float slope_time(1.);//en seconde
+bool start_slope(false);//flag debut de montee
+int ticks_total;
+int count_ticks;
+int count_slope(0);
+int count_max(0);
+
+
+//variables calcul de l'asservissement en vitesse et position 
+float Tetaco; //valeur de la consigne position en radians
+float Tetam;//valeur mesuree de la position en radians
+
+float dTetam;
+float integ;
+float A;
+
+float dTetam_n1;
+float Tetaco_n1;
+float Tetam_n1;
+float integ_n1;
+float cyclic;
+int signe_rot;
+
+//declaration des differantes taches
+void task1_switch(void);
+void task2_switch(void);
+void task3_switch(void);
+void task4_switch(void);
+void task5_switch(void);
+void task6_switch(void);
+void task7_switch(void);
+void task8_switch(void);
+
+//declaration des differantes interuption timer
+Ticker time_up1; //define a Ticker, with name “time_up1”
+Ticker time_up2; //define a Ticker, with name “time_up2”
+Ticker time_up3; //define a Ticker, with name “time_up3”
+Ticker time_up4; //define a Ticker, with name “time_up4”
+Ticker time_up5; //define a Ticker, with name “time_up5”
+Ticker time_up6; //define a Ticker, with name “time_up6”
+Ticker time_up7; //define a Ticker, with name “time_up7”
+Ticker time_up8; //define a Ticker, with name “time_up8”
+
+//declaration des leds visuelle utiliser pour mesurer le temps des taches 
+DigitalOut myled1(LED1);
+DigitalOut myled3(LED3);
+
+////////////////////////////////////////
+//    Convertion pulses to radians    //
+////////////////////////////////////////
+
+//PI =3.141592653589793 =1000 pulses codeurs
+float pulsesToRadians(int pulses) 
+{
+  float radians_VAL;
+  radians_VAL=(pulses*PI)/1000.;
+  return radians_VAL;
+};
+////////////////////////////////////////
+//   calcule de la vitesse angulaire  //
+////////////////////////////////////////
+
+// ici le code du calcule 
+
+// Convert ASCII string to unsigned 32-bit decimal "string is null-terminated"
+  unsigned long Str2UDec(unsigned char string[]){
+  unsigned long i = 0;  // index
+  unsigned long n = 0;  // number
+  while(string[i] != 0){
+    n = 10*n +(string[i]-0x30);
+    i++;
+  }
+  return n;
+}
+
+////////////////////////////////////////
+//                TASKS1              //
+////////////////////////////////////////
+
+void task1_switch()
+{ 
+myled1=1;
+//lecture valeur codeur et conversion en radians
+position_actuelle=qei.GetPosition();//lecture valeur codeur et affectation a la variable globale 
+Tetam=pulsesToRadians(position_actuelle);//conversion valeur impulsionel en radians 
+
+//Calcul de la nouvelle consigne:
+
+//Etape1:derivee filtree 
+dTetam=1./(1.+taud*2./dt_vit)*(-dTetam_n1*(1.-taud*2./dt_vit)+2./dt_vit*(Tetam-Tetam_n1));
+
+//Etape2:calcul de integ non saturee
+integ=integ_n1+dt_vit/2.*((Tetaco-Tetam)+(Tetaco_n1-Tetam_n1));
+
+//Etape3:Calcul de A non saturee
+A=Kv*K_sw/Umax*(-dTetam+Kp*Ki*integ-Kp*Tetam);
+
+//Etape 4 et 5 : calcul de integ saturee
+if (A>1)
+    {
+    integ=1./Kp/Ki*(Umax/Kv/K_sw+dTetam+Kp*Tetam);
+    A=1;
+    }
+if(A<-1)
+    {
+    integ=1./Kp/Ki*(-Umax/Kv/K_sw+dTetam+Kp*Tetam); 
+    A=-1; 
+    }
+    
+//Etape 6:affectation du signe de rotation a l'etage de puissance 
+if (A>0)
+{
+    signe_rot=1;
+    sens_rotation_moteur1.write(signe_rot); //affectation du sens de rotation moteur1
+    cyclic=A;
+}
+else 
+{
+    signe_rot=0;
+    sens_rotation_moteur1.write(signe_rot); //affectation du sens de rotation moteur1
+    cyclic=-A;//peut etre une erreur ici sy??
+}
+
+PWM1.write(cyclic);// affectation  de la valeur calculé en pwm
+
+//   enregistrement des valeurs N-1
+position_actuelle_n1=position_actuelle;   
+dTetam_n1=dTetam;
+Tetaco_n1=Tetaco;
+Tetam_n1=Tetam;
+integ_n1=integ;
+
+myled1=0;
+//myled1=!myled1;//changement etat de la led1
+}
+
+////////////////////////////////////////
+//                TASKS2              //
+////////////////////////////////////////
+
+void task2_switch()
+{
+//        pc.printf("%f\r\n", Tetaco);//valeur float consigne  en radians le renvoyé par usb
+//        pc.printf("%i\r\n", position_actuelle);//valeur int du codeur renvoyé par usb        
+//        pc.printf("%f\r\n", Tetam);//valeur float du codeur en radians renvoyé par usb
+//        pc.printf("dTetam : %f\r\n", dTetam);//valeur float dTetam
+//        pc.printf("integ : %f\r\n", integ);//valeur float integ               
+//        pc.printf("%f\r\n", A);//valeur float du codeur en radians le renvoyé par usb
+//        pc.printf("%e\r\n", cyclic);//valeur float du codeur en radians le renvoyé par usb
+//        pc.printf("\r\n");//retour chario
+//        pc.printf("$%d %d %d;", position_actuelle,position_actuelle/2,position_actuelle/10 ); //utiliser avec logicielle serial port ploter 
+pc.printf("$%d;", position_actuelle); //utiliser avec logicielle serial port ploter 
+                 
+};
+
+////////////////////////////////////////
+//                TASKS3              //
+////////////////////////////////////////
+
+void task3_switch()
+{ 
+myled3=1;
+
+//generation de la tragectoire 
+if(start_slope)
+{
+    Teta_debut=Tetam;//affectation de la consigne a la variable globale
+    Teta_fin=pulsesToRadians(consigne);//affectation de la consigne a la variable globale
+    Teta_diff = Teta_fin - Teta_debut;
+    delta_Teta=(Teta_diff/slope_time)*5*1e-4;
+    //timer1.start();// déclenchement du timer1
+    count_slope = 0;
+    count_max = slope_time/(5*1e-4);
+    start_slope=false;
+}
+//float timeco = timer1.read();
+count_slope++;
+if (count_slope<=count_max){Tetaco=Tetaco+delta_Teta;}
+//if (timeco<slope_time){Tetaco=Tetaco+delta_Teta;}
+//if (timeco==slope_time){Tetaco=Teta_fin;}
+//if (timeco>slope_time){timer1.reset(); // remise à zéro du timer1
+
+//myled3=!myled3;
+myled3=0; 
+}
+
+////////////////////////////////////////
+//                TASKS4              //
+////////////////////////////////////////
+
+void task4_switch()
+{ 
+device.printf("$%d;", position_actuelle); //utiliser avec logicielle serial port ploter 
+
+}
+
+////////////////////////////////////////
+//                TASKS5              //
+////////////////////////////////////////
+
+void task5_switch()
+{
+// ici code de la tache 5
+}
+
+////////////////////////////////////////
+//                TASKS6              //
+////////////////////////////////////////
+
+void task6_switch()
+{ 
+// ici code de la tache 6
+}
+
+////////////////////////////////////////
+//                TASKS7              //
+////////////////////////////////////////
+
+void task7_switch()
+{ 
+// ici code de la tache 7
+}
+
+////////////////////////////////////////
+//                TASKS8              //
+////////////////////////////////////////
+
+void task8_switch()
+{ 
+// ici code de la tache 8
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//                   declaration de la fonction moteur1                    //
+/////////////////////////////////////////////////////////////////////////////
+
+void motor1_mouve(int position_final,int T1)
+{
+//calcule nombres de ticks tache2 suite au temps T1 demander
+ 
+//calcule delta_Teta
+
+
+///////////////////////////////////////////////////
+//                debut du mouvement             //
+///////////////////////////////////////////////////
+
+timer1.start(); // déclenchement du timer1 
+timer2.start(); // déclenchement du timer2
+    
+//generation de consigne position   
+for(int i=0;i<=consigne;i++)
+{
+}
+    if (timer1.read_us()>T1) // lecture du temps du timer1 en us
+    { 
+      device.printf("TIME out  motor1  0\r\n"); 
+    } 
+
+    if (timer2.read_ms()>T1) // lecture du temps du timer1 en ms
+    { 
+      device.printf("TIME out  motor1  0\r\n"); 
+    }      
+timer1.reset(); // remise à zéro du timer1
+timer2.reset(); // remise à zéro du timer2
+};
+
+////////////////////////////////////////////////////////////////////////////
+//                       PROGRAMME PRINCIPAL                              //
+////////////////////////////////////////////////////////////////////////////
+                                                
+int main()
+            {
+               int cycles;
+                //NVIC_SetPriority(EINT3_IRQn, 252);//set interupt to highest priority 0.
+                //NVIC_SetPriority(TIMER1_IRQn, 253);// set mbed tickers to lower priority than other things
+                //NVIC_SetPriority(TIMER2_IRQn, 254);// set mbed tickers to lower priority than other things
+                //NVIC_SetPriority(TIMER3_IRQn, 255);// set mbed tickers to lower priority than other things
+                //NVIC_set_all_irq_priorities(0);
+                
+                qei.SetDigiFilter(480UL);//filtre 
+                qei.SetMaxPosition(0xFFFFFFFF);//position max 4294967295 pulses
+                
+//initialisation de la com rs232                
+                device.baud(9600);//rs232 28800 baud    
+                device.printf("serial rs232 ok \n");
+                
+                //calculs  de tau ,Kv,Kp          
+                tau=(J*R)/K;
+                Kv=r1*r2*tau*Ki-1.;
+                if(Kv<0){Kv = -Kv;}
+                Kp=r1*Ki*(1.+Kv)/Kv;
+                              
+//initialisation moteur   
+PWM1.period(0.00005);// initialisation du rapport cyclique fixe la période à 50us----f=20Khz
+frein_moteur1.write(0);//affectation de la valeur du frein moteur1
+sens_rotation_moteur1.write(0); //affectation du sens de rotation moteur1 non utiliser puisque c'est la tache1 qui le fait non pas la generation de trajectoire
+
+//lancement des tasks               
+                time_up1.attach(&task1_switch, 0.0005); //initialises the ticker  2Khz "tous les 500us il y as une interruption task1"
+                time_up2.attach(&task2_switch, 0.01); //initialises the ticker 100hz
+                time_up3.attach(&task3_switch, 0.0005); //initialises the ticker 2khz
+                time_up4.attach(&task4_switch, 0.01); //initialises the ticker 100hz
+                time_up5.attach(&task5_switch, 0.0005); //initialises the ticker 2kh
+                time_up6.attach(&task6_switch, 0.0005); //initialises the ticker 2kh
+                time_up7.attach(&task7_switch, 0.0005); //initialises the ticker 2kh
+                time_up8.attach(&task8_switch, 0.0005); //initialises the ticker 2kh
+ 
+count_ticks=0;                      
+        while(1)
+                {
+                 c='1';  
+               //device.scanf("%c",&c);//capture du caract ascii 
+                     
+                switch(c)
+                {
+                    case '1':
+                        consigne=70000;                                  
+                        slope_time=0.001;
+                        start_slope=true;
+                        wait(3);
+                        consigne=0;
+                        slope_time=2.;
+                        start_slope=true;
+                        wait(3);
+      
+                    break; 
+                    
+                    case '2':
+                        device.printf("profile de mouvement 2\r\n");                              
+                    break; 
+
+                     case '3':
+                        device.printf("moving3 Robotic Axis 1\r\n");             
+                    break;  
+
+                    case '4':
+                        device.printf("moving4 Robotic Axis 1\r\n");           
+                    break; 
+      
+                    case '5':
+                        device.printf("moving5 Robotic Axis 1\r\n");             
+                    break; 
+ 
+                    case '6':
+                        device.printf("moving6 Robotic Axis 1\r\n"); 
+                    break;
+                    
+                    case '7':
+                        device.printf("moving7 Robotic Axis 1\r\n"); 
+                    break;
+                    
+                    case '8':
+                        device.printf("moving8 Robotic Axis 1\r\n"); 
+                    break;  
+                    
+                    case '9':
+                        device.printf("moving9 Robotic Axis 1\r\n"); 
+                    break;
+                    
+                    case '0':
+                        device.printf("moving7 Robotic Axis 1\r\n"); 
+                    break;                 
+                }                   
+                }
+                                                    
+        }
diff -r 000000000000 -r 6aa00967963c mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Nov 13 15:44:15 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/b484a57bc302
\ No newline at end of file