2008年12月30日 星期二
機械手臂修改篇(1) -- 夾具修正前篇
在夾具的部分比較脆弱
很容易折損
所以利用紙模的概念做了一下修正
第一張提供的是CorelDRAW的圖面
是手掌部分的樣子
由原來的一個SERVO變成兩個
並將標準型的SERVO改成是9G的小SERVO
加工好的樣子大概是這樣
再看看其它角度
加工時有缺角的部分
可以用白膠填補
等白膠乾了以後
再上點色就看不出來了~~~
經過這樣的修正
機構就不容易折損了
其它的關節暫時延用原來的機構
只有SERVO的傳動桿需要重製
等修改好再放上來給大家參考
如此一來
加上原來的四軸
一共就是六軸的機械手臂了!!
2008年12月27日 星期六
機械手臂材料篇(2) -- 光碟機構
機械手臂材料篇(1) -- 紙模機構
有很多的感想跟心得
最近好不容易備妥第二隻手臂的需求
要開始動工了
不過這一次花費的時間會比之前久
因為機構的部分打算用紙來做
這是基座軸動力所使用的SERVO
這是手臂關節與夾具所使用的SERVO
選用的紙有兩種
第一種是西卡紙
用來印製加工圖面與當成機構表面的材料
第二種是厚紙板
厚度約1.7mm
約西卡紙的15~20倍厚
看一下這張圖
體會一下兩種材料的差異吧!!
上面的材料就是厚紙板
粗糙但容易填入並吸收白膠
西卡紙細緻而且光滑
當機構表面可以減少機構接合面的磨擦力
增加機構的壽命~~~
再提供一張基座的機構圖面給大家想像一下!!
圖是用CorelDRAW畫的
一來我對這套軟體比較熟
二來電腦剛好沒裝CAD軟體
不然其實應該是用CAD來畫會比較好
未來建3D圖會比較好建
現在立體圖的部分都是手工草繪
只畫出平面圖供製作機構用
************************************************************************************************************
2009/1/7 補充說明
使用的西卡紙是200P 8K
http://goods.ruten.com.tw/item/show?21207226758462
2008年12月23日 星期二
兩足機器人製作超入門的簡介
這個網址算是這本書的官方網站
是作者淺草的網站
裡面有詳細的簡介和周邊產品
有興趣的朋友可以去參考看看
把目錄稍微翻譯一下
提供給大家過過癮
0. 序章
0-1 前言
0-2 機器人製作的概念
0-3 零件清單 (BOM List)
1. 電路板的製作
1-1 電源板的製作 (電力系統的規劃)
1-2 主控板的製作 (MCU Board)
2. MCU的程式編寫
2-1 MCU的動作原理
2-2 點亮LED燈 (大家概念都一樣, 一定要會點LED燈)
2-3 定時亮滅LED燈, Pulse的產生
2-4 用MCU控制SERVO運作
3. 機構的製作
3-1 材料與工具
3-2 用鋁板來製作機構
4. 試著讓機器人動起來
4-1 組裝的確認
4-2 軸與扭距
4-3 四軸的兩足步行機器人
5. 機器人的追加功能
5-1 觸摸感測器 (IO狀態的判定)
5-2 距離感測器 (AD功能的練習)
5-3 音頻輸出 (用串列通訊與其它設備連線)
5-4 無線控制
6. 開始打造屬於自己的機器人
6-1 自學的心理準備
6-2 自學的參考書籍
附錄
A. 鋁板加工圖面
B. ATmega32的特殊暫存器一覽表, ASCII表, 進位轉換表
C. 電阻值與電容量的表示法
D. MCU
E. 本書機器人的應用實例 (ROBO-ONE參賽機種)
F. 焊接
G. 連接線的製作
H. 英文專有名詞的翻譯
I. 三角函數表
2008年12月20日 星期六
新書到 -- 兩足機器人
終於等到書了
放個封面給大家瞧瞧
接下來就要試作看看囉!!
補上兩本書的網址給大家參考(2008/12/22 更新)
ROBO-ONEのための二足歩行ロボット製作ガイド
二足歩行ロボット製作超入門 バッテリーからRCサーボまで
********************************************************************************
今天其實在忙的是房間佈置
只完成了一半
下了班就一直在收拾還沒收拾乾淨的房間
還要每一塊壁磚地磚通通擦乾淨
收拾好之後像這樣
接著就開始拼地墊
總共四種顏色
用最沒創意的方式拼起來
因為還有其它的東西要擺
時間又很趕(答應老婆這星期要完成)
擺好後大概像這樣
然後稍微休息一下....
再繼續鋪上這塊大墊子!!
然後用抹布把大墊子徹底擦乾淨
(小朋友很可能因為好奇而直接在墊子上舔來舔去?!)
還沒全部完成
剩下牆壁的墊子還沒搞定
門還要加個門欄
明天中午前看看能不能全部完成!!
再來就可以玩機器人了!!
^+++++^
(2008/12/21 更新)
今天是冬至
也是小犬滿八個月
送個遊戲房給他當禮物
老婆看了很滿意唷~~~
門有加上門欄了
就算不關門還是可以避免他爬出來摔下樓梯
看一下側邊的牆
通通都有貼上墊子唷!!
大大的海報牆
可以讓他早一點識字
********************************************************************************
(2008/12/23 更新)
為什麼要把上面星號這一段內容po出來呢?
其實我還想表達另一個層面的概念
好像沒有人發現
只好自己再補充上來......
單就一個房間約4~5坪的空間布置
花費也不過7000大洋上下
跟一隻isobot 的費用相當
而一隻KONDO KHR的費用
可以讓我布置這樣的房間三間 !!
但如果請人來布置
費用大概要四五萬起跳
現在的行情可能會差一點
但兩三萬也跑不掉......
所以說
技術這玩意是很值錢的
不管是 "時間成本" 或是 "實體開發成本"
如果我們總是期待別人把東西做出來
那麼就沒有立場去批評人家的東西很貴
因為別人做得出來
而自己做不出來......
台灣的惡性競爭
就是只看材料成本
不看技術成本
所以把玩技術的人搞得四不像
一大堆人過勞死
身為技術人
千萬不要賤賣技術
寧可分享技術做公益
也不要賤賣技術破壞市場
這一代的台灣已經嘗到惡果
希望下一代不要繼續惡性循環
讓願意DIY的人享有DIY的成就
這樣就會有更多的人願意DIY
進而藏富於民
讓各產業可以做出更好更具國際競爭性的產品
同時也讓不願意DIY的人懂得技術的價值可貴
而不會漫天殺價
現下的環境
就是太容易取得高科技產品
才讓人覺得高科技很廉價
(謎之音: 所以高科技人才=廉價勞工) ~~><~~
2008年12月16日 星期二
MCU -- ATmega64的怪問題
話說最近在用AVR開發系統
遇到了一些很不可思議的問題
到目前還是無解的狀態
提供給大家參考看看~~~
1. Reset 的不穩定
ATmega64大概是我目前用到過reset最不正常的MCU
或許是因為內部架構太複雜的關係
也或許是我還沒把硬體與軟體完全搞懂的關係
總覺得好像哪裡怪怪的
從一開始用M64
就發現它在reset時有時候會成功
有時又reset不起來!!
由reset信號去觀察
發現reset信號很穩定
因為有用reset IC的緣故
所以0電位有確實拉到0
石英晶體也有起振
但系統就是沒有reset起來
用mkII去reset也OK
獨獨Power_ON reset就是很不順
不曉得是哪裡出了問題??!!
(赫然發現, Arduino所有版本都有用reset key, 難不成是因為這個問題??)
2. EEPROM 之"隨它高興"存取
這是最詭異的問題
抓了整整一天還沒抓到問題
WinAVR有內建eeprom的函式
一個是eeprom_read_word();
另一個是eeprom_write_word();
使用write再用Studio把資料read回來
OK~~~
確定資料都有順利填入
可是一用了read功能
災難就來了
read 0~7的值OK (該Byte的儲存值是0x00~0x07)
read 8~F的值系統就當掉!!! (該Byte的儲存值是0x08~0x0F)
而且不管換到哪一個位址都一樣
這是相當詭異的!!
而且匪夷所思!!!
連老闆也愛莫能助
只說可能是編譯器版本的問題
用免費的開發工具就是有這樣的缺點
Orz........
ps.
剛剛找到一個解決方案
還沒試過
明天來試一下看看
http://lysoft.g4soft.net/article.asp?id=46
ps2.
上面的方案確定可行
不過建議在函式的最後要加上sei();
因為系統所有的中斷資源都被關掉了
如果不恢復
很多動作都會不正常唷~~~
比較快的解決方法是
直接呼叫原來eeprom.h的內建函式
只是呼叫前加上cli();
呼叫後加上sei();
這樣就不會出問題了~~~
(2008/12/17 更新)
2008年12月11日 星期四
充電一下 -- 紙橋載重
做完一隻機器手臂之後
就一直在思考這個問題
前陣子UUCWW大大在機器人論壇上貼了一個32in1的紙模製作
我就開始很認真在思考用西卡紙來完成機構的可能性
而思考的方向
是學生時代所接觸過的紙橋載重
什麼是紙橋載重?
顧名思義就是用紙做成橋
然後去承載一定的重量
它是一個結構製作的比賽
比的是載重與紙橋重的比例
比例越大就得勝
印象中
有人以4000多克的紙橋
成功載重近一百公斤的重物
比例高達20多倍
紙橋的技巧
在於黏合的均勻度
及紙張上應力分佈的強化
這兩天工作較忙
所以沒太多時間找資料
未來實作的時候再跟大家分享一些細節
有興趣瞭解紙橋的人
可以用"紙橋載重"的關鍵字上網查看看唷~~~
應該會有一些收穫的!!
ps.
剛剛發現一篇報導
現在的記錄是1673倍
以159G承載266KG
http://news.epochtimes.com/b5/8/6/17/n2157274.htm
http://blog.youthwant.com.tw/ywcampus/newscenter/1369/
2008年12月9日 星期二
充電一下 -- MODBUS 通訊技巧
至於接收的部分
我想跳過編碼的介紹
直接介紹通訊間的一些問題
編碼的部分
上一篇文章中所提供的PDF文件
有很完整的描述
只是內容是英文的
如果有人看了不太能理解的
再告訴我一聲吧~~~
我們都曉得
根據MODBUS所制定的格式來看
裝置端(slave)在接收指令的負擔是很輕的
以RTU模式來看
只要8Bytes就完成一組指令了
ASCII的話也只要17Bytes就搞定 (1+8x2)
但是回應的時候
RTU長一點就可能要30~40個Bytes
(假設一次要拿16組資料, 每組都2 Bytes)
同樣的ASCII就要近80Bytes 的資料在傳~~~
對於暫存區空間較少的MCU來說
這是一個夢魘!!!
因為通訊時別台裝置的回應碼
不單單只是回應給主控端
還同時會傳給其它的裝置端
如果串列中斷裡沒有規劃好因應的對策
災難很快就會發生
要不是系統的堆疊會爆掉
就是串列資料不小心改掉堆疊的內容
讓程式進入亂七八糟的鬼上身狀態
規劃的方向有幾個重點
提一下概念給大家思考看看
1. Timeout 機制 (逾時中止)
Timeout是MODBUS通訊中一定會用到的第一個概念
特別是在RTU傳送模式下
因為通訊碼裡面並沒有結束碼的設計
所以只能透過"經過多久時間沒有在送資料"來判斷它已經結束了
這個等待時間一般來說是5~10 個Bytes的時間間隔
拿9600bps的鮑率來看
1個Byte約需1mS
那麼適當的Timout時間就是5mS~10mS
為什麼要這樣設定?
因為資料在傳送的過程
主控端有可能受到其它多工運作的影響
導致指令並不是連續送出來的
把Timeout設得太低
有可能當指令傳到一半時
裝置就開始分析指令了
這樣一來
指令分析一定會錯誤
裝置也就不會正確動作及回應了!!
2. 循環指標歸零時機
一般在設計通訊碼的暫存空間
會使用循環旗標
意思就是讓暫存器透過串列中斷一直存放資料
不要去管內容是什麼
每存一個Byte指標就+1
當發生Timeout
或是旗標已經加到陣列的邊界
才把旗標歸零
分析指令時
如果是第一種歸零時機
通常是正確的通訊碼
第二種則是部分資料被覆蓋的不完整碼
透過歸零時機的判斷
可以拿到正確的通訊資料
3. 善用ASCII的啟始碼與結束碼
在ASCII的模式下
:是啟始碼
CRLF是結束碼
只要遇到啟始碼
就自動擺到暫存空間的最前面
遇到結束碼就立刻分析資料
這樣就能保證資料一定是從頭開始而且是完整的
以上
就是MODBUS的必勝秘訣
如果能依照這樣的原則來寫程式
一定可以避開很多莫須有的怪問題
不過
很多實際的應用還是會有出乎意料的狀況
此時就要善用示波器來觀察通訊的波形是否正確了~~~
2008年12月8日 星期一
充電一下 -- MODBUS 通訊格式
剛剛完成機械手臂的基本雛形
要銜接下一個進度的空檔
來談談通訊中最常被使用的格式 -- MODBUS
MODBUS是一種通訊碼的標準
有別於硬體的RS232, RS485, USB...等規範
它純粹是定義軟體的碼
如果你告訴別人MODBUS就是9600,n,8,1
那觀念上就差了十萬八千里囉!!
到底什麼是MODBUS??
簡單說
就是兩台機器彼此用來溝通的語言
標準格式如下
1. 站號 -- 2. 指令 -- 3. 資料位址 -- 4. 資料長度 -- 5. 檢查碼
底下分別說明各個部分
1. 站號 (0~255)
其實就是我們常說的ID(身份證號碼)
用來表示您所正在溝通的對象硬體
因為絕大多數的通訊
都是並接很多台設備同時進行連線的
如果不能明確告知要跟哪一台溝通
很可能機器跟機器之間會溝通不良而罷工或暴動
2. 指令
這就是您對硬體所要求執行的動作
常見的指令如下
0x01 : Read digital (ON/OFF) parameter (讀取一個數位參數)
0x03 : Read analog parameter (讀取一組類比參數)
0x05 : Write digital parameter (寫入一個數位參數)
0x06 : Write analog parameter(寫入一組類比參數)
標示藍色的指令(digital)
就是一次只能存取一個 bit 的資料
標示紅色的指令(analog)
就是一次能存取一組 16 bits 的資料
3. 資料位址
固定格式為2 Bytes
如果是數位的位址
代表的意思就是第幾個bit的位置
假設我寫位址是0000
那麼就代表第一個bit
位址是0013
就代表第20個bit (0x0013=19)
同樣的
類比所代表的位址
就是代表第幾組資料的位址(一組是16bits)
4. 資料長度 (或寫入資料)
當指令為讀取時
這兩個Bytes的功能就是告訴對方我要讀取幾個Bytes
當指令為寫入時
就是把前一組位址寫入現在這裡所填的資料
5. 檢查碼
MODBUS的檢查碼分兩種
第一種是給ASCII(文字形)通訊用的
叫做LRC
它簡單來說就是checksum的功能
把前面所有的通訊碼的值累加起來
再用0去減掉這個總合
得到一個8 bits的運算值之後
再把這個值拆成兩個 ASCII文字
最後補上結束碼(CRLF)
第二種是給RTU(二進位形)通訊用的
叫做CRC16(簡稱CRC)
它比較複雜
是透過一連串的互斥運算所得到的值
不過現下絕大多數的CRC
是用查表比對出來的
在這種檢查碼的格式下
有一個很重要的參數
我把它稱做"啟始種子"
一般來說
這個種子應該是0xffff開始的
也就是互斥運算的一開始
必須是0xffff
然而隨著通訊碼的諜對諜
這個種子可能會變成是0x0000或是0x8000
小弟在實際的應用場合
就看到這兩個異類種子出現過
然而這是否算是違反MODBUS格式呢?
那就見人見智囉!!
在什麼地方看得到MODBUS呢?
大多數的PLC通訊
應該是用MODBUS平台來架構的
某一些大型的加工機台
或是機械手臂
也會用MODBUS來進行通訊
大致來說
MODBUS就像機器界的中英文一樣
是最多人使用的語言
所以想要玩通訊的人
要稍微熟悉一下這個格式唷~~~
以上是一點小分享
詳細的資料可以參考一下這篇文章
http://www.eecs.umich.edu/~modbus/documents/PI_MBUS_300.pdf
2008年12月6日 星期六
MCU -- AVR DATABOOK 1997
放一些相片給大家瞧瞧
這是書本的正面
簡潔有力
反正就是讓大家知道是AVR就好了
Atmel的招牌
標明了1997年出的
都過了十幾年了!!!
翻開書的最前面
一樣是廠牌宣告
索引的地方
標示了四顆早期在推的MCU型號
最棒的部分
就是把整個指令集都寫在書裡了!!
另外還有開發工具的介紹
這就是開發工具的樣子
跟現在小小一台的mkII比起來
真的是壯觀多了!!!
公司裡的第一顆AVR
就是書中所提到的第一個型號AT90S1200
跟AT89C2051一樣
是20pins的DIP包裝
連腳位都幾乎是pin to pin!!
功能也很相近
所以當我剛要學MCU時
我也在猶豫要先投靠哪一邊
後來會投靠51
最重要的因素就是參考資源豐富
不過AVR也一直放在心上
畢竟在硬體架構上
就像前一篇文章提到的
AVR真的比8051好很多
其次就是燒錄工具
在我要切入MCU的當時
已經有比較便宜的燒錄器可以用了
只是沒有USB界面的燒錄器而已
一般都還是LPT埠的燒錄器
而碰巧公司又正開發推出了USB燒錄器(for 8051)
就在我剛進公司的時候
所以順理成章就從8051開始學起~~~
Edison大大問過我很多次
為啥我們對AT89C2051這麼情有獨鍾?
對我來說
它是我的第一個MCU
這樣的說法
或許可以透露出個中的端倪
您對AVR很有興趣嗎?
千萬不要只是有興趣唷~~~
現下很多高精度的儀器
其內部所使用的MCU正是AVR
快點找個有興趣的型號上手吧!!
個人挺推薦Arduino的(雖然還沒入手....^+++++^)
可以試試看唷!!!
2008年12月5日 星期五
MCU -- AVR ATmega64
這次來談談我最近在忙的板子吧!!
ayu大大問我說
我是不是打算用AVR做機器人呀?!
或許會吧!
不過這一片的功能並不是機器人用途的唷~~
是公司裡目前要完成系統的一小部分
名稱是八通道溫度量測器
板子偏右側所卯上的最多腳位的IC
就是ATmega64的MCU
腳位數量剛好就是64隻~~~
由於目前還在測試階段中
所以先賣個關子
但大概可以提一下的是
上面有一個20bits的AD
量電壓目前可以準確到的100uV
換算成溫度
如果選用的感測電阻夠準
溫度是可以準確到0.1C以內的
未來上市還請大家多多捧場~~
這個就是傳說中的mkII
早期想學就是沒有這玩意
所以一直都只是看看
現在有工具了
總算可以好好玩一下~~~
話說AVR已經在MCU的世界中行之有年了!!
很多對51失望的人
轉用的MCU中以AVR最為普遍
因為不論在硬體空間
或是IO與中斷的規劃
都超越51太多太多了!!!
可惜的是
在台灣一直沒有正式支援
賣MCU的經銷商很多
卻沒有專屬的FAE或是原廠的工程師在推
會使用AVR的人
多半是已經有MCU底子之後
再自己摸索跳過去的!!!
而AVR之所以會在台灣流行
原因跟Linux一樣
因為它的程式編輯工具光是free的就超好用
(AVR studio + WINAVR)
只要有C概念的人就可以輕鬆上手
如果能熟悉組語
看到精簡的程式碼與強大的硬體支援
沒有不心動的啦!!!
而且連USB的韌體程式
都有高手free丟在網路上供人下載
不需要特地選用搭配USB功能的MCU
只要程式碼一掛就能擁有USB
這就是AVR最讓人驚豔的地方~~~
底下是參考連結
http://www.obdev.at/products/avrusb/index.html
價格上
AVR也是很有競爭性的
只是定位上比較模糊
因為效能上跟DSP還有一段差距
可是拿來當MCU又覺得有點大材小用
或許是我所應用的場合沒有很迫切需要AVR的地方吧
真正用過之後
就是讚不絕口
好用!!!
不過AVR還是有些缺點的
因為系統比51複雜得多
很多設定對剛要使用的人來說
是一個不小的門檻
光是程式編輯界面
就一大堆設定搞不清楚
更別提AVR的硬體設定
整個就是亂成一團
好在有一套軟體叫ICCV7
它可以快速幫你產生硬體設定檔
只要開啟Application Builder(暫時翻譯做硬體設定精靈)
然後從晶振一路勾選到Timer, Uart
再按OK
所有的暫存器你通通不用去查datasheet
它就全部幫你設定好產生對應的程式碼
當然
如果你要讓設定變得有彈性
還是得自己K一下datasheet比較好
但對一個剛要上手的使用者來說
這樣的功能就太好用啦~~~
若您用過其它的MCU
改用AVR只需不到三天的時間
就可以開始開發您的產品了!!!
(我大概花了一天半....)
當然您還是要有一些程式範例可以參考
瞎子摸象一定是會浪費不少時間的!!!
2008年12月3日 星期三
機械手臂控制篇(10) -- 操作界面篇
完成了!!
VB6的界面
原始程式下載
操作的方法很簡單
就是用[+]跟[-]調整SERVO的位置
用test motion看一下是不是自己要的
再按一下save motion
這樣就可以了
要執行的話
按一下run motion XXX to XXX
就可以執行已經儲存好的設定
最後如果要更新動作
就按一下clear all motions
再重新儲存motion
這樣就大功告成了
目前每一個動作的時間間隔是0.25秒
要增加停頓的時間
就把該動作連續存幾次就可以了
照慣例要來個影片
請笑納
ps1.
不要太期待會有很穩定的動作
因為SERVO本身光是送固定寬度的PWM就已經抖個不停
更別提要連續改變SERVO的角度
應該是慘不忍睹的
參考一下就好了~~~~
ps2.
程式其實有預留一些函數沒有呼叫
包含將動作存到檔案
漸進式傳送角度的功能
這些都還沒掛上
所以看動作的時候會比較粗糙
晃動也比較利害
2008年12月1日 星期一
機械手臂控制篇(9) -- 控制板組裝篇
先把手臂的控制板先組裝起來吧!!
記得一開始所提到的洞洞板嗎?
長得跟MCU板一樣大小的那一片?
由於板子的空間真的很小
所以我就放棄原來要加74HC14的作法
改用一般最常做的方式
(其實是因為我的MCU程式已經寫成正邏輯驅動的關係 )
看一下焊好的樣子吧~~~
這一張是正面的樣子
開關的部分我用指撥開關
由於有兩個馬達要同訊號
所以有兩個接頭是共用一個指撥開關的
而指撥開關所管制的就是每一組SERVO的電源
(目前有四組)
因為電流不算小
本來想用鍍銀線
後來全部都用AWG24的線來上!!
焊得挺累的~~
接下來把MCU板焊到洞洞板上
就像圖中所看到的一樣
這可是特別設計過的唷~~~
看看背面的焊線吧!!!
信號線(橙)稍微用小一點
是AWG26的線
連接好的總圖就是這樣囉!!!
在焊接的過程想到一個問題
為啥SERVO的電源大多都設計在中間腳與一側腳
卻不是將電源放在兩側
而信號跑中間??
焊接跟PCB LAYOUT時
你就知道為啥了!!!
最後來看張大合照
萬事皆備
只欠東風
界面程式加油
就要到結尾囉!!!
ps1.
提醒一下
焊接類似這樣的小東西
特別是線一堆的板子
每焊好一條就要用電表量一下
是否點到點有導通
不然等全部焊完才發現最裡面的線沒焊好.....
那就暈暈暈暈暈.........
倒倒倒倒倒.........
Orz...........
ps2.
通電後
MG995的手臂一直在搖
它對信號的截取一直很不穩定
所以在寫界面程式的時候
記得千萬別一次動太多個SERVO
也絕對不要一次跳太多解析度
因為光是要維持動作
它的電流就已經在0.03~0.125A在跳動
扣掉MCU不到0.01A的電流
再次讓人感受到MG995被罵的劣根性
一分錢一分貨
千萬不要貪便宜唷~~~
2008年11月30日 星期日
機械手臂控制篇(8) -- 通訊連線動作篇
先從改變一個SERVO的信號開始就好
在AccessPort上鍵入"00" "FF"
再按下[發送資料]
在示波器上會看到這樣的波形
黃色是UART的信號
而粉紅色是PWM改變後的寬度
這樣看也許體會不到
再看一張送"00" "01"的圖
有看到了嗎?
SERVO的PWM寬度明顯縮小了!!!
有發現我送信號都是送"00" "XX"嗎?
這就是在程式中加入歸零的好處
我可以每次都改變SERVO1的PWM就好
不用一次都改變四個SERVO的值
當然如果要改到後面的SERVO還是要四個一起送
但在測試時
這樣就可以節省不少時間唷~~~
不過通訊碼當然不能只是這麼簡單
未來改版再慢慢考慮編碼的問題
現下先讓信號正確就好
接下來把SERVO1~4的測棒都接上
實際看一下信號的改變
在這裡所輸入的數值都是16進位的唷
請自行用工程型的小算盤換算一下
看到了嗎?
四組SERVO的信號改變了!!!
再換一組數值看看
不錯吧!!
連線成功~~~~
可以開始撰寫pc的操作介面了!!!
ps.
記得剛剛說過的嗎?
不要急躁!!
如果現在你急著接到SERVO上看動作
很可能還是會有災難發生唷~~~
驗證步驟是要按步就班的
今天先到此為止囉!!
機械手臂控制篇(7) -- 通訊硬體改裝篇
所以只好自己拼裝
還記得之前介紹的USB轉UART工具嗎?
現在就要透過他來進行連線的測試囉
在這之前要先作個小改裝
這一張是轉接板要焊上的跳線
記得要把TxD與GND都接上MCU的RxD與GND唷
這樣信號才有參考準位
不然如果只接TxD與MCU的RxD
那是一定不會通的!!!
(會亂入~~~)
MCU這端的接線就是這樣
有空一點再把線路圖整理出來給大家看
連好之後就像這樣
同時把示波器跟測棒也準備好
到此我們就可以開始進行測試了
在旗威論壇中有介紹一套很好用的[AccessPort]
底下就來試用一下
順便提供一下download的地方好了
[AccessPort下載]
首先要設定一下COMPORT的位址
可以從裝置管理員中的連接埠找到
我的是COM4
所以就選COM4
鮑率按照前一篇程式所設定的9600,N,8,1
從PC上送出資料後
確認TxD腳位上有信號出來
這樣就算OK了~~~~
接下來要測試SERVO信號囉!!!
ps.
如果您在示波器上看不到這個信號
那有下列幾種可能
1. 示波器的觸發準位設定不對
2. 確認MCU的程式中設定IO狀態是對的, UART的功能有確實被打開
3. 兩邊的GND是否有接上?沒有共地信號是會亂掉的....
4. 其它狀況請回應讓我知道, 我來幫您看看~~~ ^+++++^
機械手臂控制篇(6) -- 通訊測試MCU程式篇
相信這一段是很多人心中的痛
並不是通訊連不上
而是連上了卻不正確動作
其中有很多設定的部分是要重覆確認的(Double Check)
程式的中斷也是很重要的部分
更重要的是程式的編碼組成
為了簡化程式困難度
所以我採用四個Byte 的通訊
每個Byte以1~255來決定SERVO的角度
而0是一個特別指令
用來將信號歸零用
這個功能的優點
大家稍後就會知道了~~~
先來看看程式吧!!
//-----------------------------------------------------------------------------
// ROBO_ARM.c
//-----------------------------------------------------------------------------
// AUTH: Nichal
// DATE: 2008/11/30
//
// Target: C8051F30x
// Tool chain: KEIL C51 6.03 / KEIL EVAL C51
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include // SFR declarations
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F30x
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // data pointer
sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define SYSCLK 24500000 // SYSCLK frequency in Hz
#define BAUDRATE 9600 // Baud rate of UART in bps
#define SAMPLE_RATE 50 // Sample frequency in Hz
#define SERVO1_PWM SERVO1=1
#define SERVO2_PWM SERVO2=1
#define SERVO3_PWM SERVO3=1
#define SERVO4_PWM SERVO4=1
#define TMH (65536-(SYSCLK/12/SAMPLE_RATE))/256
#define TML (65536-(SYSCLK/12/SAMPLE_RATE))%256
#define MAX_ANGLE 62200
#define MIN_ANGLE 12400
#define MID_ANGLE 37300
sbit SERVO1 = P0^0;
sbit SERVO2 = P0^1;
sbit SERVO3 = P0^2;
sbit SERVO4 = P0^3;
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void SYSCLK_Init (void);
void UART0_Init (void);
void UART0_ISR (void);
void PORT_Init (void);
void Timer0_Init (void);
void Timer0_ISR (void);
void Timer2_Init (void);
void Timer2_Switch (unsigned int counts);
void Timer2_ISR (void);
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
bit start_flag;
bit change_flag;
unsigned char servo_counts;
unsigned int S[4]={MID_ANGLE,MID_ANGLE,MID_ANGLE,MID_ANGLE};
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer enable)
SYSCLK_Init (); // initialize oscillator
PORT_Init (); // initialize crossbar and GPIO
Timer2_Init ();
Timer0_Init ();
start_flag=0;
change_flag=0;
servo_counts=0;
UART0_Init ();
EA=1;
while (1)
{
if (start_flag)
{
start_flag=0;
SERVO1_PWM;
Timer2_Switch(S[0]);
while (change_flag==0);
change_flag=0;
SERVO2_PWM;
Timer2_Switch(S[1]);
while (change_flag==0);
change_flag=0;
SERVO3_PWM;
Timer2_Switch(S[2]);
while (change_flag==0);
change_flag=0;
SERVO4_PWM;
Timer2_Switch(S[3]);
while (change_flag==0);
change_flag=0;
// add new servo here
}
}
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
void SYSCLK_Init (void)
{
OSCICN |= 0x03; // configure internal oscillator for
// its maximum frequency}
RSTSRC = 0x04; // enable missing clock detector
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for and 8-N-1.
//
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON |= 0x10; // T1M = 1; SCA1:0 = xx
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON |= 0x01; // T1M = 0; SCA1:0 = 01
CKCON &= ~0x12;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x13; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON |= 0x02; // T1M = 0; SCA1:0 = 10
CKCON &= ~0x11;
}
TL1 = 0xff; // set Timer1 to overflow immediately
TMOD |= 0x20; // TMOD: timer 1 in 8-bit autoreload
TMOD &= ~0xD0; // mode
TR1 = 1; // START Timer1
IP |= 0x10; // Make UART high priority
ES0 = 1; // Enable UART0 interrupts
}
//-----------------------------------------------------------------------------
// UART0_ISR
//-----------------------------------------------------------------------------
//
//
void UART0_ISR (void) interrupt 4
{
unsigned char x;
if(RI0)
{
RI0=0;
x=SBUF0;
if (x)
{
S[servo_counts]= ((unsigned int)(x)*190) + 12980;
servo_counts++;
if (servo_counts>3) servo_counts=0;
}
else servo_counts=0;
}
if (TI0) TI0=0;
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
void PORT_Init (void)
{
XBR0 = 0xdf;
XBR1 = 0x02;
XBR2 = 0x40;
P0MDOUT = 0xdf;
P0MDIN = 0xff;
P0 &= 0xf0;
}
//-----------------------------------------------------------------------------
// Timer0_Init
//-----------------------------------------------------------------------------
// 20mS Timer
//
void Timer0_Init (void)
{
TCON &= 0xcf; // Stop Timer0; Clear TF0
CKCON &= ~0x08; // Timer0 uses SYSCLK/12
TMOD |= 0x01; // Timer0 in 16-bit mode
TH0 = TMH; // 20mS interrupt
TL0 = TML;
ET0 = 1; // enable Timer0 interrupts
TR0 = 1; // Timer0 enabled
}
//-----------------------------------------------------------------------------
// Timer0_ISR
//-----------------------------------------------------------------------------
//
//
void Timer0_ISR (void) interrupt 1 // wheel signal off
{
TF0 = 0;
TH0 = TMH;
TL0 = TML;
start_flag=1;
}
//-----------------------------------------------------------------------------
// Timer2_Init
//-----------------------------------------------------------------------------
// PWM Timer
//
void Timer2_Init (void)
{
TMR2CN = 0x00;
CKCON |= 0x20;
ET2 = 0;
TR2 = 0;
}
void Timer2_Switch (unsigned int counts)
{
TMR2 = -counts; // set to reload immediately
ET2 = 1; // disable Timer2 interrupts
TR2 = 1;
}
//-----------------------------------------------------------------------------
// Timer2_ISR
//-----------------------------------------------------------------------------
//
void Timer2_ISR (void) interrupt 5
{
TF2H = 0; // clear Timer2 interrupt flag
TR2 = 0;
P0 &= 0xf0;
change_flag=1;
}
顏色與眾不同的
就是新加入或修改的部分
接下來談一談為啥要這樣規劃程式
1. 中位點的運算
大家都知道
所謂的一個Byte
指的是8 bit
由2的八次方來看
它可以代表1~256
然而實際上在MCU裡
並沒有256這個值
它所對應的是0~255
以中位點來說
(0+255)/2=127.5
如果程式碼要決定中位點
必須送出一個127.5的值
請問大家這個值要怎麼送???
答案是
我也不會!!! ^+++++++^
因為MCU的每一個值都只能定義整數
小數點是我們自己幫它加上去的!!!
如果要提高到127.5
就必須多一個Byte讓它變成65535之後
以1275去加小數點
為了讓中位點更中位
所以我用1~255來表示
又最大與最小值的間隔是62200-12400=49800
以49800/256會得到 194.xxxxxx
所以我直接取190做為每一個count的時間間隔
在UART0_ISR的程式中可以看到
2. 預防指令誤傳的法寶
同樣在UART0_ISR的程式中
有一個if (x)..... else servo_counts=0;
為什麼要加這個動作呢?
我們先分析一下這個UART的中斷裡
SERVO的值是如何被改變的:
首先是servo_counts=0
所以當你收到第一個Byte的資料後
你會把資料填在S[0]裡面
接著把servo_counts加1
再接收下一個byte
放在S[1]....
依序放完4個Byte後
servo_counts會自己歸零
完美的寫法!!!
????
如果不小心多送一個byte
會怎樣???
那災難就會發生了!!!!
因為往後所有的信號都會錯開一個Byte
送給第一個servo的信號會被第二個servo用
.......
你或許會問
怎麼可能會多送一個Byte?
我也覺得不可能
可是有時候因為信號線被誤觸
多一個或少一個信號是常有的事
這時候系統就要夠聰明
多一個防呆動作
利用0來將信號歸零後再繼續動作
確保就算這一次不小心送錯了
下一次也絕對不要一直錯下去
3. 其它部分
原則上多了一個數據陣列
用來儲存SERVO的角度
預設是停在中位點
大家看一下宣告就知道了
IO的設定要小心
F300在這方面很講究
設錯了就不會動作
大致上就這樣囉~~~
下一篇再來看看如何動作的
2008年11月29日 星期六
機械手臂控制篇(5) -- 通訊前的準備
接下來就是通訊的部分了
在正式通訊之前
先來說明PC與MCU之間是如何溝通的
首先是MCU的部分
一般來說
MCU最常用的通訊功能是UART
它是透過RxD與TxD的通訊腳位進行通訊
然而PC雖然也有所謂的RxD與TxD
卻沒辦法與MCU直接溝通
因為PC的通訊界面稱為RS232
它的工作電壓是DC12V
而一般MCU是DC5V或DC3.3V
所以如果直接通訊的話
MCU馬上會罷工給你看!!!!!
那該怎麼辦?
這時候就有一種叫做RS232轉UART的工具
用來把RS232的信號準位轉變成UART的準位
這樣就可以通訊了
常見的轉換IC有MAX232 , HIN232....等等
底下提供他們的相關資料給大家參考
MAX232相關資料
HIN232相關資料
不過
隨著時代在進步
很多個人電腦已經放棄RS232介面
全面改成USB介面了
而MCU改朝換代後
很多也都內建USB的功能
這意謂著學通訊的人
要開始接受新的科技洗禮
不然很可能會慢慢變成古"懂"
(就是懂的東西都作古了!!)
雖然時代在轉變
但還是會有一些變遷性的產物
不然過去那麼多的MCU一下子失去支援
很可能全部都變成廢品
(就像無鉛的禁令一出, 很多有鉛品馬上變成廢料.....)
這比不做資源回收還恐怖!!!
這樣的產物叫做USB轉UART
在台灣最早出現的是PL-2303
這一個也是現在USB轉RS232用得最多的晶片
該晶片的驅動也已經通過微軟認證
只要上網執行Windows Update就可以完成驅動
PL-2303相關資料
全台灣第一台USB的AT89C2051燒錄器
用的也是這一個晶片
(就是小弟公司所生產的PGM2051啦)
此外
第一代的USB轉RS485轉接盒也是用這個晶片
換句話說
早期台灣很多標榜USB的產品
骨子裡並不真的是USB架構的東西
而是包了一個USB的轉換介面
讓它可以相容於USB的通訊格式
實際用的還是UART的通訊方式!!!
這個就是第一代的USB轉RS485的片段照片
圖中黑黑的一顆SMD元件就是它的樣子
不過雖然它有這麼輝煌的豐功偉業
在公司裡也已經不再使用這個晶片了
畢竟科技真的是一直在進步
不是嗎?
現下用的晶片是Silicon Labs所出的
至於是哪一個
大家去查一查就知道啦~~~
好像又離題了
再回到主題.....
有了USB轉UART的功能
就可以讓電腦與MCU搭起友誼的橋樑
聽起來很神奇齁?
下一篇文章我們就來實際看看
到底PC與MCU到底是如何透過轉換介面通訊的
敬請拭目以待
ps.
對USB架構有興趣的朋友
有一個人你們一定要認識
讓我鄭重向各位推薦
chamber大大的網站
http://chamberplus.myweb.hinet.net/
他是USB界的神人
或者
說魔人更為恰當~~~