最近學(xué)習(xí)單片機想做個項目試試,其實這個想法在好幾年前就有的,但因為工作原因,沒有時間和精力做這些東西
今年宅在家沒事做,翻出了幾年前遺棄的東東重新擺弄。
硬件介紹:
底部
底部
頂部
1、兩個掃地機器人上的減速馬達(帶紅外光電編碼器);
2、MPU6050模塊,淘寶買的,GY-521模塊(當時買成10元左右,現(xiàn)在3元就能買到)
3、L298電機驅(qū)動模塊;
4、51單片機最小系統(tǒng);
5、STC12C5A60S2單片機1片
6、外置電源1個(12V的電瓶,有點重,實驗時沒有加裝到車子上,準備車子能站立了再加裝上)
/*------------------------------------------------------------------------------------------------------------------------------------------*/
但剛開頭就遇到了問題,
1、電機驅(qū)動問題;
- 編碼器,因為是紅外線的,開始不知道有一個已經(jīng)壞了,后面拆卸后用手機攝像頭查看才知道有個紅外發(fā)送管被我沒有加裝限流電阻的情況下燒壞了。在網(wǎng)上淘了些紅外發(fā)射二極管回來修復(fù)了。
- 編碼器計數(shù),開始預(yù)計用外部中斷計數(shù)的,確實很快,外部中斷很快,但也是因為太快了,每轉(zhuǎn)動一下就發(fā)出2000~5000的脈沖,用邏輯分析儀抓了下脈沖波形,發(fā)現(xiàn)光電編碼有抖動。能看到的最小時間間距居然只有幾十個納秒,完全不符合我的想法。后面想到用定時器的方式采樣計數(shù)。
- 電機同步的問題,兩個電機時運行時無法做到同步,程序是根據(jù)脈沖個數(shù)進行控制的,同時開始,同時結(jié)束,停止時兩個電機的計數(shù)變量不一樣,估計是電機機械性能的問題。
- 測試了電機往返運動,通過脈沖計數(shù)的方式可以控制往返幾圈后返回起始點(空載,低速),告訴不能保證,會超出預(yù)定位置50~120個脈沖(剎不住車
)
2、MPU6050模塊的數(shù)據(jù)讀取,測試用代碼可以直接用范例的代碼改,但不知道讀取的數(shù)據(jù)是不是要的數(shù)據(jù)(Y軸的旋轉(zhuǎn)角度,Y軸的旋轉(zhuǎn)加速度)測試了這連個值好像是正確的,不過網(wǎng)上資料所MPU6050需要用卡爾曼濾波什么的,但不會,很可惜,希望直接讀出的數(shù)據(jù)能比較穩(wěn)定。
3、電機的加減速控制,雖然通過PWM進行調(diào)速,但啟動和停止時,PWM值太高電機的反作用力太大,PWM值太小又無法啟動電機。我想通過程序調(diào)制PWM值實現(xiàn)啟動時線性加速,要停止時線型減速,以降低電機啟動或停止時的慣性。
電機控制是第一次做,希望有類似經(jīng)驗的朋友給我點撥點撥 。
測試代碼如下:
#include "stc12c5a60s2.h"
#define FOSC 11035000L //晶振頻率
///*聲明與PCA關(guān)聯(lián)的SFR */
//sfr CCON = 0xD8; //PCA控制寄存器
//sbit CCF0 = CCON^0; //PCA模塊-0中斷標志
//sbit CCF1 = CCON^1; //PCA模塊1中斷標志
//sbit CR = CCON^6; //PCA定時器運行控制位,置1啟動PCA定時器
//sbit CF = CCON^7; //PCA計時器溢出標志
//sfr CMOD = 0xD9; //PCA模式寄存器
//sfr CL = 0xE9; //PCA基本計時器低
//sfr CH = 0xF9; //PCA基本計時器高
//sfr CCAPM0 = 0xDA; //PCA模塊-0模式寄存器
//sfr CCAP0L = 0xEA; //PCA模塊-0捕捉寄存器低
//sfr CCAP0H = 0xFA; //PCA模塊-0捕捉寄存器高
//sfr CCAPM1 = 0xDB; //PCA模塊1模式寄存器
//sfr CCAP1L = 0xEB; //PCA模塊1捕獲寄存器低
//sfr CCAP1H = 0xFB; //PCA模塊1捕捉寄存器高
//sfr PCAPWM0 = 0xf2; //PWM0第9位,8位PWM未用到
//sfr PCAPWM1 = 0xf3; //PWM1第9位,8位PWM未用到
sbit k0=P2^0;
sbit k1=P2^1;
sbit mL1=P3^6; //左電機方向控制為1
sbit mL0=P3^7; //左電機方向控制為0
sbit mR1=P3^4; //右電機方向控制為1
sbit mR0=P3^5; //右電機方向控制為0
sbit LT0 =P3^2; //左電機轉(zhuǎn)動脈沖傳感位
sbit LT1 =P3^3; //右電機轉(zhuǎn)動脈沖傳感位
bit LTT0=0,LTT1=0;//轉(zhuǎn)動脈沖備份
unsigned char quan= 0;//轉(zhuǎn)動圈數(shù)
unsigned int ji=0,sd=0,jt=0,st=0;
unsigned char ptxd[8];
unsigned int sdd,stt;
bit flagt0=0;
#define MD 1000
void initPWM()
{
CCON=0;
CL=0;
CH=0;
CMOD=0X08;
CCAP0H = 0X80;
CCAP0L = 255 - CCAP0H;
CCAPM0 = 0x42;
CCAP1H = 0X80;
CCAP1L = 255 - CCAP1H;
CCAPM1 = 0x42;
CR = 1;
}
unsigned char T0RH=0;T0RL=0;//全局變量,定時器0重載值
void ConfigTimer0(unsigned int x100us) //配置T0模式1定時器 ,需要預(yù)先設(shè)置FOSC晶振頻率
{
unsigned long tmp;
AUXR |= 0x80; //定時器時鐘1T模式
tmp=FOSC; //FOSC為晶振頻率
tmp=(tmp*x100us)/10000; //計算所需計數(shù)值
tmp=65536-tmp; //計算定時器重載值
tmp=tmp+31; //修正中斷響應(yīng)延時找出的誤差
T0RH=(unsigned char)(tmp>>8); //定時器重載值拆分高低字節(jié)
T0RL=(unsigned char)tmp; //
TMOD&=0XF0; //清除T0控制位
TMOD|=0X01; //配置T0為模式1(16位定時器)
TH0=T0RH; //加載TH0初值
TL0=T0RL; //加載TL0初值
ET0=1; //使能T0中斷
TR0=1; //啟動T0
EA=1;
}
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位數(shù)據(jù),可變波特率
AUXR |= 0x04; //獨立波特率發(fā)生器時鐘為Fosc,即1T
BRT = 0xDC; //設(shè)定獨立波特率發(fā)生器重裝值
AUXR |= 0x01; //串口1選擇獨立波特率發(fā)生器為波特率發(fā)生器
AUXR |= 0x10; //啟動獨立波特率發(fā)生器
TI=1;
}
/*----------------------------
發(fā)送串口數(shù)據(jù)
----------------------------*/
void SendData(unsigned char dat)
{
while (!TI); //等待前面的數(shù)據(jù)發(fā)送完成
TI=0;
ACC = dat; //獲取校驗位P (PSW.0)
SBUF = ACC; //寫數(shù)據(jù)到UART數(shù)據(jù)寄存器
k0=0;
}
/*----------------------------
發(fā)送字符串
----------------------------*/
void SendString(unsigned char *s)
{
while (*s) //檢測字符串結(jié)束標志
{
SendData(*s++); //發(fā)送當前字符
}
}
void mada(bit ma)
{
if(ji>jt)
{
mL1=1;mL0=1;//停止
if((ji-jt)<30)
{
mL1=1;mL0=0;
}
}
if(ji<jt)
{
mR1=1;mR0=1;//停止;
if((jt-ji)<30)
{
mR1=1;mR0=0;
}
}
// if(!ma)
// {
// if(ji>=MD)
// {
// ji=0;
// mL1=!mL1;mL0=!mL0;//換向
// }
// if(((MD-ji)<300) && (CCAP0H<230))
// {
// ++CCAP0H;
// }
// if((ji<300) && (ji<MD) && (CCAP0H>1))
// {
// --CCAP0H;
// }
// }
// else
// {
// if(jt>=MD)
// {
// jt=0;
// mR1=!mR1;mR0=!mR0;//換向
// }
// if(((MD-jt)<300) && (CCAP1H<230))
// {
// ++CCAP1H;
// }
// if((jt<300) && (jt<MD) && (CCAP1H>1))
// {
// --CCAP1H;
// }
// }
//
}
void main()
{
unsigned char txt[20]="00000,00000,00000\r\n";
unsigned int tmp=0;
ConfigTimer0(1);
UartInit();
initPWM();
PT0=1;
mL1=1;mL0=0;
CCAP0H=0;
mR1=1;mR0=0;
CCAP1H=0;
// EX0=1;
// IT0=1;
while(1)
{
mada(0);
mada(1);
}
}
/*外部中斷0*/
//void init0() interrupt 0
//{
// EX0=0;
// flagt0=1;
//}
/*定時器中斷0*/
void int0() interrupt 1
{
static unsigned int t=0;
TH0=T0RH; //加載TH0初值
TL0=T0RL; //加載TL0初值
t++;
/*檢測馬達L計數(shù)器*/
if(LT0 !=LTT0)
{
ji++;
k0=~k0;
LTT0=LT0;
}
/*檢測馬達R計數(shù)器*/
if(LT1 !=LTT1)
{
jt++;
k1=~k1;
LTT1=LT1;
}
}
測試代碼鏈接:https://pan.baidu.com/s/1EzX07Ay1S2nU1XOXJnWu4g
提取碼:999o
全部資料51hei下載地址:
20-PWMmada-1.rar
(44.77 KB, 下載次數(shù): 28)
2020-2-28 01:04 上傳
點擊文件名下載附件
|