|
電機(jī)驅(qū)動(dòng)電路使用H橋可逆斬波電路,通過采樣電阻和旋轉(zhuǎn)編碼器測量電機(jī)轉(zhuǎn)速和電流
單片機(jī)代碼如下:
- /*
- 設(shè)計(jì)思路
- 電機(jī)驅(qū)動(dòng)電路:使用H橋可逆斬波電路去驅(qū)動(dòng)電機(jī)轉(zhuǎn)動(dòng),該電路可在網(wǎng)上查找學(xué)習(xí)相關(guān)知識(shí)。
- 電機(jī)的調(diào)速可通過改變PWM波的占空比實(shí)現(xiàn),當(dāng)占空比為50%時(shí),電機(jī)不轉(zhuǎn),
- 當(dāng)占空比大于50%時(shí)電機(jī)正轉(zhuǎn),并且越大轉(zhuǎn)速越快,但不要超過80%,超過可能會(huì)使電路發(fā)燙
- 當(dāng)占空比小于50%時(shí)電機(jī)反轉(zhuǎn),并且越小轉(zhuǎn)速越快,但不要超過20%,超過可能會(huì)使電路發(fā)燙
- 測電流是在驅(qū)動(dòng)電路兩個(gè)下橋臂和電源地之間加了一個(gè)采樣電阻,通過AD轉(zhuǎn)換讀取采樣電阻電壓得到電流
- 測電機(jī)轉(zhuǎn)速是利用電機(jī)上的旋轉(zhuǎn)編碼器,編碼器為96線編碼器,所以電機(jī)轉(zhuǎn)一圈會(huì)發(fā)出96個(gè)脈沖
- 使用單片機(jī)的外部中斷,設(shè)置觸發(fā)方式為邊沿觸發(fā),記錄脈沖數(shù)
- 使用單片機(jī)的定時(shí)器中斷,每50ms產(chǎn)生一次中斷,在中斷里讀取當(dāng)前脈沖數(shù),計(jì)算轉(zhuǎn)速,之后脈沖數(shù)置0
- 根據(jù)直流電機(jī)的電流與轉(zhuǎn)矩之間的關(guān)系,計(jì)算電機(jī)的轉(zhuǎn)矩
- 轉(zhuǎn)矩和扭矩是一個(gè)物理量,只是在不同的場合稱呼不同
- */
- #include "reg52.h"
- #include "iic.h"
- #include "oled.h"
- #include<stdio.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define PCF8591 0x90 //PCF8591 地址
- #define qCt 12.75
- uchar data_byte;
- u8 RH,RL,TH,TL,U8FLAG;
- sbit PWM1=P1^2;//接IN1 控制正轉(zhuǎn)
- u8 duty = 7 ; //定義占空比,H橋可逆斬波電路在50%占空比時(shí)電機(jī)不轉(zhuǎn),大于50%正轉(zhuǎn),小于50%反轉(zhuǎn),
- //6表示占空比為70%,不要修改占空比,不同占空比下電機(jī)功率不同,導(dǎo)致扭矩計(jì)算錯(cuò)誤
- u8 time;
- int pluse = 0 ; //電機(jī)編碼器的脈沖數(shù)
- float Speed = 0.0 ; //速度
- #define NOP() _nop_() /* 定義空指令 */
- #define _Nop() _nop_() /*定義空指令*/
-
- sbit m_SCL=P1^4; //I2C 時(shí)鐘
- sbit m_SDA=P1^3; //I2C 數(shù)據(jù)
- bit ack; /*應(yīng)答標(biāo)志位*/
-
- /*******************************************************************
- 起動(dòng)總線函數(shù)
- 函數(shù)原型: void Start_I2c();
- 功能: 啟動(dòng)I2C總線,即發(fā)送I2C起始條件.
- ********************************************************************/
- void Start_I2c()
- {
- m_SDA=1; /*發(fā)送起始條件的數(shù)據(jù)信號(hào)*/
- _Nop();
- m_SCL=1;
- _Nop(); /*起始條件建立時(shí)間大于4.7us,延時(shí)*/
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- m_SDA=0; /*發(fā)送起始信號(hào)*/
- _Nop(); /* 起始條件鎖定時(shí)間大于4μs*/
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- m_SCL=0; /*鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) */
- _Nop();
- _Nop();
- }
- /*******************************************************************
- 結(jié)束總線函數(shù)
- 函數(shù)原型: void Stop_I2c();
- 功能: 結(jié)束I2C總線,即發(fā)送I2C結(jié)束條件.
- ********************************************************************/
- void Stop_I2c()
- {
- m_SDA=0; /*發(fā)送結(jié)束條件的數(shù)據(jù)信號(hào)*/
- _Nop(); /*發(fā)送結(jié)束條件的時(shí)鐘信號(hào)*/
- m_SCL=1; /*結(jié)束條件建立時(shí)間大于4μs*/
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- m_SDA=1; /*發(fā)送I2C總線結(jié)束信號(hào)*/
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- }
- /*******************************************************************
- 字節(jié)數(shù)據(jù)發(fā)送函數(shù)
- 函數(shù)原型: void SendByte(UCHAR c);
- 功能: 將數(shù)據(jù)c發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對(duì)
- 此狀態(tài)位進(jìn)行操作.(不應(yīng)答或非應(yīng)答都使ack=0)
- 發(fā)送數(shù)據(jù)正常,ack=1; ack=0表示被控器無應(yīng)答或損壞。
- ********************************************************************/
- void SendByte(unsigned char c)
- {
- unsigned char BitCnt;
-
- for(BitCnt=0;BitCnt<8;BitCnt++) /*要傳送的數(shù)據(jù)長度為8位*/
- {
- if((c<<BitCnt)&0x80)m_SDA=1; /*判斷發(fā)送位*/
- else m_SDA=0;
- _Nop();
- m_SCL=1; /*置時(shí)鐘線為高,通知被控器開始接收數(shù)據(jù)位*/
- _Nop();
- _Nop(); /*保證時(shí)鐘高電平周期大于4μs*/
- _Nop();
- _Nop();
- _Nop();
- m_SCL=0;
- }
-
- _Nop();
- _Nop();
- m_SDA=1; /*8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位*/
- _Nop();
- _Nop();
- m_SCL=1;
- _Nop();
- _Nop();
- _Nop();
- if(m_SDA==1)ack=0;
- else ack=1; /*判斷是否接收到應(yīng)答信號(hào)*/
- m_SCL=0;
- _Nop();
- _Nop();
- }
- /*******************************************************************
- 字節(jié)數(shù)據(jù)接收函數(shù)
- 函數(shù)原型: UCHAR RcvByte();
- 功能: 用來接收從器件傳來的數(shù)據(jù),并判斷總線錯(cuò)誤(不發(fā)應(yīng)答信號(hào)),
- 發(fā)完后請(qǐng)用應(yīng)答函數(shù)應(yīng)答從機(jī)。
- ********************************************************************/
- unsigned char RcvByte()
- {
- unsigned char retc;
- unsigned char BitCnt;
-
- retc=0;
- m_SDA=1; /*置數(shù)據(jù)線為輸入方式*/
- for(BitCnt=0;BitCnt<8;BitCnt++)
- {
- _Nop();
- m_SCL=0; /*置時(shí)鐘線為低,準(zhǔn)備接收數(shù)據(jù)位*/
- _Nop();
- _Nop(); /*時(shí)鐘低電平周期大于4.7μs*/
- _Nop();
- _Nop();
- _Nop();
- m_SCL=1; /*置時(shí)鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效*/
- _Nop();
- _Nop();
- retc=retc<<1;
- if(m_SDA==1)retc=retc+1; /*讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中 */
- _Nop();
- _Nop();
- }
- m_SCL=0;
- _Nop();
- _Nop();
- return(retc);
- }
- /********************************************************************
- 應(yīng)答子函數(shù)
- 函數(shù)原型: void Ack_I2c(bit a);
- 功能: 主控器進(jìn)行應(yīng)答信號(hào)(可以是應(yīng)答或非應(yīng)答信號(hào),由位參數(shù)a決定)
- ********************************************************************/
- void Ack_I2c(bit a)
- {
-
- if(a==0)m_SDA=0; /*在此發(fā)出應(yīng)答或非應(yīng)答信號(hào) */
- else m_SDA=1;
- _Nop();
- _Nop();
- _Nop();
- m_SCL=1;
- _Nop();
- _Nop(); /*時(shí)鐘低電平周期大于4μs*/
- _Nop();
- _Nop();
- _Nop();
- m_SCL=0; /*清時(shí)鐘線,鉗住I2C總線以便繼續(xù)接收*/
- _Nop();
- _Nop();
- }
- /*******************************************************************
- DAC 變換, 轉(zhuǎn)化函數(shù)
- *******************************************************************/
- bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
- {
- Start_I2c(); //啟動(dòng)總線
- SendByte(sla); //發(fā)送器件地址
- if(ack==0)return(0);
- SendByte(c); //發(fā)送控制字節(jié)
- if(ack==0)return(0);
- SendByte(Val); //發(fā)送DAC的數(shù)值
- if(ack==0)return(0);
- Stop_I2c(); //結(jié)束總線
- return(1);
- }
- /*******************************************************************
- ADC發(fā)送字節(jié)[命令]數(shù)據(jù)函數(shù)
- *******************************************************************/
- bit ISendByte(unsigned char sla,unsigned char c)
- {
- Start_I2c(); //啟動(dòng)總線
- SendByte(sla); //發(fā)送器件地址
- if(ack==0)return(0);
- SendByte(c); //發(fā)送數(shù)據(jù)
- if(ack==0)return(0);
- Stop_I2c(); //結(jié)束總線
- return(1);
- }
- unsigned char IRcvByte(unsigned char sla)
- { unsigned char c;
- Start_I2c(); //啟動(dòng)總線
- SendByte(sla+1); //發(fā)送器件地址
- if(ack==0)return(0);
- c=RcvByte(); //讀取數(shù)據(jù)0
- Ack_I2c(1); //發(fā)送非就答位
- Stop_I2c(); //結(jié)束總線
- return 0;
- }
- float Get_Current(unsigned char s) //讀取電流
- {
- float t ;
- t = IRcvByte(s) ;
- if(Speed != 0 )
- {if(Speed <= 250)
- {
- t = 7.8 -0.027*Speed;
- return t ;
- }else
- {return 0.1;}
- }
- else
- {
- return 0 ;
- }
- }
- void int0() interrupt 0 using 0//外部中斷0的執(zhí)行程序。
- { //interrupt 0指外部中斷0 using 0指第0組寄存器
- pluse++ ;
- }
- void timer0_init()
- {
- TMOD=0x01;//定時(shí)器0工作方式1 定時(shí)器1工作方式1
-
- TH0=0xff;
- TL0=0xa3;//定時(shí)50ms
-
- TH1=0x4b;
- TL1=0xff;//定時(shí)0.1ms
-
- IT0=1;//外部中斷0為跳變沿觸發(fā)方式
-
- EA=1;//開總中斷
- EX0=1;//打開外部中斷0
-
- ET0=1;//打開定時(shí)器0中斷開關(guān)
- TR0=1;//打開定時(shí)器0運(yùn)行開關(guān)
- ET1=1;//打開定時(shí)器0中斷開關(guān)
- TR1=1;//打開定時(shí)器0運(yùn)行開關(guān)
- PT1 = 0 ;
- PX0 = 1 ;
- PT0 = 1 ;
-
- }
- void tim0() interrupt 1
- {
- TR0=0; //賦初值時(shí),關(guān)閉定時(shí)器
- TH0=0xff;
- TL0=0xa3; //定時(shí)0.1ms
- TR0=1; //打開定時(shí)器
- time++;
-
- if(time>=10) //10*0.1ms=1ms pwm波一個(gè)周期1ms,即1khz
- {
- time=0;
- }
- if(time<=duty) PWM1=1; //點(diǎn)空比70%
- else PWM1=0;
- }
- void tim1() interrupt 3 //定時(shí)器1的中斷服務(wù)函數(shù)
- {
- EX0 = 0 ;//關(guān)閉外部中斷,停止記錄脈沖數(shù)
- TR1=0; //賦初值時(shí),關(guān)閉定時(shí)器
- TH1=0x4b;
- TL1=0xff; //定時(shí)50ms
- TR1=1; //打開定時(shí)器
- Speed = pluse*12.5 ; //將脈沖數(shù)轉(zhuǎn)化為轉(zhuǎn)速,編碼器為96線,轉(zhuǎn)一圈輸出96個(gè)脈沖,所以轉(zhuǎn)速=脈沖數(shù)/50ms/96*60 ,單位轉(zhuǎn)/分鐘
- pluse = 0 ;
- EX0 = 1 ;//打開外部中斷
- }
- void main() //主循環(huán)
- {
- char a[6] ;
- float Current=0.0 ;
- float T = 0.0 ;
- OLED_Init(); //初始化屏幕
- OLED_Clear();
- OLED_ShowString(0,0,"Speed:",12);//顯示字符
- OLED_ShowString(95,0,"r/m",12);
- OLED_ShowString(0,3,"I:",12);
- OLED_ShowString(95,3,"A",12);
- OLED_ShowString(0,5,"T:",12);
- OLED_ShowString(95,5,"N*m",12);
- timer0_init(); //配置定時(shí)器和外部中斷
-
- while(1)
- {
- sprintf(a,"%.1f ",Speed); //顯示速度
- OLED_ShowString(50,0,a,12);
-
-
- if(ISendByte(PCF8591,0x40))
- {
- Current= Get_Current(PCF8591);
- }
- T = Current*qCt; //電機(jī)扭矩=電流*轉(zhuǎn)矩常數(shù)*磁通量
-
- sprintf(a,"%.2f ",Current); //顯示電流
- OLED_ShowString(40,3,a,12);
-
-
- sprintf(a,"%.2f ",T); //顯示扭矩
- OLED_ShowString(40,5,a,12);
- }
-
- }
復(fù)制代碼
Keil代碼下載:
電機(jī)轉(zhuǎn)速電流.zip
(350.44 KB, 下載次數(shù): 42)
2022-5-5 16:05 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|