Category Archives: 樂高機器人EV3/NXT/RCX

[樂高EV3機器人教學] CAVEDU教你開外掛:如何在EV3軟體中安裝擴充指令?

又到了機器人比賽的旺季,如何增添LEGO機器人的威力呢?本篇教你禁斷的密技,開外掛如何安裝非樂高原廠預設的指令。

作者/攝影

腦波弱老闆

文章分類教學技術文
時間

10分鐘內(如果網路不慢的話)

成本

看你有多少預算

難度

材料表
  • LEGO EV3

  • 第三方感應器

機器人比賽百百種,EV3可以參戰的項目當然也很多,目前除了WRO(國際奧林匹克機器人大賽)的競賽項目,與FLL(FIRST LEGO league)之外,大多不會限制使用非LEGO原廠(以下稱之為第三方)的感測器或零組件。

 

但若買了第三方的感測器,使用者首先要解決的就是,如何在EV3的軟體環境中使用它們。

 

既然你真心誠意的問了,我就大發慈悲的告訴你!!

 

發行第三方感應器的主要品牌有Hitechnic、minisensors、Dexter Industries(對了,機器人王國都有賣)。

 

本篇就以機器人足球賽中最常用到的Hitechnic Compass sensor電子羅盤感應器為例,來跟大家介紹:

 

Step1:首先,先去弄到一個感應器,不然,裝了軟體外掛也沒用。

 

Step2:到原廠網站找重要關鍵字「Download」,下載相關指令。通常在產品介紹或技術支援的頁面可找到,不然,就看是跟誰買的就找誰幫忙提供。

注意:有些第三方感應器會提供好幾種、在不同軟體環境下使用的指令或函式庫,請認明後再下載。

圖1

 

Step3:下載後,通常要解壓縮,請放在你找得到的地方。解壓縮後,應該會看到副檔名為.ev3b的檔案。

 

Step4:接下來,啟動EV3軟體,不論是零售版或教育版皆可,並開啟至程式編輯頁面

圖2

 

Step5:點選「Tools->Block Import」

圖3

 

Step6:按「Browse」先去找你剛剛解壓縮的資料夾。順利的話,你在「Select Block to Import」清單中,就會看到可安裝的指令,以及它們的版本。

圖4

 

Step7:選我們要安裝的指令(在這個範例中,我們選的是HTCompass.ev3b),再按下「Import」。一切順利的話,你就會看到如下圖的畫面,表示安裝成功,重新啟動軟體就能用。

圖5

 

Step8:如果剛剛所有動作都沒出錯,重新啟動軟體後,就可看到相關的指令了。

圖6

 

如果安裝還是不成功,可以帶著你的器材跟電腦,來跟我們預約上課時間,我們會安排老師教你裝到好(如果東西都是正常的)。剩下來,就是你的事了。

 

相關文章

[教學文]久等囉!Scratch 3.0可以與Lego EV3 機器人連線了!

作者/攝影曾吉弘
文章分類

教學 (介紹性)

時間0.5小時
成本
難度**(1~10)
材料表

Scratch 3.0 preview版

八月快到了,對於全球Scratch的使用者來說,最引頸期盼的就是Scratch 3.0的發佈。雖然許多功能仍在緊鑼密鼓製作的階段,但Scratch團隊已在3個月前提供了Scratch 3.0 preview版。今天阿吉老師也發現,在擴充功能中的Lego EV3與Micro:bit皆可以使用了,一起來玩玩看吧!

 

CAVEDU教育團隊有參與正體中文的翻譯,若您覺得哪個語詞可以更好的話,請截圖跟我們說喔!另外,還記得阿吉老師曾與Mitchel Resnick教授聊過Scratch 3.0的影片嗎?來聽聽看M教授想對台灣使用者說的話吧:


那就開始吧!

 

STEP1:請用瀏覽器開啟Scratch 3.0 preview版,主畫面如下:

圖1

 

STEP2:點選右下角的extension,並點選 Lego EV3。此時,系統會開始尋找是否有可用的EV3,先跳過沒有關係。

圖2

 

若您的電腦還未與Lego EV3主機進行藍牙配對的話,請參考本頁說明。首先要下載一個小檔案名為「ScratchLink」,這個檔案Windows/MAC作業系統皆支援。

圖3

 

點選下載,解壓縮後安裝即可。

圖4

 

也有說明如何讓電腦與Lego EV3進行連線。

圖5

 

實際上,只要點選Lego EV3指令區的連線icon就可開啟連線畫面,只要先打開EV3的藍牙就可搜尋了(預設的配對密碼為1234)。

 

連線、斷線皆相當方便,操作上可感受藍牙傳輸的延遲,也可從Lego EV3指令區的連線icon 為打勾或驚嘆號,看出是已經連線或尚未連線等狀態。

圖6

 

 

圖7

 

圖8

 

頁面下方有提供入門範例,都相當可愛。

圖9

 

寫一個簡單的範例看看吧!以下是實際執行的影片:

圖10

 

 

也可以這樣試試看喔!

圖11

 

圖12

 

今天阿吉老師便介紹至此,日後若有Scratch 3.0的相關消息,我們也會以最快的速度,幫大家進行相關介紹,敬請期待!

相關文章

[ 密技 ] 如何製做出可挑戰「創意皂飛車競賽」動力組的作品

2018年6月9日在淡江大學要舉辦全台第一場,可能也是亞洲第一場,使用無動力小車(Nerdy Derby)軌道的動力攀登競賽。在比賽之前,分享一些製作心得,以及創作時的注意事項。

作者/攝影

腦波弱老闆包辦大部分,感謝允赫、琮琮提供作品,還有紅聲數位的阿凱幫忙畫圖。

文章分類教學文
時間

10分鐘起跳

成本O元起
難度中等
材料表
  • 田宮大腳車*1

  • Linkit 7697 + RoboShield (選購連結),或是 LEGO EV3。

 

  2018年6月9日在淡江大學要舉辦全台第一場,可能也是亞洲第一場,使用無動力小車(Nerdy Derby)軌道的動力攀登競賽。這個比賽還是由科技部指導,南科AI_ROBOT自造基地贊助的喔!

 

  整個活動包括了上午的無動力組工作坊,將由「Maker一哥」鄭鴻旗主持。下午就都是比賽時間了,分成無動力組和動力組,動力組又分成競速攀登組與動力折返挑戰組。比賽詳情可以看這裡:創意皂飛車競賽

 

報名不但不用錢,還有獎金可以領喔!

不過,這篇文章的重點是,如何打造一台可以完成挑戰的車子

 

  首先分析一下軌道,軌道是由四片木板組合而成,中間兩片較高,寬約34mm,高低落差約為6mm,軌道全寬約68mm。

圖1

 

  由此可知,車體設計時,輪胎接地點至車底高度需大於6mm,輪胎內距需大於34mm。

 

  重點在於車體的「重心」位置,四個輪子的接地點所圍起來的區域為支撐區,當坡度改變,不論是上坡或下坡,只要車體重心不要落在支撐區外,就不會翻車了。

 

  重心位置愈低愈好,所以車體零件中比較重的零件,如電池、馬達、EV3主機皆盡量裝在較低的位置。而支撐區愈大愈好,而輪胎的左右距離受限於軌道寬度,只能從增長前後輪距著手,但車體太長,可能會卡在軌道坡度變換的區域,請謹慎選擇。

 

軌道側視全圖:

圖2 (修改自Nerdy Derby所提供的設計圖)

 

  不過,這次車子是沿著軌道跑,軌道除了上下起伏之外,沒有左右轉彎的需求。所以,輪子的轉向、差速機構皆可以不用準備,只要注意車體左右配重,以及左右輪胎受力狀況一致就可以。

 

  由設計圖得知,坡道斜約30度,除了夠力的馬達,你還需要抓地力夠強的輪胎。輪胎斷面較寬、較高的會比較適合。

 

圖3

 

  我們情商了創作者,先把他們的作品分享給大家參考。這是使用LEGO EV3:

圖4

 

競速攀登影片:

 

動力折返影片:

 

  或許你會發現,上述許多條件都是互斥的,例如重心要低但輪胎又要大,然而,創作的樂趣就是在諸多限制中,找到最佳平衡點。

  比賽規則與比賽道具,還是要以主辦單位公告與現場陳列的為準喔。

 

相關文章

[ 課程紀錄文 ] 2018.6-前進蘆洲開設「樂高機器人」課程 歡迎報名!

 

紀錄撰寫宗諭
紀錄攝影台北全真一對一補習班蘆洲分校余峻霆主任提供
課程時間107年6月2日開始
課程講師林韋儒
上課地點台北全真一對一補習班蘆洲分校(新北市蘆洲區長樂路106-1號4樓)

 

  這一次,CAVEDU教育團隊又有新創舉。究竟是什麼樣的新創舉呢?在台北全真一對一補習班蘆洲分校余峻霆主任協助下,我們與該分校合作,首次前往蘆洲地區開設「樂高機器人」課程,真是非常感謝余主任!

 

  5月19日下午,一位CAVEDU的同仁,帶著這次「樂高機器人」課程的講師林韋儒,首次挺進蘆洲分校。當天現場吸引了不少家長帶著孩子前來聽課程說明會。

圖1

 

  有了家長捧場,講師當然不能漏氣。他精心預備了有趣的「投石機課程」,讓家長與孩子透過實作,製作投石機。孩子們也依照韋儒老師的教導,再加上實際操作產生的想法與創意,自行改造出足以投得最遠的投石機。

圖2

 

圖3

 

  對於「樂高機器人」這門課程,CAVEDU教育團隊有非常豐富的教學經驗。過去曾前往台北市的萬大國小、新北市的新北高工和淡水商工、高雄高工⋯⋯等學校,開設樂高機器人研習,也多次舉辦針對國小學童的樂高機器人夏令營,更曾出版數本相關書籍及多篇文章。而每位參與課程的CAVEDU講師,課前皆需經過充分預備、演練、試講,課後更會充實相關新知,務必使自己能勝任各種教學場域與學生。

圖4

 

  對於這門課程的期許,韋儒老師盼望幫小朋友們打好扎實基礎,更了解相關的物理原理。同時透過組裝樂高積木,充分認識機械結構,以及如何讓機械有韌性而穩定。

 

  總而言之,蘆洲地區的家長與學童們,我們CAVEDU教育團隊來了!藉由這門「樂高機器人」課程,孩子們將能以有趣、活潑的方式,學習製作機器人,同時增強信心、耐心及面對挫折的能力。

 

  「樂高機器人」課程熱烈開課中,歡迎大家洽詢、試聽。請洽:(02)2282-5621台北全真一對一補習班蘆洲分校余峻霆主任。

圖5 台北全真一對一補習班蘆洲分校的地理位置

 

相關文章

[Lego 新訊 ]Lego Boost 機器人來了,除了EV3 與 WeDo 之外的新選擇?

Lego 公司選在 CES 2017 之前發布了新的機器人產品線:Boost。提供了介於 EV3 WeDo 之間的另一個選擇,預計在今年八月上市,一起來看看它有什麼內容吧

撰寫/攝影  曾吉弘

 

2017 Lego 發布了新的機器人產品線:Boost,也許是既定時程,但去年小米推出的米兔機器人(人民幣499),光是我的Facebook好友應該就有50篇開箱文以上,因此中價位(Boost 定價 160美金) 的產品勢必是一個新的戰場。

Continue reading

EV3 讀取光感測器,使用 Grove EV3/NXT感測器轉接頭

本範例是透過 MindSensors 公司的Grove EV3/NXT感測器轉接頭將光感測器(光敏電阻)數值顯示於 EV3 螢幕

您的 EV3/NXT主機可以藉此控制/讀取多種 Arduino 系列周邊,需要另外下載本模組的 EV3 指令並匯入 EV3環境中。

延伸閱讀:

Continue reading

Grove感測器轉接EV3/NXT模組:燈光閃爍

一個機器人或自動化系統的豐富性就在於可運用的週邊數量與種類。樂高EV3系列除了樂高原廠所推出的數種感測器之外,還可以轉接其他公司所生產的感測器,例如HiTechnic 與 MindSensors。另一方面,Seeed Stduio 原本用於 Arduino 平台的Grove感測器系列中,有許多EV3沒有的感測器,搭配Mindsensor 公司所推出的Grove感測器轉接EV3/NXT模組,就能讓EV3控制LED燈、紫外線感測器、光敏感測器等眾多感應器,大大增加了EV3專題的變化性,並且降低了Grove感應器的使用門檻。當然,您需要將 Mindsensor 的 Grove adapter block 匯入EV3軟體中,請參考本文說明即可。

目前EV3可透過轉接模組使用的 Grove 模組如下(我們都有賣,歡迎洽詢喔):

  • 數位式光感測器
  • 光感測器
  • 氣壓感測器
  • 氣體感測器
  • 溫度感測器
  • 紅外線接收器/發射器
  • 繼電器
  • 按鈕
  • 開關
  • XY搖桿
  • 水位感測器 
  • 酒精感測器
  • 電力感測器
  • 聲音感測器
  • 濕度感測器
  • PH 酸鹼值感測器
  • UV 紫外線感測器

gsawithsensorsw1024

gsawithsensorsw1024

註:Grove是 Seeed Studio公司所生產週邊之專用 4 pin 接頭

延伸閱讀:

如何匯入其它指令模組到EV3環境

機器人王國商城購買Grove Adapter for NXT/EV3連結

[youtube=”https://www.youtube.com/watch?v=g33aGs73BfE”]

感測器接法相當直覺,轉接模組一頭接上EV3訊號線,一頭接Grove感應器訊號線即可使用。

14274407_1186268728133976_2134908349_o

網站向下滑,點選EV3 Block下載,如果需官方提供的範例檔可以點選旁邊的EV3 Sample

3

下載之後打開EV3,選擇 Tool > Block import > Browse > 選擇剛剛下載的EV3 Block > import,完成後重新開啟EV3軟體即可。

2

重新開啟後即可以在黃色感應器類別中的最右邊發現GroveSensorAdapter的指令方塊

4

Continue reading

[3月底出版] 機器人程式超簡單 LEGO MINDSTORMS EV3 動手做專題卷

照過來,照過來~ CAVEDU 2016 年第二本出版品要登場囉![機器人程式超簡單 LEGO MINDSTORMS EV3 動手做專題卷]讓您更能發揮手邊機器人的實力,還能藉著簡易的圖形化程式介面培養許多重要的程式設計觀念喔!

本書深入介紹了樂高EV3 機器人的諸多進階應用,介紹了迴圈、分岔、多工等程式設計技巧,也介紹了其他可用於EV3 的非原廠感測器。期待您的孩子、學生,或是您自己,都能體驗動手做學習過程中的滿足與喜悅。

機器人程式超簡單EV3(增訂版)-封面-正-01

以下為本書目錄,預計本月底出版。屆時本書相關程式檔(.ev3)  CAVEDU 網站下載。

第1 章 樂高機器人發展史與零件介紹

1-1 樂高機器人發展史
1-2 EV3 硬體介紹
1-3 EV3 主機介面介紹

第2 章 EV3軟體安裝與環境介紹

2-1 零售版軟體下載安裝
2-2 EV3軟體介面
2-3 我的第一個程式

第3 章 碰碰車與避障車

3-1 碰碰車
3-2 避障車
3-3 Mindensors SumoEye 避障車

第4 章 紅外線遙控車

4-1 紅外線感測器方塊模式
4-2 機器人設計
4-3 程式設計

第5 章 藍牙遙控車

5-1 學習目標
5-2 簡易線控遙控車
5-3 訊息傳遞指令介紹
5-4 藍牙遙控車

第6 章 循跡機器人

6-1 基本組裝
6-2 程式編寫
6-3 P 控制程式編寫
6-4 MindSensors LineLeader-v2 光感測器陣列

第7 章 打地鼠一

7-1 學習目標
7-2 陣列指令介紹
7-3 程式說明

第8 章 打地鼠二

8-1 學習目標
8-2 變數指令介紹
8-3 讓你的EV3 可以發出聲音
8-4 地鼠冒出頭程式之二
8-5 成績計算

第9 章 超音波電子琴

9-1 新增超音波方塊
9-2 電子琴組裝
9-3 EV3 的聲音指令
9-4 程式編寫

第10 章 App Inventor 結合機器人控制

10-1 學習目標
10-2 App Inventor2
10-3 藍牙遙控機器人
10-4 程式說明

附錄A 組裝範例機器人
附錄B 聲音與圖片功能
附錄C 使用Wifi
附錄D 匯入MindSensors 指令模組到EV3軟體

Lego Wedo 2.0 軟體介面

樂高的 Wedo 2.0 來了,定位在比EV3機器人套件更容易使用的軟體與硬體,但維持樂高一貫的沒有說明書也會用的風格。只要填好相關資訊就可以下載電腦端軟體(PC / Mac都有),也有 iOSAndroid 版本可用。更多細節請參考 LEGO Wedo 的問答頁面以及探奇邱老師的部落格

WeDo core set 詳細內容請看這,幫各位簡單整理如下:

  • 280 片樂高零件
  • WeDo 2.0 主機 – Smarthub 是屬於 LEGO Power Function (LPF)  2.0 系統下的電子系統,內建了 BLE 可與外部的軟體 / App 連線。電源為 AA 電池兩顆或用充電電池,有兩個 I/O埠可連接馬達、感測器或 LPF 系統元件。另外也有 RGB 燈號,可以顯示最多10種顏色來與使用者互動。
  • 中型馬達Medium Motor
  • 動態感測器Motion sensor – 可偵測 15cm 範圍之內是否有東西在移動,也可當作簡易的測距儀來使用 (最多一樣是 15 cm)
  • 傾斜感測器Tilt sensor – 偵測本體傾斜的方向。WeDo 新增了 “搖晃 (shake)” 模式。本感測器可偵測六種不同位置的變化:Tilt This Way, Tilt That Way, Tilt Up, Tilt Down, No tilt, Any tilt (shake)
  • 標示用的貼紙

就來看看PC端的環境吧,其他環境當然也是差不多的,就看您喜歡哪一種環境囉。某方面來說應該與售價(官網定價159.95美金)有不小的關係,直接購買 EV3 好像划算多了呢。

Continue reading

150402 木柵國中EV3機器人體驗課程

木柵國中輔導室為了讓小朋友接觸不同的課程、吸收更多的資訊,特別開了一天半的機器人課程,本日只有半天三小時,時間相當緊湊,參加的小朋友人數多達15位,EV3七套,只好採用分組方式,2-3人一組,雖然如此,小朋友還是很認真的在「玩」積木、學程式,透過不斷的嘗試錯誤,小朋友和機器人都愈來愈進步,讓我們來看看過程吧:

首先當然要組裝車子,透過觀察事先準備好的範例車體來進行組裝,看似簡單,實則考驗耐心與細心,而且有限時二十分鐘喔!!!

3

分組的好處就是每個人透過討論都能有參與感,壞處就是要討論出一個共識需要花很久的時間,而範例提供了一個清楚的目標讓組員去達成,目標有了,所有的討論都會集中於一點,每個人的參與度提高,效率不錯!!

1

 

加上有限定時間二十分鐘,緊張度提高,在最後五分鐘的時候,幾乎每一組都拿著積木跑到台前來組裝!!

2

 

再來就是讓車子動起來,透過EV3-G的馬達方塊,除了基本的前進、後退、轉彎外,還利用差速方式讓車有擁有三種轉彎方式,最後再加裝觸碰感測器,做出讓車子碰到牆壁後能再走回來的效果。

4

 

透過不斷地嘗試錯誤,慢慢修改出聰明的車子

5

 

回車競賽:看誰的車子碰到牆壁後最先跑回起點!!

6

 

車子衝出去的瞬間,大家都笑了…

7

 

第二回合稍微調換了一下位置後,再出發!!

9

8

雖然只有短短的三個小時,但大家都玩得很高興,過程中甚至大家都還會改裝車子,期待下次再相會囉!!

[Mindsensors測試]馬達與感測擴充(NXTMMX-v2、SensorMUX-v1、TouchMux、SPLIT-Nx-v2)

Mindsensors有許多有趣的感測器與擴充,但並不是每個都可以讓EV3使用,而有些長得一樣,功能並不一樣,近日也被人問到這些東西到底有哪裡不一樣,今天我們就以這四款擴充器來一一比較解釋:

T1

觸碰感測器擴充(TouchMux),顧名思義就是專門來裝觸碰感測器用的,EV3/NXT都可使用,範例和使用者手冊可點此前往查看。

touchmux1touchmux

感測器擴充(SensorMUX-v1),顧名思義也是讓你裝感測器用,如果裝馬達,則全部的馬達會同時動,但裝馬達則需要額外接電池,NXT用,無EV3專用的BLOCK,相關範例及使用者手冊點此前往。

mux1mux

馬達與感測器擴充(NXTMMX-v2),有二個馬達埠和一個感測器埠,需額外裝電池,EV3/NXT可用,相關範例及使用者手冊可點此前往。

mmx1mmx

最後一個分接器,只能接數位感測器,支援的裝置這裡有說明,目前並沒有專用的BLOCK,而是需要輸入感測器的I2C值來讀取,點此前往查看使用者手冊,目前測試分接器接NXT超音波感測器可以讀得到值。

[即將出版] 樂高機器人創意寶典 181種絕妙新組合 – 五十川芳仁老師大作

五十川芳仁老師的 EV3 Idea book,英文版由 no starch press 出版,繁體中文就由 CAVEDU 翻譯完成囉(其實沒幾個字…)

每每在設計機構卡關時,就會到五十川老師的網站來尋找靈感,因此這本書之後也會用在 CAVEDU 的基礎組裝與機器人課程中喔,多玩就對了~

ach018700-01

[3/29_C-Day有什麼?]系列之七:leJOS Wifi 遙控多台樂高EV3 機器人

手機遙控樂高機器人在以往 NXT 的時代,只能用藍牙點對點,手機端是 master,樂高機器人則是 slave。手機端能連多少台藍牙裝置是根據胎手機而定,不過一般來說兩台是沒問題的。今天如果改用 Wifi 的話就不會受限於Android 手機的藍芽配對裝置數量了。本文說明如何透過 Wifi 來控制兩台樂高 EV3 機器人,同步或非同步控制都可以,請看以下影片。

延伸閱讀:

[leJOS] 準備開機用 SD記憶卡 – 用 Java 程式控制樂高EV3機器人

這是使用 App Inventor 來控制兩台樂高 NXT 機器人:

接著來看程式碼,這是 Android 端的src,重點在於建立兩個 socket 來對兩台機器人發送指令(line 179,205):

package com.cavedu.ev3_socketremote;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends ActionBarActivity implements OnClickListener {

	//Device 1
	Socket clientSocket1;
	BufferedReader inbound;
	PrintWriter outbound;

	String sendStr = "";

	Button Connect, FWD, BACK, LEFT, RIGHT, STOP;
	EditText deviceIP, devicePort;
	
	//Device 2
	Socket clientSocket2;
	BufferedReader inbound2;
	PrintWriter outbound2;

	String sendStr2 = "";

	Button Connect2, FWD2, BACK2, LEFT2, RIGHT2, STOP2;
	EditText deviceIP2, devicePort2;

	//初始化
	void init(){
		FWD = (Button) findViewById(R.id.FWD);
		BACK = (Button) findViewById(R.id.BACK);
		RIGHT = (Button) findViewById(R.id.RIGHT);
		LEFT = (Button) findViewById(R.id.LEFT);
		STOP = (Button) findViewById(R.id.STOP);

		FWD.setOnClickListener(this);
		BACK.setOnClickListener(this);
		LEFT.setOnClickListener(this);
		RIGHT.setOnClickListener(this);
		STOP.setOnClickListener(this);
		
		deviceIP = (EditText) findViewById(R.id.device1_ip);
		devicePort = (EditText) findViewById(R.id.device1_port);
		Connect = (Button) findViewById(R.id.Connect);

		FWD2 = (Button) findViewById(R.id.FWD2);
		BACK2 = (Button) findViewById(R.id.BACK2);
		RIGHT2 = (Button) findViewById(R.id.RIGHT2);
		LEFT2 = (Button) findViewById(R.id.LEFT2);
		STOP2 = (Button) findViewById(R.id.STOP2);
		
		FWD2.setOnClickListener(this);
		BACK2.setOnClickListener(this);
		LEFT2.setOnClickListener(this);
		RIGHT2.setOnClickListener(this);
		STOP2.setOnClickListener(this);
		
		deviceIP2 = (EditText) findViewById(R.id.device2_ip);
		devicePort2 = (EditText) findViewById(R.id.device2_port);
		Connect2 = (Button) findViewById(R.id.Connect2);
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		init();		//初始化

		//設定前進、後退、左轉、右轉按鈕Enabled為Flase 在未連線時無法點選
		setDeviceButton(false);
		setDevice2Button(false);
		
		//按下Connect使Device1連線
		Connect.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				
				//Device 1 Socket Client連線
				if (Connect.getText().equals("Connect")) {
					
					//建立Socket連線
					Thread t1 = new Thread(runnable);	
					t1.start();
					
				} 
				
				//Device 1 Socket Client斷線
				else if (clientSocket1.isConnected()) {
					try {
						Log.w("AndyDebug", "ClientSocket1 Close");
						clientSocket1.close();
						Connect.setText("Connect");
						setDeviceButton(false);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		});
		
		//按下Connect使Device2連線
		Connect2.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				
				//Device 1 Socket Client連線
				if (Connect2.getText().equals("Connect")) {
					Thread t1 = new Thread(divice2runnable);
					t1.start();
				} 
				
				//Device 2 Socket Client斷線
				else if (clientSocket2.isConnected()) {
					try {
						Log.w("AndyDebug", "ClientSocket1 Close");
						clientSocket2.close();
						Connect2.setText("Connect");
						setDevice2Button(false);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		});

	}

	//Device 1 建立Socket連線
	Runnable runnable = new Runnable() {
		public void run() {
			try {

				String ip = deviceIP.getText().toString();
				int port = Integer.parseInt(devicePort.getText().toString());

				clientSocket1 = new Socket(ip, port);	//建立Socket連線

				if (clientSocket1.isConnected()) {
					runOnUiThread(new Runnable() {
						public void run() {
							Connect.setText("Close");
							setDeviceButton(true);
						}
					});
				}

				Log.d("AndyDebug", "is?" + clientSocket1.isConnected());

				//Socket 接收
				inbound = new BufferedReader(new InputStreamReader(
						clientSocket1.getInputStream()));

				//Socket 發送
				outbound = new PrintWriter(clientSocket1.getOutputStream(),
						true);

			} catch (IOException ioe) {
				System.err.println("IOException: " + ioe);
				runOnUiThread(new Runnable() {
					public void run() {
						Connect.setText("Connect");
						setDeviceButton(false);
					}
				});
			}
		}
	};

	//Device 1 透過Socket收發資料
	Runnable runnable2 = new Runnable() {
		public void run() {
			try {

				String sss = sendStr + "\r\n";

				char send[] = sss.toCharArray();

				Log.d("AndyDebug", "送出: " + sss);

				outbound.println(send);		//送出資料

				String inputLine = "";

				//接收資料
				while ((inputLine = inbound.readLine()) == null) {
				}
				Log.d("AndyDebug", "收到:" + inputLine);

			} catch (Exception e) {
				System.err.println("IOException: " + e);
			}
		}
	};
	
	//Device 2 建立Socket連線
	Runnable divice2runnable = new Runnable() {
		public void run() {
			try {

				String ip = deviceIP2.getText().toString();
				int port = Integer.parseInt(devicePort2.getText().toString());

				clientSocket2 = new Socket(ip, port);		//建立Socket連線

				if (clientSocket2.isConnected()) {
					runOnUiThread(new Runnable() {
						public void run() {
							Connect2.setText("Close");
							setDevice2Button(true);
						}
					});
				}

				Log.d("AndyDebug", "clientSocket2"+clientSocket2.toString());

				//Socket 接收
				inbound2 = new BufferedReader(new InputStreamReader(
						clientSocket2.getInputStream()));

				//Socket 發送
				outbound2 = new PrintWriter(clientSocket2.getOutputStream(),
						true);

			} catch (IOException ioe) {
				System.err.println("IOException: " + ioe);
				runOnUiThread(new Runnable() {
					public void run() {
						Connect2.setText("Connect");
						setDevice2Button(false);
					}
				});
			}
		}
	};

	//Device 2 透過Socket收發資料
	Runnable device2runnable2 = new Runnable() {
		public void run() {
			try {

				String sss = sendStr2 + "\r\n";
				Log.e("AndyDebug", sendStr2);
				char send[] = sss.toCharArray();

				Log.d("AndyDebug", "送出: " + sss);

				outbound2.println(send);		//送出資料

				String inputLine = "";

				//接收資料
				while ((inputLine = inbound2.readLine()) == null) {
				}
				Log.d("AndyDebug", "收到:" + inputLine);

			} catch (Exception e) {
				System.err.println("IOException: " + e);
			}
		}
	};

	@Override
	public void onClick(View v) {
		switch (v.getId()) {

		case R.id.FWD:
			sendStr = "FWD";
			sendCommand();
			break;

		case R.id.BACK:
			sendStr = "BACK";
			sendCommand();
			break;

		case R.id.LEFT:
			sendStr = "LEFT";
			sendCommand();
			break;

		case R.id.RIGHT:
			sendStr = "RIGHT";
			sendCommand();
			break;

		case R.id.STOP:
			sendStr = "STOP";
			sendCommand();
			break;
		case R.id.FWD2:
			sendStr2 = "FWD";
			sendCommand2();
			break;

		case R.id.BACK2:
			sendStr2 = "BACK";
			sendCommand2();
			break;

		case R.id.LEFT2:
			sendStr2 = "LEFT";
			sendCommand2();
			break;

		case R.id.RIGHT2:
			sendStr2 = "RIGHT";
			sendCommand2();
			break;

		case R.id.STOP2:
			sendStr2 = "STOP";
			sendCommand2();
			break;
		default:
			break;
		}
	}

	private void sendCommand() {
		Thread t2 = new Thread(runnable2);
		t2.start();
	}
	private void sendCommand2() {
		Thread t2 = new Thread(device2runnable2);
		t2.start();
	}

	private void setDeviceButton(boolean b) {
		FWD.setEnabled(b);
		BACK.setEnabled(b);
		LEFT.setEnabled(b);
		RIGHT.setEnabled(b);
		STOP.setEnabled(b);
	}
	
	private void setDevice2Button(boolean b) {
		FWD2.setEnabled(b);
		BACK2.setEnabled(b);
		LEFT2.setEnabled(b);
		RIGHT2.setEnabled(b);
		STOP2.setEnabled(b);
	}
}
Wifi 遙控,Android 端程式

樂高機器人端的程式,使用 leJOS 編寫。一樣是去判斷 socket 收到的內容之後執行對應的動作即可:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

import lejos.hardware.Button;
import lejos.hardware.Key;
import lejos.hardware.KeyListener;
import lejos.hardware.lcd.LCD;
import lejos.hardware.motor.Motor;

class LeJOS_WiFi {

	static int angle = 270; // 馬達轉動的角度

	private static boolean OutServer = false;
	private static ServerSocket server;
	private final static int ServerPort = 1234; // 要監控的port

	public static void main(String[] args) {

		//按下ESCAPE鍵離開程式
		Button.ESCAPE.addKeyListener(new KeyListener() {
			public void keyReleased(Key k) {
				System.exit(0);
			}
			public void keyPressed(Key k) {}
		});

		print("Start");
		
		Thread socketServer_thread = new Thread(socketServer_runnable);
		socketServer_thread.start();

		while (true);
	}

	//建立SocketServer
	public static void SocketServer() {
		try {
			server = new ServerSocket(ServerPort);

		} catch (java.io.IOException e) {
			print("Socket Error!");
			print("IOException :" + e.toString());
		}
	}

	static Runnable socketServer_runnable = new Runnable() {
		public void run() {
			SocketServer();

			Socket socket;

			print("Socket Server OK!");

			while (!OutServer) {
				socket = null;
				try {
					synchronized (server) {
						socket = server.accept();
					}
					print(socket.getInetAddress().toString()); //印出目前連線設備的ip

					//Socket接收
					BufferedReader inbound = new BufferedReader(
							new InputStreamReader(socket.getInputStream()));

					//Socket發送
					PrintWriter outbound = new PrintWriter(
							socket.getOutputStream(), true);

					while (true) {
						String data = "";

						outbound.println("Success");

						while ((data = inbound.readLine()) == null)
							;

						if (data.length()>=3)
							print("getData:" + data);

						if (data.equals("FWD")) {
							go();
							outbound.print(data + " OK");
						} else if (data.equals("BACK")) {
							back();
							outbound.print(data + " OK");
						} else if (data.equals("LEFT")) {
							left(angle);
							outbound.print(data + " OK");
						} else if (data.equals("RIGHT")) {
							right(angle);
							outbound.print(data + " OK");
						} else if (data.equals("STOP")) {
							stop();
							outbound.print(data + " OK");
						}
					}

				} catch (java.io.IOException e) {
					print("Socket Error");
					print("IOException :" + e.toString());
					Thread socketServer_thread = new Thread(socketServer_runnable);
					socketServer_thread.start();
				}
			}
		}
	};
	
	//前進
	private static void go() {
		Motor.A.forward();
		Motor.B.forward();
	}

	//後退
	private static void back() {
		Motor.A.backward();
		Motor.B.backward();
	}

	//左轉
	private static void left(int angle) {		
		Motor.A.rotate(-angle, true);
		Motor.B.rotate(angle, true);
	}

	//右轉
	private static void right(int angle) {
		Motor.A.rotate(angle, true);
		Motor.B.rotate(-angle, true);
	}

	//停止
	private static void stop() {
		Motor.A.stop();
		Motor.B.stop();
	}

	//在EV3螢幕印出字串
	private static void print(String str) {
		LCD.clear();
		LCD.drawString(str, 0, 3);
	}

}
Wifi 遙控,機器人端程式

 

MindSensors 推出的 Grove Sensor Adapter,可用於樂高 EV3 與 NXT 機器人主機

Grove 感測器系列是 Seeed Studio 推出的感測器套件包,搭配自家的擴充板,讓複雜的接線變得簡潔許多。現在 MindSensors 推出了 Grove Sensors 轉接頭,可將各種Grove 感測器轉接到樂高 EV3 與 NXT 主機上使用。

 

GSAwithsensorsw1024

 

當然,也提供了 EV3 的指令,請在本頁面下載後匯入 EV3 環境即可使用。但由下圖可知,提供的是底層的讀寫指令,並未針對特定的感測器提供專屬的讀寫指令。分別有 I2C Read, I2C Write, Analog 與 Digital 等四大類指令。

螢幕快照 2015-02-28 下午11.53.39 螢幕快照 2015-02-28 下午11.53.50