标题: STM32直流电机位置PID调节程序 上位机显示波形,直流电机位置环 [打印本页]

作者: 51小白冬    时间: 2021-8-15 12:31
标题: STM32直流电机位置PID调节程序 上位机显示波形,直流电机位置环
其中包含原理图,pcb,bom表 app 上位机stm32f103c8t6为主控,app控制显示波形,上位机显示波形,直流电机位置环。
位置PID调节使用说明
简介:
应用stm32f103c8t6最小系统与双相编码器电机实现电机位置pid调节。
主要功能:
整体结构:
使用说明:

第一行数据为目标值(初始为10000脉冲的位置);
第二行为目前数值(初始为10000脉冲的位置故初始电机不动作);

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)



STM32单片机源程序如下:
  1. #include "oled.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "TIME.h"
  5. #include "usart.h"         
  6. #include "DataScope_DP.h"
  7. #include "usart2.h"
  8. #include "string.h"

  9. u8 modle=3;        //改变倍数选择  
  10. u16 Target=30000; //初始化目标值
  11. float Kp=120,Ki=0,Kd=360;//pid参数初始设定
  12. unsigned char i;          //计数变量
  13. unsigned char Send_Count; //串口需要发送的数据个数
  14. void gui(void);//oled界面函数
  15. void blup(void);//上位机传输函数
  16. void blue_recive(void);//蓝牙接收函数
  17. int main(void)
  18. {         

  19.         delay_init();                     //延时函数初始化         
  20.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组
  21.         TIME_init(); //定时器,定时中断初始化
  22.         PWM_init();//pwwm初始化
  23.         usart2_init(115200);//串口2初始化 只用到发送
  24.         uart_init(9600);//串口1初始化
  25.         LED_Init();  //相关io初始化
  26.         OLED_Init();                          //初始化OLED      
  27.         OLED_Refresh_Gram();                //更新显示到OLED  
  28.          
  29.         while(1)
  30.         {            
  31.   gui();
  32.         blup();
  33.         blue_recive();
  34.         delay_ms(70);         
  35.         printf("%d",((int)((TIM2->CNT)*0.02)));
  36.         //printf("PID调节测试程序ok");
  37.         }
  38. }
  39.   
  40. /************************************************
  41. 名称:蓝牙接收程序
  42. 介绍:接收来自app的串口数据
  43. 应用:串口1
  44. ************************************************/

  45. void blue_recive()
  46. {      

  47.     if(USART_RX_STA&0x8000)                                             //如果串口有数据发来
  48.     {                     
  49.                         
  50.                                 if(USART_RX_BUF[0]=='T') {Target=(USART_RX_BUF[1]-'0')*10000+(USART_RX_BUF[2]-'0')*1000+
  51.                                                         (USART_RX_BUF[3]-'0')*100+(USART_RX_BUF[4]-'0')*10+(USART_RX_BUF[5]-'0')*1;}                //解码app发来的 tardgt的位置
  52.                                                         if(USART_RX_BUF[0]=='s')  modle=1;//改变倍数*0.01
  53.                                                         if(USART_RX_BUF[0]=='S')  modle=2;//改变倍数*0.1
  54.                                                         if(USART_RX_BUF[0]=='M')  modle=3;//改变倍数*1
  55.                                                         if(USART_RX_BUF[0]=='L')  modle=4; //改变倍数*10
  56.                                                                                                                                        
  57.                                                         if(USART_RX_BUF[0]=='B')  Target+=2000;  //响应正步进2000
  58.                                                         if(USART_RX_BUF[0]=='b')  Target-=2000;  //响应负步进2000
  59.                                                         
  60.                                                 
  61.                   if(modle==1)//倍数*0.01
  62.                                                                  {
  63.                                                            if(USART_RX_BUF[0]=='P'&USART_RX_BUF[1]=='+') {Kp+=0.01;}//如果发来的数据以p为帧头则为p的变量以下同理
  64.                                                                   if(USART_RX_BUF[0]=='I'&USART_RX_BUF[1]=='+') {Ki+=0.01;}//此部分可以用str函数进行                                         
  65.                                                            if(USART_RX_BUF[0]=='D'&USART_RX_BUF[1]=='+') {Kd+=0.01;}               
  66.                  if(USART_RX_BUF[0]=='P'&USART_RX_BUF[1]=='-') {Kp-=0.01;}
  67.                                                            if(USART_RX_BUF[0]=='I'&USART_RX_BUF[1]=='-') {Ki-=0.01;}
  68.                                                            if(USART_RX_BUF[0]=='D'&USART_RX_BUF[1]=='-') {Kd-=0.01;}
  69.                                                                  }     
  70.                   if(modle==2)//倍数*0.1
  71.                                                                  {
  72.                                                            if(USART_RX_BUF[0]=='P'&USART_RX_BUF[1]=='+') {Kp+=0.1;}
  73.                                                                   if(USART_RX_BUF[0]=='I'&USART_RX_BUF[1]=='+') {Ki+=0.1;}                                                
  74.                                                            if(USART_RX_BUF[0]=='D'&USART_RX_BUF[1]=='+') {Kd+=0.1;}               
  75.                  if(USART_RX_BUF[0]=='P'&USART_RX_BUF[1]=='-') {Kp-=0.1;}
  76.                                                            if(USART_RX_BUF[0]=='I'&USART_RX_BUF[1]=='-') {Ki-=0.1;}
  77.                                                            if(USART_RX_BUF[0]=='D'&USART_RX_BUF[1]=='-') {Kd-=0.1;}
  78.                                                                  }   
  79.                   if(modle==3)//倍数*1
  80.                                                                  {
  81.                                                            if(USART_RX_BUF[0]=='P'&USART_RX_BUF[1]=='+') {Kp+=1;}
  82.                                                                   if(USART_RX_BUF[0]=='I'&USART_RX_BUF[1]=='+') {Ki+=1;}                                                
  83.                                                            if(USART_RX_BUF[0]=='D'&USART_RX_BUF[1]=='+') {Kd+=1;}               
  84.                  if(USART_RX_BUF[0]=='P'&USART_RX_BUF[1]=='-') {Kp-=1;}
  85.                                                            if(USART_RX_BUF[0]=='I'&USART_RX_BUF[1]=='-') {Ki-=1;}
  86.                                                            if(USART_RX_BUF[0]=='D'&USART_RX_BUF[1]=='-') {Kd-=1;}
  87.                                                                  }   
  88.                   if(modle==4)//倍数*10
  89.                                                                  {
  90.                                                            if(USART_RX_BUF[0]=='P'&USART_RX_BUF[1]=='+') {Kp+=10;}
  91.                                                                   if(USART_RX_BUF[0]=='I'&USART_RX_BUF[1]=='+') {Ki+=10;}                                                
  92.                                                            if(USART_RX_BUF[0]=='D'&USART_RX_BUF[1]=='+') {Kd+=10;}               
  93.                  if(USART_RX_BUF[0]=='P'&USART_RX_BUF[1]=='-') {Kp-=10;}
  94.                                                            if(USART_RX_BUF[0]=='I'&USART_RX_BUF[1]=='-') {Ki-=10;}
  95.                                                            if(USART_RX_BUF[0]=='D'&USART_RX_BUF[1]=='-') {Kd-=10;}
  96.                                                                  }                                                                                    
  97.                USART_RX_STA=0;                                       //清除中断 标志位
  98.     }
  99. }

  100. /************************************************
  101. 名称:上位机波形显示程序
  102. 介绍:向上位机发送波形信息
  103. 应用:串口2
  104. ************************************************/
  105. void blup(void)
  106. {

  107.         DataScope_Get_Channel_Data(TIM2->CNT, 1 );
  108.         DataScope_Get_Channel_Data(Target, 2 );
  109.         Send_Count = DataScope_Data_Generate(2);
  110.         for( i = 0 ; i < Send_Count; i++)
  111.         {
  112.         while((USART2->SR&0X40)==0);  
  113.         USART2->DR = DataScope_OutPut_Buffer[i];
  114.         }
  115. }


  116. /************************************************
  117. 名称:oled界面程序
  118. 介绍:编辑oled界面提示相关信息
  119. 应用:spi通讯
  120. ************************************************/
  121. void gui(void)
  122. {

  123.   OLED_ShowString(0,0,"Target:",12);  
  124.         OLED_ShowNum(48,0,Target,5,12);        
  125.                                 
  126.         OLED_ShowString(0,16,"CNT:",12);  
  127.         OLED_ShowNum(48,16,TIM2->CNT,5,12);        
  128.                
  129.         OLED_ShowString(0,32,"PWM:",12);  
  130.         OLED_ShowNum(42,32,PWMA,4,12);        
  131.         OLED_ShowString(66,32,"/7100",12);                  
  132.                
  133.         OLED_ShowString(0,46,"Kp:",12);       OLED_ShowNum(15,46,Kp,3,12);        
  134.   OLED_ShowString(50,46,"Ki:",12);      OLED_ShowNum(66,46,Ki*100,2,12);        
  135.   OLED_ShowString(90,46,"Kd:",12);                  OLED_ShowNum(108,46,Kd,3,12);        
  136.         if(modle==1)        OLED_ShowString(100,16,"s",12);  
  137.         if(modle==2)        OLED_ShowString(100,16,"S",12);  
  138.         if(modle==3)        OLED_ShowString(100,16,"M",12);  
  139.         if(modle==4)        OLED_ShowString(100,16,"L",12);  
  140.   OLED_Refresh_Gram();                //更新显示到OLED
  141. }
复制代码

上位机和app没有代码,只有单片机有代码
资料51hei下载地址:
PID演示调节资料.7z (12.17 MB, 下载次数: 155)
PID调节演示pcb.zip (3.67 MB, 下载次数: 103)


作者: xyw@6    时间: 2021-11-2 11:03
楼主想问一下,可以实现精准控制电机转动角度,或者距离吗
作者: 51小白冬    时间: 2021-12-20 21:14
xyw@6 发表于 2021-11-2 11:03
楼主想问一下,可以实现精准控制电机转动角度,或者距离吗

可以的 精度取决于你的负载和pid参数

作者: mick32    时间: 2022-4-2 18:38
Hello
after trying MiniBalance.exe I am getting error

Data Scope cannot operate normally because it cannot create the necessary configuration information!
Please try to run DataScope as a sound agent

Does it work on WIN10 X64 ?

Thank you
作者: xzp0630    时间: 2022-4-23 21:13
请问可以借鉴下上位机和APP代码吗?
作者: mick32    时间: 2022-4-24 01:29
" Does it work on WIN10 X64 ?"

This program must be run under Win32
found with ultraedit...
作者: 51小白冬    时间: 2022-4-28 22:04
xzp0630 发表于 2022-4-23 21:13
请问可以借鉴下上位机和APP代码吗?

上位机不是 我写的 你可以用qt做一个

作者: cuihaodianzi    时间: 2022-11-18 15:02
好东西,下载完了评论点赞




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1