2014年1月29日 星期三

可程式化陣列邏輯 GAL16V8

此顆 IC 為 Lattice 公司製造之通用可程式化陣列邏輯 (Generic Array Logic), 可重複燒錄 100 次以上, 價格也很低廉, 大約一顆 10 ~ 30 元左右, 通常用來燒錄數百個邏輯閘電路, 也就是簡易的自製 IC 啦, 很多 PC 的除錯卡就是用 GAL16V8 做的.

GAL 屬於 SPLD (Simple PLD) 的一種, 乃較低階的可程式化邏輯裝置, 主要由 AND 閘陣列 (此為主要的可程式化部份), 與 OR 閘陣列 (不可程式化), 以及由 D 暫存器與多工器組成之輸出邏輯巨胞 (Macrocell) 構成. 其優點是有 DIP 封裝, 適合小型專案在洞洞板焊接, 體積小價格便宜, 而且製造商較多, 除了 Lattice 公司的 GAL16V8 以外, ATMEL 公司也有製造相容晶片 ATF16V8, 露天都買得到.

GAL 設計工具可免費下載 Lattice 的 ispLEVER Classic (可編繹出所需之 jed 檔) 或 ATMEL 的 Synario, 或者舊一點,  National 的 OPALjr 搭配德國人寫的 GALBLAST 燒錄程式. 燒錄器製作可參考 Simple GAL Programmer.

參考資料 :
  1. 數位邏輯 
  2. PLD GAL CPLD FPGA 介紹
  3. 維基 : 通用陣列邏輯
  4. 維基 : 可程式邏輯裝置
  5. 可程式邏輯裝置簡介
  6. 硬體描述語言 PALASM
  7. MMI PALASM 
  8. Programming of GALs
  9. Creative Hardware Project (交大行動寬頻實驗室 IC 燒錄教學)
  10. GAL16V8 Data Sheet
  11. Using GAL Development Tools (GAL 程式開發工具介紹
  12. OLMC for GAL16V8, Tri-state Buffer and OLMC output pin (ABEL 語言) 
  13. How can I program GAL 16V8-25QJ?
  14. Lattice ispLEVER Classic 
  15. INTRODUCING SYNARIO
  16. How to create a JEDEC file 
  17. GAL 傳統程式開發工具 SYNARIO (從 ATMEL 下載)
  18. Simple GAL Programmer (簡易燒錄器) 
  19. 思泰佳 GA540 萬用燒錄器 (微控科技 $1230) 思泰佳
  20. Introduction to GAL Device Architectures
  21. 一种适合菜鸟的GAL16V8芯片开发方法
  22. 基于LabVIEW和Atmega16的GAL16V8編程器的制作 (PDF 下載)
  23. 【廣維微電腦科技】ATMEL ATF16V8B DIP20 ($30) 
  24. ATF16V8B ($24) 
  25. 《59show》ATF16V8B-15PC DIP ($19 高雄 icShopping) 
  26. 千里網購 atf16v8b-15pu 系列单片机全新原装 一標5個 ($20)
  27.  GAL16V8D-25LP DIP-20 (10個一拍) ($210) 
  28. GOGO平價 可編程邏輯加密IC,GAL16V8,16V8,PALCE16V8 ($13)
  29. 6.4 可编程通用阵列逻辑(GAL) 
2016-09-05 補充 :

我今天在下面這篇找到 ATMEL 公司的 WinCUPL 工具程式可用來編輯 GAL 系列 SPLD :

# ATMEL WinCUPL SPLD/ GAL 開發工具@ 8051動手做[實作班]

下載頁面在這裡 :

http://www.atmel.com/tools/WINCUPL.aspx

要先用 Email 註冊, 填寫公司資訊後會寄一封認證信及註冊碼才能下載. 程式安裝後開啟時也需要註冊碼.

這家在楠梓惠昌街 112 號可自取 (拆機品) :

# GOGO平價 IC, 可編程邏輯加密IC,GAL22V10,22V10,PALCE22V10,LATTICE,AMD $18


明星與敗類

新的一年, 選舉又要到了, 所謂的超人氣政治明星, 也在抬轎者的簇擁下, 開始暖場. 但是我們小民有沒有吸取過去 14 年的教訓? 政治智慧有沒有提升? 古語說, 嫁雞隨雞, 嫁狗隨狗, 嫁人當然就隨人, 在只能選不能罷免更不能公投的閹割式假民主制度下, 未來是要嫁畜生, 還是嫁郎君, 就看手中的一票, 這一票選前很神聖, 選後就很賤,  攸關我們未來幾年的幸福, 不可不慎.

我們要對所謂政治明星保持高度戒心, 因為這些超人氣明星通常是政黨透過媒體操弄民調 "造王" 造出來的. 這些明星其實很可能只是會操弄民粹媚俗的政治敗類, 滿口謊言亂開支票, 大作政治無本生意, 吃我們人民的, 用我們人民的, 謀取高位後前呼後擁吃香喝辣, 好不威風, 有看到民貧國弱嗎? 如果不記取過去的慘痛經驗, 那就不要再罵這個爛政府了.

Arduino 初體驗

晚上在看神雕俠侶時, 接到老張電話, 問我 Arduino 買了沒, 原來他已持有兩年還沒有時間動手, 要先借我把玩. 打開一看, 哇咧, 比我想像中還要小, 大概是信用卡的 2/3 寬而已 (高度一樣) :


這塊是正義大利原廠製品, 從 USB 接口下方那個綠金色 501N 電阻就可確認 (參考 : 如何分辨正版盜版). 通電後 ON 燈恆亮, L 燈閃爍表示板子正常. 依照葉難的這篇說明安裝 USB 驅動程式 :

# Arduino Uno開箱文與安裝設定

需注意的是, 有可能沒辦法第一次就安裝 OK, 那就回上一步再來一次就可以了.

開啟 Arduino IDE 選取 Examples 中的 Blink 範例編譯後上傳, 可看到 Tx 與 Rx 燈在傳送中會閃爍, 看來此板完全沒問題.

Arduino UNO 其實也可以自己用麵包板兜, 如下列影片 :

# DIY Arduino Uno using the ATMEGA 328 Chip
# Arduino UNO R3 印刷电路图和元件单

但是光準備 atlmega328 跟 atmega16u2 這兩顆 IC 就快 200 元了, 還不如花 300 元買一張副廠的 UNO.

2016-07-28 補充 :

上傳程式時必須選對板子類型, 例如用 UNO 不要選到 Nano, 否則會出現 not in sync 錯誤, 參考 :

# 葉難: Arduino:stk500_getsync(): not in sync


2014年1月28日 星期二

Gravitech 的 Arduino Nano USB+乙太迷你板

今天在美商貿澤電子 (Mouser) 網站上找到這款迷你開發板, 正是我夢想中的產品, 一片報價 $1300, 我打電話去問得知貨品在美國, 小部件滿 3000 元可免運費, 經 UPS 直接郵寄到台灣, 所以要一次買三片才符合.

# Gravitech 乙太網開發工具 992-ETHERNET-4NANO

雖然有點貴, 但尺寸真的很小. 如果用 Nano 加 W5100 迷你板, 大約只要 $900 元就可以了, 如果空間要求不是很高, 當然不需要再花 400 元 :
  1. 【方塊奇品】Arduino NANO V3.0 ATMEGA328P ($320)
  2. WIZnet W5100 Ethernet Module SPI 以太網模組 適合Arduino 迷你板 ($550)

Arduino 的視頻遙控車

在中國網站上看到有人用 Arduino 來處理視訊, 雖然感覺效果可能不會很好, 但值得參考 :

  1. http://bbs.52solution.com/thread-499-1-1.html
  2. http://blog.sina.com.cn/s/blog_683c571b0100w1il.html 

Practical Electronics for Inventors

找電子零件時發現這本好書 :

# Practical Electronics for Inventors, Third Edition

2014年1月27日 星期一

脆弱的安定

兩天沒看新聞, 昨日聽小舅講才知道竟然有這種事. 正如我跟朋友們談到脆弱的文明一樣 (眼前一切舒適的環境, 只要電力一中斷, 就馬上回到洪荒時代, 大部分沒仔細想的人聽了都會一笑置之, 怎麼可能沒電呢?), 這個看似安定的社會其實也是很脆弱的, 只要出現一個偏激的人, 一個就夠了, 就足以把眼前的安定, 搞得天翻地覆, 但大部分的人都是如此近視, 沒有遠慮, 認為那是阿富汗或巴基斯坦才會出現的事.

不公義的社會, 就是反社會新血的培養皿. 不要把這些都輕忽地認為是個案. 司法是正義的最後防線, 真正司法獨立是民主穩固的最重要的根基. 但司法黃牛, 法官心證獨裁, 法官檢察官貪瀆, 北素如南逸事, ...., 都是給培養皿加入不少養分, .... , 做傻事的人固然不對, 在法治社會應受處罰, 但這個不公義的社會是不是也正在源源不斷地製造這樣的悲劇人物呢?

# 張嫌投書媒體 吐槽司法不公

2014年1月26日 星期日

拉筋術

很久沒上臉書, 同學介紹的這網站, 好哇 :

# 拉筋術!終於找到了,珍藏了!太有用了!

我不是很喜歡臉書 (太複雜, 搞不懂), 故轉貼於此.

浮沉子

菁菁的寒假作業之一是要準備下學期的科學園遊會的遊戲, 早上兩人找了很久, 覺得很多不是老梗, 就是製作麻煩. 最後在國外網站看到這個浮沉子 (Cartesian diver), 似乎很有趣, 製作也很簡單, 連我以前也沒聽過, 沒玩過, 資料如下 :
  1. 維基 : 浮沉子 (Cartesian diver) 英文
  2. THE CARTESIAN DIVER
  3. Youtube : part1 
  4. Youtube : part 2



2014年1月25日 星期六

朱元璋的三個遺憾

在維基看到這篇傳國玉璽的條目, 感到很有意思, 原來這是秦始皇定天下後以和氏璧所製, 上書 "受命於天, 既壽永昌" 八字, 隨朝代遞嬗, 被歷代登九五之尊者視為繼位之合法信物, 但傳至五代後唐末帝李從珂時, 石敬塘攻入洛陽, 李從珂縱火焚燒宮廷, 此傳國玉璽便不知所蹤, 繼位者兒皇帝後晉石敬塘手上便沒有此信物, 玉璽從此在歷史中消失了, 這也是朱元璋的三個遺憾之一. 我覺得因為朱元璋是個沒讀過書的大老粗, 搞不清楚傳國玉璽早已失傳, 才會引以為憾, 叫北伐軍搜尋元故宮, 可能還認為被元順帝帶到大漠的北元去了呢!

朱元璋的另外兩個遺憾是什麼呢 ?
  1. 定都問題
    他一直想定都故鄉鳳陽, 但劉基等大臣反對, 定都南京又忌諱歷朝定都於此者皆短命 ... 其實南京這地名就是朱元璋時才改的, 以前叫金陵或應天府. 那北京呢? 北京是開封, 作為北伐的基地.
  2. 太子朱標早逝
    朱標會早死, 還不是朱元璋自己害的, 朱元璋誅殺功臣殆盡, 仁厚的朱標跑去求情, 氣得朱元璋拿文鎮砸他, 罵說會這麼做還不是為他登位鋪路, 朱標嚇得回去後憂懼不已, 得病死了, 朱元璋到了六十多歲才要重新挑繼任者, 傳位皇孫, 難怪要遺憾.
# 朱元璋登基的三大遺憾
# 維基 : 傳國玉璽
# 維基 : 李從珂

大咪沒回來

這幾天打電話回鄉下時都會問媽, 大咪回來沒? 自從上週四離家後, 已經超過一週沒回來了, 以前最高紀錄是 7 天, 令我擔心其安危. 特別是本週寒流肆虐, 這傢伙到底跑去哪裡了?

以前養的貓都一隻隻不見了, 只有大咪待最久, 也最有感情.

2014.01.26 補 :
昨晚回到鄉下, 還是沒看到大咪, 但吃過晚飯卻聽到他喵喵喵地從前門方向回來, 哈哈哈, 這傢伙平安無事就好, 但肚子瘦了一圈, 這次離家長達 9 天!


方便的五穀米漿

最近在全聯買了一包五榖米回來做米漿, 我發現作米漿比做豆漿簡單方便, 因為 ... 不用過濾啊! 我那台九陽豆漿機有五穀這選項, 剛好可用. 作法超簡單, 就是量一杯五穀米, 不用浸泡, 漂洗兩次就放進豆漿機, 加入兩湯匙砂糖或紅糖, 選五穀, 按下按鈕, 二十分鐘就 ok. 完成後沖洗豆漿機就可以了, 不用濾豆渣省工不少.


四分之ㄧ不到的殘障民主

今天在商周看到一篇談公民運動的文章, 提到台灣的民主現況是殘缺的四分之一, 讓我心有戚戚焉, 我認為四分之一都不到. 民主發展到現在, 選舉, 罷免, 創制, 複決, 我們多年來其實只有行使選舉權而已, 其他三權都給最鴨霸的政黨給 .... 閹了.  而且選舉在龐大黨產大打廣告, 私底下給走路工, 還有 .... 買票等等手段干擾下形成不公平競爭, 大概只剩下不敢做票足堪自慰矣. 連罷免一個薇閣立委, 原本應該中立的中選會都 GGYY 的技術阻撓, 你說有到四分之一嗎?

最可惡的當然是原本屬於直接民權的創制複決, 具體實踐就是公投法, 被這些專門幫黨圍事的黨籍立委搞成鳥籠公投, 我們的直接民權早已經被這些政治代理人架空啦! 說也是啦, 他們這些靠選舉拿到代理權的政棍 (靠搞政治吃飯的傢伙), 如果讓我們自己搞直接民權, 那他們吃啥喝啥?

黨, 拆開來就是尚黑, 就是白道中最黑的啦. 政治現在就是被這些黨綁架了, 早就沒什麼理想性可言, 只有利益的算計而已. 我希望公民運動能扭轉這個死結, 對於這個土地有愛的人, 要思考如何利用公民運動來換新這個腐朽的政治機器, 如果繼續袖手旁觀, 讓為富不仁的資本家繼續囂張地巧取豪奪, 等中產階級消失社會崩壞, 就是跌入革命暴亂的歷史循環之時.


2014年1月24日 星期五

繁體 LCD 顯示

今天去市圖還書時, 從一本 8051 書上看到 SDEC 這個自帶繁體中文字庫的 LCD 顯示器, 一般的 1862 都只有英文, 中國製標榜可顯示漢字的其實都是簡體中文這種怪胎. 回來找網路, SDEC 原來是國內一家雄鐸科技出品, 露天有賣, 一個 $450 :
  1. Arduino 8051 12864 128X64 19264 192X64 LCD 繁體中文 字庫 + 圖形 + 自定義 雙介面 SDEC
  2. 雄鐸科技


兩種 RF 無線模組

書上介紹的 RF 模組有好幾種, 其中最常見, 市面上也比較買得到的有兩種  : TG-11 (315M 與433M) 與 nRF24L01 (2.7G), 價格都很低廉, 一組約 100~200 元左右. RF 模組需成對, 收發各一個才能運作, TG-11 是收發由不同板子負責, 因此如果要雙向互傳, 必須兩組收發模組; 而 nRF24L01 則是收發都是相同板子, 如果加上微控器控制, 一組應該就可以做雙向單工收發吧.

參考文章 :
  1. 無線電收發原理
  2. Arduino-使用RF模組
  3. 無線模組 (RF 315MHz) 發射接收,使用8051與ATtiny2313
  4. 無線電收發模組-無線電燈光控制 (PDF)
  5. 單晶片實習-無線電收發模組應用 (PDF) 網頁
  6. 專題製作-無線遙控車 (PDF)
  7. 無線電搖控車 (PDF)
  8. 無線電收發模組電路製作介紹 (PPT)
  9. 8051 應用-無線遙控車 (PDF)
  10. 無線開關控制系統 (PDF)
  11. 無線溫度量測模組 (PDF)
  12. 應用無線傳輸系統於聲控家電 (PDF)
  13. 家庭服務保全機器人實作 (PDF)
  14. 自動化家庭電機系統 (PDF)
  15. 使用樹莓派模擬 HT12E 遙控器編碼晶片的編碼格式
露天拍賣市調 :
  1. ★浩哲電子【送程式】TG-11 315MHz ~433Mhz RF無線發射模塊 ($79+$40)
  2. 發射接收模組TG-11(434MHz) ($100+$50)
  3. 【iFlyTech】nRF24L01 (加強版) 台產,2.4G無線傳輸模塊 ($50+$50)
  4. 【Almigtec】NRF24L01+ 的功率加強版 台產 2.4G無線模塊 比原廠遠100% SI24R1 ($50+$40)
  5. Proteus : RF433MHz(無線發射接收模組)入門學習套件 ($350 + $60)
2015-03-09 補充 :
上面幾款商品已經不再販售, 找到其他賣家如下 :
  1. RF 433M 超再生模組 發射接收一對(附範例) $65
  2. Arduino 台產 SI24R1 遠距版 7dBm 2.4G 無線模塊 兼容NRF24L01+(附範例) $40
  3. TX-2B RX-2B一套 取代 HT12D HT12E 12E 12D 遙控玩具車發射接收IC $15

Arduino 板子市調

Arduino 板子很多店家在賣, 價格多在 300 元左右 :
  1. Arduino IDE相容 最小USB開發板 ATtiny85 pro mini uno nano ($85 + $50)
  2. 【方塊奇品】Arduino NANO V3.0 ATMEGA328P ($320 + $30)
  3. 【方塊奇品】最新 Arduino UNO R3 / 送學習課程 100%相容官方最新版 ($350+$40)
  4. 【方塊奇品】ENC28J60 乙太網路卡模組 網絡模組 提供中文手冊及Arduino ($190+$40)
  5. 【鈺瀚網舖】Arduino UNO R3 超值套件/初學套件/入門套件《送配套入門教程、電子書》 ($1080+$40)
  6. Arduino入門套件基本版 配1.5米USB線 提供詳細視頻教程 ($950+$55)
  7. arduino 基礎入門套件 2012 UNO R3 主板 入門套裝 收納盒 ($820+$40)
  8. 鎰盛-Arduino入門學習套件(繁體中文) ($980+$60)
  9. 【大放送 38堂教學課程 + 軟體】Arduino UNO R3 Mega328 RFID 門禁 開發套件 ($1300)
  10. buyIC : Arduino UNO R3 開發板 送基礎學習教程 送USB線1條/Arduino/8051/AVR ($310+$45)
  11. buyIC : Arduino Nano 3.0 with ATMEGA328附USB一條 ($230)
  12. buyIC : 4*4薄膜鍵盤 /按鍵/微動開關/薄膜鍵盤/矩陣薄膜鍵盤/矩陣鍵盤 ($25)
  13. buyIC : HC-SR04超音波模組/超聲波/避障模組/測距模組感測器 ($50)
  14. buyIC : $萬用洞洞板 萬用板/洞洞板 5*7公分 ($4)
  15. buyIC : 自走車 附送多芯線材 附送豐富的教學資料 車體/小車/智能車 ($350)
  16. boyic : 研發零件:需焊接/接線$ NRF24L01+ 模組 ($55)
糊涂塔克学习笔记01 Arduino+nRF24L01
NRF24L01 Module Demo For Arduino
Arduino -- 參考文獻- 陳鍾誠的網站
http://forum.arduino.cc/index.php?topic=167304.0 

2014年1月23日 星期四

三種乙太網晶片

在嵌入式系統中常見的乙太網晶片有下列三種 :
  1. RTL8019
    RealTek 公司出品, 硬體僅實作到第二層 MAC 而已, 第三層以上的 TCP/UDP/IP 需用軟體實現, 使用並列介面, 熟悉乙太網者, 價格較低廉, 單顆約 90~160 左右.
  2. ENC28J60
    Microchip 公司出品, 硬體僅實作到第二層 MAC 而已, 第三層以上的需用軟體實現, 使用 SPI 串列介面, 適合熟悉乙太網者, 價格較低廉, 單顆約 80~150 左右.
  3. W5100
    Wiznet 公司出品, 此為 Arduino 官方建議的晶片, 硬體實做完整乙太網協定堆疊 (TCP/UDP/IP), 適合初學者, 價格較高, 單顆約 180~250 左右.

上面三種晶片模組在露天都有賣, 不過價格價差異頗大, 其中 W5100 板有新舊之分, 板子佈局不同, 新的 R3 版價格都在 $400 以上,  舊版 (2011/2012) $300 左右, 詳見 方塊奇品 或 Kohikan17 說明 (有些寫新版, 但 Layout 看來不像), 也有迷你板, 適合跟 Nano 搭配在麵包板上 :
  1. RTL8019模組 ($150+$60)
  2. 【秋葉原電腦周邊-旗艦店】㊣ rtl8019as乙太網模組 ($400+$50)
  3. 《德源科技》RTL8019AS模組 以太網 TCPIP ($410+$60)
  4. 【廣維微電腦科技】REALTEK RTL8019AS TCP/IP ($100+$35)
  5. 千里網購 rtl8019as 全新原裝現貨 ($89+$40)
  6. $柏毅電子$ ENC28J60 網路模組 ($150+$45)
  7. 【方塊奇品】ENC28J60 乙太網路卡模組 網絡模組 提供中文手冊及Arduino / 51/AVR/ARM/PIC範例代碼 ($190+$40)
  8. buyIC ENC28J60 乙太網路卡模組 Arduino ($150+$45)
  9. ENC28J60 spi 接口 以太網 網絡模塊 51/AVR/ARM/PIC代碼 mini版 ($180+$60)
  10. ENC28J60 網路模組 SPI介面 以太網 ARDUINO 送全套資料 mini 板 ($150+$40)
  11. 長明街薪興電子 : 乙太網路模組 ENC28J60 ($200 )
  12. 千里網購 enc28j60 全新原裝現貨 ($80+$40)
  13. 【方塊奇品】新款 R3版 Arduino Ethernet Shield W5100 網路擴展板 ($460+$40)
  14. 新版的 Arduino Ethernet W5100 R3 網路擴展板 ($440+$60)
  15. WIZnet W5100 Ethernet Module SPI 以太網模組 適合Arduino 迷你板 ($550+$40)
  16. 【鈺瀚網舖】Arduino Ethernet W5100 網路擴展板/SD卡擴展板 ($280+$40)
  17. buyIC 2012最新版 Arduino Ethernet W5100 網路擴展板 SD卡擴展板 ($320+$45)
  18. 【贈源碼】2013最新版 Arduino Ethernet W5100 網路擴展板 ($340+$40)
  19. 新版 Arduino Ethernet W5100 R3 網絡擴展板 支持MEGA 2560 UNO ($290+$45)
  20. Arduino Ethernet W5100 網路擴展板 ($270+$60)
  21. 千里網購 w5100 全新原裝現貨 ($180+$30)

2014年1月22日 星期三

購買 Raspberry Pi

上週六帶姊姊去明儀買她的生日禮物, 順便買了葉難寫的 "Raspberry Pi從入門到應用", 書既然買了, 下一步就是買主板了. 剛好今年尾牙抽中 2000 元現金, 扣掉請客 400 元, 還剩 1600, 買主板是綽綽有餘, 但連配件可能要貼一點錢了. 就當作是尾牙抽到的禮物好了.

在露天市調結果, 以樹苺派專賣店較佳 (一年保固), 清單如下 :
  1.  ★樹莓派專賣店★【免運費】主機板+高透明外殼+散熱片+電源組+8G SD卡 Raspberry Pi ($1790)
  2. ★樹莓派專賣店★PHILIPS高品質 2米 HDMI線 Raspberry Pi ($100)
  3. ★樹莓派專賣店★【升級加190元】英國製主機板(三星晶片) Raspberry Pi Model B 512MB Made in UK ($190)
  4. Proteus : Raspberry Pi (樹莓派) GPIO 彩色連接排線 ($70+$60)
  5. Proteus : MCP3008 - (SPI 協議) 8 通道 10-bit ADC (數位類比轉換) IC  ($136+$60)
  6. Proteus : RF433MHz(無線發射接收模組)入門學習套件 ($350 + $60)
  7. 柏益 : 麵包板 + 麵包板電源模組 + 麵包板連接線 紮線 測試線 三件組 ($200+$45)
  8. 柏益 : NRF24L01+ 模組 * 2 ($110 + $50)
  9. 柏益 : 315MHz/433MHz RF模組 ($80+$45)
  10. 柏毅電子$74HC595 (一包1入) DIP封裝 ($4+$45)
  11. 柏毅電子$ 紅色 四位數 七段顯示器 帶時間分號 4digit 7segment 共陰極 數碼管 ($25)
  12. 柏毅電子$2節4號電池座 電池盒 電池座 ($7)
  13. 柏毅電子$ 74HC273 (D 暫存器 一包1入) DIP-20封裝 ($10)
  14. 柏毅電子$ 74HC04 NOT閘 (一包1入) DIP-14封裝 ($4)
  15. 柏毅電子$ ADC0804 (一包1入) DIP-20封裝 ($50)
  16. 柏毅電子$ 74LS245 (3態轉換器,可用來擴充I/O, 一包1入) DIP-20封裝 ($16)
  17. 【345電腦★建國店】7 Ports USB 2.0 Hub - Support 480 Mps 集線器 獨立電源 ($250)
  18. 可傑有限公司 micro SD 8G C10 記憶卡 Transcend T-Flash Class10 ($205)
 免開發票 (預粘散熱片)
1790+100+190=2080

所以, 我要補貼 $480. 差不多就是被上司要求請客的錢. 其實不升級三星晶片也是可以, 反正都是 UK 製的, 只要不是 CN 製就好. 但據說三星的最穩. HDMI 轉 VGA 線不用買, 因為家裡電視有 HDMI, 而且根據 "如何用树莓派Raspberry Pi做一个简单的控制系统" 這篇說明, 只要透過 USB 無線網卡連上 WIFI, 就可以用 secureCRT 在區網中連線樹苺了.

為啥要買 Raspberry Pi ? 只用 Arduino 不是也可以做很多控制嗎? 原因如下 :
  1. 它是 Linux, 有作業系統的, 有許多免費資源可用; Arduino 沒有作業系統 (要 Yun 才有).
  2. 已有乙太網, 網路存取方便
參考文章 :
#「Raspberry Pi 購買指南」系列文章
# Raspberry Pi 第一次接觸
# Raspberry Pi情報彙整 (7)
# 幫Pi裝上Webcam做stream server即時傳輸監控影像 
# Raspberry Pi 能做什麼(5/6):做為家庭監視系統主機
# Raspberry Pi 能做什麼(6/6):控制自走車或機器人
# radio-controlled Raspberry Pi race rover (來自 TRAC)
# 深入淺出Raspberry Pi GPIO - SlideShare
# Raspberry Pi的GPIO外接板(分線板、原型板、緩衝板、擴充板)
# Raspberry Pi 緩衝板製作 (GPIO 保護電路)  分線板
# Raspberry Pi 常見的技術問題
# 打造增强型Raspberry Pi-液晶屏篇
# GPIO Tool For Raspberry Pi 2.38.1510 (Android)
# Raspberry Pi Voice Recognition Works Like Siri (真是太強了)
# RPi Tutorial EGHS:GPIO Protection Circuits (GPIO 保護電路)
# Raspberry Pi GPIO 介紹及基本使用
# 如何用树莓派Raspberry Pi做一个简单的控制系统

改造住家門禁防盜系統

最近因注意到我們大樓的門禁防盜系統, 每一戶客廳牆上都有一個小小的主控盒, 大門, 後門, 臥室窗戶都有有線門磁, 主臥室有 SOS 按鈕, 透過弱電系統連接到主控盒, 門口有一個設定鈕, 設定後只要門窗被打開或 SOS 鈕被按下, 主控盒就會發出聲響, 同時管理室也會告警. 但管理室主機應該早就壞了, 所以即使觸動 SOS 鍵或防盜狀態下開門, 管理員也不會來電關心. 不過打開門窗時, 客廳主控盒的相對應 LED 燈還會亮, 可見弱電系統, 門磁感測器, 與主控盒都還正常運作中.



昨晚費了一番功夫, 把客廳的主控盒打開, 發現裡面是一塊 PIC16C55 主控的小電路板, 經過 17 年還能正常運轉, 真勇. 既然管理室主機已故障失修, 其門禁防盜功能就失去作用了, 只好自行改造讓其恢復應有功能. 我打算把弱電的電源與門磁信號線接出來, 接上 433MHz 的 RF 發射模組, 再由 Raspberry 主板接收後上網路 (或者只要 Arduino+TCP 就可以?). 使用 RF 原因是主控盒位於電視對面牆上, 而我的 Raspberry 主板當然要跟電視放一起, 要從管線拉線那是不可能, 所以只好用無線通訊方式處理.

首先是要找出控制面板上各 LED 燈號所連接的門磁, 確認 SOS 是緊急呼叫鈕, GAS 是廚房瓦斯偵測器, 1S 是大門, 2S 為後門, 3S 為書房窗戶, 但是 4S 卻四處找都沒發現在哪兒, 先不管它, 反正把這六個接點信號, 加上弱電系統的 VCC 與 GND 電源共 8 條線都抓出來, 連接到 RF 發射模組就對了. 把板子翻過來, 對照 PIC16C55 晶片接腳找了好久, 終於標定了各個接出點, 因為弱電排線頭可能年久與插座密合, 拔不出來, 所以接點接出焊錫只好活線作業囉.

第一個問題是, 經三用電表測量, 門磁在關閉時為接地 (0V), 開啟時為 1V 左右, 查了一下 HT12E 的輸入準位, 發現其高位準 VIH 最低是 0.8VDD, 也就是 4V, 而 VIL 最高是 0.2VDD, 亦即 1V, 1V~4V 是邏輯模糊區, 因此門磁送來的信號線不能直接拿來用, 必須在板子上找看看有沒有信號轉換後的接點, 要不然就得想辦法隔離提升準位.

無線模組在露天有賣, 市調如下 :
  1. RF433MHz(無線發射接收模組)入門學習套件 ($350+$60)
    含無線模組與 HT12E, HT12E 編解碼 IC, 以及 DIP 開關, 電阻與線材等. 有附源碼等資料. 
  2. 【廣維微電腦科技】433MHz 無線RF模組 ($80+$30)
  3. 【廣維微電腦科技】HOLTEK HT12E DIP-18 ($20+$35)
  4. 【廣維微電腦科技】HOLTEK HT12D DIP-18 ($20+$35)
  5. 【廣維微電腦科技】8P DIP SW 指撥開關 5入 ($40+$35)
  6. 浩哲電子【送程式】TG-11 315MHz ~433Mhz RF無線發射模塊 ($79+$40)
關於 HT12E 與 HT12D 的用法如下 :

  1. HT12E 規格書 (PDF)
  2. HT12D 規格書 (PDF)
  3. HT12E Encoder IC for Remote Control Systems 
  4. Problem with RF circuit using HT12D and HT12E
  5. A remote control using HT12E and HT12D chips
  6. Library for HT12E
  7. send 8bits using RF 434 Mhz module(with ht12d-ht12e)
  8. Arduino - 使用RF模組
  9. 89C51 與 RF 發射模組的問題 (加上編解碼器後可以發射較遠)
  10. 使用樹莓派模擬 HT12E 遙控器編碼晶片的編碼格式 
  11. Why use HT12E?



2014年1月21日 星期二

露天拍賣上的電子零件商

最近對硬體舊情復燃, 除了找 Arduino 資料外, 也把買了兩年的 8051 板子拿出來清一清把玩一下, 覺得還真是會拖, 這塊板子買來竟然還沒通電, 能不能 work 還不知道咧, 真扯.

自從離開 ASIC 設計後就沒再碰過硬體了, 我的電子電路功力已退化到入門級, 連場效應電晶體怎麼接都忘記了, 還好三用電表還會用!

現在要買電子零件很方便, 露天拍賣有許多廠商, 不必為了一個小零件專程跑一趟長明街.
  1. kennyhido (東東大批發) : 3C 配件
  2. proteus : 樹莓派相關產品為主, Arduino 套件
  3. boyi101 (柏毅電子) : 一般電子零件 IC, Arduino 套件
  4. ee_engineer (浩哲企業社) : Arduino 套件, PCB 洗板, 電路設計
  5. kingway-tech (廣維微電腦科技) : 一般電子零件 IC
  6. mrswoo00000 (千里網購) :  一般電子零件 IC
  7. ichome3689 (iCshopping) : 一般電子零件 IC, Arduino 原廠套件 (高雄 07-5564686)
  8. buyic : 一般電子零件 IC, Arduino 套件, 樹莓派 (高雄 07-3457042, 文學路 678 號)
  9. op771112 (薪興電子) : 一般電子零件 IC, Arduino 套件 (高雄 0987-731983, 長明街269號)
  10. bcb0354 (小蝸牛 AJB) : 一般電子零件 IC, Arduino 套件, PCB 洗板
  11. ematt99 (伊瑪購物) : 一般電子零件 IC 
  12. sam1113 (采彥) : 一般電子零件 IC 
  13. lovekazubi (和欣電子) : 一般電子零件 IC 庫存出清 (鳳山有 9 折券)
  14. ic995 : 一般電子零件 IC, 九如二路225號14樓之6台企銀大樓

2014年1月19日 星期日

第一顆草莓

本週回鄉下發現小舅上回帶回來的十幾株草莓,種在雞舍邊兩個月多,陸續開出白色小花,其中一株已結出鮮紅的果實,我在想,如果高雄的陽台放幾盆來種,既美觀,又有得吃,多好。

 

2014年1月16日 星期四

對賴很不爽

最近對  "賴 (Line)" 異常反感, 同事換了智慧型手機, 裝了 Line, 申請了吃到飽, 於是整天掛網, 但這不是問題, 問題是把音量開到最大聲, 三不五時就叮咚一下, 說不這樣就不曉得有人賴他, 真的很吵耶.

現在走到哪裡都看到低頭族, 是的, 整個城市都是低頭族. 我不曉得現在的人會無聊到這種地步. 去哪裡都要打卡; 餐廳一邊吃飯一邊滑手機; 情侶對面吃飯也在 Line; 公共場所到處是叮咚; 這世界到底怎麼了? 無時無刻分享行蹤有那麼重要嗎? 智慧型手機時代的人們已經失去無聊與發呆的能力了.

我沒跟上時代嗎? 從有智慧型手機上市, 我就開始使用了, 除了資料管理, 還能即時上網查資料, 雖然上網吃到飽, 但只在要用到時才上網, 從來沒玩過 Game, 因為要做的事情很多, 還沒無聊到玩 Game 的地步. 無聊? 我只要一本書就夠了, iPad 對我的意義, 只是它可以裝上數百本電子書, 方便上 TED 而已. 3C 設備其實只是我的奴才, 呼之即來, 揮之即去.

我不喜歡那種被奴才宰制的感覺.


2014年1月15日 星期三

PHP 與 Javascript 變數的 Scope

PHP 與 Javascript 是我日常使用的程式語言, 但是其變數的 scope (範疇, 作用域, 有效範圍) 有些不同, 偶而恍神的時候會兩者互相混淆, 故在此紀錄一下兩者差別的測試結果.

首先來看 PHP 變數的 scope. PHP 的變數分為函式外宣告的全域變數與函式內宣告的區域變數兩種, 即使同名也不會互相干擾, 全域變數作用域為整個網頁檔案, 即使在不同的 <?php ?>區段中都是指涉同一個變數, 例如下列範例 1 所示 :

測試範例 1 : http://mybidrobot.allalla.com/phptest/scope_1.php [看原始碼]  

$a=1; //全域變數
function func(){
  $a=2; //區域變數不會改變全域變數之值
  echo $a;
  }
func(); //顯示 2 (顯示區域變數之值)
echo $a; //顯示 1 (顯示全域變數之值, 不會被函式修改)

結果顯示 21, 可見函式中的程式碼看不到外面的全域變數, 因此無法存取外面的 $a 之值. 相同的, 函式外面的程式碼也看不到函式內的區域變數. 如果想要在函式內存取全域變數, 必須在函式內用 global 宣告其為全域變數, 如下列範例 2 所示 :

測試範例 2 : http://mybidrobot.allalla.com/phptest/scope_2.php [看原始碼]  

$a=1; //全域變數
function func(){
  global $a; //宣告 $a 為全域變數
  $a=2; //修改全域變數值為 2
  echo $a; 
  }
func(); //顯示 2 (顯示全域變數之值)
echo $a; //顯示 2 (顯示全域變數之值) 

可見在函式內部, 只要先用 global 宣告, 就可以存取外面的全域變數了, 上例中函式內的 $a 已指向外面的同名全域變數, 因此將其值改為 2, 事實上就是改了外面那個全域變數 $a 之值. 注意, global 必須獨立宣告, 不可以宣告同時賦值, 例如下列用法是錯誤的 :

global $a=2;  //錯誤用法

如果我們傳參數進去會怎樣? 當然會因為 global 的關係改到外部全域變數之值啦, 如下列範例 2-1 所示 :

測試範例 2-1http://mybidrobot.allalla.com/phptest/scope_2_1.php [看原始碼] 

$a=1; //全域變數
function func($a){
  global $a; //宣告 $a 為全域變數
  $a=2; //修改全域變數值為 2
  echo $a; //顯示 2
  }
func(3); //顯示 2 (顯示全域變數之值)
echo $a; //顯示 2 (顯示全域變數之值)

結果顯示 22, 雖然傳入 3, 但在函式內又被改為 2, 故輸出 2, 同時因為 global 緣故, 也把外部之同名全域變數改為 2. 

除了 global 之外, 還可以利用超全域變數 $GLOBALS[] 陣列來存取全域變數 (關聯式陣列, 用變數名稱當索引), 如下列範例 3 所示 :

測試範例 3 : http://mybidrobot.allalla.com/phptest/scope_3.php [看原始碼]  

$a=1; //全域變數
function func(){
  $GLOBALS["a"]=2; //修改全域變數值為 2
  echo $GLOBALS["a"]; 
  }
func(); //顯示 2 (顯示全域變數之值)
echo $a; //顯示 2 (顯示全域變數之值) 

可見效果是一樣的. 因為每宣告一個全域變數, PHP 就會在 $GLOBALS 陣列中添加一個元素, 儲存指向該全域變數的參考.

當函式呼叫完畢, 函式內的區域變數就會從記憶體中釋放, 例如下列範例 4 所示 :

測試範例 4 : http://mybidrobot.allalla.com/phptest/scope_4.php [看原始碼]  

$a=1; //全域變數
function increment(){
  echo ++$a; //沒有設值預設為 null, 增量計算時會轉為 0
  }
echo $a; //顯示 1 (顯示全域變數之值)
increment(); //顯示 1 (null 值為 0 增量後為 1)
increment(); //顯示 1 (null 值為 0 增量後為 1)

結果顯示 111, 後面兩個 1 是呼叫 increment() 函式的結果, 因為區域變數 $a 沒有設值 (=null), 增量計算時會被 PHP 認為是整數, 而整數變數預設為 0, 故先轉為 0 再增量, 故輸出 1, 但是因為函式執行完畢就釋放記憶體中的區域變數, 因此沒辦法記憶其值, 不論呼叫幾次都是輸出 1. 若要記憶區域變數之值, 必須宣告為靜態變數, 如下列範例 5 所示 :

測試範例 5  : http://mybidrobot.allalla.com/phptest/scope_5.php [看原始碼]  

$a=1; //全域變數
function increment(){
  static $a;
  echo ++$a; //增量
  }
echo $a; //顯示 1 (顯示全域變數之值)
increment(); //顯示 1 (預設 null 值為 0 增量後為 1)
increment(); //顯示 2 

對於 Javascript 來說, 它也是有分宣告於函式外的全域變數與函式內的區域變數, 如下列範例 6 所示 :

測試範例 6  : http://mybidrobot.allalla.com/phptest/scope_6.htm [看原始碼]  

    var a=1;   //全域變數
    function func(){
      var a=2;   //區域變數
      document.write(a);  //顯示 2
      }
    func();  //顯示 2
    document.write(a);  //顯示 1

結果顯示 21, 這結果與 PHP 是相同的, 亦即全域變數與區域變數互不侵犯, 函式內看不到外面的變數; 函式外也看不到函式內的變數. 但是如果我們將函式內的變數宣告關鍵字 var 拿掉, 結果就不同了, 如下列範例 7 所示 :

測試範例 7  : http://mybidrobot.allalla.com/phptest/scope_7.htm [看原始碼]  

    var a=1;  //全域變數
    function func(){
      a=2;  //函式內變數未宣告直接賦值, 解譯器將其視為全域變數
      document.write(a);  //顯示 2
      }
    func();  //顯示 2
    document.write(a);  //顯示 2

結果顯示 22, 很奇怪吧! 函式內的變數有沒有用 var 宣告是有很大差別的, 有用 var 宣告的就是區域變數, 即使與函式外的全域變數同名也沒關係, 井水不犯河水, 但若沒有用 var 宣告就直接使用, 就會被 Javascript 解譯器視同全域變數處理 (跟 PHP 使用 global 存取全域變數效果一樣), 如果與全域變數同名, 就會改變全域變數的值; 反過來說也是一樣, 函式內本該對外隱藏的區域變數就全都露了, 從函式封裝上來看,  Javascript 有不夠嚴謹的弱點, 這是與 PHP 的不同之處. 寫 Javascript 要養成良好習慣, 最好用 var 宣告變數.

Javascript 的變數可以不宣告直接賦值, 其實是解譯器在執行前的預編譯階段自動幫我們加上去了, 但只對函式外的變數自動加 var, 不會對函式內的變數加 var, 所以範例 7 函式裡的 a 變數就被當成全域變數處理了. 但是, 如果有傳入參數, 那結果又不同了, 如下列範例 7-1 所示 :

測試範例 7-1  http://mybidrobot.allalla.com/phptest/scope_7_1.htm [看原始碼] 

    var a=1;  //全域變數
    function func(a){  //傳入參數 a
      a=2;  //此 a 變數被視為參數 (區域變數), 故不會更改外部 a 之值
      document.write(a);  //顯示 2
      }
    func(3); //顯示 2
    document.write(a);  //顯示 1

結果顯示 21, 此例中函式 func() 帶了一個參數 a, 雖然函式內第一行 a=2 沒有用 var 宣告, 但是因為有傳入參數 a=3, 因此變數 a 會被解譯器視為傳入之參數, 而參數就是區域變數, 雖然傳入值為 3, 但隨即被改成 2, 故呼叫 func(3) 卻輸出 2. 當然它也不會改到全域變數 a 之值, 因此最後一行指令仍輸出 1. 這跟上面 PHP 的範例 2-1 結果截然不同.

最後來研究一下靜態變數, 在 Javascript 規格裡是沒有靜態變數的, 但範例 7 函式內未宣告的變數等同於全域變數, 這個特性倒是可以拿來當作靜態變數使用, 如下列範例 8 所示 :

測試範例 8  : http://mybidrobot.allalla.com/phptest/scope_8.htm [看原始碼]  

    var a=1;  //全域變數
    function increment(){
      ++a;  //函式內變數未宣告直接賦值, 解譯器將其視為全域變數
      }
    increment();  //a 增量為 2
    increment();  //a 增量為 3
    document.write(a);  //顯示 3

可見因為函式內同名變數未宣告即賦值, 被視為全域變數, 當函式執行完畢時, a 不會消失, 所以每呼叫一次就增量, 跟上面 PHP 的 static 變數效果一樣.


2014年1月14日 星期二

美國是民主國家嗎?

以前在中山大學念外文時, 一位教我們英文作文的美國老師 (我還記得名叫 Dampsy) 在課堂上提到政治制度, 有同學說美國是民主國家的老大, Dampsy 老師睜大眼睛說 : "No, you're mistaken; America is not a democratic nation." (不, 你搞錯了, 美國不是民主國家), 這時換成我們睜大眼睛, 面面相覷, 美國人說美國不是民主國家, 很奇怪不是嗎?

後來對政治了解越來越多, 特別是搞清楚 "美國人如何選總統" 後, 我終於了解 Dampsy 老師的意思了. 美國總統不是全民普選產生的, 而是由選舉人團票數定江山的, 所以有時會出現總得票率大勝卻輸了總統選舉的奇怪現象. 今天看了這篇 "美國是個民主國家嗎?" 後, 又再印證了 Dampsy 老師的說法.

最近一位印度駐美女外交官因為謊報保母薪資遭到美國司法當局當街上銬, 並脫光衣服檢查掀起美印外交衝突之事, 讓我領悟, 即使美國不是所謂的 "民主國家", 但她絕對是一個法治國家. 美國司法獨立, 一切依法辦事, 頗似秦穆公時代的商鞅變法, 法家也是主張必須依法辦事, 國家才會富強 (有關係就沒關係, 當然貪汙橫行啊).

美國政治制度一言以蔽之, 就是菁英政治, 只有受過良好教育的上流社會菁英才有可能在政界冒出頭. 美國立國設計就是不相信民主, 或者精確些, 民粹, 認為受萬民擁戴的候選人不見得是好的領導者, 有可能只是很會討好普羅大眾的機會主義野心家. 見諸台灣的政治現況與近日之泰國亂象, 不就是這樣嗎? 我們不能說民主不好, 應該釐清的是, 民粹不好.

美國的強大, 主要是其三權分立的共和體制. 美國憲法賦予總統強大的行政權力, 但任期制, 國會立法權與司法獨立卻有效制止他成為獨裁君王. 強大的行政效率使得美國成為現代的羅馬帝國. 像我們這個既非總統制, 亦非內閣制, 更不是雙首長制的四不像政府, 只要強人不在就螺絲掉滿地, 難怪國勢日弱.

2014年1月13日 星期一

自製風力發電機

很早以前我就想做一台風力發電機, 因為鄉下風大, 幾乎一整年都呼呼地吹, 如果屋頂有一台小型風車, 至少可以點亮一盞燈吧! 更何況二十多年前我就拿到電機技師執照了, 沒理由連一台發電機都無法 DIY.  十年前我花 200 元買了一個滾珠軸承, 但是一直沒動手. 今天看到下面這篇, 手真的就有點癢了 :

風力發電機DIY

同時我也蒐集了好幾篇研究, 發現垂直式桶型葉片在角度 10 度時發電效率最好, 但是我喜歡的是飛機造型的風車, 直筒形感覺不像風車. 我的構想是拿老舊的電扇來改 (註 : 電扇是交流感應, 理論上無法作發電機用, 要改為永磁很難), 因為網路上現成的都很貴 ($5000 以上), 除了教學用那款之外. 其他參考文章如下 :

# 小型風力發電機設計與製作(簡體書8-ac1 C63.05 久保大次郎)
# P300W風力發電機,低啟動家用小型風力發電機 ($7500)
# DIY簡易風力發電機製作 Wind-driven generator
# 唐從聖 史特林引擎 stirling engine
# 結合風力發電機與太陽能電池模組之混合式充電系統之研製 (pdf 論文)
# 幽靈教主80w風力發電機 ($5000)
# 洞洞板焊24鉛酸電池充電電路
Automatic 12V Lead Acid Battery Charger
# Ceiling Fan to Wind generator conversion demo
# DIY 1000 watt wind turbine
# Home Build Wind Turbine Using Car Alternator
# 1600 watt Wind Turbine
# Wind Turbine Project - First Big Wind
# JAMAICAN BUILT WIND TURBINE

2015-03-11 補充 :

露天的教學小發電機已經改到這裡 :

# 教學小發電機 (葉片150+發電機300 共 450)

2015-03-25 補注 :
經購買實際測試結果, 此發電機啟動風力應超過 3 公尺/秒, 一般的微風或小風無法驅動, 要大風才行, 誠如賣家所言, 此為教學用耳. 也有可能是葉片太短小了, 受力不夠所致, 考慮找長一些的木片做葉片試試, 如果還是不行, 就轉作水力發電機用.

中輟生談教育

在 Tsung's blog 看到這篇, 一個大學沒讀完的工程師黃敬群所寫的 :

http://www.slideshare.net/jserv/education-usingopensource

在這篇簡報的第 66 頁看到找尋已久的那段話 :

"我們這一代不得不從事軍事和政治, 為的是讓我們兒子一代能從事科學與哲學; 讓我們孫子一代能從事文學和舞蹈"

原來這是約翰亞當斯說的, 我一直以為是傑佛遜.

無線門磁的控制問題

以前鄉下家裡曾遭小偷, 雖然沒甚麼好被偷, 但是感覺不太安全, 於是花了 $26000 裝了 24 小時監控的監視器, 還買了一個 GSM 安全控制組, 附了四個無線門磁, 當設定監控時, 只要有人開門, 磁簧開關就會斷開, 並發出無線電訊號 (315MHz), 監控主機收到後就會對預設好的手機發出簡訊, 是很不錯的防盜設計. 但觸發後若未關閉告警, 主機會持續發出 bibi 聲, 因為沒時間研究設定問題, 乾脆關機不用了.

最近研究 Arduino, 發現可以利用門磁來做居家安全監控, 回鄉下時把門上的無線門磁拆下來研究, 發現裡面除了線圈發射器外, 就一顆 SC2262 的 DIP IC, 查了一下原來是編碼器, 防止訊號被破解用的, 接收端需要一顆 SC2272 解碼器, 所以那個 GSM 主機裡面應該有 2272.

2272 接收器露天有在賣, 高雄 buyIC 約  40 元 :

http://goods.ruten.com.tw/item/qa?21209120281299

關於 2722 的控制可以參考 :

315m无线遥控模块 PT2262、PT2272
PT2262/PT2272编解码集成电路介绍
# 用arduino来遥控家电
# 基于AT89S52的远距离照明控制无线遥控开关系统 # PT2262/2272遥控集成电路的应用

2014年1月10日 星期五

Raspberry Pi 與 Cubieboard 的比較

Raspberry Pi 與 Cubieboard 的比較 :

# 兩款主流ARM架構的開發板 Raspberry PI 與 Cubieboard 介紹

兩塊都是 ARM 板子, Cubieboard 性能稍強, 但 Raspberry Pi 較便宜. 都可以用來作為上位機, 例如下面這篇文章 :

非智能 WIFI视频小车-基于arduino+cubieboard

Cubieboard 1GB ARM Cortex-A8開發板 比 樹莓派Raspberry pi 運算速度更快 (露天 $1550) 
高雄 BuyIC (左營區文學路 678 號 )

Arduino 飛航控制

我在 "amoBBS 阿莫电子论坛" 看到這個用 Arduino Nano 直接將無線接收器訊號轉成 Ar.Drone 指令的方法, 不再使用 WiFi 訊號. 在 Git 有完整的 Wiki 與檔案下載 :

  1. https://code.google.com/p/ardudrone/


Arduino 小型控制器 ATtiny85 晶片

一般 Arduino 板用的是 Atmel, 而這個 ATTiny85 是縮小版的, 有 8 隻腳, 具 8K flash. 對於不需要太多輸出與邏輯的小專案, 不需要動用 Arduino UNO 或 Nano, 改用 ATtiny85 就可以了. 露天也有賣 ATtiny85 的開發板, 才 $85 元而已. ATtiny 可以用 UNO 板子來燒錄程式, 參考下列連結 1. 此晶片簡介參考 : An introduction to ATtiny85.
  1. 用 ATtiny 幫你的專案減肥 

    Using the Arduino Uno to program ATTINY84-20PU
  2. 將Arduino Uno當做一台ISP線上燒錄器,燒錄sketch到麵包板上的ATtiny85-20PU晶片
  3. 使用 Arduino 燒錄 ATtiny

  4. Process of getting attiny85 to work with nRF24L01 on RF24 libraries
  5. ATTINY85-20PU AVR DIP 單晶片 Arduino (露天 1 顆 $78)
  6. 《iCshop2》ATTINY85 微型開發板(mini USB)【Arduino,Arduino IDE相容】$110

RC 遙控飛機

在 Youtube 上看到這位 ey0927399 君的遙控飛機試飛, 真是太厲害了 :
  1. Q版F-18遙控飛機飛行
  2. Q版國軍F-16太陽神塗裝遙控飛行
  3. 自製Q版米格飛行 
  4. 2013柯南滑板機及三軸陀螺儀使用介紹
其他 :
  1. 下課花路米 太陽能無人飛機
  2. 自製遙控飛機 DIY F-16 過程
  3. 我玩遙控飛機  FMS免費飛行軟體介紹
    (GWS 遙控器接上連接線即可用電腦模擬遙控各種飛機,減少摔機的成本。)
  4. 請問如何用保麗龍或珍珠板自製遙控飛機
  5. 珍珠板RC Katana (Depron RC Katana) 
  6. DIY遙控飛機 自製遙控飛機
  7. 雙翼機製作教學 窮學生的鷹機...製作說明
  8. 港都 RC : 高雄市鼓山區中華一路61號 rc_shop_tw (近明誠中學)
  9. 飛控套件 (馬達, 伺服機)  
  10. 港都RC GWS 廣營 UM RYAN STA 寶麗龍材質自由飛電動小飛機


2014年1月8日 星期三

大蒜與番茄要怎麼吃

今天收到同事傳來的 email, 提到抗癌之王大蒜與番茄的正確吃法, 節錄如下 :
  1. 大蒜是抗癌之王, 但大蒜加溫等於零. 大蒜正確的吃法必須先把它切成片, 一片一片的薄片放在空氣裏15分鐘, 它跟氧氣結合以後產生大蒜素再吃. 大蒜本身不抗癌, 大蒜素才抗癌. 如果不這麼吃, 那就是白吃了, 大蒜有味不用怕, 吃點山楂, 嚼點花生米, 再吃點好茶葉就沒味了.
  2. 番茄裏面有個東西叫蕃茄素, 它和蛋白質結合在一塊, 周圍有纖維素包裹, 很難出來. 所以必須加溫, 加溫到一定程度才出來. 番茄炒雞蛋最值錢了, 還有蕃茄湯, 或番茄雞蛋湯也是好的. 生吃番茄是白吃了, 不抗癌. 
  3. 血黏稠不要吃阿司匹靈, 應該吃黑木耳. 因為吃阿司匹靈後果是眼底出血. 黑木耳有兩個作用, 其中一個是使血不粘稠. 黑木耳有兩個作用, 其中一個是使血不粘稠.   
根據維基百科之 "大蒜素" 與 "" 詞條 :

"研究顯示大蒜素有抗菌、抗真菌、消炎、抗氧化、抗血栓、降血壓、維持脂蛋白平衡、防治動脈硬化等功效。2009年,Vaidya、Ingold 和 Pratt 的研究表明大蒜素的生物功效主要是由大蒜素分解產生的2-丙烯次磺酸造成的,該化合物不穩定,很快便與體內的自由基發生反應使之失活。"

"現代醫學認為大蒜能提高免疫力,提高人體淋巴T細胞、巨噬細胞等免疫系統轉化能力。將新鮮的大蒜切片或搗碎後生吃有助於心臟健康。醫學上被用來驅除腸內的寄生蟲。 "

"一般的大白蒜在經過發酵後會成為黑蒜,其蒜素的濃度是一般大白蒜的20倍。"

亦即, 其抗癌機制來自於二丙烯次磺酸捕捉自由基 (致癌因子) 的效果. 與大蒜同為蔥科蔥屬的洋蔥也是富含大蒜素.

2014年1月7日 星期二

核名求實

新聞報導, 江宜樺一怒為廁所, 國父紀念館廁所壞了半年沒人理, 說螺絲鬆了半年多, 交代要辦人. 私以為, 何止鬆了半年, 這個馬政府根本就是沒上螺絲就上路, 邊開邊找螺絲咧. 當初說我們準備好了, 五年下來薪資倒退 20 年, 萬物齊漲, 任期剩兩年多, 還能有啥作為?

管理無他, 核名求實而已, 如果官員平庸, 不像當年李國鼎, 趙耀東等人有遠見, 那麼核名求實至少讓官僚體系時時警惕, 國家機器可以正常運轉, 如果連最起碼的核名求實做不到, 當然滿地找螺絲呀! 更何況這是科長負責之事, 竟然還要閣揆管事, 這是誰在當家?

而記者本身更有問題, 中時這篇明顯是捧軟趴之文, 君不見 :

"與江有互動的友人說,江宜樺聰明絕頂,一切「點滴在心頭」。"

聰不聰明, 人民不清楚, 但記者做到這樣, 只能說噁心 (搞不好是江宜樺的學生哩).

Raspberry Pi 與物聯網平台 Yeelink

今天在找 Raspberry Pi 家庭監控資料時, 找到這個中國最大物聯網服務網站 Yeelink, 他是一個開放的物聯網開發平台, 提供豐富 API, 配合 Raspberry Pi 可以做各種物聯網應用.

我覺得 Raspberry Pi 非常適合作為物聯網的智慧終端, 因為 :
  1. 價格低 ($35, 低於台幣 NT$950)
  2. 功能強 (Linux + Python/Java + 網路)
  3. 體積小 (僅信用卡大小)
  4. 功耗低 (僅 3.5 瓦)
  5. 應用廣 (可軟可硬, 有 GPIO 可與 Arduino 等互聯)
真是一個偉大的發明啊! 特別是非常適合做為資訊紮根的工具, 例如偏鄉多為經濟弱勢, 無預算採購 Wintel 高價電腦 (一台至少要 10000 元), 如果採用 RPi 只要 1000 元就可以了 (價錢差 10 倍), 不管是學校或家庭, 負擔都減輕許多, 而且學生不但可以學到文字模式為主的 Linux 操作, 視窗模式的 email 收發與上網都沒有問題. 我概算一下最小系統大約 4000 元出頭 :
  1. Raspberry Pi 主板 : $950
  2. 液晶螢幕 : $2600 (若用電視螢幕則不需要)
  3. 鍵盤滑鼠組 : $500
  4. SD 卡 : $200 (裝 Linux 作業系統)
這樣只要 $4250 就搞定了, 若使用家裡的電視螢幕, 則只要 $1650 即可. 如果買一般電腦, 全套就要 $14000 以上囉. 我比較在意的是資訊紮根工作, 國家需要的是軟實力與硬實力兼具的人才, 而不是只會上網聊天打電動, 只要 4000 元就可以開始教小朋友們寫程式了, 這樣的工作, 國家有在做嗎?

Raspberry Pi 能做什麼(5/6):做為家庭監視系統主機
# 树莓派+USB摄像头+Yeelink--5分钟内DIY你自己的家庭监控
維基 : 物聯網 (Internet Of Things)
# IThome : 物聯網技術大剖析
# 物聯網工程師認證  (底下有參考資料連結)
# GS1 Taiwan 物聯網認證
# 关于 Raspberry Pi 的 30+ 个超酷的点子
# 监控报警系统-Raspberry Pi和Arduino的完美结合
# 教你用Raspberry Pi通过usb摄像头实现网络监控功能
# 少年 Raspberry Pi 的奇幻漂流開箱文
# Raspberry Pi vs MK802 (這我也有一台)
# 使用树莓派来做家庭安全告警器 (RPi 相容的 webcam 型號)
# Raspberry Pi – Simple Home Security System

2014年1月6日 星期一

忘情水

今天整理給二姨媽的 mp3 播放器時, 聽到其中劉德華的 "忘情水", 思緒頓時又跌回 20 多年前, 這首歌是弟弟以前很愛聽的一首歌. 轉眼一晃已過了 18 個年頭, 時光過得可真快啊.

小狐狸們以前曾問過我關于他們未曾謀面的叔叔, 我只說他消失在 29 歲的那年夏天, 直到前陣子在回鄉下的路上, 我才說得詳細些.

我一直把未能及時買給他一台電腦引為此生最大的遺憾, 看了建國路很多家電腦店, 想說再等看看會不會再降價, 如果當時就買了, 或許世界就不同了.

整理 e-mail

今早做完例行公事後, 便開始清理公司郵件, 已經累積近 3000 封, 全部轉存成檔案備考. 下午則整理 hinet 郵件, 一口氣從 98% 降到 28%, 刪掉一大堆垃圾.

28% 要再成長到 100% 爆掉應該會撐一段很長時間了, 吁 !


2014年1月5日 星期日

淡淡幽情的戀戀風塵

本週的公視人生劇展播侯孝賢的戀戀風塵, 節奏有點慢, 散發一種淡淡幽情, 我很喜歡這種文學味的電影. 女主角辛樹芬即悲情城市女主角, 但我看過就忘了.

這部戲是吳念真的自傳, 描寫從青少年到當兵那一段成長的故事. 與青梅竹馬的女朋友阿雲 (辛素芬) 中學畢業後到台北工作, 本來就是兩家內定的親事, 卻在去金門當兵時, 退伍前半年遭遇兵變, 阿雲跟每天送情書的郵差公証結婚了. 這是以前多少台灣青年的共同記憶呢? 我當兵時就聽過不少這類故事, 有些是很悲情的, 所以我當值星官時對這種問題特別敏感, 很注意衛兵與安官的感情問題. 以前在金門的時候, 我就知道輔導長會偷看阿兵哥的信, 有一次進去輔導長室很巧就被我碰到他正在小心翼翼地拆信.

我們鄉下也聽過不少兵變的悲傷故事, 大都是站衛兵時想不開開槍的. 真傻ㄚ, 又不是以後都娶不到老婆, 死心眼. 戀戀風塵中的阿遠在輔導長幫忙下, 獲營長特准回台看看, 但阿遠臨行前突然決定不回去了, 他說 : 回去了也是別人的老婆了. 如果是你的, 你放手, 她還會回來, 如果不是你的, 留在身邊又有何意義? 阿遠決定放手, 雖然苦澀, 但是卻成長了.

看到一半時, 剛好調音師來了, 所以中間一段沒看到, 可惜. 鄉下這台老鋼琴有三個鍵不靈光, 剛好童先生週日有空到鄉下, 請他調音順便整理.

# 好電影
曼哈頓的東村 部落格

2014年1月4日 星期六

可惡的 Mystart

今天又被一個瀏覽器綁架軟體 Mystart 搞得很火, 因為我在 Firefox 每開一個新分頁, 就顯示 Mystart 搜尋, 把我預設的 Google 給幹掉了, 我到 Firefox 的選項與 plugin 中檢查, 一切正常, 到控制台的服務中去找也沒看到蹤跡, 到底躲在哪裡?

搜尋網路, 果然這傢伙惡名昭彰, 一大堆 how to remove mystart. 我在這篇底下找到解法 :

# https://support.mozilla.org/zh-TW/questions/930367

原來方法很簡單, 先在網址列敲 about:config, 會顯示一個警告, 要你別亂搞, 按 "我發誓一定會小心" 鈕, 然後在搜尋框輸入 "mystart" 按 enter, 馬上就找到賊影了, 我是找到三筆, 雙點右邊的值, 按 "重設" 還原即可成功幹掉 Mystart 矣. 


2014年1月3日 星期五

漲價了

今天去喜多園吃晚飯, 一看菜單才發現漲價了, 各類炒飯全面漲 10 元, 五個人就比平常多了 50 元, 接著正忠排骨該不會又要漲了吧? 去年才漲一波呢!

馬英九, 感謝您, 上任五年多, 萬物皆漲, 除了您的荷包, 大家的荷包都沒漲. 你唯一的政績就是 : 漲價.

無能真的比貪污更可恨.


2014年1月2日 星期四

ExtJS 4 測試 : 類別與物件

Javascript 是一個 classless (無類別) 的語言, 本質上屬於函數式語言 (functional), 雖然有內建物件, 也可以自訂物件, 但那是透過 prototype 來實作, 所以只能算是 prototype-based 的物件導向, 不是像 Java 那樣的純粹物件導向語言 (class-based). 

ExtJS 利用 Javascript 的 prorotype 物件模擬 (emulate) 出一個像 Java 那樣的跨平台物件導向用法的框架, 它是眾多 Javascript 框架中, 極少數為熟悉物件導向開發者而設計的 API, 其函式庫是模仿 Java 用套件 (package) 與類別 (class) 組織起來的, 對已熟悉物件導向的程式設計者而言, 以 ExtJS 做為前端網頁架構, 在學習上較容易上手.

ExtJS 在第四版重新設計了其類別系統, 結構上與 ExtJS 3 有所不同, 而且添加了新的功能. 但為了向後相容 (backwar compatible), 也利用別名 (alias 或 AlternateClassName) 來讓 ExtJS 3 程式能以最低痛苦指數移植到 Ext JS4. 其 API 文件與類別相關原始碼如下 :

http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.MessageBox
Ext.Base 原始碼
Ext.ClassManager 原始碼

類別與套件命名方式

ExtJS 4 的基礎類別為 Ext.Base, ExtJS 的所有類別均繼承自 Ext.Base.

ExtJS 的類別名稱以大寫字母開頭, 駝峰格式命名 (camel case), 例如 :

Ext.ComboBox
Ext.TabPanel
Ext.LocalStorage

Ext JS 內建了許多類別, 每一個都是以 "Ext." 開頭. Ext 是所有內建類別的根命名空間 (root name space), 它是一個 Javascript 全域物件 (global object), 用來裝載全部的 ExtJS 4 內建類別. 事實上, 在 API 的 src 目錄下的 Ext.js 原始碼第一行即定義 :

var Ext = Ext || {};

所以 Ext 一開始就是個空物件 {}, 然後才定義其各項屬性與方法.

ExtJS 4 所有內建類別均以 Java 的階層式套件方式管理, 實際上就是反映各類別的 js 原始檔在目錄結構中的存放位置, 例如負責向伺服器取得後台資料的 Ext.data.proxy.Ajax 類別, 其原始碼 Ajax.js 就放在 \src\data\proxy 下, 而 "Ext.data.proxy" 就是 Ajax 類別的命名空間, data 稱為一個套件 (package), proxy 是子套件 (sub-package).


大部分的 ExtJS 內建類別都分門別類放在套件中, 亦即放在較低階層的名稱空間裡, 但有一部份的屬性與公用函式是直接放在 Ext 這個根名稱空間下面, 例如判斷瀏覽器版本的  Ext.isIE9 屬性, 定義類別的 Ext.define() 方法與建立物件的 Ext.create() 方法等等.

如何定義類別與建立物件

撰寫 ExtJS 程式的過程其實就是創造自己的類別 (不繼承內建元件類別), 或者利用 ExtJS 的內建類別衍生出我們自己的類別 (繼承內建元件類別), 再以此自訂類別為模子, 壓製出所需之物件來建構應用程式. 所以, 物件導向的程式設計就像玩樂高堆積木一樣, ExtJS 已經幫我們準備好形形色色的積木, 我們要學習的, 就是如何從箱子裡找到合用的積木來實現想像力.

ExtJS 4 的新類別系統已經改用 Ext.define() 方法來定義類別, 取代 ExtJS 3 所使用的 Ext.extend(); 而建立物件則改用 Ext.create() 方法, 取代 ExtJS 3 所用的 new. 

Ext.define() 事實上是 Ext.ClassManager.create() 方法的別名, 而 Ext.create() 則是 Ext.ClassManage.instantiate() 方法的別名. 當我們用 Ext.define() 定義一個類別時, 在 ExtJS 內部事實上是呼叫  Ext.ClassManager.create() 方法來建立一個 Ext.Class 類別的實體, 其建立過程是將我們傳入之參數分成 pre-processing (前處理) 與 post-processing (後處理) 兩階段 :


我們可以呼叫 Ext.Class 類別的 getDefaultPreprocessors() 方法取得前置處理器名稱, 此方法會傳回一個陣列, 因此可以用 Ext.each() 來拜訪它 (關於迴圈的探討, 請參閱 : ExtJS 4 測試 : each 與 forEach 迴圈測試) :

前置處理http://mybidrobot.allalla.com/extjstest/preprocessor.htm [看原始碼]

      var pre="";
      Ext.each(Ext.Class.getDefaultPreprocessors(),
               function(item,index){
                 pre += "pre[" + index + "]=" + item + "<br>";
                 }
               );
      Ext.Msg.alert("Pre-processor",pre);


可見它會先解析類別名稱, 處理名稱空間之後再處理動態載入, 繼承, 靜態成員, 設定項, 混入類別, 以及類別別名. 而後置處理器名稱則可透過 Ext.ClassManager 類別的 defaultPostprocessors 屬性取得, 其值也是一個陣列 :

後置處理http://mybidrobot.allalla.com/extjstest/postprocessor.htm [看原始碼]

      var post="";
      Ext.each(Ext.ClassManager.defaultPostprocessors,
               function(item,index){
                 post += "post[" + index + "]=" + item +
"<br>";
                 }
               );
      Ext.Msg.alert("Post-processor",post);

 

新的類別系統有兩個好處 :
  1. ExtJS4 已經將宣告 Namespace 的功能整合到 Ext.define() 的第一參數中, ExtJS 4 會自動偵測並建立 Namespace, 因此不需要再像 ExtJS 3 那樣, 在定義類別之前先呼叫 Ext.namespace() 來宣告名稱空間. 同時, 若有繼承其他類別時, 類別管理器會自動檢查類別的相依關係, 不用再擔心類別的載入順序. 
  2. 使用 Ext.create() 會在物件實體化前, 自動載入與類別相依的全部 Javascript 檔案, 這種功能稱為動態載入 (dynamic loading). 雖然 ExtJS 3 使用的之 new 仍然可用, 但是這樣就無法使用 ExtJS 4 新類別系統的動態載入功能.
類別的定義語法格式為 :

Ext.define("MyApp.package.subPackage.MyClass",
                     {  //在此定義類別之屬性, 方法, 以及繼承關係  }
                      );

建立物件的語法格式為 :

var myObj=Ext.create("MyApp.package.subPackage.MyClass", [config]); 


Ext.define() 的第一個參數是個字串, 用來宣告類別的全名, 完整的名稱建議包括應用程式名稱 (MyApp), 套件名稱 (package), 子套件名稱 (subPackage), 以及類別名稱 (MyClass), 以點號串接. 其中前面的 MyApp.package.subPackage 稱為類別 MyClass 的名稱空間 (name space), 用來管理類別結構, 區隔其他同名類別避免衝突. 多層次的名稱空間可以降低衝突的機率.

ExtJS 4 採用字串 (string-based) 為基礎的方法來定義名稱空間與類別, ExtJS 框架會自動將此字串解析出名稱空間與類別, 再進行類別之建立程序. 命名習慣是除類別用首字母大寫的駝峰字外, 其他均用首字母小寫的駝峰字 (如套件名稱, 屬性與方法名稱), 名稱應僅由字母與數字組成 (但不可用數字開頭), 不要使用符號.

注意, 使用 Ext.define() 定義類別時, 名稱空間不是必要的, 亦即 Ext.define("MyClass") 也是合法的, 但當類別增多時可能會有同名衝突問題.

Ext.define() 的第二個參數是類別內容, 以 JSON 物件實體來宣告類別的屬性 (property) 與方法 (method), 方法是用函式來定義. 定義類別可以想成是打造一個紅龜粿的模子, 而建立物件就是用這模子來製作紅龜粿.

Ext.create() 方法的第一個參數是傳入類別名稱, 第二個參數是用來設定屬性的物件, 會傳給建構子 (constructor) 設定各屬性之值, 但它是備選 (optional) 參數. config 物件格式如下 :

var config={property1:value1, property2:value2, ....}

呼叫 Ext.create() 方法時, ExtJS 會先判斷傳入的第一參數是不是 ExtJS 的內建類別 (搜尋內建類別表), 如果沒找到, 那就是自訂類別, 這時就要拆解名稱空間, 然後去 Ext.global 屬性中去找之前是否有用 Ext.define() 定義過此類別.

下列範例 1 展示如何自訂一個類別, 並依此建立其物件 (又稱為實例, instance) :

測試範例 1 : http://mybidrobot.allalla.com/extjstest/class_1.htm [看原始碼] 

      Ext.define("MyApp.Users",{
        account : "Tony",
        password : "12345",
        email : "tony@abc.com",
        getInfo : function(){
           return "account=" + this.account + " " +
                      "password=" + this.password + " " +
                      "email=" + this.email;
           }
        });
      var user1=Ext.create("MyApp.Users");
      Ext.Msg.alert("訊息",
                              "Hello! " + user1.account,
                              function(){Ext.Msg.alert("訊息",user1.getInfo());}
                              );



這裡我們宣告了三個屬性 (又稱為欄位, field) : account, password, email, 與一個方法 getInfo(). 當我們建立此類別的物件 user1 後, 就可以用點符號存取其屬性與方法. 在上例中, 我們用 user1.account 取得其帳號屬性值, 用 user1.getInfo() 呼叫其方法, 然後以兩層 ExtJS 訊息框顯示結果, 關於訊息框用法, 請參考 :

# ExtJS 4 測試 : 對話框與進度條

類別別名 alias

我們也可以用 alias 屬性為類別取一個簡短的別名, 這樣在建立物件時就可以不需敲這麼長的全名, 如下範例 1-1 所示 :

測試範例 1-1http://mybidrobot.allalla.com/extjstest/class_1_1.htm [看原始碼]

      Ext.define("MyApp.Users",{
        alias:"Users",
        account:"Tony",
        password:"12345",
        email:"tony@abc.com",
        getInfo:function(){
          return "account=" + this.account + " " +
                 "password=" + this.password + " " +
                 "email=" + this.email;
          }
        });
      var user1=Ext.create("Users");
      Ext.Msg.alert("訊息","Hello! " + user1.account,
                    function(){
                      Ext.Msg.alert("訊息",user1.getInfo());
                      }
                    );

上例顯示經 alias 指定 MyApp.Users 之別名為 Users 後, 就可以用 Users 來建立物件了.


建構子 (Constructor)

建構子是建立物件時第一個被呼叫的方法, 用來設定物件屬性的初始值 (所以叫做建構子). 在上面範例 1 中, 我們在定義類別時就預設其屬性值為特定值了, 雖然這沒啥不對, 這對於類別是一個一般化的模子這概念而言, 似乎不夠一般啊! 帳號為什麼不用 Peter, 偏要用 Tony?, 用空字串不是更一般嗎?

比較自然的方式是將預設值設為空字串, 再用建構子方法來設定屬性值. 在 ExtJS 4 中, 建構子方法是用特定屬性名稱 constructor 設定, 此方法傳入一個屬性設定物件 config, 也就是用Ext.create() 方法建立物件時所傳入的第二個參數, 再用 this (表示物件本身) 來設定屬性值, 其語法如下 :

constructor : function(config) {
   this.property1=config.property1,
   this.property2=config.property2,
   .....
   }

我們將範例 1 改為範例 2 如下 :

測試範例 2http://mybidrobot.allalla.com/extjstest/class_2.htm [看原始碼] 

      Ext.define("MyApp.Users",{
        account : "",
        password : "",
        emai l: "",

        getInfo : function(){
          return "account=" + this.account + " " +
                     "password=" + this.password + " " +
                     "email=" + this.email;
          },
        constructor : function(config){
          this.account=config.account;
          this.password=config.password;
          this.email=config.email;
          }

        });
      var user1=Ext.create("MyApp.Users",
                                       {account:"Tony",
                                         password:"12345",
                                         email:"tony@abc.com"
                                         }

                                      );
      Ext.Msg.alert("訊息","Hello! " + user1.account,
                             function(){
                                Ext.Msg.alert("訊息",user1.getInfo());
                                }
                             );

結果與範例 1 一樣, 但使用 constructor 來初始化物件比較有 OO 感, 這樣在建立物件時, 傳入不同的設定物件, 就會得到不同屬性的物件, 比較符合類別是一個模子的觀念. 注意, constructor 方法中的參數 config 就是 Ext.create() 方法所傳入的第二個參數.

其實, 初始化參數也可以不用 config 物件形式, 而是直接依序傳進去, 如下列範例 2-1 所示 :

測試範例 2-1http://mybidrobot.allalla.com/extjstest/class_2_1.htm [看原始碼]

      Ext.define("MyApp.Users",{
        account:"",
        password:"",
        email:"",
        getInfo:function(){
          return "account=" + this.account + " " +
                 "password=" + this.password + " " +
                 "email=" + this.email;
          },
        constructor:function(account,password,email){
          this.account=account;
          this.password=password;
          this.email=email;
          }
        });
      var user1=Ext.create("MyApp.Users","Tony","12345","tony@abc.com");
      Ext.Msg.alert("訊息","Hello! " + user1.account,
                    function(){
                      Ext.Msg.alert("訊息",user1.getInfo());
                      }
                    );

但不建議用此方式, 因為 create() 方法中的引數必須與 constructor 中的參數一一對應, 當屬性多時就容易混淆, 還是用上面範例 2 的 config 物件較明確.

設值器與取值器 (setter & getter)

在上面的例子中, 我們用 user1.account 來取得物件的屬性值, 在物件導向設計中, 應該透過 API (也就是 setter 與 getter 方法) 來存取屬性, 而非利用點號直接存取屬性. 設值器與取值器功能很簡單, 前者是用 this.property=value 來設定屬性值; 而後者則是用 return this.property 傳回屬性值. 如下範例 2-2 所示 :

測試範例 2-2http://mybidrobot.allalla.com/extjstest/class_2_2.htm [看原始碼]

      Ext.define("MyApp.Users",{
        account:"",
        password:"",
        email:"",
        getInfo:function(){
          return "account=" + this.account + " " +
                 "password=" + this.password + " " +
                 "email=" + this.email;
          },
        getAccount:function(){
          return this.account;
          },
        constructor:function(config){
          this.account=config.account;
          this.password=config.password;
          this.email=config.email;
          }
        });
      var user1=Ext.create("MyApp.Users",
                           {account:"Tony",
                            password:"12345",
                            email:"tony@abc.com"
                            }
                           );
      Ext.Msg.alert("訊息","Hello! " + user1.getAccount(),
                    function(){
                      Ext.Msg.alert("訊息",user1.getInfo());
                      }
                    );


但是建構子方法裡面一大堆 this 實在很囉唆, 因此 ExtJS 4 引進了一個 initConfig() 方法, 讓我們只要在 constructor 方法中呼叫此方法, 就會自動幫我們初始化物件之屬性. 但是有一個條件, 所有的類別屬性都要放到名為 config 的屬性中, 這樣 initConfig() 方法才能找到要設定的對象, 如下列範例 3 所示 :

測試範例 3 : http://mybidrobot.allalla.com/extjstest/class_3.htm [看原始碼]

      Ext.define("MyApp.Users",{
        config:{
          account:"",
          password:"",
          email:""
          },
        getInfo:function(){
          return "account=" + this.account + " " +
                    "password=" + this.password + " " +
                    "email=" + this.email;
          },
        constructor:function(config){
          this.initConfig(config);
          }
        });
      var user1=Ext.create("MyApp.Users",
                           {account:"Tony",
                            password:"12345",
                            email:"tony@abc.com"
                            }
                           );
      Ext.Msg.alert("訊息","Hello! " + user1.account,
                    function(){
                      Ext.Msg.alert("訊息",user1.getInfo());
                      }
                    );

可見用 config 與 initConfig() 後, 程式碼就簡潔多了, 也較省工, ExtJS 4 已經背後幫我們搞定初始化工作了. 但是切記類別的全部屬性都要放在 config 屬性中宣告, 否則 initConfig() 的初始化會破功 (雖然程式沒有語法錯誤), 如下列範例 3-1 所示 :  

測試範例 3-1 : http://mybidrobot.allalla.com/extjstest/class_3_1.htm [看原始碼] (無效)

除了呼叫 initConfig() 方法外, 也可以在建構子內呼叫 Ext.apply(this, config) 方法來初始化物件, 此 apply方法會將傳進來的設定物件 config 複製到物件本身 this, 也能達成初始化效果, 如下列範例 3_2 所示 :


測試範例 3-2http://mybidrobot.allalla.com/extjstest/class_3_2.htm [看原始碼]

        constructor:function(config){
          Ext.apply(this,config);
          }


使用 config 設定物件來初始化的好處不只是這樣, ExtJS 還會自動替每一個放在 config 裡面的屬性產生 setter 與 getter 方法, 其名稱就是 setProperty(value) 與 getProperty(), 如下面範例 4 所示 :


測試範例 4http://mybidrobot.allalla.com/extjstest/class_4.htm [看原始碼]

      Ext.define("MyApp.Users",{
        config:{
          account:"",
          password:"",
          email:""
          },
        constructor:function(config){
          this.initConfig(config);
          }
        });
      var user1=Ext.create("MyApp.Users",
                           {account:"Tony",
                            password:"12345",
                            email:"tony@abc.com"
                            }
                           );
      var info1="account=" + user1.getAccount() + " " +
                      "password=" + user1.getPassword() + " " +
                      "email=" + user1.getEmail();
      user1.setAccount("Peter");
      user1.setPassword("54321");
      user1.setEmail("peter@xyz.com");

      var info2="account=" + user1.getAccount() + " " +
                      "password=" + user1.getPassword() + " " +
                      "email=" + user1.getEmail();
      Ext.Msg.alert("info1",info1,
                    function() {
                      Ext.Msg.alert("info2",info2);
                      }
                    );



上例中先以 getter 取得物件建立時初始化所設定之使用者資訊, 接著用 setter 去修改物件屬性. 我們並沒有特地寫 setter 與 getter 方法, 但卻可以呼叫每一個屬性之設值與取值方法, 這都是在建構子方法中呼叫 initConfig() 或 Ext.apply() 時自動幫我們加上去的.  

接著我們要測試靜態成員 (Static Members),包含靜態屬性與靜態方法. 靜態成員是屬於類別的, 直接使用類別名稱存取, 不需要建立物件實體. 所有此類別所建立的全部物件實體都共用靜態成員, 因此一個物件更改了靜態成員之值, 其他物件也受到影響, 因為它們共用一個ExtJS 4 的靜態成員使用 statics 屬性宣告, 格式如下 :

statics : {
  staticProperty1 : value1, 
  staticProperty2 : value2,
  ...
  staticMethod1 : function() {...}, 
  staticMethod2 : function() {...},
  ...
  }

我們將範例 4 改為如下範例 4-1, 加入一個設定總使用者數目的靜態屬性 :

測試範例 4-1http://mybidrobot.allalla.com/extjstest/class_4_1.htm [看原始碼]

      Ext.define("MyApp.Users",{
        config:{
          account:"",
          password:"",
          email:""
          },
        statics:{
          totalUsers:0,
          resetTotalUsers:function(){
            this.totalUsers=0;
            }
          },
        constructor:function(config){
          this.initConfig(config);
          this.self.totalUsers++;

          //this.statics().totalUsers++; //用 this.statics() 亦可
          }
        });
      var user1=Ext.create("MyApp.Users",
                           {account:"Tony",
                            password:"12345",
                            email:"tony@abc.com"
                            }
                           );
      var user2=Ext.create("MyApp.Users",
                           {account:"Peter",
                            password:"54321",
                            email:"peter@abc.com"
                            }
                           );
      var info="totalUsers=" + MyApp.Users.totalUsers;
      Ext.Msg.alert("info",info,callBack);
      function callBack(info){
        MyApp.Users.resetTotalUsers();
        var info="totalUsers=" + MyApp.Users.totalUsers;
        Ext.Msg.alert("info",info);
        }




上例中, 我們用 statics 宣告了一個靜態屬性 totalUsers, 用來記錄總用戶人數, 也定義了一個靜態方法 resetTotalUsers() 用來將 totalUsers 歸零. 在建構子方法中, 可用 this.self 來取得類別本身的參考, this.self.totalUsers 即取得此靜態變數, 然後將其增量. 因此每次呼叫 Ext.create() 建立一個物件實體時, 靜態變數 totalUsers 就會加 1. 我們使用類別名稱 MyApp.Users 直接存取靜態變數與方法, 並於 Ext.Msg.alert() 的回呼函式中, 呼叫靜態方法 resetTotalUsers() 將 totalUsers 歸零. 關於對話框請參閱 "ExtJS 4 測試 : 對話框與進度條".

這裡值得一提的是 this 與 self 這兩個會令人感到疑惑的關鍵字. 在 Javascript 中, this 表示目前的物件, 上例中 statics 屬性之值為一個物件實例, 所以在其內部方法 resetTotalUsers() 裡要存取自己物件的 totalUsers 屬性時就要用 this, 這個 this 指的就是 statics 這個物件. ExtJS 4 的 this 就是 Javascript 的 this, 代表目前物件的參考, 指向一個物件實例. 但是在建構子方法 constructor 中, this 指的卻是一個 MyApp.Users 物件, 因為建構子不是 statics 物件的成員, 要存取 statics 物件之成員必須透過類別本身, 所以 ExtJS 4 創造了一個 self 來指涉一個物件所屬類別的參考 (跟 Java 的 getClass 方法類似), this.self 就是指向此物件之類別本身  (事實上就是一個 Ext.Class 物件). 每次用 Ext.create() 建立物件實例時, ExtJS 都會在每一個實例中建立一個指向其類別之 self 參考. 注意, this 與 self 都是在類別內部使用, 在類別外部要用類別名稱來存取靜態成員. 

上面提到靜態成員屬於類別, 那靜態成員可不可以用物件實體來存取呢? 答案是不行的, 讀取屬性會得到 undefined, 用物件呼叫方法則會報出 "Uncaught Type Error (無此方法)",  如下列範例 4-2 所示 :

測試範例 4-2http://mybidrobot.allalla.com/extjstest/class_4_2.htm [看原始碼]

      Ext.define("MyApp.Users",{
        config:{
          account:"",
          password:"",
          email:""
          },
        statics:{
          totalUsers:0,
          resetTotalUsers:function(){
            this.totalUsers=0;
            }
          },
        constructor:function(config){
          this.initConfig(config);
          this.statics().totalUsers++;
          }
        });
      var user1=Ext.create("MyApp.Users",
                           {account:"Tony",
                            password:"12345",
                            email:"tony@abc.com"
                            }
                           );
      var user2=Ext.create("MyApp.Users",
                           {account:"Peter",
                            password:"54321",
                            email:"peter@abc.com"
                            }
                           );
      var info="user1.totalUsers=" + user1.totalUsers + "<br>" +
                    "user2.totalUsers=" + user2.totalUsers;
      Ext.Msg.alert("info",info);





可見, 靜態成員是屬於類別的, 不屬於物件.

接著要測試物件導向最重要的特性 : 繼承, 與此相關的設定屬性為 extend 與 mixins.

繼承 (inheritance) : extend 與 mixins

物件導向訴求元件的重用性 (reusable), 亦即 "不重新打造輪子", 最重要的特性便是繼承機制. C++ 允許多重繼承, Java 為了避免混淆與複雜而採用單一繼承, ExtJS 4 也是單一繼承, 其 extend 屬性僅能指定一個類別名稱 (字串而非陣列), 但透過 mixins 屬性卻擁有多重繼承的效果 , 可指定要從哪些類別 (字串陣列或物件) 複製其屬性與方法.

首先, 我們來測試 extend 屬性的用法, 此屬性值為所要繼承之類別名稱 (字串), 如下面範例 5 所示 :

測試範例 5http://mybidrobot.allalla.com/extjstest/class_5.htm [看原始碼]

      Ext.define("Myapp.Vehicle",{    //父類別
        config:{
          onwhere:"land",  //land,air,water,space
          power:"oil"      //oil,electric,hybrid,wind,human,animal
          },
        constructor:function(config){
          this.initConfig(config);
          },
        move:function(dir){return "Vehicle is moving " + dir + "..."},
        turn:function(dir){return "Vehicle is turning " + dir + "..."},
        stop:function(){return "Vehicle stops."}
        });
      Ext.define("Myapp.Car",{  //子類別
        extend:"Myapp.Vehicle",  //繼承
        config:{
          type:"van", //sports,van,truck
          wheels:4
          },
        constructor:function(config){
          this.initConfig(config);
          },
        move:function(dir){return "Car is moving " + dir + "..."},
        turn:function(dir){return "Car is turning " + dir + "..."}
        });
      var myCar=Ext.create("Myapp.Car",
                           {type:"sports",
                            wheel:4,
                            power:"hybrid"
                            }
                           );
      var info="type=" + myCar.getType() + "<br>" +
               "wheel=" + myCar.getWheels() + "<br>" +
               "power=" + myCar.getPower() + "<br>" +
               myCar.move("forword") + "<br>" +
               myCar.turn("right") + "<br>" +
               myCar.stop();
      Ext.Msg.alert("info",info);


在上例中, 我們定義了 Vehicle 與 Car 兩個類別, 其中 Car 有一個 extend 屬性指向 Vehicle, 表示繼承 Vehicle 的全部屬性與方法, 故 Car 是 Vehicle 的子類別, 當然也擁有了 move, turn, 與 stop 三個方法, 但是, 我們在 Car 類別中又重複定義了 move 與 turn 兩個方法, 這稱為方法覆蓋 (method override), 即新定義的方法將覆蓋繼承而來的同名方法. 當父類別的方法不合用時, 我們就可以透過 override 製作自己的方法. 因此上圖中呼叫此三方法時, 僅 stop 方法為執行父類別的 stop 方法, 顯示 "Vehicle stops".

緊接著我們要測試 mixins (混入), 這是物件導向中的一個觀念. 關於 Mixin 的說明, 可參考下列文章 :

  1. 維基百科 : Mixin 多重繼承
  2. 用 MIXIN 設計模式來作多重繼承
  3. 談多重繼承:Ruby 利用 Mix-in 實現多重繼承

要言之, 因為多重繼承 (例如 C++ 與 Python) 有容易造成混淆的缺點 (例如名稱的衝突), 比較複雜, 因此 Java 在實現繼承 (implement) 上採用單一繼承, 後來的 C#, Ruby 也都是單一繼承. 但是 Java 允許類別在抽象層面上可以實作多個介面 (interface), 利用此方式也可以達成多重繼承的功能. 而 Ruby 則用 mixin 來實現多重繼承, ExtJS 也是如此.

我們將範例 5 稍微改一下來測試 mixins 的功能, 如下範例 6 所示 :

測試範例 6http://mybidrobot.allalla.com/extjstest/class_6.htm [看原始碼]

      Ext.define("Myapp.Activity",{
        src:"mixin",
        move:function(dir){return "Act: moving " + dir + "..."},
        stop:function(){return "Act: stops"}
        });
      Ext.define("Myapp.Vehicle",{
        config:{
          onwhere:"land",  //land,air,water,space
          power:"oil"      //oil,electric,hybrid,wind,human,animal
          },
        constructor:function(config){
          this.initConfig(config);
          },
        move:function(dir){return "Vehicle is moving " + dir + "..."},
        });
      Ext.define("Myapp.Car",{
        extend:"Myapp.Vehicle",
        mixins:["Myapp.Activity"],
        config:{
          src:"Myapp.Car",
          type:"van", //sports,van,truck
          wheels:4
          },
        constructor:function(config){
          this.initConfig(config);
          },
        turn:function(dir){return "Car is turning " + dir + "..."}
        });
      var myCar=Ext.create("Myapp.Car",
                           {type:"sports",
                            wheel:4,
                            power:"hybrid"
                            }
                           );
      var info="type=" + myCar.getType() + "&ltbr>" +
               "wheel=" + myCar.getWheels() + "&ltbr>" +
               "power=" + myCar.getPower() + "&ltbr>" +
               myCar.move("forword") + "&ltbr>" +
               myCar.turn("right") + "&ltbr>" +
               myCar.stop() + "<br>" +
               myCar.mixins.src + "<br>" +
      Ext.Msg.alert("info",info);


在上例中, 我們新定義了一個類別 Activity, 含有一個屬性 src 與兩個方法 : move() 與 stop(). 在定義 Car 類別時, 我們用 mixins 屬性指定混入之類別名稱 MyApp.Activity. 因為 ExtJS 採單一繼承, 所以 extend 屬性值為一個字串 (而非陣列或物件), 故只能指定一個父類別; 但是 mixins 屬性值則為一個陣列 (或物件), 可以指定要混入之多個類別.

要注意的是, mixins 雖然能夠達到類似多重繼承的功效, 但是它跟繼承還是不完全一樣 : 混入的類別屬性與方法不會覆蓋原有的成員, 例如上面的 Car 類別從 Vehicle 繼承了 move() 方法, 也從 Activity 類別混入 move() 方法, 但是呼叫 move() 時卻是呼叫從 Vehicle 繼承來的方法. 在屬性方面]也是一樣, Car 與 Activity 都有 src 屬性, 但是讀取 myCar.src 時卻讀到 Car 的 src.

總之, mixins 最主要的功能就是能使用其他類別的屬性與方法, 達到程式碼重用之目的, 彌補 extend 只能繼承單一類別的缺點. 但是 mixins 的類別沒有 override 功能, 因此存取同名的成員時不會存取到對混入的成員, 如果要存取混入類別的成員該怎麼做呢? 這時 mixins 屬性必須用物件, 這樣混入之類別就會有一個 key, 透過此 key 便可存取混入之類別成員了. 我們將範例 6 稍作修改為下列範例 7 :

測試範例 7http://mybidrobot.allalla.com/extjstest/class_7.htm [看原始碼]

      Ext.define("Myapp.Activity1",{
        move:function(dir){return "Act1: moving " + dir + "..."}
        });
      Ext.define("Myapp.Activity2",{
        stop:function(){return "Act2: stops"}
        });
      Ext.define("Myapp.Vehicle",{
        config:{
          onwhere:"land",  //land,air,water,space
          power:"oil"      //oil,electric,hybrid,wind,human,animal
          },
        constructor:function(config){
          this.initConfig(config);
          }
        });
      Ext.define("Myapp.Car",{
        extend:"Myapp.Vehicle",
        mixins:{act1:"Myapp.Activity1",act2:"Myapp.Activity2"},
        config:{
          src:"Myapp.Car",
          type:"van", //sports,van,truck
          wheels:4
          },
        constructor:function(config){
          this.initConfig(config);
          },
        move:function(dir){return "Car is moving " + dir + "..."},
        turn:function(dir){return "Car is turning " + dir + "..."}
        });
      var myCar=Ext.create("Myapp.Car",
                           {type:"sports",
                            wheel:4,
                            power:"hybrid"
                            }
                           );
      var info="type=" + myCar.getType() + "<br>" +
               "wheel=" + myCar.getWheels() + "<br>" +
               "power=" + myCar.getPower() + "<br>" +
               myCar.move("forword") + "<br>" +
               myCar.turn("right") + "<br>" +
               myCar.stop() + "<br>" +
               myCar.mixins.act1.move("backward") + "<br>";
      Ext.Msg.alert("info",info);


上例中, 我們定義了兩個類別 Activity1 與 Activity2, 並混入 Car 類別中. 由於 Car 自己也定義了一個 move() 方法, 如上所述, 混入類別不會覆蓋已有之方法, 因此 myCar.move() 會呼叫 Car 類別自己的 move() 方法. 如果要呼叫混入類別之同名方法, 就必須用物件的 mixins 屬性與混入類別的 key 取得混入類別之實體, 再呼叫其方法, 例如 myCar.mixins.act1.move(), 這  act1 就是用物件宣告 mixins 類別時, 指定給該混入類別之 key. 事實上, 如果沒有這樣的用途時, mixins 的屬性值用陣列即可, 例如 :

mixins : ["class1", "class2", ... ]

OK, 現在回過頭來看看在繼承父類別時, 靜態成員會有何影響.

~~~未完待續~~~