網(wǎng)上有很多關(guān)于沃pos機(jī),stm32做PID算法控制減速直流電機(jī)的知識,也有很多人為大家解答關(guān)于沃pos機(jī)的問題,今天pos機(jī)之家(www.shineka.com)為大家整理了關(guān)于這方面的知識,讓我們一起來看下吧!
本文目錄一覽:
沃pos機(jī)
本例程采用了HAL庫進(jìn)行項目開發(fā)(主要使用軟件CubexMX和keil5),文章末尾會有代碼開源,歡迎各位對文章進(jìn)行指正和探討。
基于PID的減速電機(jī)控制一、 硬件模塊與原理圖1、硬件組成硬件組成:stm32f103c8t6最小系統(tǒng)板;0.96寸LED12864(I2C通訊模式);智能小車12v移動電源;25GA370直流減速電機(jī)(帶霍爾編碼器);JDY-31藍(lán)牙模塊;L298N電機(jī)驅(qū)動模塊;杜邦線若干;1個面包板;
圖片如下:
2、模塊分析1、L298N電機(jī)驅(qū)動模塊1.模塊可驅(qū)動兩路直流電機(jī),輸出A和B各接一直流電機(jī)即可;
2.若使用12V供電,將12V供電端口及GND接上電源正負(fù)即可,同時5V供電端可以作為最小系統(tǒng)板的輸入電源;
3.若不需要使用PWM調(diào)速,只需要控制電機(jī)正反轉(zhuǎn),則邏輯A與B跳線帽插上即可,相當(dāng)于始終使能;
4.若需要使用PWM調(diào)速,需將跳線帽拔起,將使能端接上單片機(jī)IO口。(定時器IO口,PWM輸出模式);
5.邏輯輸入四個端口IN1、IN2、IN3、IN4接單片機(jī)四個IO口,每兩個端口控制的一路電機(jī)。
溫馨提示: 特別不建議新手或者資金有限的情況下,使用電機(jī)驅(qū)動模塊直連成品開發(fā)板,很容易燒壞。
原因:(1) 由于電機(jī)的特性,電機(jī)在堵轉(zhuǎn)或者高負(fù)載下,電流會增大,可能會影響到單片機(jī)。(2)新手玩單片機(jī)可能出現(xiàn)短路等情況,很容易板子冒煙;
L298N的轉(zhuǎn)動邏輯圖:
2、0.96寸OLED(I2C通訊)(1)目前市面主要分為OLED與LCD這2種屏幕;
(2)OLED自發(fā)光特性,LCD都要背光,而OLED不需要,因?yàn)樗亲园l(fā)光。這樣同樣的顯示,OLED效果要來得好一些;
(3)多種接口方式:6800,8080兩種并行接口方式,4線的穿行SPI接口,IIC接口方式(2線);
(4)不要接過高電壓,3.3V就可以正常工作了;
(5)OLED不足之處是做大之后成本較高。
本實(shí)驗(yàn)采用了0.96寸OLED的屏幕(通訊方式IIC),4個接線柱(SCL,SDA,GND,VCC); IIC通訊實(shí)現(xiàn)方式: IIC(Inter-Integrated Circuit)總線是一種由 PHILIPS 公司開發(fā)的兩線式串行總線,用于連接微控制器及其外圍設(shè)備。它是由數(shù)據(jù)線 SDA 和時鐘 SCL 構(gòu)成的串行總線,可發(fā)送和接收數(shù)據(jù)。高速 IIC 總線一般可達(dá) 400kbps 以上。
模擬IIC通訊:
I2C 是支持多從機(jī)的,也就是一個 I2C 控制器下可以掛多個 I2C 從設(shè)備,這些不同的 I2C從設(shè)備有不同的器件地址,這樣 I2C 主控制器就可以通過 I2C 設(shè)備的器件地址訪問指定的 I2C設(shè)備了。SDA 和SCL 這兩根線必須要接一個上拉電阻,一般是 4.7K。其余的 I2C 從器件都掛接到 SDA 和 SCL 這兩根線上,這樣就可以通過 SDA 和 SCL 這兩根線來訪問多個 I2C設(shè)備。
I2C 協(xié)議:(1)起始位;(2)停止位;(3)數(shù)據(jù)傳輸;(4)應(yīng)答信號;(5)I2C 寫時序;(6)I2C 讀時序
I2C 寫時序:
1)、開始信號。
2)、發(fā)送 I2C 設(shè)備地址,每個 I2C 器件都有一個設(shè)備地址,通過發(fā)送具體的設(shè)備地址來決
定訪問哪個 I2C 器件。這是一個 8 位的數(shù)據(jù),其中高 7 位是設(shè)備地址,最后 1 位是讀寫位,為
1 的話表示這是一個讀操作,為 0 的話表示這是一個寫操作。
3)、 I2C 器件地址后面跟著一個讀寫位,為 0 表示寫操作,為 1 表示讀操作。
4)、從機(jī)發(fā)送的 ACK 應(yīng)答信號。
5)、重新發(fā)送開始信號。
6)、發(fā)送要寫寫入數(shù)據(jù)的寄存器地址。
7)、從機(jī)發(fā)送的 ACK 應(yīng)答信號。
8)、發(fā)送要寫入寄存器的數(shù)據(jù)。
9)、從機(jī)發(fā)送的 ACK 應(yīng)答信號。
10)、停止信號。
I2C 讀時序:
I2C 單字節(jié)讀時序比寫時序要復(fù)雜一點(diǎn),讀時序分為 4 大步,第一步是發(fā)送設(shè)備地址,第二步是發(fā)送要讀取的寄存器地址,第三步重新發(fā)送設(shè)備地址,最后一步就是 I2C 從器件輸出要讀取的寄存器值,我們具體來看一下這幾步。
1)、主機(jī)發(fā)送起始信號。
2)、主機(jī)發(fā)送要讀取的 I2C 從設(shè)備地址。
3)、讀寫控制位,因?yàn)槭窍?I2C 從設(shè)備發(fā)送數(shù)據(jù),因此是寫信號。
4)、從機(jī)發(fā)送的 ACK 應(yīng)答信號。
5)、重新發(fā)送 START 信號。
6)、主機(jī)發(fā)送要讀取的寄存器地址。
7)、從機(jī)發(fā)送的 ACK 應(yīng)答信號。
8)、重新發(fā)送 START 信號。
9)、重新發(fā)送要讀取的 I2C 從設(shè)備地址。
10)、讀寫控制位,這里是讀信號,表示接下來是從 I2C 從設(shè)備里面讀取數(shù)據(jù)。
11)、從機(jī)發(fā)送的 ACK 應(yīng)答信號。
12)、從 I2C 器件里面讀取到的數(shù)據(jù)。
13)、主機(jī)發(fā)出 NO ACK 信號,表示讀取完成,不需要從機(jī)再發(fā)送 ACK 信號了。
14)、主機(jī)發(fā)出 STOP 信號,停止 I2C 通信。
3、JDY-31藍(lán)牙模塊市場上藍(lán)牙模塊有很多,常見的JDY-xx,HC-xx等系列。其實(shí)看似高級的藍(lán)牙功能背后就是簡單的串口通訊;
USART 的全稱是 Universal Synchronous/Asynchronous Receiver/Transmitter,也就是同步/異步串行收發(fā)器。相比 UART 多了一個同步的功能,在硬件上體現(xiàn)出來的就是多了一條時鐘線。一般 USART 是可以作為 UART 使用的,也就是不使用其同步的功能。
串口通訊協(xié)議:
數(shù)據(jù)包:串口通訊的數(shù)據(jù)包由發(fā)送設(shè)備通過自身的TXD接口傳輸?shù)浇邮赵O(shè)備得RXD接口,在協(xié)議層中規(guī)定了數(shù)據(jù)包的內(nèi)容,具體包括起始位、主體數(shù)據(jù)(8位或9位)、校驗(yàn)位以及停止位,通訊的雙方必須將數(shù)據(jù)包的格式約定一致才能正常收發(fā)數(shù)據(jù)。
具體如圖所示:
波特率:由于異步通信中沒有時鐘信號,所以接收雙方要約定好波特率,即每秒傳輸?shù)拇a元個數(shù),以便對信號進(jìn)行解碼,常見的波特率有4800、9600、115200等。STM32中波特率的設(shè)置通過串口初始化結(jié)構(gòu)體來實(shí)現(xiàn)。
注意:MCU設(shè)置的波特率大小要與藍(lán)牙APP設(shè)置的大小一致!
4、6線減速電機(jī)(帶編碼器)模塊:
市面上電機(jī)有很多,常用的有步進(jìn)電機(jī),直流減速電機(jī),伺服電機(jī)等等; 編碼器:用來測量電機(jī)轉(zhuǎn)速的儀器元件,常見的有:霍爾編碼器,光電編碼器等 電機(jī)的驅(qū)動原理很簡單,給電壓差即可使得電機(jī)轉(zhuǎn)動,調(diào)速則利用PWM調(diào)節(jié)發(fā)。
編碼器原理: 編碼器是一種將角位移或者角速度轉(zhuǎn)換成一串電數(shù)字脈沖的旋轉(zhuǎn)式傳感器。 編碼器工作原理: 霍爾編碼器是有霍爾馬盤和霍爾元件組成。霍爾馬盤是在一定直徑的圓板上等分的布置有不同的磁極。霍爾馬盤與電動機(jī)同軸,電動機(jī)旋轉(zhuǎn)時,霍爾元件檢測輸出若干脈沖信號,為判斷轉(zhuǎn)向,一般輸出兩組存在一定相位差的方波信號。
注意:通過判斷A與B相哪一位在前,即可判斷出正轉(zhuǎn)還是反轉(zhuǎn)
二、CubexMX設(shè)置使用的MCU為stm32f103c8t6:
RCC:
SYS:
注意:Debug這里一定要設(shè)置成Serial Wire否則可能出現(xiàn)芯片自鎖
GPIO設(shè)置:
定時TIM2用來測速與測量正轉(zhuǎn)反轉(zhuǎn)(計數(shù)器模式)
定時3:PWM調(diào)節(jié)
I2C:
USART1:
之后按照自己習(xí)慣生成初始化文件
三、代碼自動生成的:
需要自己編寫的:
I2C代碼:
#include "oled.h"#include "asc.h"#include "main.h"void WriteCmd(unsigned char I2C_Command)//??? {HAL_I2C_Mem_Write(&hi2c2,OLED0561_ADD,COM,I2C_MEMADD_SIZE_8BIT,&I2C_Command,1,100); }void WriteDat(unsigned char I2C_Data)//??? {HAL_I2C_Mem_Write(&hi2c2,OLED0561_ADD,DAT,I2C_MEMADD_SIZE_8bit,&I2C_Data,1,100); }void OLED_Init(void){HAL_Delay(100); //????????WriteCmd(0xAE); //display offWriteCmd(0x20);//Set Memory Addressing ModeWriteCmd(0x10);//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,InvalidWriteCmd(0xb0);//Set Page Start Address for Page Addressing Mode,0-7WriteCmd(0xc8);//Set COM Output Scan DirectionWriteCmd(0x00); //---set low column addressWriteCmd(0x10); //---set high column addressWriteCmd(0x40); //--set start line addressWriteCmd(0x81); //--set contrast control registerWriteCmd(0xff); //???? 0x00~0xffWriteCmd(0xa1); //--set segment re-map 0 to 127WriteCmd(0xa6); //--set normal displayWriteCmd(0xa8); //--set multiplex ratio(1 to 64)WriteCmd(0x3F); //WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM contentWriteCmd(0xd3); //-set display offsetWriteCmd(0x00); //-not offsetWriteCmd(0xd5); //--set display clock divide ratio/oscillator frequencyWriteCmd(0xf0); //--set divide ratioWriteCmd(0xd9); //--set pre-charge periodWriteCmd(0x22); //WriteCmd(0xda); //--set com pins hardware configurationWriteCmd(0x12);WriteCmd(0xdb); //--set vcomhWriteCmd(0x20); //0x20,0.77xVccWriteCmd(0x8d); //--set DC-DC enableWriteCmd(0x14); //WriteCmd(0xaf); //--turn on oled panel} void OLED_SetPos(unsigned char x, unsigned char y) //???????{ WriteCmd(0xb0+y);WriteCmd(((x&0xf0)>>4)|0x10);WriteCmd((x&0x0f)|0x01);} void OLED_Fill(unsigned char fill_Data)//????{unsigned char m,n;for(m=0;m<8;m++){WriteCmd(0xb0+m);//page0-page1WriteCmd(0x00);//low column start addressWriteCmd(0x10);//high column start addressfor(n=0;n<128;n++){WriteDat(fill_Data);}}} void OLED_CLS(void)//??{OLED_Fill(0x00);} void OLED_ON(void){WriteCmd(0X8D); //?????WriteCmd(0X14); //?????WriteCmd(0XAF); //OLED??} void OLED_OFF(void){WriteCmd(0X8D); //?????WriteCmd(0X10); //?????WriteCmd(0XAE); //OLED??} // Parameters : x,y -- ?????(x:0~127, y:0~7); ch[] -- ???????; TextSize -- ????(1:6*8 ; 2:8*16)// Description : ??codetab.h??ASCII??,?6*8?8*16???void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize){unsigned char c = 0,i = 0,j = 0;switch(TextSize){case 1:{while(ch[j] != '\\0'){c = ch[j] - 32;if(x > 126){x = 0;y++;}OLED_SetPos(x,y);for(i=0;i<6;i++)WriteDat(F6x8[c][i]);x += 6;j++;}}break;case 2:{while(ch[j] != '\\0'){c = ch[j] - 32;if(x > 120){x = 0;y++;}OLED_SetPos(x,y);for(i=0;i<8;i++)WriteDat(F8X16[c*16+i]);OLED_SetPos(x,y+1);for(i=0;i<8;i++)WriteDat(F8X16[c*16+i+8]);x += 8;j++;}}break;}} // Parameters : x,y -- ?????(x:0~127, y:0~7); N:???.h????// Description : ??ASCII_8x16.h????,16*16??void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N){unsigned char wm=0;unsigned int adder=32*N;OLED_SetPos(x , y);for(wm = 0;wm < 16;wm++){WriteDat(F16x16[adder]);adder += 1;}OLED_SetPos(x,y + 1);for(wm = 0;wm < 16;wm++){WriteDat(F16x16[adder]);adder += 1;}} // ????????????????,????????“??——???——????”??????ascll.h?????(????)//???????:x:????? //y:???(??0-7) //begin:????????????????ascll.c??????? // num:????????// ????“??”,??????????????????0,1,???0,??????,??:x:0,y:2,begin:0,num:2void OLED_ShowCN_STR(u8 x , u8 y , u8 begin , u8 num){u8 i;for(i=0;i<num;i++){OLED_ShowCN(i*16+x,y,i+begin);} //OLED????} // Parameters : x0,y0 -- ?????(x0:0~127, y0:0~7); x1,y1 -- ?????(???)???(x1:1~128,y1:1~8)// Description : ??BMP??void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]){unsigned int j=0;unsigned char x,y; if(y1%8==0)y = y1/8; elsey = y1/8 + 1;for(y=y0;y<y1;y++){OLED_SetPos(x0,y); for(x=x0;x<x1;x++){WriteDat(BMP[j++]);}}} void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size){ unsigned char c=0,i=0;c=chr-' ';//???????if(x>128-1){x=0;y=y+2;}if(Char_Size ==16){OLED_SetPos(x,y);for(i=0;i<8;i++)WriteDat(F8X16[c*16+i]);OLED_SetPos(x,y+1);for(i=0;i<8;i++)WriteDat(F8X16[c*16+i+8]);}else {OLED_SetPos(x,y);for(i=0;i<6;i++)WriteDat(F6x8[c][i]);}}u32 oled_pow(u8 m,u8 n){u32 result=1; while(n--)result*=m; return result;}//??2???//x,y :???? //len :?????//size:????//mode:??0,????;1,????//num:??(0~4294967295); void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2){ u8 t,temp;u8 enshow=0; for(t=0;t<len;t++){temp=(num/oled_pow(10,len-t-1));if(enshow==0&&t<(len-1)){if(temp==0){OLED_ShowChar(x+(size2/2)*t,y,' ',size2);continue;}else enshow=1; } OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); }}
UART代碼:
#include "uart.h" uint8_t USART1_RX_BUF[USART1_REC_LEN];//????,??USART_REC_LEN???.uint16_t USART1_RX_STA=0;//??????//bit15:??????,bit14~0:??????????uint8_t USART1_NewData;//?????????1???????? extern int flag; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//????????{ if(huart ==&huart1) { if((USART1_RX_STA&0x8000)==0)//????? { if(USART1_NewData==0x5A)//????0x5A { USART1_RX_STA|=0x8000; //?????,?USART2_RX_STA??bit15(15?)?1 } else { USART1_RX_BUF[USART1_RX_STA&0X7FFF]=USART1_NewData; if(USART1_RX_BUF[1] == 0x01){flag = 2;} USART1_RX_STA++; //???????1 if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//??????,?????? } } HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_NewData,1); }}
常規(guī)的編寫如上,但是本人的MCU存在問題,單片機(jī)并未接收到預(yù)設(shè)的數(shù)據(jù)。
所以,本人項目中采用了下方代碼:
#include "uart.h" uint8_t USART1_RX_BUF[USART1_REC_LEN];//????,??USART_REC_LEN???.uint16_t USART1_RX_STA=0;//??????//bit15:??????,bit14~0:??????????uint8_t USART1_NewData;//?????????1???????? extern int flag; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//????????{ if(huart ==&huart1) { USART1_RX_BUF[USART1_RX_STA&0X7FFF]=USART1_NewData; USART1_RX_STA++; //???????1 if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//??????,??????if(USART1_RX_BUF[USART1_RX_STA-4] == 0xA0){flag = 1;}if(USART1_RX_BUF[USART1_RX_STA-4] == 0x90){flag = 2;}if(USART1_RX_BUF[USART1_RX_STA-4] == 0xD0){flag = 3;}if(USART1_RX_BUF[USART1_RX_STA-4] == 0x88){flag = 4;}if(USART1_RX_BUF[USART1_RX_STA-4] == 0x48){flag = 5;} HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_NewData,1); }}
如果大家自己使用的花,可以根據(jù)自己的藍(lán)牙APP寫這段程序,有問題歡迎留言
Motor代碼:
#include "motor.h" void MOTOR_GO(){__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,3000);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);} void MOTOR_BACK(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);} void MOTOR_STOP(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);} void MOTOR_UP(){__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,1);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);} void MOTOR_DOWN(){__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,400);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);}
PID:
PID算法:
PID分為位置型和增量型
增量型即通過 u(k)-u(k-1) 從而得出式子:
公式的第一部分是比例式 是為了讓值按一定比例達(dá)到目標(biāo)值;
第二部分是積分值,正值,在計算的過程中往往會受到環(huán)境等一些其他因素的影響,導(dǎo)致值不能到達(dá)目標(biāo)值;
第三部分是微分值,通常是負(fù)值,后一次偏差值往往小于前一次偏差值,目的是為了防止值增加過大,通常起一個阻礙的作用;
PID代碼:
#include "pid.h"#include "tim.h"#include "main.h"#include "math.h"#include "i2c.h"#include "oled.h" unsigned int MotorSpeed;//è???±?á?£?μ??úμ±?°×a?ùint SpeedTarget = 750;//??±ê×a?ùint MotorOutput;//μ??úê?3? //1.à?ó?TIM2????μ??ú×a?ù void GetMotorSpeed(void){//int CaptureNumber =(short)__HAL_TIM_GET_COUNTER(&htim2); //HAL?aoˉêy??????3?′?êy//////μ??ú×a?ù×a??Speed=1s?úμ???3?êy/44(ò?è|11??D?o?£?4±??μ·¨)/34???ù±è//int MotorSpeed=CaptureNumber*20/44/34*2*3.14*3;//OLED_ShowNum(40,0,MotorSpeed,4,16);////__HAL_TIM_GET_COUNTER(&htim2) = 0;//??êy?÷??á?int CaptureNumber =(short)__HAL_TIM_GET_COUNTER(&htim2); //???????__HAL_TIM_GET_COUNTER(&htim2) = 0;//int Speed=CaptureNumber*5/44/34*2*3.14*3; int Direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2); if(Direction == 1){CaptureNumber -= 65535;}MotorSpeed=CaptureNumber;OLED_ShowNum(40,0,MotorSpeed,4,16);HAL_Delay(100);OLED_CLS();//__HAL_TIM_GET_COUNTER(&htim2) = 0;} //2.??á?ê?PID?????÷£¨PID3£??·??a????PIDoí??á?ê?PID£? int Error_Last,Error_Prev;//é?′??ó2?£?é?é?′??ó2?int Pwm_add,Pwm;//PWM??á?,PWM????±è int Kp = 5, Ki = 3, Kd = 1;//PID??·¨?μêy£???μ?ààDí£?D????????üá|ò?°?ê±?¨òé??Dí£??ò??*1024 int SpeedInnerControl(int Speed,int Target)//?ù?è?ú?·????{ int Error = Target - Speed;//?ó2? = ??±ê?ù?è - êμ?ê?ù?è Pwm_add = Kp * (Error - Error_Last) + //±èàyKi * Error +//?y·?Kd * (Error - 2.0f * Error_Last + Error_Prev);//?¢·? Pwm += Pwm_add;//ê?3?á?=?\xadê?á?+??á?Error_Prev = Error_Last;//±£′?é?é?′??ó2? Error_Last = Error;//±£′?é?′??ó2? if(Pwm > 4999) Pwm = 3000;//?T??é????T£?·à?1PWM3?3?á?3ì if(Pwm <-4999) Pwm =-3000; return Pwm;//·μ??ê?3??μ} //3.μ??ú×a?ùó?·??òμ?oˉêy£¨PID????£? void SetMotorVoltageAndDirection(int Pwm){ if(Pwm < 0)//è?1?PWMD?óú0 { HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET); Pwm = (-Pwm);//PWM???üè??y?μ£?è?1??a?oêy£??±?óè?·′ __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, Pwm);//PWMμ÷?ù } else {HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, Pwm);//PWMμ÷?ù }} void ModePID(){ GetMotorSpeed(); MotorOutput = SpeedInnerControl(MotorSpeed,SpeedTarget); SetMotorVoltageAndDirection(MotorOutput);}
主函數(shù)代碼:
while (1) { switch(flag) { case(1):MOTOR_GO();break; case(2):MOTOR_BACK();break; case(3):MOTOR_STOP();break; case(4):MOTOR_UP();break; case(5):ModePID();break; default:break; } /* USER CODE END WHILE */if(flag != 5){int CaptureNumber =(short)__HAL_TIM_GET_COUNTER(&htim2); //???????__HAL_TIM_GET_COUNTER(&htim2) = 0;// int Direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2); //μ??ú×a?ù×a??Speed=1s?úμ???3?êy/44(ò?è|11??D?o?£?4±??μ·¨)/34???ù±è//int Speed=CaptureNumber*5/44/34*2*3.14*3; int Direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2); if(Direction == 1){CaptureNumber -= 65535;}int Speed=CaptureNumber; OLED_ShowNum(40,0,Speed,5,16);HAL_Delay(100);OLED_CLS();} int Direction = __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim2); OLED_ShowCN_STR(0,0,0,3);// OLED_ShowNum(40,0,Speed,4,16);OLED_ShowStr(90,0,"cm/s",2);OLED_ShowCN_STR(0,3,3,2); if(Direction==0){OLED_ShowCN_STR(40,3,5,2);}if(Direction==1){OLED_ShowCN_STR(40,3,7,2);}//HAL_Delay(1000);//OLED_CLS(); /* USER CODE BEGIN 3 */ }
藍(lán)牙APP源代碼以及技術(shù)論文:鏈接:https://pan.baidu.com/s/1-rbicxuyLVCq6rglCWcJTg 提取碼:huzm
以上就是關(guān)于沃pos機(jī),stm32做PID算法控制減速直流電機(jī)的知識,后面我們會繼續(xù)為大家整理關(guān)于沃pos機(jī)的知識,希望能夠幫助到大家!
