gpio模拟pwm_模拟智能台灯
模擬智能臺燈設計
摘? 要:本文以STM8單片機為核心設計一款模擬智能臺燈設計作品,用LED來模擬臺燈,用光敏電阻來檢測環境的光照強度,STM8單片機則根據光照的強度來控制LED燈的亮度,光強燈弱,光弱燈強,超聲測距儀測試是否有人在前面,還要用它來判斷是否是人還是物品擋在了前面,如果是人在前面LED才亮,如果是物品LED燈就不會亮。
關鍵詞:光敏電阻;PWM波;模擬智能臺燈;應用;超聲測距;
?1? 設計要求
熟悉應用電子系統的設計流程;熟悉Altium Designer等EDA工具軟件的使用;培養在實踐中綜合運用專業基礎知識的能力;熟悉PCB的制作流程與工藝;熟悉元器件的特性;訓練焊接技術;以STM8單片機為核心設計一款模擬智能臺燈作品,用LED模擬臺燈,用光敏電阻檢測光照強度,單片機根據光照強度控制LED燈的亮度;利用光照的強度作為臺燈的起控點,實現外界的光線較亮時,模擬智能臺燈自動關閉,晚上光線較暗時,并且前面有人事,將自動開啟智能臺燈,臺燈的亮度則根據實際外界的光線的強弱度來自動調節。
2 設計方案
根據設計需求,本設計主要包含四個完成步驟:
一是原理與PCB設計:電路應包含超聲檢測、光強檢測、串口通信和LED亮度控制等部分,光強檢測的實現參照熱敏電阻測溫進行,直接用杜邦線連接到最小系統板,超聲檢測和串口通信也是用杜邦線連接相應模塊和單片機最小系統板實現,無需制作PCB;而LED亮度控制盡管可以用一個GPIO輸出PWM波直接驅動LED來實現,但本著學習訓練的目的,在此給出一個相對復雜一些的電路,包含二階有源低通濾波器和恒流源。
二是PCB制作與元件焊接:LED亮度控制電路的元器件較少,總共約10來個,包括一個運放MCP6002,一個三極管MMBT5551,一個1206封裝貼片LED,幾個0603封裝貼片電阻和電容,以及一個3pin的單排針。
三是軟件設計:作為STM8系列中最低端的一款單片機,STM8S003F3的定時器不多,如果不算看門狗定時器的話只有三個:高級控制定時器TIM1,通用定時器TIM2以及基本定時器TIM4,其中前二者為16bit,后者為8bit且沒有輸出引腳。高級控制定時器功能比較豐富,通用定時器簡化了某些高級特性。TIM1和TIM2都能輸出PWM波,本次實驗可選用TIM2,用其通道1來輸出PWM波。TIM2的通道1對應的引腳為pin1,主功能為PD4。
四是調試與測試:單片機運行PWM波產生模塊,在pin1生成占空比為50%的方波,作為激勵信號加到LED亮度控制電路的輸入端,先用示波器觀察低通濾波器輸出的波形(運放U1A的輸出,pin1),留意此波形的特性,是否有明顯波動,電壓值為多少等,由此判斷低通濾波器工作是否正常。如果沒有示波器,用萬用表測量濾波器輸出電壓也能粗略判斷濾波器工作是否正常。
3 設計說明(硬件系統)
3.1? 原理圖設計
在本次實驗中我們設計電路圖用的是立創里面的軟件設計的的電路圖,本次的電路我們設計只需要設計一個用PWM(脈沖寬度調制),也就是用脈沖波驅動LED,脈沖的占空比與LED的發光強度緊密關聯。而其他的電路連接只需要在外面用杜邦線連接即可。在電路圖中恒流源通常用一個電壓控制輸出電流,稱為電壓控制電流源(VCCS),其實現方式有多種,針對電流較大的LED驅動,可采用“運放+三極管”的電路形式。恒流源驅動的對象為貼片LED,封裝為1206,最大正向電流為25mA。恒流源輸入的控制信號為直流電壓,為調節輸出電流,此電壓應能根據需要而變化。為得到一個可控的直流電壓,最容易想到的是用數模轉換器(DAC)實現。但STM8單片機并未配置DAC模塊,而外加一片DAC芯片代價較高,且控制比較復雜。好在單片機內置的定時器可以輸出PWM波,經低通濾波后得到其平均值為一直流電壓,此直流電壓與PWM波的占空比成正比,故控制PWM波的占空比就能調節濾波后直流電壓的大小,由此用定時器的PWM輸出就能變通實現DAC的功能。低通濾波通常用有源濾波器,如果PWM波的頻率與低通濾波的截止頻率差距較大(比如100倍左右),用二階低通濾波器就能達到良好的效果。輸入PWM波的頻率大約為1kHz,從FilterLab中可以看出,經過此低通濾波器之后,1kHz的衰減約為68dB,交流分量能濾除得比較干凈。濾波之后的直流電壓幅度最大為3V左右,根據后面的恒流源工作原理,不能用這么大的電壓直接去控制恒流源(請思考為什么),所以用電阻R3、R4對其分壓后再去控制恒流源。之后的恒流源包括運放U1B,電阻R5、R6,三極管Q1,發光二極管LD1即為最終受控的對象。恒流源為典型的VCCS電路結構,抓住運放的虛短和虛斷特性不難分析其原理。如下圖3-1所示的電路就是我們自己設計繪制的一個電路原理圖:
圖3-1
3.2? PCB板設計
在PCB設計中我們也遇到過很多的問題,比如在找封裝的時候有些封裝里面沒有,所以沒有辦法我們只有找了一些差不多的,記得里面還有一個連一個差不多的都沒,然后我們就自己做了一個。還有我們遇到一個問題就是因為學校的資源有限電路板只能用一層不能用多層,所以電路的原件擺放是一個很大的問題,我們試了很久才擺放成功(下面也有我們電路做出來的圖片)(PCB版圖如圖2所示)不過這次的PCB板還是成功的設計出來了。
圖3-2
3.3PCB板的制作及元件焊接
在PCB板的制作及原件的焊接中我們使用的個人電腦、打印機、熱轉印機、熱轉印打印機、熱轉印機、鉆臺、腐蝕槽、電烙鐵和焊錫絲。我們開始通過個人電腦和打印機打印出熱轉印圖,然后哈銅板用砂紙打磨干凈,然后再把我們打印出來的熱轉印圖用波紋膠布粘貼到銅板上,粘貼好會就可以用熱轉印機來加熱銅板,把熱轉印機開到175度左右,然后開始加熱,一般要加熱3次左右。加熱完后我們就等它冷下來,然后把上面的膠布撕了,看看電路是否完整,如果不完整就可以用馬克筆把沒有完整的地方連接起來,然后我們再把它放入腐蝕槽中進行腐蝕,一般腐蝕3分鐘就可以了,但是有時候腐蝕一次不行,那我們就可以在進行一次腐蝕。當腐蝕好后就拿出來去洗干凈,再一次用砂紙把上面剩到的抹干凈,在倒上一些酒精就可以,最后我們最通過給電路板進行打孔,焊接原件,在焊接原件的時候我們是從小的開始焊接的,因為小的要比打的難焊接一點所以先焊接小點要好一點,還有我們焊接集成塊時溫度調低了一些,因為我們怕溫度高了把集成塊燒壞了。最后通過一步一步的努力我們就把我們的電路做了出來。(如果所示)
圖3-3
4 設計說明(程序設計)
程序測試我們主要分為四個部分1.設計超聲測距的程序;2.設計用ADC檢測光照強度的程序;3.設計用定時器實現PWM波輸出的程序;4.設計用檢測到的光照強度、障礙物距離去控制LED等的亮滅以及亮度的程序;下面我們來一一介紹我們的代碼程序
1、設計超聲測距的程序:可見,MCU需要給出一個10μs的正脈沖作為觸發信號,隨后超聲模塊給出一個回響脈沖,脈沖的寬度跟被測距離成正比。測距周期最小為50ms,也就是說測距結果的更新率最高可達每秒200次。
?? ?? 控制某GPIO產生一個10μs的正脈沖作為超聲模塊的觸發信號;
?? ?? 測量回響脈沖信號的寬度。
?? ?? #define GetPulseNum 20
?? ?? #define ULTRA_IN_PORT?? GPIOC
#define ULTRA_OUT_PORT? GPIOC
#define ULTRA_IN_PIN??? GPIO_PIN_4??? //PC7
#define ULTRA_OUT_PIN?? GPIO_PIN_3??? //PC6
#define TRIG_ON()?? GPIO_WriteHigh(ULTRA_OUT_PORT, ULTRA_OUT_PIN)
#define TRIG_OFF()? GPIO_WriteLow(ULTRA_OUT_PORT, ULTRA_OUT_PIN)
#define GET_ECHO()? GPIO_ReadInputPin(ULTRA_IN_PORT, ULTRA_IN_PIN)
#define??????? uint???????? unsigned??? int
#define??????? uchar??????? unsigned??? char
#define??????? ulong??????? unsigned??? long
void? delay_ms(uchar? ms)
{
??? uchar? i,j;
??? while(ms--)
??? {
??????? for(i=100;i!=0;i--)
????????? for(j=100;j!=0;j--);
??? }
}
void init()
{
GPIO_Init(ULTRA_OUT_PORT, (GPIO_Pin_TypeDef)ULTRA_OUT_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
??? //ECHO?IN 上拉輸入
??? GPIO_Init(ULTRA_IN_PORT,?(GPIO_Pin_TypeDef)ULTRA_IN_PIN, GPIO_MODE_IN_PU_NO_IT);
??? TRIG_OFF();
}
u16 Frequency_Array[GetPulseNum]={0};
u16 AverageFrequency;
void get_dist()
{
??? uint16_t?tmp_dist = 0, tmp_cnt[2];
??? uint8_t?count = 0;
??? uint16_t?tim_count1 = 0;//, tim_count2 = 0;
??? TIM1_Cmd(ENABLE);
??? for?(count = 0; count < 2; count++)
??? {
??????? TRIG_ON();
??????? delay_ms(3);?//delay > 10us
??????? TIM1_SetCounter(0);
??????? TRIG_OFF();
??????? while(RESET?== GET_ECHO());
??????? //tim_count1?= TIM1_GetCounter();
??????? TIM1_SetCounter(0);
??????? while(GET_ECHO());
??????? tim_count1?= TIM1_GetCounter();
??????? tmp_cnt[count]?= tim_count1;//tim_count2 - tim_count1;
??? }
??? TIM1_Cmd(DISABLE);
??? //?us / 58 = cm
??? tmp_dist?= ((tmp_cnt[0] + tmp_cnt[1] ) >> 1) / 58;
??? printf("\r\npresent?Get The Frequency is:%ld Hz\r\n",tmp_dist);
}
2.設計用ADC檢測光照強度的程序;
?? ?? #include
#define??????? uint???????? unsigned??? int
#define??????? uchar??????? unsigned??? char
#define??????? ulong??????? unsigned??? long
void? delay_ms(uchar? ms)
{
??? uchar? i,j;
??? while(ms--)
??? {
??????? for(i=4;i!=0;i--)
????????? for(j=100;j!=0;j--);
??? }
}
void? adc_init(void)
{
??? ADC_CR1_ADON?= 1;????? //打開adc
??? ADC_CSR_CH?= 3;??????? //AIN3腳
??? ADC_CR1_SPSEL?= 2;???? //4分頻時鐘
}
uint? adc_get(void)
{
??? uint? dataH,?dataL;
??? ulong? value?= 0;
??? uint?? voltage?= 0;???????? //電壓單位為(mV)
??? ADC_CR1_ADON?= 1;?????????? //使能adc
??? while(ADC_CSR_EOC==0);
??? dataH?= ADC_DRH;??????????? //左對齊數據
??? dataL?= ADC_DRL;??????????? //讀取寄存器數據
??? ADC_CSR_EOC?= 0;
??? value?= dataH<<2|datal;< span="">
??? voltage?= (value*3300)>>10;???? //計算實際電壓
??? return? voltage;
}
3.設計用定時器實現PWM波輸出的程序;
CLK->CKDIVR= 0x00; //內部16M時鐘不分頻
? TIM2->PSCR = 0x00; //定時器2預分頻系數為1
? TIM2->CR1 = 0x01; //內部計數器使能;
? TIM2->ARRH = 0x00;//0140,320分頻,16M/320=50K,實測49.75K
? TIM2->ARRL = 0x8a;//自動裝載寄存器低位;實測013e正好為50.0K
? /*PWM通道1設置*/
? TIM2->CCER1 |= 0x01; //開啟OC1信號輸出腳
? TIM2->CCMR1 = 0x60; //PWM1模式
? TIM2->CCR1H = 0x00; //占空比高位
? TIM2->CCR1L = 0x37; //占空比低位
? TIM2->CCMR1 |= 0x08; //輸出比較1預裝載使能
? /*PWM通道2設置*/
? TIM2->CCER1 |= 0x10; //開啟OC2信號輸出腳
? TIM2->CCMR2 = 0x60; //PWM1模式
? TIM2->CCR2H = 0x00; //占空比高位
? TIM2->CCR2L = 0x37; //占空比低位
? TIM2->CCMR2 |= 0x08; //輸出比較2預裝載使能
? /*PWM通道3設置*/
? TIM2->CCER2 |= 0x01; //開啟OC3信號輸出腳
? TIM2->CCMR3 = 0x60; //PWM1模式
? TIM2->CCR3H = 0x00; //占空比高位
? TIM2->CCR3L = 0x37; //占空比低位
? TIM2->CCMR3 |= 0x08; //輸出比較3預裝載使能
? TIM2->CR1 |= 0x01;
5 、最后的合成程序
int main(void)
{
? /*?Infinite loop */
? CLOCK_Config();//系統時鐘切換為HSE(8MHz/4=2MHz)
? GPIO_Config();//超生波觸發引腳
? //CLK_init();
? TIM1_Config();
? Init_Tim2();
?? uart_conf();
? /*?ADC模塊初始化 */
? adc_init();
?asm("rim");?????????????? //enable interrupts
?static uint tmp=0;
? char?cnts=0;
? printf("\r\n硬件平臺為:%s\r\n","iCreate?STM8 開發板");
? while(1)
? {
???? setchar(tmp);
???? x=adc_get();
???? PA_ODR_ODR1?=1;//保證最短10us的低電平
??? for(cnts=15;cnts>0;cnts--);
??? PA_ODR_ODR1?=0;
??? for(cnts=2;cnts>0;cnts--)
??? {
????? delay();
??? }
??? if(bFinish_Flag==1)
??? {
????? //1000000us/2000000=0.5us
????? //340(m/s)=34/1000(cm/us)=0.034cm/us
????? tmp=(float)tim2_ccr2*0.1*0.017-6;
???? bFinish_Flag=0;
??? }
??? if(tmp<20&&x>400)
??? {
????? setpwm((int)(((float)x*0.075)-35.0));
??? }
??? else
??? {
????? setpwm(0);
??? }
?//?? asm("wfi");
??? printf("當前距離:");
??? SendChar(arr[0]);
??? Delay_ms(5);
??? SendChar(arr[1]);
??? printf("cm");
??? SendChar('\n');
??? delay();
? }
}
5? 調試及實際驗證結果
5.1 硬件測試結果
5.2 軟件與系統測試結果
6 結論
怎么說呢,這次的實驗對我來說,是一個很大的挑戰。可能部分同學不以為然,認為這個任務就是一個普通的任務,再簡單不過。但是你要考慮我們這些基礎比較差的同學呀,付出了很多可能還是做不出來,但是他們卻能輕松完成,這真是打擊。我相信這世上真有天賦之說,像我這種悟性差的人,為了趕上他們,只有付出更多的努力和汗水,可能還是像這次實驗,還不如人家。我有覺得我已經在兢兢業業,勤勤懇懇學習stm8單片機課程,但是后來的實驗我還是一竅不通,我不知道怎么回事。到網上查閱資料還是一無所獲,線上悻悻而歸,線下我就去問老師同學,這才算是有了一些收獲。大家都在做實驗課程,我也不好多問,大部分問題還是請教的老師。不過,正因為有了他們的幫助,我才能完成這次的實驗內容。前面畫電路圖,做實物都還比較簡單,后面軟件編程真的讓我頭大,真是不會呀,太難了!去找例程的代碼,改來改去還是存在很多問題,當時我真的放棄了。但是看到后來那么多同學都做好了,我簡直不敢相信,我決定再努力一下,一定要做出來!感謝自己的努力,費盡心力我最終還是做出來了!做出來后的那種成就感簡直是不可言喻,我從來沒覺得自己這么高興過。正因為這次的成功,我對st單片機有了一些更想深入學習的欲望,還好當時沒徹底放棄。不過說真的,一個人做的話,真的是艱辛,還好這次分了組,負擔一下就減輕了許多,我們各自分工,他去焊板子的時候我就看代碼,即使看不懂…我們一起上網查資料,卻發現網上關于stm8的資料極少,還好有老師給的例程。網上算是沒什么收獲,問同學的話,有一些收獲,還有老師也給了我很大幫助,加上自己本身的一些理解,看懂一些簡單的代碼還是沒問題的。不管怎么說,我還是做出來了。這次實驗雖然很困難,但是做出來的話真的會有很大成就感,對我來說的話是這樣,不知道他們怎么想。通過這次的實驗,我也明白了團隊分工協作的重要性。以前吧,我總是獨來獨往,做什么事都是自己一個人完成,這次之后,哇,仿佛發現了新大陸一般,協作的感覺真的不錯,負擔也減輕了好多,效率飛一般的提升,今后我也會更多的考慮解決問題來找一個隊友合作。
總結
以上是生活随笔為你收集整理的gpio模拟pwm_模拟智能台灯的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 盘点韩国的传奇IP游戏韩国网游传奇
- 下一篇: 亚洲男篮排名