Chen Huan
/
MotorPID
闭环步进电机
Revision 1:cbd6a3232d5b, committed 2018-04-05
- Comitter:
- heroistired
- Date:
- Thu Apr 05 01:37:17 2018 +0000
- Parent:
- 0:5b4f19f8cd85
- Commit message:
- New
Changed in this revision
diff -r 5b4f19f8cd85 -r cbd6a3232d5b GUI.cpp --- /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; +} + +
diff -r 5b4f19f8cd85 -r cbd6a3232d5b GUI.h --- /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
diff -r 5b4f19f8cd85 -r cbd6a3232d5b main.cpp --- 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; }
diff -r 5b4f19f8cd85 -r cbd6a3232d5b motor.cpp --- 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; } //控制接口