2014年12月25日 星期四

[玩具] 單層自走車底盤 + 一萬向輪 + 二馬達

在網路上買了一個聖誕禮物給自己。




































下訂的隔天就收到一只郵局箱子



















搖一搖沒聲音,打開一看,心都涼了一半,以為遇到詐騙。














移除報紙一糰,本尊出現。
















正面來一張
















背面來一張
















零件圖

輪仔


單層板
















萬向輪


電池盒

















直流馬達

測速盤以及小零件
組合說明 step 1(看不太懂)

所以我們還是看照片吧 ,先把測速盤裝上馬達轉軸向內一邊。

再把二個T型支架照說明書穿過來後,用最長的螺絲穿過馬達上

的孔與T型支架後用羅帽鎖上。注意一下是這幾張照片都是裝在

反面(沒有印刷任何東西的那一面),而上面那一個說明是在

正面的安裝圖。

第二顆直流馬達也裝上去,順便把開關也塞進洞裡。


安裝萬向輪,注意一件事,萬向輪與版子間需要安裝銅柱,

不然高度會不對稱,銅柱的螺絲在版子正反面不同。

下圖是版子的反面(裝馬達那一面),用的螺絲頭比較扁,

也稍微寬一點,可以壓住萬向輪的

在版子正面的地方,螺絲頭比較圓也稍微小了一點。
B+ 似乎只有後面二個螺孔可以對的上版子上的螺絲孔,





台灣樹梅派回覆告知馬達的規格。

3V工作電壓
空載電流:120mA
減速比:1:48
負載電流:180mA
負載轉速:115rpm
扭矩:0.7kgf.cm
堵轉電流:780mA

6V工作電壓
空載電流:180mA
減速比:1:48
負載電流:240mA
負載轉速:230rpm
扭矩:1.2kgf.cm
堵轉電流:1000mA




經過測試,以4顆3號電池,正接正,負接負,會正轉。正負對調接會逆轉。

2014年12月22日 星期一

[HTML5] 用HTML5 開啟WebCam

無意間發現HTML5 可以輕易的開啟Webcam,手癢來Try一下,順手做個筆記。


程式碼來源


首先要加body中加入一個Video Element
  <video id="video" width="640" height="480" autoplay></video>    


在head中新增一個JavaScript ,並新增一個事件監聽

  <script type="text/javascript">  
       // 建立一個監聽事件 (事件名稱 ,要執行的function, useCapture)  
       window.addEventListener("DOMContentLoaded", function () {  
         // Grab elements, create settings, etc.  
         var video = document.getElementById("video"),  
              //使用影像: true ,取用聲音 true  
             videoObj = {video: true ,audio: true},  
         errBack = function (error) {  
           console.log("Video capture error: ", error.code);  
         };  
         // 依據Browser不同使用不同的API          
         if (navigator.getUserMedia) { // Standard  
           navigator.getUserMedia(videoObj, function (stream) {  
             video.src = stream;  
             video.play();  
           }, errBack);  
         } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed  
           navigator.webkitGetUserMedia(videoObj, function (stream) {  
             video.src = window.webkitURL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
         else if (navigator.mozGetUserMedia) { // Firefox-prefixed  
           navigator.mozGetUserMedia(videoObj, function (stream) {  
             video.src = window.URL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
         else if (navigator.msGetUserMedia){  
          navigator.msGetUserMedia(videoObj, function (stream) {  
             video.src = window.URL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
       }, false);  
     </script>  

這裡補充一下onloadDOMContentLoaded 差異: 

當onload事件觸發時,頁面上所有的DOM,樣式表,Script,圖片,flash都已經加載完成了。

當DOMContentLoaded事件觸發時,僅當DOM加載完成,不包括樣式表,圖片,flash。 

我們需要給一些元素(element)的事件綁定處理函數。但問題是,如果那個元素(element)還沒有加載到頁面上,但是綁定事件已經執行完了,是沒有效果的
這時候DOMContentLoaded事件就是一個很好的選擇,當DOMContentLoaded觸發時,所有的元素(element)己加載完成。

 資料來源

http://www.cnblogs.com/hh54188/archive/2013/03/01/2939426.html



接下來說明一下JavaScript整個架構

window.addEventListener 整個函式的架構為

 element.addEventListener(event, function, useCapture);  

event指的事件名稱,在這裡指的是DOMContentLoaded事件。

function 則是發生DOMContentLoaded事件後要執行的事情。

在此則是執行取得WebCam影像以及Mic的動作並顯示在video element中

useCapture則是指是否使用bubbling propagation

此參數是可選擇性的,預設為false

當為false時,為bubbling propagation,  為true時為capturing propagation

這二個的差異可以參考這一篇,寫的挺清楚。


JavaScript 天書 -- 什麼是event bubbling


或是


w3schools 


videoObj = {video: true ,audio: true} 

vide:true 表示取用WebCam , audio :true則表示取用Mic 。

如果這二個值都為true則啟用時如下圖





video: true , audio :false 則如下圖





video: false ,audio: true 則如下圖






  navigator.getUserMedia(videoObj, function (stream) {  
             video.src = stream;  
             video.play();  
           }, errBack);  

getUserMedia() 它提供了存取camera以及麥克風的串流方法。並將取得的串流
當作是video element的資料來源,並啟動video element為播放模式。



完整程式碼如下


 <!DOCTYPE html>  
 <html>  
   <head>   
     <title>Demo HTML5 WebCam</title>  
     <meta charset="UTF-8">  
     <script type="text/javascript">  
       // 建立一個監聽事件 (事件名稱 ,要執行的function, useCapture)  
       window.addEventListener("DOMContentLoaded", function () {  
         // Grab elements, create settings, etc.  
         var video = document.getElementById("video"),  
              //使用影像: true ,取用聲音 true  
             videoObj = {video: true ,audio: true},  
         errBack = function (error) {  
           console.log("Video capture error: ", error.code);  
         };  
         // 依據Browser不同使用不同的API          
         if (navigator.getUserMedia) { // Standard  
           navigator.getUserMedia(videoObj, function (stream) {  
             video.src = stream;  
             video.play();  
           }, errBack);  
         } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed  
           navigator.webkitGetUserMedia(videoObj, function (stream) {  
             video.src = window.webkitURL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
         else if (navigator.mozGetUserMedia) { // Firefox-prefixed  
           navigator.mozGetUserMedia(videoObj, function (stream) {  
             video.src = window.URL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
         else if (navigator.msGetUserMedia){  
          navigator.msGetUserMedia(videoObj, function (stream) {  
             video.src = window.URL.createObjectURL(stream);  
             video.play();  
           }, errBack);  
         }  
       }, false);  
     </script>  
   </head>  
   <body>  
     <!-- 放一個Video element 上去 指定大小為640*480 並且自動播放 -->  
     <video id="video" width="640" height="480" autoplay></video>      
   </body>  
 </html>  



*執行時記得允許存取相機/麥克風

 (Chrome)



FireFox





















執行畫面

















瀏覽器支援如下表 ,資料來源




 

2014年12月16日 星期二

[Java] java.sql.PreparedStatement 值得注意的地方

某日,我想用java.sql.PreparedStatement做一個可以用程式去指定where的條件 ,

原本我認為應該會合成這樣的一個SQL:

"SELECT id, name, color FROM animal where 1=1 and name='cat';"

But, 卻出現了錯誤。
嚴重: null
org.postgresql.util.PSQLException: 

ERROR: syntax error at or near "$1"

程式碼如下:
public static void main(String[] args) {

     Connection conn;
    String url = "jdbc:postgresql://localhost/demo?"
            + "user=postgres&password=abcd1234";
    String sql = "SELECT id, name, color FROM animal where 1=1 ?;";
    try {
        //載入驅動器
        Class.forName("org.postgresql.Driver");
        //取得Connection(取得成功表示己與資料庫連上線)
        conn = DriverManager.getConnection(url);

        PreparedStatement st=conn.prepareStatement(sql);
        st.setString(1, "and name='cat'");

        //查詢資料(把查到的資料放進ResultSet)
        ResultSet rs = st.executeQuery();
        //讀取ResultSet中的資料
        while (rs.next()) {
            //id 是數值列態
            System.out.print(rs.getInt("id") + "\t");
            //name 及 color 是String型態
            System.out.print(rs.getString("name") + "\t");
            System.out.print(rs.getString("color") + "\n");
        }
    } catch (ClassNotFoundException e) {
        System.exit(1);
    } catch (SQLException ex) {
        Logger.getLogger(DemoPreparedStatement.class.getName()).
                log(Level.SEVERE, null, ex);
    }
}
用Debug Mode看了一下合成出來的SQL:
SELECT id, name, color FROM animal where 1=1 'and name=''cat'''
沒錯,它自動幫我再單引號的地方,再多加了一個單引號,並且在字串的前後也加上單引號,

因為在SQL語法中,2個單引號表示你要輸入的是一個單引號字元。這是它貼心的地方,

可以避免發生SQL Injection 。雖然這樣也會造成某使用上的些限制,

但PreparedStatement 對於只需替換參數的SQL語法有較好的效能。

以上是小弟在實作時遇到問題的經驗分享。

2014年12月15日 星期一

[C#]幫Button加入Tooltip

吐Day遇到一個小小的問題,想要幫Button加上提示字時,挖~沒有這個屬性。 在MSDN上爬到一篇,可以先拉一個ToolTip控制項出來,可以實現我們的要求。


Step 1 .點開工具箱,找到TooTip點二下




Step2 . 然候拉出你要的Button ,在這裡,我把它命名為button1,
注意此時ToolTip1己經在底下了 。






























Step 3. 接下來有二種方法可以實現提示文字

3.1 用 Soruce
toolTip1.SetToolTip(控制項名稱, "要提示的字");
  
我們可以把它放在Form_Load 中,如下所示
private void Form1_Load(object sender, EventArgs e)
{
    toolTip1.SetToolTip(button1, "I am Button Tooltip");
}


3.2 在你拉出toolTip1後,其實控制項的屬性會多出一個「在toolTip1上的ToolTip,
 也可以預先打好在這裡,效果相同。




























執行結果如下圖









2014年12月14日 星期日

[Raspberry pi] 在 Raspberry pi 上安裝v4l4j

v4l4j  A java package to access the Capture interface of the Video4Linux API

                        (讓Java可以存取v4l(Video4Linux API)的package。)



接下來說明安裝v4lj 的步驟,資料來源請參考此連結


一、安裝JDK (可以選擇安裝openjdk-7-jdk 或使用 raspberry pi 中的JDK8)



sudo apt-get install openjdk-7-jdk

or 

使用系統內建的Oracle JDK8 (不必裝)

二、安裝Ant

sudo apt-get install ant

三、安裝libjpeg8-dev

sudo apt-get install libjpeg8-dev

四、安裝libv4l-dev

sudo apt-get install libv4l-dev

五、取得v4lj 原始碼(有時候會失敗,多試幾次)

svn co http://v4l4j.googlecode.com/svn/v4l4j/trunk v4l4j-trunk

六、進入資料夾

cd v4l4j-trunk/

七、設定環境變數

JDK8 方式

export JDK_HOME=/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/

OPEN JDK方式

export JDK_HOME=/usr/lib/jvm/java-7-openjdk-armhf/ 

八、編譯

ant clean all
























sudo ant install
























九、測試 (參考連結在此

編譯測試檔案

ant deviceInfo 
























執行

java -cp /usr/share/java/v4l4j.jar -Djava.library.path=/usr/lib/jni au.edu.jcu.v4l4j.examples.DumpInfo


紅色框起來的地方,是小弟的WebCam型號,以及Device file所在的名稱。

它很仔細的列出了我的webcam所支援的影像規格,例如640*480 解析度可以在 1/30秒~1/15秒(取像的時間間隔,也就是硬體支援我在640*480解析度下,最快可以每秒30張,最快可以到每秒15張) 



2014年12月12日 星期五

[Raspberry Pi ] Raspberry Pi 用 openCV開啟WebCam

由於我用JMF 在RaspBerry Pi上無法找到WebCam,便想起念書時用過的OpenCV ,
Google了一下,有前輩們寫出解法,我參考了以下這個連結,安裝好了OpenCV ,
雖然中途有遇到一些問題,也爬文做了些修改,最後成功開啟WebCam,一切安好。

安裝OpenCV Raspberry Pi / Banana Pi

一、首先要安裝一些套件在Pi上,在官方最新版的OS上(1.3.10),

其實有部份都己經存在了。


sudo  apt-get install build-essential

sudo  apt-get install cmake

sudo  apt-get install pkg-config

sudo  apt-get install libgtk2.0-dev libgtk2.0

sudo  apt-get install zlib1g-dev

sudo  apt-get install libpng-dev

sudo  apt-get install libjpeg-dev

sudo  apt-get install libtiff-dev

sudo  apt-get install libavcodec-dev

sudo  apt-get install swig

二,下載linux/Mac 版的OpenCV ,本例我是下載2.4.10

http://opencv.org/downloads.html


































三、解壓縮

unzip opencv-2.4.10.zip 

四、進入資料夾


cd opencv-2.4.10/

五、建立一個存放編譯後檔案的資料夾

mkdir release

六、進入此資料夾

cd release

七、編譯 (注意 最後二個 ..  指的是上一層目錄  ,並不是省略)

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..

sudo apt-get update

make

make這個部份要很久,我等了2~3個小時才編譯到28% ,良心建議在睡前開下去make,

天亮起來就差不多了。

八、安裝

sudo make install

九,編輯bash.bashrc  加入環境變數

sudo nano /etc/bash.bashrc 

在文件的最下方加入

PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

export PKG_CONFIG_PATH
























按下 Ctrl + O  存檔 ,再按下Ctrl + X 離開編輯。

十、測試一下pkconfig

pkg-config --modversion opencv

如果版本和小弟的相同,應該會出現如下圖中的2.4.10






注意,在modversion前面是 2個減號。

十一、 新增一個 WebCam.cpp

sudo nano WebCam.cpp

程式碼內容如下
#include "opencv2/highgui/highgui.hpp"

using namespace cv;

int main()
{
    Mat image;
    
    VideoCapture cap;      //capture的宣告
    cap.open(0);           //0 為預設camera
    
    while(cap.isOpened())  //確認camera能開啓
    {
        cap>>image;        //截取影像到image裡方法        
        if (!image.empty()) 
         imshow("Webcam live", image);
        
        waitKey(33);//避免CPU負荷,給點delay時間
        //實際上一般webcam的framerate差不多33ms
    }
    
    return 0;
}
一樣按Ctrl + o存檔,Ctrl+x離開。 接下來要編譯程式

注意一下程式碼中的

 if (!image.empty()) 
       imshow("Webcam live", image);
在網上找到的範例中並沒有 if (!image.empty()) ,在我的桌機上是正常的,

但在Pi上沒加會爆掉,這行作用是限制讀到的影像不是空的才顯示出來。

十二、編譯程式碼


g++ `pkg-config --cflags --libs opencv` WebCam.cpp -o WebCam

注意,並沒有打錯,真的是有 ' 沒錯 ,'是在~(毛毛蟲鍵)



























十三,執行程式


 ./WebCam 

十四、 錯誤排解

我在編譯時有發生以下錯誤


./WebCam: error while loading shared libraries: libopencv_gpu.so.2.4: cannot open shared object file: No such file or directory

參考網路上的解法

sudo ldconfig -v

dconfig命令的大概作用是讀取指定文件夾裡的所有庫文件,並根據庫文件中包含的庫文件名為其創建軟鏈接文件。

資料來源  dance_rise

十五、執行結果

dance_rise

dance_rise


十八、相關知識

pkg-config 命令是可以用來讀取安裝在 linux 系統上的 library 相關資訊。這個程式主要讀取系統中位於 /usr/lib/pkgconfig 目錄或是環境變數 PKG_CONFIG_PATH 所設定的路徑中的副檔名為 .pc 的檔案,
這些檔案包含系統安裝的 library 的相關資訊,包括:安裝的目錄、程式編譯的參數等等。

資料來源 黑手

我們在編譯程式碼中用的指令

g++ `pkg-config --cflags --libs opencv` WebCam.cpp -o WebCam

當中的  `pkg-config --cflags --libs opencv`  其實意思相當於下圖中的一串長長的















20150118補充,有時候可能會遇到


HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP
HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP

OpenCV Error: Unspecified error (The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script) in cvShowImage, file /home/pi/opencv-2.4.10/modules/highgui/src/window.cpp, line 50

這時候建議確認 libgtk2.0-dev 以及 libgtk2.0是否有裝好,如果沒有安裝正確,安裝完重新

由(四 )開始 ,由於不是全部重新make ,所以速度會較前一次省很多。如果缺少的lib不

多,可能只要原本的1/10時間

[Java] java.lang.ClassNotFoundException: org.apache.commons.codec.binary.Base64

今天在工作上遇到一個錯誤,但是在NetBeans中並沒有提示錯誤。
java.lang.ClassNotFoundException: org.apache.commons.codec.binary.Base64
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass
(WebappClassLoaderBase.java:1295)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass
(WebappClassLoaderBase.java:1147)


仔細一看發現是缺少了 org.apache.commons.codec.binary.Base64 ,

直接以此做為關鍵字上 GOOGLE問大神,原來少掉的是

Base64 (Apache Commons Codec 1.10 API)。

載點在這裡 ,檔案大小約2MB http://ftp.mirror.tw/pub/apache//commons/codec/binaries/commons-codec-1.10-bin.zip 

 解壓縮後的內容








我們只需要加入commons-codec-1.10.jar 及 commons-codec-1.10-javadoc.jar

到專案中即可。

2014年12月10日 星期三

[C#]C# 把postgresql 查詢出來的資料丟入DataGridView

一開始我們查出來的資料都是直接用NpgsqlDataReader 來做操作,就像下面這段程式碼為例子。
NpgsqlConnection conn =
    new NpgsqlConnection("Server=127.0.0.1;Port=5432;User Id=postgres;Password=t@ida1234;Database=Demo;");
conn.Open();

NpgsqlCommand command =
    new NpgsqlCommand("select * from shop_sale", conn);

try
{
    NpgsqlDataReader reader = command.ExecuteReader();

    while (reader.Read())
    {
        string shop = reader["shop"].ToString(); ;
        string no = reader["no"].ToString(); ;

        Console.WriteLine(shop + "\t" + no);
    }
}

finally
{
    conn.Close();
}

如果要放進DataGridView中,我們必須先拉一個DataGridView出來,命名為dataGridView1

















宣告一個用來存放資料的DataTable
DataTable dt = new DataTable();
用NpgsqlDataReader裡的資料填進DataTable
dt.Load(reader);
指定DataGridView 的資料來源
dataGridView1.DataSource = dt;    

完整程式碼


using System;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
using Npgsql;
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        getData();     
    }
    private void getData()
    {
        DataTable dt = new DataTable();
        NpgsqlConnection conn =
            new NpgsqlConnection("Server=127.0.0.1;Port=5432;" +
                "User Id=postgres;Password=t@ida1234;" +
                "Database=Demo;");
        conn.Open();

        NpgsqlCommand command = new
            NpgsqlCommand("select * from shop_sale", conn);

        try
        {
            NpgsqlDataReader reader = command.ExecuteReader();
            dt.Load(reader);
            dataGridView1.DataSource = dt;
        }

        finally
        {
            conn.Close();
        }
    }
}
執行結果

2014年12月8日 星期一

[Microsoft] IE- Automation伺服器無法產生物件























近日在工作上遇到一個難題,客戶的IE8無論怎樣都無法順利載入JavaScript。

即使解除IE 8 回到IE 6 問題依然存在。 啟用IE 8 的開發者工具,

發現錯誤是在執行這一段程式碼後



錯誤原因是



且發生錯誤時,網頁上的JavaScript並未正確運做,

且IE左下角會顯示"完成" (IE6),




點二下錯誤訊息會顯示類似這樣























或是"已完成 但是網頁發生錯誤"(IE8)。





點二下錯誤訊息













很幸運的找到一篇文章

卸载360安全卫士,以致ajax报错:找不到指定的模块


覺得情況十分類似,在客戶端用命令提示字元下了以下指令

cd \Windwos\System32 

dir msx*


比對了客戶端以及公司內部XP,發現客戶端少了msxml3.dll。














將xp裡的msxml3.dll 複制給客戶端後,IE功能回復正常。

經測試,此檔案無論用檔案總管或是命令提示字元,皆無法有效刪除,

但在安全模式下可輕易刪除。


XMLHttpRequest ->AJAX核心

AJAX引擎只是一個JavaScript的物件而以,也就是XMLHttpRequest物件。
 微軟IE5最先支援這個物件,Mozilla 1.0(Netscape 7),Safari 1.2及Opera都開始支援相容的物件。 值得注意的是XMLHttpRequest物件並不是標準,只是知名的瀏覽器都相繼支援。 提示找不到這個URI。但直接以瀏覽器貼上此URI卻可以正確下載此js檔案。

資料來源-

http://jck11.pixnet.net/blog/post/11624882-ajax%E6%A0%B8%E5%BF%83-xmlhttprequest%5B%E7%AD%86%E8%A8%98%5D