RoBoard魔人的機器人日誌

2012/1/16

[NXT系列第一彈] RoBoard控制Touch Sensor

NXT-Touch Sensor


首先來介紹下NXT的線

NXT-線材

看起來很像電話線(題外話)


好    拿起線材看一下他裡面的顏色吧!
NXT的線是固定的顏色
由右至左看的話
白 , 黑 , 紅 , 綠 , 黃 , 藍

每條線都對不同的Sensor都有不同的意義
所以千萬別亂接

為了要接到RoBoard上
可能需要買轉接頭   (如果要直接剪線直接做也是可以)

需要注意的一點是
白線要特別做一個10歐姆的電阻然後要並聯接起來(圖上是9+1)


一切準備就緒後
將Sensor接上RB吧!

首先
將白線10歐姆那條   接到VCC(5V)
白線 無電阻的那條接到  AD
黑線   接到GND
紅線   接到AD的GND
這是標準的接法    (讓兩條共地)

小提醒: 要先接地再接電比較安全喔

注意別接錯了   Sensor燒壞...  不負責...


程式部份
基本上  他只是讀取AD值   
未按下時通常為5V(值1023左右)      
被按下時會變到0.93V(值190左右)


範例影片:





範例code:
#include "stdio.h"
#include "conio.h"
#include "roboard.h"
int main(){
 roboio_SetRBVer(RB_110);
 int val = 0;
 bool setDo = false;
 spi_Init(SPICLK_21400KHZ);
 while(!kbhit()){
  val= adc_ReadCH(0);
  if(val == ADC_READFAIL){
   printf("error\n");
   break;
  }else{
   if(val < 512 && !setDo){
    setDo = true;   
    system("CLS");
    printf("PRESS\n");
   }else if(val >= 512 && setDo){
    setDo = false;   
    system("CLS");
    printf("RELEASE\n");
   }
  }
 }
 spi_Close();
 return 0;
}
Share:

2012/1/9

[開箱文] RB總部搶先看


1/30更新:

機器人足球場蓋好啦~~~ 三個小球場一個大球場
之前就說過這空間可以讓機器人追趕跑跳碰吧~

擺設機器人中...不然只拍場地頗單調

這場地真的還不小
以機器人的比例來看應該跟真的球場一樣大吧?

很大吧!!!??   本魔都變那麼小了!!!


1/18更新:
窗外的耶穌光


捷運站   跟上一次看起來真的差蠻多的


風景宜人~


有點散掉了   可惜


夕陽無限好阿~



捷運站   拉近版


右上角那看起來像天使??   (好像有些牽強)


透出一道道的耶穌光~


真期待捷運快蓋好   蓋好就可以拍到捷運了XD...






DM&P 瞻營全總部已經換地方囉!!



本魔在此推出RB總部的開箱文!!



 5星級的廁所!?





總部外空間真的很大!
都可以給機器人追趕跑跳碰了?





總部的辦公室內部
旁邊一排書架!

又一排書架!
一共3排
呈現一個ㄇ字型


.屋頂
太陽能板~!!
完全是綠建築阿!!


側面

近捷運
據說走路3分鐘可以到


風景宜人
好像說有耶穌光
可惜天氣不好

後面可以看到觀音山 


RB魔人的座位
目前東西都還在家中...
不過真的...很大!?


RB團隊(小部分)
Share:

2012/1/1

[練習] adjacency multilist

由於某天學到了這個圖形表示法

本魔就開始覺得這表示法怪怪的

問了RoBoard Lab後 我們找到了一篇N年前的論文

他主要是比較各種圖形表示法的優缺點


可以看得出來是用打字機打的...
他用的語言是Pascal
有興趣的人可以自己研究看看


然後我稍微介紹一下這種圖形表示法

他是用一個結構來做的

那結構有 mark,value1,value2,link1,link2

每個link代表本點接到的下一條線

舉例:  (網路搜尋到相關文章 都會找到一樣的範例)


mark是用來偵測是否把後面兩個link填完用的

填完後其實沒有什麼用處

畫掉的地方代表NULL 表示為沒有其他線了





然後我自己又想出了另一種方法來做adjacency multilist

我是用遞迴一層一層丟

遇到該新增的就新增

遇到該搜尋的就搜尋

然後將自己的address回傳

這樣就會自己填完這表格

也不需要特別去做mark的空間

以下為code:

#include <stdio.h>
#define graph_Max 4
struct Multilist{
 int val1;
 int val2;
 struct Multilist *link1;
 struct Multilist *link2;
};
Multilist **Matrix_to_Multilist(bool [][graph_Max]);
Multilist *Multilist_recursion(bool [][graph_Max],Multilist *[graph_Max],int,int);
int main(){
 //-------------graph-------------//
 /*
     ┌─0─┐
     │ │ │
     1─┼─2
     │ │ │
     └─3─┘
 */
 //-------------------------------//
 bool graph[graph_Max][graph_Max] = {
           {0,1,1,1},
           {1,0,1,1},
           {1,1,0,1},
           {1,1,1,0}};
 Multilist **list;
 list = Matrix_to_Multilist(graph);
 getchar();
 return 0;
}
Multilist **Matrix_to_Multilist(bool graph[][graph_Max]){
 Multilist *start[graph_Max];
 for(int i = 0; i < graph_Max; i++){
  start[i] = Multilist_recursion(graph,start,i,0);
  //-------------output steps-------------//
  Multilist *t = start[i];
  bool out = false;
  printf("start[%d] --> %X\n",i,t);
  while(!out){
   printf("%X:\t%d,%d,%X,%X\n",t,t->val1,t->val2,t->link1,t->link2);
   t = t->val1 == i ? t->link1 : t->link2;
   if(t == NULL)
    out = true;
  }
  printf("\n");
  //-------------output steps-------------//
 }
 return start;
}
Multilist *Multilist_recursion(bool graph[][graph_Max],Multilist *start[graph_Max],int x,int y)
{
 if(y >= graph_Max)  //If search out of the graph, then return NULL, means it's end.
  return NULL;
 if(!graph[x][y])  //If two point are not linked, then skip this step.
  return Multilist_recursion(graph,start,x,y+1);
 Multilist *t;  //Use on add a Mutilist or get next Mutilist. 
 if(x < y){  //If x < y, means we need to add a Multilist.
  t = new Multilist();
  t->val1 = x;
  t->val2 = y;
  t->link1 = Multilist_recursion(graph,start,x,y+1);  //let the Multilist link to next list.
  return t;
 }else if(x > y){  //If x > y, means we had a Multilist before.
  t = start[y];
  while(t->val2 != x)  //Loop until we find the Multilist which we need.
   t = t->val1 == y ? t->link1 : t->link2;  //Find next list.
  t -> link2 = Multilist_recursion(graph,start,x,y+1);  //let the Multilist link to next list.
  return t;
 }
}
Share:

2011/12/22

[練習] graph走訪程式

當一台機器人

想要讓他走到所有想讓他去的地方

那就需要利用走訪的程式

(本魔承認有點硬要扯到機器人...)

總之

來介紹一下兩種走訪方式



深度優先搜尋(depth - first search) 簡稱DFS

簡單的說就是先找到最深的路  再退回來走其他的路

像我的範例

若是用深度優先
他會從1 -> 2 -> 4 -> 3 然後沒路了   退回4  再走5     再往後退   都沒路就結束

以下為DFS的code

#include "stdafx.h"
#define graph_Max 5
void DFS(int);
static bool graph[graph_Max][graph_Max] = {
           {0,1,1,0,0},
           {1,0,0,1,0},
           {1,0,0,1,0},
           {0,1,1,0,1},
           {0,0,0,1,0}};
static int point_name[graph_Max] = {1,2,3,4,5};
int main(){
 DFS(0);
 getchar();
 return 0;
}
bool visited[graph_Max] = {false};
void DFS(int v){
 visited[v] = true;
 printf("%d\n",point_name[v]);
 for(int i = 0; i < graph_Max; i++)
  if(graph[v][i] && !visited[i])
   DFS(i);
}


廣度優先搜尋(breath - first search) 簡稱BFS

簡單的說就是將所有可走的路先走過  再走第二次...走到全部沒路為止
像我的範例

若是用廣度優先
他會從1 -> 2 & 3  然後1沒其他路   
2 -> 4  然後2沒其他路   
3 也沒其他路
再來到4 -> 5
最後的5  也沒路了    全部都沒路   結束


以下為BFS的code

#include "stdafx.h"
#define graph_Max 5
static bool graph[graph_Max][graph_Max] = {
           {0,1,1,0,0},
           {1,0,0,1,0},
           {1,0,0,1,0},
           {0,1,1,0,1},
           {0,0,0,1,0}};
static int point_name[graph_Max] = {1,2,3,4,5};
void BFS(int);
void push(int);
int pop();
bool isEmpty();
int main()
{
 BFS(0);
 getchar();
 return 0;
}
bool visited[graph_Max] = {false};
void BFS(int v){
 visited[v] = true;
 printf("%d\n",point_name[v]);
 for(int i = 0; i < graph_Max; i++)
  if(graph[v][i] && !visited[i]){
   visited[i] = true;
   push(i);
  }
 while(!isEmpty())
  BFS(pop());
}
int queue[graph_Max];
int first = 0;
int last = 0;
void push(int x){
 if(last >= graph_Max)
  last = 0;
 queue[last++] = x;
}
int pop(){
 return queue[first++];
}
bool isEmpty(){
 return first == last;
}



以上就是本魔這次介紹的兩個走訪程式
Share:

2011/12/16

[練習] 數獨程式


用NXT做的數獨機器人

前面比較繁瑣的工作是判斷位置

以及掃描出數字

將9*9表格讀入機器後就可以開始進行運算





藉此機會

就來研究看看解數獨的程式該如何寫吧

首先要瞭解規則

在1~9行內絕對只有1~9的數字 且不重複
在1~9列內絕對只有1~9的數字 且不重複
以每9格(正方) 為單位  9格內也只有1~9的數字 且不重複

例如:

1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 4 5 6 7 8 9 1
5 6 7 8 9 1 2 3 4
8 9 1 2 3 4 5 6 7
3 4 5 6 7 8 9 1 2

這就算是一個數獨的答案

然而數獨的每個題目  永遠都只會有一個答案(如果有很多答案就沒什麼好玩了)










第一種解法:
利用佇列解
我是參考書上寫的
不過這方法似乎只能解基本的數獨
因為他是將未填入數字的位置 存入佇列中
再一一拿出來做

因為有一些數獨是需要用判斷的才能解
所以這種解法可能無法適用於所有的題目




#include <stdio.h>
struct data_item{
 int x,y,val;
};
struct sudoku_item{
 int x,y;
 int num;
 int val[10];
 int resVal;
};
sudoku_item sudoku[9][9];
int rear,front;
data_item *dataQ[9*9];
void createQueue(){
   rear = front = 0;
}
void enque(data_item *dataItem){
 dataQ[rear] = dataItem;
 rear = (rear +1) % (9*9);
}
data_item *deque(){
 data_item *dataItem = dataQ[front];
 front = (front + 1)% (9*9);
 return dataItem;
}
int isEmpty(){
 return rear == front;
}
data_item *clrSudokuItem(int x, int y, int n){
 data_item *dataItem;
 int i;
 if(sudoku[x][y].resVal == 0){
  sudoku[x][y].num-= sudoku[x][y].val[n];
  sudoku[x][y].val[n] = 0;
  if(sudoku[x][y].num == 1)
   for(i = 1; i < 10; i++)
    if(sudoku[x][y].val[i] == 1){
     sudoku[x][y].resVal = i;
     dataItem = (data_item *) new data_item;
     dataItem ->x = x;
     dataItem ->y = y;
     dataItem ->val = i;
     return dataItem;
    }
 }
 return NULL;
}
void preprocess(int dataArr[][9]){
 data_item *dataItem;
 int i,j,k;
 createQueue();
 for(i = 0; i < 9;i++){
  for(j = 0; j< 9; j++){
   printf("%d ",dataArr[i][j]);
   if(dataArr[i][j] != 0){
    sudoku[i][j].num = 1;
    sudoku[i][j].resVal = dataArr[i][j];
    dataItem = (data_item *) new data_item;

    dataItem->x = i;
    dataItem->y = j;
    dataItem->val = dataArr[i][j];
    enque(dataItem);
   }else{
    sudoku[i][j].x = i;
    sudoku[i][j].y = i;
    for(k = 1; k<10; k++)
     sudoku[i][j].val[k] = 1;
    sudoku[i][j].num = 9;
    sudoku[i][j].resVal = 0;
   }
  }
  printf("\n");
 }
}
void processSudoku(){
 data_item *dataItem,*retData;
 int i,j;
 while(!isEmpty()){
  int x,y,val;
  dataItem = deque();
  x =dataItem->x;
  y =dataItem->y;
  val = dataItem->val;
  for(i = 0; i<9; i++){
   if(i != y){
    retData = clrSudokuItem(x,i,val);
    if(retData != NULL)
     enque(retData);
   }
   if(i != x){
    retData = clrSudokuItem(i,y,val);
    if(retData != NULL)
     enque(retData);
   }
  }
  for(i = 0; i<3; i++)
   for(j = 0; j<3; j++){
    int m = x/3 *3 +i;
    int n = y/3 *3 +j;
    if(m!=x && n != y){
     retData = clrSudokuItem(m,n,val);
     if(retData != NULL)
      enque(retData);
    }
   }
 }
}
void output(){
 int i,j;
 printf("Answer:\n");
 for(i = 0; i<9; i++){
  for(j = 0; j<9; j++)
   printf("%d ",sudoku[i][j].resVal);
  printf("\n");
 }
}
int main(){
 int data[9][9] = {
  {3,0,1,0,0,9,0,5,0},
  {0,9,0,0,0,4,1,8,0},
  {0,0,0,6,2,0,9,0,4},
  {1,0,0,0,4,0,0,6,0},
  {0,5,0,0,6,0,0,4,0},
  {0,8,0,9,7,0,5,0,2},
  {0,0,5,0,3,2,0,0,0},
  {0,2,9,0,0,0,0,0,5},
  {0,6,0,5,9,0,4,0,0}};
 preprocess(data);
 processSudoku();
 output();
 getchar();
 return 0;
}







第二種解法:
第二次我是利用遞迴讓所有可能性直接跑完(直到有答案)
相信大家都知道遞迴的缺點 浪費時間,空間
不過我還沒想到可以縮短執行時間,空間的方法
若有 歡迎指教

#include "stdafx.h"
struct local_mark{
 int x[9];
 int y[9];
 int z[9];
};
struct point{
 int x;
 int y;
};
local_mark *Number_Place_set(int [][9]);
bool Number_Place_game(int [][9], local_mark *);
int local_val(int, int);
int bitcount(int );
void print_data(int [][9]);
int main(){ 
 int data[9][9] = {
     {3,0,1,0,0,9,0,5,0},
     {0,9,0,0,0,4,1,8,0},
     {0,0,0,6,2,0,9,0,4},
     {1,0,0,0,4,0,0,6,0},
     {0,5,0,0,6,0,0,4,0},
     {0,8,0,9,7,0,5,0,2},
     {0,0,5,0,3,2,0,0,0},
     {0,2,9,0,0,0,0,0,5},
     {0,6,0,5,9,0,4,0,0}};
 printf("Subject:\n");
 print_data(data);
 local_mark *mark = Number_Place_set(data);
 printf("Answer:\n");
 if(Number_Place_game(data,mark)){
  print_data(data);
 }else{
  printf("No solution!\n");
 } 

 getchar();
 return 0;
}

local_mark *Number_Place_set(int data[][9]){
 local_mark *mark = (local_mark*) new local_mark;
 for(int i = 0; i < 9; i++ )
  mark -> x[i] = mark -> y[i] = mark -> z[i] = 0;
 for(int i = 0; i < 9; i++ )
  for(int j = 0; j < 9; j++)
   if(data[i][j]){
    mark -> x[j] |= (1 << data[i][j]-1);
    mark -> y[i] |= (1 << data[i][j]-1);
    mark -> z[local_val(i,j)] |= (1 << data[i][j]-1);
   }
 return mark;
}
bool Number_Place_game(int data[][9], local_mark *mark){
 point *p = (point*) new point;
 int m , max = 0 , count = 0;
 for(int i = 0; i < 9; i++ )
  for(int j = 0; j < 9; j++)
   if(!data[i][j]){
    count++;
    m = mark->x[j] | mark->y[i] | mark->z[local_val(i,j)];
    if(bitcount(m) > bitcount(max)){
     max = m;
     p -> x = j;
     p -> y = i;
    }
   }
 if(count == 0)
  return true;
 for(int i = 0; i < 9; i++)
  if(max != (max | (1 << i))){
   data[ p->y ][ p->x ] = i+1;
   mark -> x[ p->x ] |= (1 << i);
   mark -> y[ p->y ] |= (1 << i);
   mark -> z[ local_val( p->y , p->x ) ] |= (1 << i);
   if(Number_Place_game(data,mark)){
    return true;
   }else{
    data[ p->y ][ p->x ] = 0;
    mark -> x[ p->x ] &= ~(1 << i);
    mark -> y[ p->y ] &= ~(1 << i);
    mark -> z[ local_val( p->y , p->x ) ] &= ~(1 << i);
   }
  }
 return false;
}
int local_val(int x,int y){
 return y/3+(x/3)*3;
}
int bitcount(int x){
 int b;
 for(b = 0; x; x &= x-1)
  ++b;
 return b;
}
void print_data(int data[][9]){
 for(int i = 0; i < 9; i++){
  for(int j = 0; j < 9; j++)
   printf("%d ",data[i][j]);
  printf("\n");
 }
}

Share:
技術提供:Blogger.

追蹤者