闭环步进电机

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
heroistired
Date:
Thu Apr 05 01:37:17 2018 +0000
Parent:
0:5b4f19f8cd85
Commit message:
New

Changed in this revision

GUI.cpp Show annotated file Show diff for this revision Revisions of this file
GUI.h 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
motor.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI.cpp	Thu Apr 05 01:37:17 2018 +0000
@@ -0,0 +1,166 @@
+#include "GUI.h"
+
+int screen_buf1[140] = {};
+
+int screen_buf2[140] = {};
+
+int index = 0;
+
+void RefreshGUI(Serial *Screen, int freq, float kp, float ki, int goal, int pos)
+{
+    unsigned long int long_goal, long_pos;
+    long_goal = goal;
+    long_pos = pos;
+    SXY(Screen,8,35);
+    if(freq < 10)
+        DS16(Screen,90,20,int2string(freq)+"    ",3);
+    else
+        DS16(Screen,90,20,int2string(freq)+" ",3);
+    DS16(Screen,90,40,float2string(kp),3);
+    DS16(Screen,90,60,float2string(ki),3);
+    DS16(Screen,90,80,int2string(goal)+" ",3);
+    DS16(Screen,90,100,int2string(pos)+"  ",3);
+    
+    SXY(Screen,170,75);
+    PS(Screen,index,screen_buf1[index],0);
+    //screen_buf1[index] = 110-long_goal/(16383/110);
+    screen_buf1[index] = 110-goal/(16383/110);
+    PS(Screen,index,screen_buf1[index],3);
+    PS(Screen,index,screen_buf2[index],0);
+    //screen_buf1[index] = 110-long_pos/(16383/110);
+    screen_buf2[index] = 110-pos/(16383/110);
+    PS(Screen,index,screen_buf2[index],5);
+    index++;
+    if(index == 140)
+        index = 0;
+
+
+    SXY(Screen,0,0);
+    ExecuteInstruction(Screen);
+    //wait(0.1);
+}
+
+void InitGUI(Serial *Screen)
+{
+    char c1[18]={0xB1,0xD5,0xBB,0xB7,0xB2,0xBD,0xBD,0xF8,0xB5,0xE7,0xBB,0xFA,0xCA,0xD4,0xD1,0xE9,0xCC,0xA8};//闭环步进电机试验台
+    char c2[8]={0xBF,0xD8,0xD6,0xC6,0xD0,0xC5,0xCF,0xA2};//控制信息
+    char c3[4]={0xC6,0xB5,0xC2,0xCA};//频率
+    char c4[8]={0xB1,0xC8,0xC0,0xFD,0xCF,0xB5,0xCA,0xFD};//比例系数
+    char c5[8]={0xBB,0xFD,0xB7,0xD6,0xCF,0xB5,0xCA,0xFD};//积分系数
+    char c6[8]={0xC4,0xBF,0xB1,0xEA,0xCE,0xBB,0xD6,0xC3};//目标位置
+    char c7[8]={0xB5,0xB1,0xC7,0xB0,0xCE,0xBB,0xD6,0xC3};//当前位置
+    char c8[18] = {0xC7,0xE5,0xBB,0xAA,0xB4,0xF3,0xD1,0xA7,0xB4,0xB4,0xD0,0xC2,0xB9,0xA4,0xD7,0xF7,0xB7,0xBB};//清华大学创新工作坊
+    string str= "";
+
+    SXY(Screen,0,0);
+    CLS(Screen,0);
+    for(int i=0;i<18;i++) str+=c1[i];
+    DS16(Screen,90,4,str,12);
+    str= "";
+    PL(Screen,0,28,319,28,15);
+    PL(Screen,0,29,319,29,15);
+    PL(Screen,159,35,159,190,15);
+    PL(Screen,160,35,160,190,15);
+    SXY(Screen,8,35);
+    for(int i=0;i<8;i++) str+=c2[i];
+    DS16(Screen,30,0,str,2);
+    str= "";
+    for(int i=0;i<4;i++) str+=c3[i];
+    DS16(Screen,0,20,str,2);
+    str= "";
+    for(int i=0;i<8;i++) str+=c4[i];
+    DS16(Screen,0,40,str,2);
+    str= "";
+    for(int i=0;i<8;i++) str+=c5[i];
+    DS16(Screen,0,60,str,2);
+    str= "";
+    for(int i=0;i<8;i++) str+=c6[i];
+    DS16(Screen,0,80,str,2);
+    str= "";
+    for(int i=0;i<8;i++) str+=c7[i];
+    DS16(Screen,0,100,str,2);
+    str= "";
+    
+    SXY(Screen,170,35);
+    for(int i=0;i<8;i++) str+=c6[i];
+    DS16(Screen,0,0,str,2);
+    str= "";
+    for(int i=0;i<8;i++) str+=c7[i];
+    DS16(Screen,0,20,str,2);
+    str= "";
+    PL(Screen,80,5,140,5,3);
+    PL(Screen,80,6,140,6,3);
+    PL(Screen,80,25,140,25,5);
+    PL(Screen,80,26,140,26,5);
+    SXY(Screen,0,0);
+    PL(Screen,0,195,319,195,15);
+    PL(Screen,0,196,319,196,15);
+    for(int i=0;i<18;i++) str+=c8[i];
+    DS16(Screen,85,203,str,12);
+    str= "";
+    DS16(Screen,50,222,"Developed by C.H. Dep of EEA",2);
+    SXY(Screen,0,0);
+    ExecuteInstruction(Screen);
+    wait(0.2);
+}
+
+void DS16(Serial *Screen, int x, int y, string str, int color)
+{
+    string temp = "DS16("+int2string(x)+","+int2string(y)+",'"+str+"',"+int2string(color)+");";
+    Screen->printf(temp.c_str());
+}
+
+void DS24(Serial *Screen, int x, int y, string str, int color)
+{
+    string temp = "DS24("+int2string(x)+","+int2string(y)+",'"+str+"',"+int2string(color)+");";
+    Screen->printf(temp.c_str());
+}
+
+void SXY(Serial *Screen, int x, int y)
+{
+    string temp = "SXY("+int2string(x)+","+int2string(y)+");";
+    Screen->printf(temp.c_str());
+}
+
+void CLS(Serial *Screen, int color)
+{
+    string temp = "CLS("+int2string(color)+");";
+    Screen->printf(temp.c_str());
+}
+
+void PL(Serial *Screen, int x1, int y1, int x2, int y2, int color)
+{
+    string temp = "PL("+int2string(x1)+","+int2string(y1)+","+int2string(x2)+","+int2string(y2)+","+int2string(color)+");";
+    Screen->printf(temp.c_str());
+}
+
+void PS(Serial *Screen, int x1, int y1, int color)
+{
+    string temp = "PS("+int2string(x1)+","+int2string(y1)+","+int2string(color)+");";
+    Screen->printf(temp.c_str());
+}
+
+void ExecuteInstruction(Serial *Screen)
+{
+    Screen->printf("\r\n");
+}
+
+string int2string(int x)
+{
+    stringstream ss;
+    ss << x;
+    string str = ss.str();
+    return str;
+}
+
+string float2string(float x)
+{
+    int xx = x * 100;
+    float xxx = (float)xx / 100;
+    stringstream ss;
+    ss << xxx;
+    string str = ss.str() + ' ';
+    return str;
+}
+
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI.h	Thu Apr 05 01:37:17 2018 +0000
@@ -0,0 +1,30 @@
+#ifndef __GUI_H
+#define __GUI_H
+#include "mbed.h"
+#include <string> 
+#include <sstream>
+
+void InitGUI(Serial *Screen);
+
+void RefreshGUI(Serial *Screen, int freq, float kp, float ki, int goal, int pos);
+
+void DS16(Serial *Screen, int x, int y, string str, int color);
+
+void DS24(Serial *Screen, int x, int y, string str, int color);
+
+void SXY(Serial *Screen, int x,int y);
+
+void CLS(Serial *Screen, int color);
+
+void ExecuteInstruction(Serial *Screen);
+
+void PL(Serial *Screen, int x1, int y1, int x2, int y2, int color);
+
+void PS(Serial *Screen, int x1, int y1, int color);
+
+string int2string(int x);
+
+string float2string(float x);
+
+
+#endif 
\ No newline at end of file
--- a/main.cpp	Fri Mar 30 12:03:12 2018 +0000
+++ b/main.cpp	Thu Apr 05 01:37:17 2018 +0000
@@ -2,17 +2,23 @@
 
 #include "mbed.h"
 #include "as5047.h"
+#include "GUI.h"
 #include <string> 
 #include <sstream>
 
 // software ssel
-SPI motor_encoder(D11, D12, D13); // mosi, miso, sclk
-DigitalOut motor_encoder_cs(D3); // ssel
-DigitalOut motor_dir(D2); // ssel
-Serial pc(SERIAL_TX, SERIAL_RX);
+SPI motor_encoder(PB_15, PB_14, PB_13); // mosi, miso, sclk
+DigitalOut motor_encoder_cs(PB_12); // ssel
+DigitalOut motor_dir(PA_11); // ssel
+Serial pc(PA_2, PA_3,9600);
+Serial screen(PB_10, PB_11,115200);
 MotorType Motor;
 Ticker PIDInterrupt;  //PID中断 500Hz
 
+int counter = 0;
+
+DigitalIn Mode(PA_12);
+
 void PIDInterruptIRQ(); 
 
 
@@ -20,28 +26,44 @@
 {
     string UartBuf = "";
     char temp = 0;
+    InitGUI(&screen);
     StepMotorInit(&Motor, &motor_dir, &motor_encoder_cs, &motor_encoder);
     Encoder_Init(&Motor);
     PIDInterrupt.attach(&PIDInterruptIRQ, 0.002);
     Motor.Goal = 5000;
     while(1)
     {
-        if(pc.readable())
+        if(pc.readable())// && (Mode.read() != 0))
         {
             temp = pc.getc();
-            if((temp != 'i') && (temp != ';') && ((temp < '0') || (temp > '9')))   //收到的非法字符
+            if((temp != 'p') && (temp != 'i') && (temp != 'x') && (temp != ';') && ((temp < '0') || (temp > '9')))   //收到的非法字符
                 continue;
-            else if(temp == 'i')  //请求信息
-                pc.printf("Position : %d, PWM Freq : %d, Goal : %d\r\n", Motor.Encoder, Motor.PIDControl, Motor.Goal);
+            else if(temp == 'x')  //请求信息
+                pc.printf("Position : %d, PWM Freq : %d, Goal : %d Kp : %.2f Ki : %.2f\r\n", Motor.Encoder, Motor.PIDControl, Motor.Goal, Motor.Kp, Motor.Ki);
             else if((temp >= '0') && (temp <= '9'))  //收到0-9
                 UartBuf = UartBuf + temp;
-            else  //收到 ;
+            else if (temp == ';') //收到 ;
             {
                 Motor.Goal = atoi(UartBuf.c_str());
                 pc.printf("Goal is set at %d\r\n", Motor.Goal);
                 UartBuf = "";
+                counter = 0;
+            }
+            else if (temp == 'p') //收到 ;
+            {
+                Motor.Kp = (float)atoi(UartBuf.c_str())/10;
+                pc.printf("Kp is set at %.2f\r\n", Motor.Kp);
+                UartBuf = "";
+            }
+            else if (temp == 'i') //收到 ;
+            {
+                Motor.Ki = (float)atoi(UartBuf.c_str())/10;
+                pc.printf("Ki is set at %.2f\r\n", Motor.Ki);
+                UartBuf = "";
             }
         }
+        if(counter < 1500)
+            RefreshGUI(&screen, Motor.PIDControl, Motor.Kp, Motor.Ki, Motor.Goal, Motor.Encoder);
         //pc.printf("Angle : %d, PID Value : %d, Difference : %d\r\n", Motor.Encoder, Motor.PIDControl, Motor.Difference);
     }
 }
@@ -59,6 +81,15 @@
     MotorPIDController(&Motor);
     //更新脉冲频率
     StepMotorSetFreq(&Motor);
+    /*if(Mode.read() == 0)
+    {
+        MotorPIDController(&Motor);
+        //更新脉冲频率
+        StepMotorSetFreq(&Motor);
+    }*/
+    counter++;
+    if(counter > 60000)
+        counter = 2001;
 }
 
 
--- a/motor.cpp	Fri Mar 30 12:03:12 2018 +0000
+++ b/motor.cpp	Thu Apr 05 01:37:17 2018 +0000
@@ -8,7 +8,7 @@
 //////////////////////////////////////////////////////////////////////////////////
 void StepMotorInit(MotorType *Motor, DigitalOut *MotorDirPin, DigitalOut *EncoderCsPin, SPI *SPI_EncoderObj)
 {
-    RCC->APB1ENR|=1<<0;     //TIM2时钟使能   
+    /*RCC->APB1ENR|=1<<0;     //TIM2时钟使能   
     RCC->APB2ENR|=1<<2;     //GPIOA时钟使能 
     GPIOA->CRL&=0XFFFFFF0F; //PA1清除之前的设置
     GPIOA->CRL|=0X000000B0; //复用功能输出 
@@ -21,7 +21,24 @@
     TIM2->CCER|=1<<4;       //OC2 输出使能  
 
     TIM2->CR1=0x0080;       //ARPE使能
-    TIM2->CR1|=0x01;        //使能定时器2
+    TIM2->CR1|=0x01;        //使能定时器2*/
+    
+    RCC->APB2ENR|=1<<11;    //TIM1时钟使能    
+    RCC->APB2ENR|=1<<2;     //GPIOA时钟使能 
+    GPIOA->CRH&=0XFFFFFFF0; //PA8清除之前的设置
+    GPIOA->CRH|=0X0000000B; //复用功能输出 
+    
+    TIM1->ARR=899;          //设定计数器自动重装值 
+    TIM1->PSC=999;          //预分频器设置
+  
+    TIM1->CCMR1|=7<<4;      //CH1 PWM2模式         
+    TIM1->CCMR1|=1<<3;      //CH1预装载使能   
+    TIM1->CCER|=1<<0;       //OC1 输出使能    
+
+    TIM1->BDTR|=1<<15;      //MOE 主输出使能    
+
+    TIM1->CR1=0x0080;       //ARPE使能 
+    TIM1->CR1|=0x01;        //使能定时器1                                       
     
     //初始胡电机控制结构体
     Motor->Encoder = 0;
@@ -89,7 +106,7 @@
     Motor->ChangeRateDifference = Motor->Difference - Motor->Difference_pre;
     
     //切换参数
-    if(Math_abs(Motor->Difference) <= ApproachDistance)  //很接近目标距离了
+    /*if(Math_abs(Motor->Difference) <= ApproachDistance)  //很接近目标距离了
     {
         Motor->Ki = MotorKi_End;
         Motor->Kp = MotorKp_End;
@@ -109,7 +126,7 @@
         Motor->Kp = MotorKp;
         Motor->V_Ki = MotorVKi;
         Motor->V_Kp = MotorVKp;
-    }
+    }*/
         
         Motor->Integral += Motor->Difference;  //计算积分量
         if(Motor->Integral>15000)   Motor->Integral=15000; //积分限幅
@@ -220,7 +237,7 @@
     //500-100 720k
     //100-1 72k
     //Motor->PIDControl = 5000;
-    if(Motor->PIDControl > PulseFreqLimit)
+    /*if(Motor->PIDControl > PulseFreqLimit)
         Motor->PIDControl = PulseFreqLimit;
     else if((Motor->PIDControl <= PulseFreqLimit) && (Motor->PIDControl > 5000))
         TIM2->PSC=0;            //预分频器设置
@@ -239,9 +256,30 @@
     }
     
     Motor_ARR = APB2Freq / (TIM2->PSC+1) / Motor->PIDControl;
+    TIM2->ARR = Motor_ARR;
+    TIM2->CCR2 = Motor_ARR/2;*/
+    if(Motor->PIDControl > PulseFreqLimit)
+        Motor->PIDControl = PulseFreqLimit;
+    else if((Motor->PIDControl <= PulseFreqLimit) && (Motor->PIDControl > 5000))
+        TIM1->PSC=0;            //预分频器设置
+    else if((Motor->PIDControl <= 5000) && (Motor->PIDControl > 1000))
+        TIM1->PSC=1;            //预分频器设置
+    else if((Motor->PIDControl <= 1000) && (Motor->PIDControl > 500))
+        TIM1->PSC=35;           //预分频器设置
+    else if((Motor->PIDControl <= 5000) && (Motor->PIDControl > 100))
+        TIM1->PSC=99;           //预分频器设置
+    else if((Motor->PIDControl <= 100) && (Motor->PIDControl > 0))
+        TIM1->PSC=999;          //预分频器设置
+    else
+    {
+        Motor->PIDControl = 1;
+        TIM1->PSC=999;          //预分频器设置
+    }
+    
+    Motor_ARR = APB2Freq / (TIM1->PSC+1) / Motor->PIDControl;
     //printf("ll%dll \r\n", Motor_ARR);
-    TIM2->ARR = Motor_ARR;
-    TIM2->CCR2 = Motor_ARR/2;
+    TIM1->ARR = Motor_ARR;
+    TIM1->CCR1 = Motor_ARR/2;
 }
 
 //控制接口