RoBoard魔人的機器人日誌

2014/3/6

[86Duino] ZERO硬體介紹

究竟什麼是86Duino?


86Duino ZERO正面


86Duino ZERO背面



根據86Duino的網站(http://www.86duino.com/index.php?lang=TW),
它是:

86Duino為新一代的開放式硬體平台(open-source hardware platform),採用Vortex86EX 處理器,提供更快的處理效能及高擴充性,且完全相容Arduino系列,並可支援x86架構的作業系統及執行以Arduino為基礎的系統。
86Duino採用了高性能32位元的x86兼容處理器,可以額外安裝Windows、Linux 和最流行的32位RTOS O/S,在單一封裝內集成了PCIE,DDR3,ROM控制器,xISA,I2C,SPI,IPC(DMA和中斷定時器/計數器包括內部外設控制器),網路,FIFO UART,USB2.0和SD/ SATA控制器形成一個系統級晶片(SOC)。
86Duino 提供了一個超完美的解決方案,開放式的硬體與軟體,可自行下載電路圖,讓使用Arduino及嵌入式系統的藝術家、設計師、業餘愛好者、任何有興趣的人,建立打造互動式科技所需的性能。

簡單來說86Duino是一套可程式化的微型計算機系統,
你可以使用指令與各種形式的輸入與輸出進行互動。
圖示86Duino的型號為ZERO,體積遠小於魔人的手掌大小。

體積相當小的86Duino ZERO

對於剛接觸的人來說,它的功能相當類似於Arduino,
對於輸入和輸出的設備幾乎是無限制的,例如:感測器、顯示器、電機設備等,
你可以設定確切需要的互動,創建一個符合功能的裝置。
事實上,86Duino是可以完全相容Arduino的程式的,測試後,
你將會發現86Duino可以完美的做出Arduino可以做的事,但卻又增加了新的功能。

現在,讓魔人帶領你們更仔細的探索86Duino ZERO硬體(也就是瞭解「實體的部分」),
並看看我們將實做出什麼。
別太擔心要如何寫程式或設計電路,因為本魔會陸續的將這些東西做出個簡易的成果。

●現在讓我們快速的瀏覽ZERO,從版子的左側開始,你將會看到三個連接器,如圖示:

USB_DEV、USB與電源連接器
官方硬體圖

USB_DEV(USB Device/Programming Port)連接器,
此連接器的線材使用USB轉Micro USB的線傳輸即可(即一般智慧手機之傳輸線),
此連接器為了以下三個原因連結主版與你的電腦:
  1. 提供主板電源
  2. 上傳你的指令到主版
  3. 從電腦傳送和接收資料
USB(USB 2.0 Port),
此USB與前面介紹到的USB_DEV不同點在於,USB_DEV是用來與電腦連結、傳輸資料的,
而此USB是用來與裝置連結、讀取裝置用,例如:鍵盤、滑鼠、藍芽接收器等。

最後看到的是電源連接器,透過此連接器你可以使用7-12V的電源變壓器(或電池)對86Duino供電。

●接著看到的是86Duino主版的核心:Vortex86EX SOM-128-EX

Vortex86EX SOM-128-EX(左方為正面、右方為背面)

根據86Duino的網站的介紹(http://www.86duino.com/index.php?p=374&lang=TW):


SOM-128-EX is a subtype of an embedded system and more likely an extension concept of system on chip. The reason we specially design this is that we understand what the difficult part of developing a new system is.
Usually, a tailored system for a special application would involve high overhead cost; however, if one adopts SOM, one can easily implement the already laid out pins of I/Os and connectors for consumers who want a customized system without committing months of design and paperwork.


SOM-128-EX是一個嵌入式系統的子型且系統能更容易的擴展概念在這晶片上,我們特別這樣設計的原因是因為我們知道開發一個新系統的困難點。
通常,特定系統的特殊應用會包括高昂的開銷,但是如果採用了SOM,人們可以很容易的實現輸入輸出和連接器在已經定義的腳位,這使人們不用為了一個特定的系統花幾個月的時間設計以及閱讀文件。

而此處理器是86Duino的「大腦」,他是一台具有處理器(CPU)可執行指令的微型電腦,
也包含了儲存程式中的資料與指令,並提供各種控制的途徑。

●接著看到處理器的上下方各有一排插槽,本魔由下排開始介紹:
左圖為下排插槽、右圖為官方硬體圖

第一排插槽用來提供電源,此外還有NC(Not Connected)為沒有連接的腳位,
以及可以連接一個外部重置(RESET)的按鈕進行重置功能。
第二排插槽提供了6個ADC輸入,可以用來測量電子訊號的電壓變化。

●接著看到上排:
左圖為上排插槽、右圖為官方硬體圖

這裡可以看到0到13的插槽為訊號輸入輸出(I/O),
它可以用來偵測是否存在一個電子訊號,或是用指令產生一個訊號。
插槽0與插槽1被稱為序列連接埠(Serial Port),用來傳送與接收其他設備的資料。
由波浪號(~)標記的插槽可以產生不同的電子訊號,例如:建立燈光效果或控制伺服馬達。
然而最上方可以看到串列資料(SDA)及串列時脈(SCL)的獨立插槽,
這兩個插槽通常是用在內部整合電路(Inter-Integrated Circuit,I²C)的傳輸上。

●接下來介紹在86Duino的右方的10根針腳與PCI-E插槽:


SPI與PCI-E


官方硬體圖

串列外設介面(Serial Peripheral Interface Bus,SPI),
有點類似先前介紹的內部整合電路(Inter-Integrated Circuit,I²C),
是一種4線同步序列資料協定,適用於可攜式裝置平台系統。
然而看到下面的PCI Express,簡稱PCI-E,是電腦匯流排PCI的一種,
可以與電腦直接的做溝通,但必須動些手腳,這裡就不提太多,
如果真的很想知道怎麼使用,可以直接向86Duino官方詢問。

●接下來是一些非常有用的設備,發光二極體(Light-emitting diodes,LED),

當電流通過這些微小的裝置時它們就會發亮。

左圖為發光二極體、右圖為官方硬體圖

86Duino主版有4顆LED,其中最右邊且標記ON(硬體圖為PWR)的LED,會在主板有通過電時亮燈。
然而標記TX和RX的LED會在資料透過序列埠(serial port)與USB86Duino和連接的設備間傳送與接收資料時會亮燈。
最後是標記L的LED是提供你個人使用(它與編號13的數位訊號輸入輸出(I/O)插槽連接)。

●正面的最後我們看到重置(Reset)按鈕:


重置按鈕

就如同電腦一樣,有時候86Duino也會發生錯誤,當所有的嘗試都失敗時,

你或許需要重置系統並重新啟動你的86Duino
在主板上的重置按鈕就是用來重新啟動系統來解決以上的問題。

●接下來看到86Duino的背面:



Micro-SD與LAN

我們可以明顯的看到MicroSD與LAN的插槽,
根據86Duino的網站的介紹(http://www.86duino.com/index.php?p=3401&lang=TW):


雖然每片 86Duino 開發板在出廠時,皆已內建 86Duino 韌體系統於板上的 Flash 記憶體內,但我們仍建議使用者改在 MicroSD 卡上建立及執行 86Duino 韌體系統,這有下列好處:
  • MicroSD 卡讀寫速度比板上 Flash 快,特別是寫入速度快數十倍以上,以 MicroSD 卡燒錄 sketch 程式可大幅縮短燒錄時間。此外,亦可小幅縮短 86Duino 開機時間。
  • 板上 Flash 有寫入次數限制,過度頻繁地寫入會降低其壽命,且損壞後更換不易。改由 MicroSD 卡執行 86Duino 韌體系統,可減少對板上 Flash 的寫入次數,延長 Flash 的壽命。
  • 板上 Flash 內也儲存 86Duino 的 BIOS,自行寫程式對其進行資料寫入有一定風險。MicroSD 卡價格低廉且用壞即丟,可在上面寫程式亂玩,使用限制更少更靈活。

簡單的說,加入MicroSD可以使86Duino讀取速度變快且較不用擔心控制板的壽命問題,
若是沒有使用MicroSD,也不用擔心86Duino不能使用。

接著看到區域網路(Local Area Network,LAN)的插槽,

相較於傳統Arduino,86Duino有了LAN的插槽,你就不需要為了此功能再去購買乙太網路介面擴充(Ethernet shield)。

但當然若是想要使用更多功能,86Duino也是可以相容於Arduino的擴充板的,
但請注意,你需要記得哪個擴充版使用了哪個輸入與輸出以確保不會發生「衝突」,
你也可以購買完全空的擴充板,用來新增你自己的電路。



























內容參考自:《Arduino自造指南:從65個專案玩透Arduino》
Share:

2013/12/6

[機械六足] 智慧手機控制器

上次發了一篇近況文

也告訴了大家我下一步想要做的東西

那魔人就來一步一步的製作&分享給大家吧

今天要分享的是智慧手機控制器的搖桿控制

還記得上次我的介紹吧

我要用遙感的方式控制六足的前進方向

而遙桿在網路上的範例已經有很多了

實做的方法是這樣的

用canvas畫圖 & 用Thread讀取螢幕觸碰的事件

讀取後去計算 & 重新畫圖   就可以做到搖桿的效果了

以下影片範例



這個範例是控制小android在螢幕上移動




接著是程式碼囉

MainActivity.java

package com.example.joystick;

import android.os.Bundle;
import android.app.Activity;
import android.view.WindowManager;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
    WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(new GameSurface(this));
 }
}

GameControl.java
package com.example.joystick;

import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class GameControls implements OnTouchListener{

 public float initx = 0;
 public float inity = 0;
 public Point _touchingPoint = new Point(0,0);
 public Point _pointerPosition = new Point(220,150);
 private Boolean _dragging = false;
 private double degree = 0;
 @Override
 public boolean onTouch(View v, MotionEvent event) {

  update(event);
  return true;
 }

 private MotionEvent lastEvent;
 public void update(MotionEvent event){

  if (event == null && lastEvent == null)
  {
   return;
  }else if(event == null && lastEvent != null){
   event = lastEvent;
  }else{
   lastEvent = event;
  }
  if ( event.getAction() == MotionEvent.ACTION_DOWN ){
   _dragging = true;
  }else if ( event.getAction() == MotionEvent.ACTION_UP){
   _dragging = false;
  }
  

  if ( _dragging ){
   _touchingPoint.x = (int)event.getX();
   _touchingPoint.y = (int)event.getY();
   
   _touchingPoint.x -= 250;
   _touchingPoint.y -= 250;
   if(_touchingPoint.x == 0 && _touchingPoint.y > 0)
    degree = Math.PI / 2;
   else if(_touchingPoint.x == 0 && _touchingPoint.y < 0)
    degree = Math.PI / 2 * 3;
   else if(_touchingPoint.x > 0)
    degree = Math.atan((double)_touchingPoint.y/_touchingPoint.x);
   else if(_touchingPoint.x < 0)
    degree = Math.PI + Math.atan((double)_touchingPoint.y/_touchingPoint.x);
   
   if(Math.sqrt(Math.pow(_touchingPoint.x,2) + Math.pow(_touchingPoint.y,2)) > 150){

    _touchingPoint.x = (int) (150.0 * Math.cos(degree));
    _touchingPoint.y = (int) (150.0 * Math.sin(degree));
    
   }
   
   _pointerPosition.x += ((double)_touchingPoint.x/30);
   _pointerPosition.y += ((double)_touchingPoint.y/30);
   if ( _pointerPosition.x > 480)
   {
    _pointerPosition.x= 0;
   }

   if ( _pointerPosition.x < 0){
    _pointerPosition.x = 480;
   }

   if (_pointerPosition.y > 840 ){
    _pointerPosition.y = 0;
   }
   if (_pointerPosition.y < 0){
    _pointerPosition.y = 840;
   }

  }else if (!_dragging)
  {
   if(Math.sqrt(Math.pow(_touchingPoint.x,2) + Math.pow(_touchingPoint.y,2)) <= 10){
    _touchingPoint.x = (int) initx;
    _touchingPoint.y = (int) inity;
   }else{
    _touchingPoint.x = (int) ((Math.sqrt(Math.pow(_touchingPoint.x,2) + Math.pow(_touchingPoint.y,2)) - 10)* Math.cos(degree));
    _touchingPoint.y = (int) ((Math.sqrt(Math.pow(_touchingPoint.x,2) + Math.pow(_touchingPoint.y,2)) - 10)* Math.sin(degree));
   }
   _pointerPosition.x += ((double)_touchingPoint.x/30);
   _pointerPosition.y += ((double)_touchingPoint.y/30);
   if (_pointerPosition.x > 480)
    _pointerPosition.x= 0;
   if (_pointerPosition.x < 0)
    _pointerPosition.x = 480;
   if (_pointerPosition.y > 840)
    _pointerPosition.y = 0;
   if (_pointerPosition.y < 0)
    _pointerPosition.y = 840;
  }
 }
}


GameJoystick.java
package com.example.joystick;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class GameJoystick {
 
 private Bitmap _joystick;
 private Bitmap _joystickBg;
 private Bitmap _trigger;
 private Bitmap _triggerDown;
 
 public Bitmap get_triggerDown() {
  return _triggerDown;
 }

 public void set_triggerDown(Bitmap triggerDown) {
  _triggerDown = triggerDown;
 }

 public GameJoystick(Resources res){
  
  _joystick = (Bitmap)BitmapFactory.decodeResource(res, com.example.joystick.R.drawable.joystick2);
  _joystickBg = (Bitmap)BitmapFactory.decodeResource(res, com.example.joystick.R.drawable.joystick_bg2);

 }

 public Bitmap get_joystick() {
  return _joystick;
 }

 public void set_joystick(Bitmap joystick) {
  _joystick = joystick;
 }

 public Bitmap get_joystickBg() {
  return _joystickBg;
 }

 public void set_joystickBg(Bitmap joystickBg) {
  _joystickBg = joystickBg;
 }
 
 public Bitmap get_trigger() {
  return _trigger;
 }

 public void set_trigger(Bitmap trigger) {
  _trigger = trigger;
 }
}


GameSurface.java
package com.example.joystick;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {

 private Context _context;
 private GameThread _thread;
 private GameControls _controls;

 private GameJoystick _joystick;
 private Bitmap _pointer;

 public GameSurface(Context context) {
  super(context);
  _context = context;
  init();
 }

 private void init(){
  SurfaceHolder holder = getHolder();
  holder.addCallback( this);

  _thread = new GameThread(holder, _context, new Handler(),this);
  setFocusable(true);


  _joystick = new GameJoystick(getContext().getResources());
  _pointer = (Bitmap)BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
  _controls = new GameControls();
  setOnTouchListener(_controls);
 }


 public void doDraw(Canvas canvas){

  _controls.update(null);
  
  canvas.drawBitmap(_joystick.get_joystickBg(), 100,100, null);

  canvas.drawBitmap(_joystick.get_joystick(),_controls._touchingPoint.x + 200, _controls._touchingPoint.y + 200, null);

  canvas.drawBitmap(_pointer, _controls._pointerPosition.x, _controls._pointerPosition.y, null);

 }

 @Override
 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}
 private boolean retry;
 @Override
 public void surfaceDestroyed(SurfaceHolder arg0) {
  retry = true;
  _thread.state = GameThread.STOPED;
  while (retry) {
   try {
    _thread.join();
    retry = false;
   } catch (InterruptedException e) {
   }
  }

 }

 @Override
 public void surfaceCreated(SurfaceHolder arg0) {
  if(_thread.state==GameThread.PAUSED){
   _thread = new GameThread(getHolder(), _context, new Handler(),this);
   _thread.start();
  }else{
   _thread.start();
  }
 }

 public void Update() {

 }

}



GameThread.java
package com.example.joystick;

import java.util.logging.Level;
import java.util.logging.Logger;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.view.SurfaceHolder;

public class GameThread extends Thread {

 private SurfaceHolder mSurfaceHolder;
 private Handler mHandler;
 private Context mContext;
 private Paint mLinePaint;
 private Paint blackPaint;

 private long sleepTime;
 private long delay=70;
 int state = 1;
 public final static int RUNNING = 1;
 public final static int PAUSED = 2;
 public final static int STOPED = 3;

 GameSurface gEngine;

 public GameThread(SurfaceHolder surfaceHolder, Context context, Handler handler,GameSurface gEngineS){
  mSurfaceHolder = surfaceHolder;
  mHandler = handler;
  mContext = context;
  gEngine=gEngineS;
 }

 private long beforeTime;
 @Override
 public void run() {

  //UPDATE
  while (state==RUNNING) {
   try {
    this.sleep(50);
   } catch (InterruptedException e1) {
    e1.printStackTrace();
   }
   beforeTime = System.nanoTime();
   gEngine.Update();

   Canvas c = null;
   try {
    c = mSurfaceHolder.lockCanvas(null);
    synchronized (mSurfaceHolder) {
     c.drawColor(0x66000000);
     gEngine.doDraw(c);
    }
   } finally {
    if (c != null) {
     mSurfaceHolder.unlockCanvasAndPost(c);
    }
   }


   this.sleepTime = delay-((System.nanoTime()-beforeTime)/1000000L);

   try {
    if(sleepTime>0){
     this.sleep(sleepTime);
    }
   } catch (InterruptedException ex) {
    Logger.getLogger(GameThread.class.getName()).log(Level.SEVERE, null, ex);
   }
   
   while (state==PAUSED){
    try {
     this.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }
 }}

Share:

2013/11/29

[RB魔人] 用小型區網建立良好的開發環境(五)

最近魔人拿到了一塊好東西


沒錯   它就是無線wifi啦

大家可能會好奇   現在這個時代   wifi有什麼好稀奇的

各位還記得魔人之前有發了四篇的系列文章也是介紹網路的嘛?

這次要介紹的就是   如何用wifi建立良好的開發環境

剩(線)勝有(線)嘛

而且之前本魔是使用藍芽做控制的

現在也不用這麼麻煩了

用網路就好啦~

檔案傳輸也沒問題

如此方便   就快點來教學吧

首先要有一顆USB的無線AP

裝上RoBoard



之後安裝驅動程式




安裝完之後便可找到裝置

之後設定wifi的名稱等




之後選橋接器連結   將無線網路與區網連結在一起


之後進入剛剛設定的網路就可以囉




再來是PC端

選擇連線後輸入密碼

之後就是一個小型的區域網路囉 

你也可以直接遠端到另一台電腦





















這讓本魔想到了

在某些地方連wifi時不是會有登入的頁面跑出來嘛?

如果我把機器人的手機控制程式丟在登入的網頁

那麼不就能夠用任何一台的手機裝置去控制了?


所以我最近會順便研究看看wifi登入頁面那如何實做

如果有神人知道方法    也敬請指教喔^^
Share:

2013/11/3

[機械六足] 近期新計畫

兩個月沒有更新文章了

大家有沒有想魔人阿XD

其實這一兩個月真的是由於學校的事務所以有些忙碌

然而這一兩個月魔人也不是閒著的喔!

這次要進行機械六足的新計畫了

之前各位都有看到我與實習生們合力製作的[RoBoard x League of Legends] 史加納Skarnar

而當時推出的影片也受到了大家的肯定及迴響   ((在此說聲謝謝

而現在魔人要一個人繼續製作這台機械六足

將步態變得更加的完整

之前的步態   如果各位有看過source code   或是認真看過影片的話

就會發現其實我的移動方式只有6種

包括前後左右平移,加上左右轉彎

而魔人我是不會就此滿足的!

所以現在魔人我有一個新的想法

用智慧手機控制機械六足!

以下為設計草圖


























看不懂沒關係!

魔人來為您解釋

首先就是手機上會有搖桿的圖示

在上面推移就會決定機械六足的前進方向以及步距or速度

而智慧手機上的陀螺儀感測器可以決定六足身體的平衡


那各位說不定會想問這樣到底有幾種步態

答案是1~2種   一種是轉彎的步態  一種是平移的步態

大家別急!

雖然是只有兩種步態   但是移動的方向是由搖桿決定的

而那排列組合   就可以請各位去計算看看了

而或許也會想加入一些對話的功能

這方面還在思考要怎麼做當中











別認為魔人我是光說不練的

魔人我其實有開始在動工了喔!

近期會有個小成果上來給各位看看的!
Share:

2013/9/5

[RoBoard x League of Legends] 史加納Skarnar

相信各位都知道現在相當火紅的遊戲英雄聯盟

本魔此次與第六屆的實習生們一起合作做了一隻英雄聯盟裡的角色

而此次的作品也是完全open source的

但我們必須要在2個月內趕出成果,所以我們很快的開始了這個開源計畫



最一開始

我們有想過製作烏爾加特或布里茲

烏爾加特

布里茲
但是我們最後決定選擇了史加納

史加納


六隻腳走起來比較霸氣!對吧?

所以大家開始著手製作,基本上本魔負責最後的程式控制

而機構設計以及電路與造型則是交由實習生們來做

於是找到了一款較適合機器人的模組讓我們參考


在大家的努力下,首先做出了Solidworks的機構圖


相當帥氣對吧?

基本上頭部與外殼要用3D printer印出來,這樣也可以做出我們要的樣子

既然畫好圖了,那麼大家就開始動手實做出來

而本魔也沒閒著

六足機器人如果還用編動作的不是就low掉了嗎!?

沒錯!

這次本魔要用反運動學來算!

所以要了機構的長度,以方便計算



第一次拿到實體機器時,本魔相當興奮


立刻用RoBoME簡單的編了一個走路

立刻來看看由於是貼在facebook上面,所以要請各位移駕一下

==========>影片連結video link<==========

可以很明顯的感受到機械式的走法

但本魔是不會安於現狀的!

約過了一周,首先史加納的頭印好了,而本魔的反運動學步行也有了個雛形



以下影片


看起來順暢許多吧?

沒錯,而且加上了手的動作,實在霸氣許多

最後,完整版出來了

眼睛加上了紅色的LED

外殼也加了上去

甚至加了噴漆做顏色裝飾

還有最霸氣的超大聲喇叭

先來看看圖片吧!


帥吧!?

別急

後面還有影片!






最後來個maker的合影



既然是open source的計畫

那當然要opne code與design了

以下連結

Github Robot-Skarnar

RoBoard粉絲專頁



Maker list:
朱酉致 / Chu Ue Chih
李智皓 / Li Chih Hao
鄒秉翰 / Tsou Ping Han
RB魔人 / RoBoardGod


如果你喜歡,請幫我們到facebook按【讚】,謝謝。
If you like this, please click the【Like!】on our facebook comment, thank you.


Share:
技術提供:Blogger.

追蹤者