2018年5月31日 星期四

樂拼馬達速度比較


為了拼砌出 Donkey car,我買了三套樂拼;其中兩套配備了中型馬達。從外觀看是一樣的,只是軸心的顏色有些微的分別。原本認為速度是一樣的,但緊慎起見,還是做了一個測試。由於兩顆馬達的速度很快,我用了細比大齒輪外,也利用了 iPhone 的慢鏡拍攝。片中左面的是橙色軸心馬達,右面是黑色軸心馬達,跟上圖對掉了。從片中可見,橙色的是快一些。

2018年5月30日 星期三


Raspberry Pi Zero 推出時,因它的體積細小,的確吸引。不過,機能卻差了,用來開發似乎力不到位。而且在香港不見它的影蹤...。

很久前買了一塊紅外線鏡頭模組,安裝到 Pi 2 後加裝了 3D 打印的外殻;由於不方便,基本上沒有拿出外拍照。上星期,決定在淘寶購買。希望利用 Zero W 的細小,加上官方的外殻,能隨時用它來拍照。拍照的話,Zero W 能夠勝任。

2018年5月27日 星期日

用 Arduino 控制樂拼伺服馬達


既然樂拼伺服馬達的接線造好了,接著是找出控制訊號的格式。我選了方便使用的 Arduino Nano 及用來方便切換馬達正負極的 L293D 來進行測試。


測試的概念是利用 Arduino Nano 的 D3 腳接 L293D 的 3,4EN 腳;D3 可以輸出 PWM 訊號,用來測試樂拼伺服馬達是否跟坊間的伺服馬達一樣,同樣使用 1.5ms 至 2.5ms 的方波訊號來決定角度。利用 Arduino Nano 的 D7 及 D8 接到 L293D 的 3A 及 4A。這兩隻腳的 HIGH, LOW 決定馬達順轉或 LOW, HIGH 逆轉。


把樂拼伺服馬達的 9V 接到 L293D 的 VCC2,同時也接到鋰電池的 +9V;把 GND 接到 GND,同時也接到鋰電池的 GND;把 C1 接到 3Y;把 C2 接到 4Y。到目前為止,接線已經差不多,只欠 L293D 自己的電源。把 VCC1 接到 Arduino 的 VIN 腳。我的 Arduino Nano 是由 USB 取電,所以 VIN 可當成 5V 輸出。

接線完成!之後就要編寫一個簡單程序進行測試:
//------------------------------------------------------------
//  LEGO Servo Controller
//------------------------------------------------------------
//  Platfrom: Arduino Nano + L293D + LEGO Power Function Servo
//  Copyrights Pacess Studio, 2018.  All rights reserved.
//------------------------------------------------------------

//  Constant values
const int servoEnablePin = 3;
const int servoControlPinA = 7;
const int servoControlPinB = 8;

//------------------------------------------------------------
//  60 = Center
//  200 = Side
int steering = 0;
int delta = 1;

//  0 = Clockwise
//  1 = Counter-clockwise
int type = 0;

//------------------------------------------------------------
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  pinMode(servoControlPinA, OUTPUT);
  pinMode(servoControlPinB, OUTPUT);
  pinMode(servoEnablePin, OUTPUT);

  //  Steering centered
  digitalWrite(servoEnablePin, LOW);
  setDirection();

  Serial.println("Please input a value:");
}

//------------------------------------------------------------
void setDirection()  {
  if (type == 0)  {

    //  Clockwise
    digitalWrite(servoControlPinA, LOW);
    digitalWrite(servoControlPinB, HIGH);
    return;
  }

  //  Counter clockwise
  digitalWrite(servoControlPinA, HIGH);
  digitalWrite(servoControlPinB, LOW);
}

//------------------------------------------------------------
void loop() {
  // put your main code here, to run repeatedly:
  char input[16];
  byte size = Serial.readBytesUntil('\n', input, 16-1);
  input[size] = 0;

  steering = atoi(input);
  if (steering > 0)  {
    Serial.println(steering);
    analogWrite(servoEnablePin, steering);
  }
  
  if (steering < 0)  {
    type = (type+1)&1;
    setDirection();
  }
}

結果發現,樂拼伺服馬達不像普請的伺服馬達,暫時只能做出 90 度的旋轉。數值為 60 置中,170 為 90 度。利用 C1 及 C2 的正反向決定順時針,還是逆時針。

2018年5月26日 星期六

改裝樂拼伺服馬達


要利用樂拼作為 Donkey car 的車架,需要把樂拼的馬達及伺服馬達連接到 Raspberry Pi。這樣得先了解馬達的接線及訊號規則。我把伺服馬達的接線剪斷,兩頭都分別接上母頭的彩虹線。把它們焊接,並用熱縮通包裹著,以免金屬外露而發生問題。


另一端的伺服馬達作相同的焊接。我特意選擇顏色鮮艷的排線,還把紅色線接上 +9V 端以作識別。+9V 端接正電流,GND 端是接地的,相信很容易理解。而 C1 及 C2 是用來控制馬達的方向


焊接完成後,把接線安裝到接收器,並把 C1 及 C2 母頭連到儀錶看看是如何控制角度。是用電壓?還是 PWM?


發現其中一個方向是正電壓,而另一個是負電壓。原來是靠正值、零及負值去決定伺服馬達的角度。似乎它不像遙控車般用 PWM 來決定,也不能調校任意角度。

2018年5月25日 星期五

股價波幅預測


三年多前的一次聚會中,我跟大家分享了希望用大數據結合術數,看看有甚麼結果。今日,我終於有機會把股票數據結合術數,嘗試看看預測結果。我拿了 0005.HK 的數據來進行測試。上圖是過去 900 天的表現;橙色是實際波幅;綠色是預測波幅。一如所料,預測結果十分離地...。又要再想想可以怎樣改善。

2018年5月24日 星期四

為 Donkeycar 加入自訂數據


要令 Donkeycar 跑得好,除了要有良好的駕駛技術外,還需要不同檢測器的數據協助,才能還機器學習發揮功效。為了達到這個目的,需要把測量到的數據記錄下來,再經由算法進行學習。原本 Donkeycar 已經有儲存數據的功能,要加入新的數據,只要如上圖般傳入 new_tub_writer 的 inputs 及 types 參數內。


修改後重新啟動「python manage.py drive」,錄影時便會連同新讀數一起儲存。

2018年5月23日 星期三

連接 PS3 手掣到 Donkeycar


Donkeycar 其中一個操控模式是連接 PS3 控制器。首先要 SSH 進 Raspberry Pi,跳轉到車子目錄,以「nano config.py」,把「USE_JOYSTICK_AS_DEFAULT」設定為「True」。然後,用 Mini USB 線把 Raspberry Pi 及控制器連接,以「python manage.py drive」啟動車子程式。這時在 PS3 控制器上按下 PS 鍵,程式便會進行配對。成功後,以後便可以拔掉 USB 線,進行無線遙控。有一點要留意,當預設了 PS3 控制器後,便不能以「http://dk.local:8080/」的方法控制車輛。

2018年5月22日 星期二

更改 Donkeycar WEB 介面的連接埠


Donkeycar 預設的 WEB 埠為 8887,不好記。於是動手把它改為 8080。打開 ~/donkeycar/donkeycar/parts/web_controller/web.py,把第 131 行的 port=8887 改為 port=8080。本來想改為 80 埠,但這樣做需要 root 權限,就算用 sudo python manage.py drive 也不行,因為 root 沒有設定好相關的模組路徑,會產生錯誤。


修改後調用 python manage.py drive 會見到連接埠改為 8080。用瀏覽器連接,成功。

2018年5月21日 星期一

Donkeycar 收集的數據格式


一直好奇,究竟 Donkeycar 收集了哪些數據?數據又是怎樣被儲存起來?原本向前輩請教,但得不到答案,只好自己動手做做實驗。

在網頁介面啟動了車子後,左下方還有一個「錄影」鍵,它就是用來記錄行走時的數據。數據會存放在 ~/mycar/data 內。為了方便在電腦上觀看圖像,我在 Raspberry Pi 上輸入指令「sudo python3 -m http.server 80」;這樣 Python 會即時建立起一個簡單的網頁伺服器;我只要在電腦上利用瀏覽器,輸入車子的本地域名「http://sita.local」,就可以方便地觀看檔案。


原來 Donkeycar 會以 JPG 格式儲存彩色鏡頭畫面,而加速及轉向數值則會用 JSON 格式。

2018年5月20日 星期日

安裝 Donkeycar 到 Raspberry Pi 2 Model B+


忙完「機器學習基礎課程」的工作,終於有時間研究 Donkeycar。看了官網幾次,都覺得指引不夠詳細,內容不夠清𥇦;例如:怎樣手動安裝 Donkey car?訓練數據的格式是怎樣?Raspberry Pi 2 是否能夠跑得到?用別的車架要如何調校馬達?是否每個場地都需要訓練後才能跑?...等。既然有這麼多疑問,那最好是動手做,Make the hand dirty!


首先到官網下載 Donkeycar 的 Raspberry Pi 影像檔。再利用 Mac Ether 把 .img 檔寫入到 SD 卡。然後用它來開機。過程十分順暢。我拿了一支 TP-Link TL-WN725N USB 來連接 WiFi。不用安裝驅動程式也能使用。以「sudo nano /etc/wpa_supplicant/wpa_supplicant.conf」指令加入 WiFi 連接點及密碼。同時也用「sudo raspi-config」來修改密碼、更改時區、更改成美式鍵盤、打開鏡頭支援。接著是更新 Donkeycar 程式建立新車項目。更新指令為:
cd ~/donkeycar
git pull
pip install -e .

建立新車項目指令為:
donkey createcar --template donkey2 --path ~/mycar

有了新車項目後,就是啟動新車:
cd ~/mycar
python manage.py drive

到目前為止都很順利,但當要啟動新車項目時卻出現錯誤。這是由為我沒有 I2C 的接板。我打算用積木砌成的車架及馬達,還未清楚是否同樣接 PCA9685 伺服馬達控制板;還是需要自行用 Raspberry Pi 或 Arduino 去特別處理...。


根據文件所指,所有部件都是以「Add」的形式加入到車物件內,我把出錯的地方修改一下,當無法載入時便不把它加入車子,這樣問題得以避過:


這樣,車子項目能成功載入。在瀏覽器地址輸入「http://dk.local:8887」便會見到控制畫面:

2018年5月14日 星期一

機器學習基礎.第一課


兩年前到中學教授 Android 程式開發,負責的老師認同我授課的表現,我很感謝。今年,他們希望能讓學生學習人工智能方面的知識,幸運地我可以再次幫忙。三天九小時的學習時間少,我認為應花在主軸上,不想花太多時間在安裝教學,於是起了一台 Jupyter 伺服器,安裝好需要用的模組及程式,讓學生在不同的機器也能學習。安裝步驟只放在 Keynote 簡單講解。

昨天第一課過程遇到小問題,學校的防火牆阻截了 8888 埠的通訊,需要臨時改為 8080 埠。幸好,防火牆沒有擋 SSH 的 22 埠,否則整堂也沒有 Jupyter 可以使用,總算有驚無險。課室裡約有十位學生。他們只需要用瀏覽器就能執行 Python 程式,調用 Numpy, Scikit-learn, Scipy 等模組,能夠把大部份時間都花在「機器學習」的原理及練習上。一直擔心弱弱的伺服器能否支持課堂內的學生數目,見到一切順利,現在較為安心。不過,今堂處理的都是簡單的運算,下堂用到 TensorFlow 及大量數據時,不知情況如何。我也能借此機會量度一下機器的配置應該要達到甚麼級數,好讓年底到香港理工大學教授「機器學習」時可以做得更好。

2018年5月12日 星期六

Donkey car 的積木車架入手


上星期參觀過由香港元袓 Maker Faire 的朋友們在 HKPC 舉辦的 Inno Fair 2018。這個 Faire 基本上跟 Maker Faire 一樣,只是規模小一點;沒辦法,某人見朋友們舉辦香港 Maker Faire 有聲有色後,利用學府地位搶走了舉辦權,朋友們只好重新來過。

在 Inno Fair 認識到一班玩 Donkey Car 的朋友,讓我再次重拾這個項目。一年前已經打算用積木砌一輛自走車,由於 LEGO 較貴,所以選用了樂拼,並買了一輛紅色跑車。車是砌成了卻沒有改裝。那台車只有一個馬達,要手動轉向,沒有伺服馬達;我要拿來改裝的話,則需要伺服馬達,於是物色了幾個緊達部件,夾夾埋埋也要一百多一點錢。後來在淘寶找到了上圖這輛車。它不但有緊達及伺服馬達,也有鋰電池、燈、遙控及接收器。最重要是 RMB$179 有交易!比起散賣的價錢相差無幾。可是,問過幾家店也指帶鋰電不能運送出境。可能怕會爆炸吧。既然不能送過來,只好到深水埗碰碰運氣,那裡的玩具街有七家賣樂拼的店。最後,找到了這台 HK$265 的藍白色版本。雖然我喜歡黑色版,但價錢要 HK$330。我寧願用差價買其他樂拼,然後換上那些顏色的積木。

回家後拼出車架,做了一次車速測試,十分滿意。下一步是要解決由 Raspberry Pi 接馬達的線路,相信沒有難度。

2018年5月11日 星期五

特徵檢測


在公司設置了一台電腦,它會收集路過的同事的樣貌。這些素材將會用來訓練機器學習模型,最後希望當同事路過時,電腦能分辦出是哪一位,並說句「你好」。

時間過得很快,素材已經有多達十三萬張。當中有很多是連貫的動作,相信對機器學習訓練來說作用不大,可以刪除。然而,這個動作要輪流把每張相片都看過,才能作出篩選。我實在很希望把它自動化。但自動化是先要有一個訓練好的模型;而訓練模型又需要素材,亦即是要手動分一次。好像跑不出迴圈,怎樣也要手動做一次。後來我嘗試用 Feature detection,希望可以憑此來基本判定是哪一個人;可惜卻事與願遺。不過,我發現用另一個方法能計算出兩張圖片的相似度。我編寫了程序,它能把一部份相似的相片刪除,餘下的才需要手動處理。問題是,餘下的也有好幾萬張,要如何做到快,還在思索中...。

2018年5月5日 星期六

Donkey car


今天是小女學校開放日,她們都有表演;我當然要出席支持。本來無緣參觀 Inno Fair 2018,但因為第一場表演順利拍攝完成,跟第二場有一點空檔,加上會場跟學校算是近,於是在女兒演出後便跑到 Inno Fair。

本來沒有打算過去,畢竟近三年都是看到相同的項目:立體打印機、機械人、水耕、打印義肢、蛋殻雕刻、...。但今次多了 Donkey car。因為它用上人工智能,特別吸引到我。在場內跟 Donkey car 的人員交流,知道他們有一個群組,希望聚集志同道合的人一起分享、一起進步。我立即加入了群組。他們目前都是依據 Donkey car 原型開發,並改良了電池方面的支援,全車只用一顆電池。他們還示範了自動行走模式給在場觀眾看,十分有趣。

2018年5月1日 星期二

利用 Jupyter 來授 ML 課可行嗎?


勞動節勞動了很多。由於要教授機器學習課,我在想:「要學生一步一步安裝所需要的軟件,讓他們能壓必了解箇中細節,能在家裡重新實行,雖然是好事。」;但學生手腳有快有慢,機器設定及配備有高有低,要所有人由頭到尾安裝好,解決當中遇到的問題,相信得花一堂時間,看來不值得。其真只要肯花搜尋功夫,安裝方法會找到很多。所以,我嘗試把學習環境搬到雲端上。利用 Jupyter 這個工具,學生們只需要登入頁面,便能即時進行編程及執行程式,同時能在頁面看到結果。當所需要的 Python 模組都安裝好,學生只需要 import 就成事,十分快捷。於是,我今天就快了很多時間去做一次這樣的實驗。

安裝 Juypter 到 CentOS 6 很簡單,只要:
pip3 install jupyter
python3 -m pip install jupyter
就可以。

之後要生成設定檔:
jupyter notebook --generate-config

由於網頁將會對外開放,所以要為 ~/.jupyter/jupyter_notebook_config.py 加入 SSL 證書及公鑰。然後打開防火場:
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8888 -j ACCEPT -m comment --comment "Jupyter port"

決定 Jupyter 的目錄,如 /var/www/html/notebook/,跳進去並以指令啟動:
jupyter notebook

這時,需要為網頁設置密碼。打開新的筆記簿,輸入程式:
from notebook.auth import passwd
passwd("password")

並執行,會得出 SHA1 值。把這個值加進 ~/.jupyter/jupyter_notebook_config.py。重新啟動後,便能用密碼登入。往後要進 Jupyter,可以在瀏覽器輸入服務器的域名及連接埠號碼 8888 便可。

來到這裡一直很順利。在 Jupyter 內能載入 SciKit-learn, Pillow, Matplotlib 等實用的模組。可是 TensorFlow 卻要 Python 3.6 而服務器內卻是 Python 3.5。原來 Jupyter 沒有簡單的設定去處理 Python 升級情況。花了很多時間,最終用 Virtualenv 來解決。建立一個獨立的 Python 3.6 環境:
pip3.6 install virtualenv
virtualenv -p /root/anaconda3/bin/python3.6 python3.6
source python3.6/bin/activate
pip install jupyter
python -m ipykernel install --name=python3.6
pip install ipykernel
conda install tensorflow
重啟之後,Jupyter 頁面的右上角便多了 Python 3.6 的記事簿可用了。