線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:4647
推到 Plurk!
推到 Facebook!

89S52控制RC Servo

答題得分者是:
david_ls
一般會員


發表:5
回覆:13
積分:3
註冊:2005-01-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-06-25 13:49:41 IP:123.110.xxx.xxx 訂閱
請教前輩有關控制 遙控模型 伺服器的問題

我查了一些資料 RC Servo 使用的是PWM Duty Cycle介於 1ms ~ 2ms, 週期50~60Hz
http://chipware.myvnc.com/phpbb/viewforum.php?f=20


我使用的是Keil C, 單晶片AT89S52
程式Download到單晶片上執行, 結果伺服器完全不動作!
想請板上大大幫我看看哪裡有問題了!

Ps. 8051直接輸出接Servo的Signal端, 不知道是否會有問題?

感激不盡

Source code:

//--- 2009.06.25 Writed by Te-Jung Lo
#include
#define PWMDUTY 1000 // 2us * 500 = 1ms, 2us * 750 = 1.5ms, 2us * 1000 = 2ms
#define PWMWIDTH 11250 //[24T => 12MHz/24 = 0.5MHz] 2us x 11250 = 22.5ms
sbit LED = P0^0;
sbit PWM = P0^1;
void timer0 () interrupt 1 // interrupt 1 for Timer_0, interrupt 3 for Timer_1
{
TL0 = (65536 - PWMDUTY) & 0x00FF; // if Timer count to 0x1111_1111, there will held a interrupt
TH0 = ((65536 - PWMDUTY) & 0xFF00) >> 8; // Timer count from (65536 - PWMDUTY) to 65536, total times: PWMDUTY
TL1 = (65536 - (PWMWIDTH)) & 0x00FF; // if Timer count to 0x1111_1111, there will held a interrupt
TH1 = ((65536 - (PWMWIDTH)) & 0xFF00) >> 8; // Timer count from (65536 - PWMWIDTH) to 65536, total times: PWMWIDTH

LED = 1;
PWM = 1;
TR1 = 1; // Timer_1 start to count
}
void timer1 () interrupt 3 // interrupt 1 for Timer_0, interrupt 3 for Timer_1
{
LED = 0;
PWM = 0;
TR0 = 1; // Timer_0 start to count
}
void main()
{
IE = 0x8A; // Timer_0 enable
TMOD= 0x11; // Timer_0 interrupt enable
// initialize timer
TL0 = (65536 - PWMDUTY) & 0x00FF; // & 0x00FF: mask Lower bit
TH0 = ((65536 - PWMDUTY) & 0xFF00) >> 8; // & 0xFF00) >> 8: mask Higher bit and then shift 8 bits for reserving High bits
PWM = 0; // initial PWM = 0
TR0 = 1; // Timer_0 start to count
while(1);
}
編輯記錄
david_ls 重新編輯於 2009-06-25 13:51:12, 註解 無‧
david_ls
一般會員


發表:5
回覆:13
積分:3
註冊:2005-01-31

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-06-25 20:41:31 IP:123.110.xxx.xxx 訂閱
感謝老天, 因為在寫電子鐘程式時發現我的時脈計算是錯誤的@@, 修改後 已經可以work了^_^
Timer的正確T數是 12T
輸入脈波是12MHz, 所以 12MHz/12 = 1MHz(Timer累加一次所耗時間是1us)

另外PWM pulse的部份也寫反了, 波形變成標準波形的反相, 自己把 Timer_0與Timer_1的暫存器互相對調,

還有, 我在8051 PWM的輸出P2.0外加一顆pnp電晶體來推動Servo的訊號線, 不過後來發現是多餘的, 但最後有找到問題自己已經很滿足了^^


紅色註記部份是錯誤的地方

Source code:

//--- 2009.06.25 Writed by Te-Jung Lo
#include
#define PWMDUTY 1000 // 2us * 500 = 1ms, 2us * 750 = 1.5ms, 2us * 1000 = 2ms
#define PWMWIDTH 11250 //[24T => 12MHz/24 = 0.5MHz] 2us x 11250 = 22.5ms
sbit LED = P0^0;
sbit PWM = P0^1;
void timer0 () interrupt 1 // interrupt 1 for Timer_0, interrupt 3 for Timer_1
{
TL0 = (65536 - PWMDUTY) & 0x00FF; // if Timer count to 0x1111_1111, there will held a interrupt
TH0 = ((65536 - PWMDUTY) & 0xFF00) >> 8; // Timer count from (65536 - PWMDUTY) to 65536, total times: PWMDUTY
TL1 = (65536 - (PWMWIDTH)) & 0x00FF; // if Timer count to 0x1111_1111, there will held a interrupt
TH1 = ((65536 - (PWMWIDTH)) & 0xFF00) >> 8; // Timer count from (65536 - PWMWIDTH) to 65536, total times: PWMWIDTH

LED = 1;
PWM = 1;
TR1 = 1; // Timer_1 start to count
}
void timer1 () interrupt 3 // interrupt 1 for Timer_0, interrupt 3 for Timer_1
{
LED = 0;
PWM = 0;
TR0 = 1; // Timer_0 start to count
}
void main()
{
IE = 0x8A; // Timer_0 enable
TMOD= 0x11; // Timer_0 interrupt enable
// initialize timer
TL0 = (65536 - PWMDUTY) & 0x00FF; // & 0x00FF: mask Lower bit
TH0 = ((65536 - PWMDUTY) & 0xFF00) >> 8; // & 0xFF00) >> 8: mask Higher bit and then shift 8 bits for reserving High bits
PWM = 0; // initial PWM = 0
TR0 = 1; // Timer_0 start to count
while(1);
}


------------------------------------------------------------------------------------------------------------------------

修改後的完整Keil C程式

//--- 2009.06.25 Writed by Te-Jung Lo
#include
#define PWMWIDTH 22500 // [12T => 12MHz/12 = 1MHz] 1us x 22500 = 22.5ms
int PWMDUTY; // 1us * 1000 = 1ms, 1us * 1500 = 1.5ms, 1us * 2000 = 2ms
sbit SW = P0^0;
sbit PWM = P2^0;
void timer0 () interrupt 1 // interrupt 1 for Timer_0, interrupt 3 for Timer_1
{
TL1 = (65536 - PWMDUTY) & 0x00FF; // if Timer count to 0x1111_1111, there will held a interrupt
TH1 = ((65536 - PWMDUTY) & 0xFF00) >> 8; // Timer count from (65536 - PWMDUTY) to 65536, total times: PWMDUTY
TL0 = (65536 - (PWMWIDTH)) & 0x00FF; // if Timer count to 0x1111_1111, there will held a interrupt
TH0 = ((65536 - (PWMWIDTH)) & 0xFF00) >> 8; // Timer count from (65536 - PWMWIDTH) to 65536, total times: PWMWIDTH

PWM = 1;
TR1 = 1; // Timer_1 start to count
}
void timer1 () interrupt 3 // interrupt 1 for Timer_0, interrupt 3 for Timer_1
{
PWM = 0;
TR0 = 1; // Timer_0 start to count
}
void main()
{
IE = 0x8A; // Timer_0 enable
TMOD= 0x11; // Timer_0 interrupt enable
// initialize timer
TL0 = (65536 - PWMDUTY) & 0x00FF; // & 0x00FF: mask Lower bit
TH0 = ((65536 - PWMDUTY) & 0xFF00) >> 8; // & 0xFF00) >> 8: mask Higher bit and then shift 8 bits for reserving High bits
PWM = 0; // initial PWM = 0
TR0 = 1; // Timer_0 start to count
while(1){
if(SW == 1)
PWMDUTY = 1000; // PWM_Duty = 1us * 1000 = 1ms
else
PWMDUTY = 2000; // PWM_Duty = 1us * 2000 = 2ms
}
}
編輯記錄
david_ls 重新編輯於 2009-06-25 20:43:13, 註解 無‧

版主


發表:261
回覆:2302
積分:1667
註冊:2005-01-04

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-06-26 10:40:43 IP:60.249.xxx.xxx 未訂閱
很高興你自己找到了問題. 並把你的問題與答案與大家分享!

謝謝你!
------
-------------------------------------------------------------------------
走是為了到另一境界,停是為了欣賞人生;未走過千山萬水,怎知生命的虛實與輕重!?
hch5327
一般會員


發表:0
回覆:4
積分:0
註冊:2009-08-20

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-08-21 11:41:36 IP:210.69.xxx.xxx 訂閱
請問有電路圖? 我只能一開始時轉動一次而已,謝謝!
david_ls
一般會員


發表:5
回覆:13
積分:3
註冊:2005-01-31

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-08-22 11:09:27 IP:219.84.xxx.xxx 訂閱
您可以先檢查看看Code的PWM輸出是否為固定的Duty Cycle, 也就是說只輸出一種角度的PWM訊號(Code不妨可以PO出來讓大家參考, 以利檢查是否Code有誤)


針對一樓的8051 C Code:
電路部份我先用文字描述給你, 若還是無法成功我再畫給你看(我是懶惰蟲^^), 8051我是採用 12MHz 的震盪頻率, PWM輸出腳位為P0.1, 和Servo的Signal線相接, Servo的電源當然也要一起接上, 然而我的Code中有將P0.0拉出, 連接一顆LED燈, 這是我自己測試訊PWM號有無輸出觀測用的(個人覺得加上LED成功率會比較高@@)

針對二樓修改後的8051 C Code:
硬體如同宣告部份
sbit SW = P0^0;
sbit PWM = P2^0;
P0.0拉出一條導線, P2^0為PWM訊號輸出, 當P0.0 接觸 5V時, PWM輸出的派波寬度為1ms, 反之若接地, 則輸出2ms

大致上是如此!
若還有問題, 很歡迎您跟我共同討論研究!

Rgds,
David
編輯記錄
david_ls 重新編輯於 2009-08-22 11:20:13, 註解 無‧
hch5327
一般會員


發表:0
回覆:4
積分:0
註冊:2009-08-20

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-08-27 10:37:08 IP:210.69.xxx.xxx 訂閱
謝謝你的回覆,我是用二樓修正後的程式,沒任何修改(也試著去修改),但是經過幾天的測試後,我的結果都是一樣RC Servo 都是一直在逆時鐘方向旋轉。謝謝!
hch5327
一般會員


發表:0
回覆:4
積分:0
註冊:2009-08-20

發送簡訊給我
#7 引用回覆 回覆 發表時間:2009-09-04 10:46:08 IP:210.69.xxx.xxx 訂閱
又試了幾天,不管PWMWIDTH、PWMDUTY給什麼值,都一樣一直轉,我用555來做就可經由可變電阻來控制轉向及角度,但用89S52就是一直轉,不知跟RC SERVO 廠牌有無關係,他好像也還分數位及類比的。
請問你是用哪一種RC SERVO ? 我是用http://goods.ruten.com.tw/item/show?11090710848460 這個的。謝謝!
hch5327
一般會員


發表:0
回覆:4
積分:0
註冊:2009-08-20

發送簡訊給我
#8 引用回覆 回覆 發表時間:2009-09-04 14:36:54 IP:210.69.xxx.xxx 訂閱
我把PWMWIDTH 及 PWMDUTY 顛倒,竟然可運作,跟你1樓的一樣,現在剩下精確度的問題了,不過這樣跟你2樓的更正又互相牴觸,實在搞不懂,然道真的跟廠牌型號有關? 謝謝!
david_ls
一般會員


發表:5
回覆:13
積分:3
註冊:2005-01-31

發送簡訊給我
#9 引用回覆 回覆 發表時間:2009-09-05 09:53:10 IP:219.85.xxx.xxx 訂閱
===================引 用 hch5327 文 章===================
我把PWMWIDTH 及 PWMDUTY 顛倒,竟然可運作,跟你1樓的一樣,現在剩下精確度的問題了,不過這樣跟你2樓的更正又互相牴觸,實在搞不懂,然道真的跟廠牌型號有關? 謝謝!


您好! 我用的Servo跟你買的很可能是同一顆(外型顏色包裝價格跟規格), 對於提到 "顛倒" 就可以正常的情形, 我的看法是程式部份可能有地方沒改到, 導致會有反過來的情形, 我印象中在寫Servo PWM的Timer部分也遇到類似的問題!! 提供您參考!

Rgds,
David
ererer40
初階會員


發表:37
回覆:91
積分:45
註冊:2008-05-02

發送簡訊給我
#10 引用回覆 回覆 發表時間:2009-09-07 07:13:15 IP:60.248.xxx.xxx 訂閱
建議程式中TL0與TH0直接給數值,不要帶有計算式或是先算好放在一個變數裡再給TL0與TH0
系統時間:2024-05-07 11:01:44
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!