2015年10月21日 星期三

在 Raspberry Pi 上使用和測試 XBee

這篇文章介紹把 XBee module 裝到 Raspberry Pi 上面的方法,並且使用 PC 上的 XCTU 軟體與 Node.js 測試它的連線。

硬體材料


下面是我們所需要的硬體材料:
  • 兩片 XBee module,請務必使用相同規格。
  • 四條杜邦線,母對母佳。
  • 一台樹莓派
  • 任何一種可以把 XBee module 連接上電腦的方法與材料。例如使用 SparkFun XBee Explorer,或是 Arduino XBee shield



PC端設定


在這裡我用的是Arduino XBee shield。把它如下圖的方式插好,接上電腦。注意有個開關會控制XBee的資料輸出,記得把它扳到USB那端去


另外,為了不讓 Arduino 裡的程式碼干擾 XBee 運作,請先燒錄 BareMinimum 範例程式,或是任何不會使用 serial console 輸出的程式碼。

測試軟體與模組設定


到 Digi International 的官方網站去,下載 XCTU 這套軟體。它有兩種版本,一個是較新的6.x.x版,有著比較漂亮好操作的介面,另一種是舊版的5.2.8.6。我們底下的說明以新版的6.2.0為主,而網路上有多數教學資源是使用舊版本。

打開 XCTU,點選主畫面左上的按鈕,新增 XBee Module。


如果你的模組有正確連接上 PC,它應該會以 COM port 的方式出現在列表中。點選正確的 COM port 後,按下 "Finish" 讓軟體連線。



順利連線後,可以在主畫面左側看到它。點選它會開始讀取它的出廠設定。我們可以在畫面右端看到許多設定,首先請特別注意下面幾個選項:

  • CH (Operating Channel):這是指 XBee module 的工作頻道。注意 XBee - 或者說 ZigBee/802.15.4 - 使用的是 2.4GHz,會跟 Wi-Fi / 802.11 衝突。如果環境中有 Wi-Fi 訊號,請改用不同頻道或是避開它。更多資訊請參考這裡
  • ID (Network ID):要互相通訊的XBee module,必須把此值都設定為相同。每個XBee module只會接收、轉發跟自己相同ID的訊息。
  • CE (Routing/Messaging Mode):在 ZigBee 的網路中,每個節點都會是 Coordinator、Router 或 End Device 其中之一。在這邊我們可以把 Module 都設定成 Router 以方便測試。
  • DH/DL (Destination Address):要通訊的端點位址。在單純一對一的通訊中,可以把此欄位設定為對端的 SH/DL (Source Address)值,雙方會以 unicast 的方式互通。如果把 DH 設定為 0,DL 設定為 FFFF,則封包會以廣播方式發送。在這邊我們把兩片 Module 都設定為廣播。
  • NI (Node Identifier):給 XBee module 取個名稱,方便辨識。

設定完成後,按下上方的鉛筆圖案,將設定寫入 XBee module。記得兩片 Module 必須要擁有相同的 CH、ID 值,並且要有適當的 DH/DL。




樹莓派端的準備工作


Raspberry Pi B+的接線方式如下圖,也就是分別是把XBee module的3.3V電源、Tx、Rx與Ground接到Raspberry Pi的對應腳位。如果你用的是不同的板子,請注意更換到對應的針腳。

Copyright https://dzone.com/articles/connecting-xbee-raspberry-pi

另外,在 Raspbian 中,UART  Tx/Rx 腳位預設是給 serial console 使用。我們要改接 XBee 的話,需要做出一些對應的修改。

首先編輯 /boot/cmdline.txt 檔案,把所有 ttyAMA0 相關的字眼都移除。最後檔案內容看起來會像這個樣子。

dwc_otg.lpm_enable=0 console=115200 console=tty1 root=/dev/mmcblk0p6 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

然後停用 tty console:
sudo systemctl stop serial-getty@ttyAMA0.service
sudo systemctl disable serial-getty@ttyAMA0.service


如果有在 /etc/initab 設定過 tty console,也記得拿掉任何會占用到 ttyAMA0 的服務。

連線測試


我們會進行兩種測試,一種是測試雙方連線的訊號強度,另一種則是進行訊息的收發。

訊號強度測試


首先我們回到 XCTU,找到目前與PC連線中的裝置,再點旁邊的藍色小按鈕,軟體會自動搜尋網路上的其他節點。當全部跑完後,選擇我們要連線的對象,按下 "Add selected devices" 按鈕。




完成後,再到畫面上方點選工具箱按鈕,選擇 "Range Test"。


在下一個畫面中,分別在左側點選目前連線到 PC 的 Module,再到右側點選我們早先搜尋到的其他 Module。下面有些測試項目可以調整。我們使用 "Cluster ID 0x12" 這個測試方式。它會送出一串帶有 0x12 這個特殊 Cluster ID 的封包。收到這個 ID 封包的裝置,會將其收到的內容原封不動的送回。

最後,按下 "Start Range Test" 開始測試。畫面會顯示封包的丟失率,以及 RSSI 值等等。能成功跑完此測試代表我們的兩片裝置都能正常運作,連接的線路也都正確。



封包收發測試


我們接著在 Raspberry Pi 上面撰寫 Node.js 程式,用來收發封包。目標是在 XCTU 上收到 Raspberry 送過來的 XBee 封包,同時在 XCTU 也可以送出封包給 Raspberry Pi。

首先在 XCTU 上開啟 console 模式。點選右上角的電腦終端機符號,並在主畫面點選連線的符號。XCTU 就會跟 XBee module 建立終端機連線。



接著到 Raspberry Pi 這邊,先透過 NPM 安裝兩個必要套件:

npm install xbee-api serialport

如果安裝過程中出了錯誤,通常都是套件庫裡面沒有適合目前平台與 Node.js 版本的套件。請試著參考這篇,安裝新版的 npm 與 Node.js。

接著開啟任何你喜歡的文字編輯器,輸入下面這段程式碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var util = require('util');
var SerialPort = require('serialport').SerialPort;
var xbee_api = require('xbee-api');
var C = xbee_api.constants;

var xbeeAPI = new xbee_api.XBeeAPI({
    api_mode: 1
});
var serialport = new SerialPort("/dev/ttyAMA0", {
    baudrate: 9600,
    parser: xbeeAPI.rawParser()
});

serialport.on("open", function () {
    var frame_obj = { 
        type: 0x10, 
        id: 0x01, 
        destination64: "000000000000ffff",
        broadcastRadius: 0x00,
        options: 0x00, 
        data: "Hello world" 
    };  
    serialport.write(xbeeAPI.buildFrame(frame_obj));
    console.log('Sent to serial port.');
});

serialport.on('data', function (data) {
    console.log('data received: ' + data);
});

// All frames parsed by the XBee will be emitted here
xbeeAPI.on("frame_object", function (frame) {
    console.log(">>", frame);
});

此程式會以廣播方式,送出一個包含 "Hello World" 字串的封包,接著等待任何進來的封包,並在螢幕上顯示出來。我們直接以 node 指令執行這段程式碼。

回到 XCTU,應該可以看到以紅字顯示的訊息,這就是我們剛剛送來的封包。可以將整段封包內容全選複製起來,然後使用工具箱內的 "Frames Interpreter" 來檢視它的內容。



接著我們要產生封包送回去。打開工具箱內的 "Frames Generator" 工具。注意裡面要調整的參數:
  • Mode:選擇 API 1,我們上面的 Node.js 程式碼預期收到 API 1 格式的封包。
  • Frame Type:請選擇 "0x10 - Transmit Request"。
  • 64-bit dest. ID:請輸入000000000000FFFF,也就是廣播位址。
  • RF data:在ASCII這邊輸入你想要夾帶的訊息。
完成後,按下 "Copy Frame" 按鈕,將整個封包複製起來,再按下 Close 離開。





回到主畫面後,按下 Send Packet 欄位的小加號按鈕,切換到 HEX 模式後,貼上我們剛剛複製的內容。完成後,按下 Add Packet 離開。


最後一步了,在主畫面選擇我們剛剛建好的新封包,按下右側的 "Send selected packet" 按鈕。主畫面上會以藍字顯示我們剛剛丟出去的訊息。


回到 Raspberry Pi 上,它會將我們剛剛送出的訊息顯示出來,大功告成!



結論


這篇文章紀錄了我在 Raspberry Pi 上使用和測試 XBee module 的過程,包括一開始的接線到作業系統上的調整。同時也列出了使用 PC 軟體 XCTU 對兩片 XBee module 進行測試與設定的方法及步驟。我們除了可以使用 XCTU 內建的工具測試訊號強度以外,還可以使用文中附上的 Node.js 程式碼,測試封包發送與接收的能力。

參考資料


xbee-api on NPM, by jouz
https://www.npmjs.com/package/xbee-api
"Connecting XBee to Raspberry Pi", by Sony Arouje
https://dzone.com/articles/connecting-xbee-raspberry-pi
"XBee 模組通訊實驗", by 網昱多媒體
"XBEE S1 – Sending Remote AT commands using API packet to toggle an I/O", by alselectro

2015年10月15日 星期四

在Raspberry Pi上面安裝Node.js與MongoDB

這文章簡單記錄在Raspbian上面安裝Node.js與MongoDB的方式。


Node.js


Raspbian套件庫裡面的Node.js版本很舊,大約是0.10.x,無法符合許多新套件的需求。網路上可以找到很多安裝方式,但他們大多不可行。下面我只列出一個最簡單有用的方法。

wget http://node-arm.herokuapp.com/node_latest_armhf.deb
sudo dpkg -i node_latest_armhf.deb

這兩行指令會從node-arm.herokuapp.com這個網站下載打包好,供ARM使用的deb檔案,再用dpkg安裝它。

node的版本是4.0.0,npm版本是2.14.2。

MongoDB


官方沒有提供給ARM使用的版本,所以我們可以自己下載原始碼進行編譯,或是下載別人編譯好的檔案。

我們可以在這裡找到一個事先編譯好的版本:
https://github.com/brice-morin/ArduPi

直接使用mongodb-rpi/bin裡面的檔案即可。比較完整的指令為:

svn co https://github.com/brice-morin/ArduPi/tree/trunk/mongodb-rpi
sudo cp -r mongodb-rpi/mongo/ /opt/
sudo ln -s /opt/mongo/bin/* /usr/local/bin/

這幾行指令會先用svn下載我們要的檔案,把MongoDB的執行檔都安裝到/opt下面,再建立symbolic link,方便我們存取。

mongo的版本是2.1.1。

總結


網路上有很多在Raspbian安裝這兩樣東西的文章,但多數無法成功運作。在這邊把一個在我的板子上(Raspberry Pi B+)可以運作的方式記錄下來,供有需要的人參考。


(2016/3/16補充:關於 Node.js 在樹莓派上面的安裝方式,可以參考 http://swf.com.tw/?p=836 這篇文章,有許多詳細資訊。安裝 MongoDB 的方式,可以參考 http://swf.com.tw/?p=833)

2015年9月14日 星期一

快速建立與開放本地HTTP伺服器至網際網路

這篇文章簡單敘述如何使用node.js的http-server套件與ngrok,快速在本地端建立HTTP伺服器並公開至網際網路。

Copyright ngrok.com

快速建立HTTP伺服器


在開發網站的過程中我們經常需要建立HTTP伺服器進行測試。雖然在Linux上有很多HTTP伺服器套件可用,但他們大多需要相當繁複的設定。當只是在本地端進行初步開發之時,我們其實可以使用下面介紹的http-server,快速建立本地端伺服器。

我們先在本地端寫一個簡單的index.html網頁:


接著透過npm取得http-server套件
npm install -g http-server
安裝完後,在index.html的目錄下執行http-server



預設情況下,它會抓取當前目錄下的網頁,並在port 8080上建立伺服器。此時可用本地瀏覽器連到http://localhost:8080看看是否已經正確執行。

將本地伺服器開放到網際網路


在協同開發過程可能還會需要將此網站提供給他人使用,此時我們可以利用ngrok將本地網站開放到網路上。

首先先去ngrok的官方網站下載軟體。在這裡以Linux為例,將下載下來的zip檔解壓後,透過下面的指令執行:
./ngrok http 8080
這個指令會將本地port 8080的HTTP伺服器開放出去。執行後可以看到這個畫面:



其他人就可以透過圖中的這個網址連線到這台伺服器。


注意這個網域名稱是會改變的,也就是每次重新使用ngrok時都會產生不同的名稱。如果有固定域名的需求,可以利用ngrok的付費服務達成。

TL;DR:


npm install -g http-server
http-server ./
ngrok http 8080

透過http-server與ngrok,只要簡單的幾個指令,不需要繁複的設定就可以建立起HTTP伺服器,很適合開發階段使用

http-server套件的網頁,可以在這裡看更詳細的使用方式:

ngrok的官方網站:
https://ngrok.com/


(附註:使用python也可以快速建立HTTP server:python -m SimpleHTTPServer 8080)

2015年9月11日 星期五

遊戲中的二項式分佈

遊戲裡面常常有成功率這個東西,像是成功強化武器的機率、某個技能附加能力的發動機率、抽中稀有卡片的機率等等。大多時候,單看這個數字並沒有甚麼意思,我們反而比較會在意,到底在我成功以前我要失敗幾次、投入多少資源?

到底要嘗試幾次,在這其中至少有一次成功的機率才可以提升到50%以上?


以抽卡來說好了,假設抽一次有5%的機率會成功抽中稀有卡片,除此之外抽中非稀有卡片都算是失敗,而且每次抽卡結果都是獨立事件。那到底要連抽幾次,才能有50%以上的機會可以抽中一張稀有卡?

這種情況就可以套用二項式分佈。二項式分佈的一般性公式我們可以寫成:
 f(k;n,p) = \Pr(K = k) = {n\choose k}p^k(1-p)^{n-k}
其中,k代表目標成功次數,n代表測試總數,p代表單次測試的成功機率。

回到抽卡的例子,我如果要計算出,在 10 次測試裡面,抽中 0 張稀有卡的機率,其中單一抽抽中稀有卡的機率為 5% ,那麼套進去計算:



答案大約為59.9%,也就是有接近六成的機會,10 抽抽不到稀有卡。

那要怎麼計算至少一張的機率?很簡單,排除掉完全抽不到稀有卡的情況以後,剩下來的情況就代表有抽中至少一張。所以在這裡,有1 - 59.9% = 40.1%的機率會抽到至少一張。

用Excel列表


到這邊其實可以用Excel的 BINOMDIST 公式來幫我們計算。BINOMIDIST分別接受四個參數,其中前三個參數分別是k, n, p。第四個參數改變此函數的行為,如果為 0 ,表示計算正好為 k 次成功的機率;如果為 1 ,表示計算最多有 k 次成功的機率。


正確的成功率公式如上圖,紅圈圈起來的那格。

藉由Excel的功能,我們可以很輕鬆的增加 n 值,觀察在不同測試次數下的中獎機會。回到前面抽卡的例子,我們可以看出,在14次抽獎以後,抽中至少一張稀有卡的機率會提升到50%以上。

算這個要幹嘛?


知道了達成50%成功率的最小 n 值後,我們可以用它來估計所需要投入的資源成本,不管是虛擬貨幣還是新台幣,從而與得到的回報相比,判斷是否需要把珍貴的資源投入進去。

雖然我這裡以遊戲為例子,但這個計算可以套用到生活中的許多例子,希望供大家參考利用。

關於二項式分佈,可以參考以下網頁:
https://zh.wikipedia.org/wiki/%E4%BA%8C%E9%A0%85%E5%88%86%E4%BD%88
http://dufu.math.ncu.edu.tw/calculus/calculus_eng/node222.html

在Blogger新增Paypal捐贈按鈕

國外有些軟體作者會在個人網頁上面放上一個Paypal的捐贈按鈕,讓支持者可以自由選擇金額捐贈給作者。網路上可以找到一些教學:

不過,在Blogger這裡可以透過POWr提供的第三方小工具來嵌入捐贈按鈕,可以自訂外觀等等,相當方便。首先進入到Blogger的管理後台,選擇"版面配置",並在想要的位置按下"新增小工具"。


到"其他小工具"選項中,搜尋Paypal,應該可以看到POWr Paypal Button這個項目。按下加號新增它。


之後會跳出提示視窗,提醒你到網誌版面上直接點選編輯按鈕去修改它。不過我們可以先在這個提示視窗中,修改按鈕的標題與高度。這邊建議把高度改成約120px。


按下儲存離開,按鈕就會出現在網誌頁面上。我們接著要點選右上角的齒輪圖案去修改它。

第一步是輸入Paypal帳號。

第二步是可以自訂關於此按鈕的相關資訊,首先打開Product Info頁面,將付款類別改為Donation,並自訂其他內容。你可以自訂想要的捐款金額和貨幣,或者決定是否允許使用者自訂金額和商品數量。Button Text則是要顯示在按鈕上的文字。


第三步的Design可以修改此按鈕的顏色等等外觀設定,直接保留預設設定就好。

第四步是建議你註冊POWr帳號以取得更多外掛,可以自行決定要不要註冊。最後按下面的Save,儲存設定並離開。

恭喜,你的Blogger上有了這個捐贈按鈕。你可以試著點選它看看會發生甚麼事。

如果你跟我一樣是個新手,大概會遇到一個"資料與輸入的字元集或預設編碼不符。欲知更多資料,請聯絡商店。"的錯誤訊息。這邊有個網頁提供了解決方法:
http://wordpress.bestdaylong.com/blog/archives/6751

以上是我新增這個按鈕的小記錄,各位可以在右上角看到這個按鈕。但這篇文章發表之時,Paypal才剛宣布要在2015年9月21日之後,關閉台灣帳號之間的買賣交易。我想這個按鈕暫時只能拿來當作裝飾,等待Paypal重新開放交易吧。

關於Paypal停止台灣帳號之間的交易新聞,可以看這邊



2015年8月27日 星期四

第一個Pebble App - Where to Eat?

Convert?h=160&w=360

我的第一個Pebble App - Where to Eat 終於在昨天上架了。這個App的目標是為了解決人生中最重要的一個疑問:

晚餐到底要吃什麼?


它能在手錶上面顯示附近的餐廳名稱、距離及方向,更能進一步搜尋它們的地址電話等資訊。
Convert?h=168&w=144Convert?h=168&w=144Convert?h=168&w=144


更方便的是,它還可以從中自動幫你挑選一家,省去你下決定的時間。
Convert?h=168&w=144

方便的過濾條件


你可以在手錶上設定要尋找的範圍(最遠可以到以你為中心的10公里距離)、要尋找的餐廳類型,以及是否限定當下正在營業中的店家。這樣能更快為你找到適合的店家。
Convert?h=168&w=144


支援多種語言及多種平台


目前此App介面支援正體中文、簡體中文和英文。另外它支援Pebble、Pebble Steel和Pebble Time等目前市面上的Pebble手錶平台。同樣它也可以顯示彩色。

Convert?h=168&w=144Convert?h=168&w=144


下載連結


可以在Pebble的App Store裡面找到它。目前分類是在Tools & Utilities底下。
App Store的連結:
https://apps.getpebble.com/applications/55dd6d104374cb930300000d

本App為Open Source,可以在GitHub上找到它:
https://github.com/pychen0918/pebble-where-to-eat

歡迎大家給予批評與指教,謝謝!