買書捐殘盟

2021年7月16日 星期五

多工執行緒的 Arduino 控制

 多工執行緒的 Arduino 控制

本範例在同一個時間內,同時做不同的任務(讓 led明滅、七段顯示器數字顯示),這是 圖控程式離線下所做不到的事。

 用圖控程式,它只有提供delay()函數,delay是讓工作暫時停止,必須等他做完才能執行下一個步驟。

是一種很標準的程序控制。
範例中,利用兩LED皆在Arduino的PIN-2,3,透過millis()的時間函數,分別對兩個LED提供不同的變化週期。



2020年11月28日 星期六

荷蘭風車 arduino控制

 藉由手作荷蘭風車,馬達的部分,以 Arduino晶片控制,搭配按鈕開關,來起閉風車轉動。

其中:

接腳3:偵測按鈕是否按下(高低電位偵測藉以判斷按鈕是否按下),當按下按鈕,高電位;放開按鈕,低電位。

接腳5、6:與L9110馬達驅動板的 A1A、A1B接點連結。

啟動時,因為採用PWM時Arduino會產生額外的低頻噪音,為消除噪音,在程式中,改變計時器的設定。

因為接腳5、6分屬Timer0管轄,在void setup()中增加:

  TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);  

  TCCR0B = _BV(CS00);  

  OCR0A = 180;  

  OCR0B = 50; 

上開程式碼以紅色色標之處為Timer0的0代號。

如果是採用3、11接腳,則為Timer 2;採用9、10接腳,則為Timer 1。


附上Arduino程式碼:


#define A_1A 6

#define A_1B 5

int button_pin=3;

int i=1;


void setup() {

  // put your setup code here, to run once:

  TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);  

  TCCR0B = _BV(CS00);  

  OCR0A = 180;  

  OCR0B = 50; 

  pinMode(button_pin,INPUT);

  pinMode(A_1A,OUTPUT);

  pinMode(A_1B,OUTPUT);

  pinMode(13,OUTPUT);

}


void loop() {

  // put your main code here, to run repeatedly:



     //analogWrite(A_1A,130);

     //analogWrite(A_1B,0);

     //delay(100);


     if (digitalRead(button_pin)==HIGH) {

         i=i+1;

         while(digitalRead(button_pin)==HIGH){}

     }

     if (digitalRead(button_pin)==LOW && i%3==0) {

         digitalWrite(13,HIGH);

         analogWrite(A_1A,150);

         digitalWrite(A_1B,0);

         delay(20);

     } 

     if (digitalRead(button_pin)==LOW && i%3==1) {

         digitalWrite(13,LOW);

         analogWrite(A_1A,255);

         digitalWrite(A_1B,0);  

         delay(20);     

     } 

     if (digitalRead(button_pin)==LOW && i%3==2) {

         digitalWrite(13,LOW);

         digitalWrite(A_1A,0);

         digitalWrite(A_1B,0);  

         delay(20);     

     }      

}

2020年10月17日 星期六

小木屋+荷蘭風車

利用閒暇的時間,自己用Google Sketchup軟體繪製小木屋和風車的設計圖,並使用雷射切割機將零件切出。
在課程設計上,可在生活科技九年級能源與動力、電與控制等單元做應用





2014年12月13日 星期六

從AppInventor2開發產品中,體驗智慧財產的重要

學校自這個學期開始授課App Inventor課程之後,學生普遍的反應還算不錯。
過去國三的電腦課程,通常是上Visual Baic,但對於初次接觸程式設計的孩子來說,一堆抽象的文字語言,數字與字串,或者是運算子,甚至是迴圈的應用,條件式的判斷....光是這些就足以讓孩子們失去學習的信心。

這個學期開始之前,鄭博全老師找我一起商討對於國三學生的課程時談到AppInventor課程,打算在學期中授課,當下我對於這一套軟體並不陌生,因為過去在設計機器人nxt設計時,在進行藍芽連線時,就已經開始使用App Inventor這個軟體作為手機與機器之間的溝通橋樑。

在開始授課的時候,孩子們開始學習圖形化程式設計的操作,崁入式的程式碼建構,相較於傳統的文字程式來說,是淺顯而易懂的。雖然在剛開始還是會排斥著,然而在經過一段時間的學習後,孩子們慢慢地能夠習慣操作,並能慢慢地能夠自己產生一個簡易的軟體。

這個建構的過程並不簡單,因為從零學起,從排斥到接納,雖然是半強迫式的學習,但也消弭了對程式設計的恐懼感。從程式設計中,孩子們除了培養靈活的邏輯設計觀念之外,更從中體驗到:原來開發一個程式軟體,竟是相當不簡單!

一個手機遊戲軟體,人人取得容易。然而一個軟體的生命週期,從玩家對於軟體的精緻程度,將決定喜好的程度。 因此,在建構一個軟體的過程,不斷修飾程式的外觀之外,對於程式的內涵(程式碼)的功能強度,更是考驗一個程式設計者的智慧。

我們從課程中,最後希望帶給孩子們的是:認真看待智慧財產權。在一個產品開發的階段,是如此耗費工夫(時間)的,為了讓產品能永續成長,智慧財產是不容許被侵害的,因為從設計的過程中,既然如此辛苦,就更能體會其他開發產品的原設計者,當時對這個商品的努力程度。

2014年12月12日 星期五

利用matlab,一秒鐘讀取一筆資料

影片結果:https://www.youtube.com/watch?v=JZhv-OIad-8&feature=youtu.be

程式碼:
clear all
clc

data=[100 90 80 60 80 90 75 70 80 100];
n=size(data,2);
sum=0;
average_value=0;

for i=1 :10
 if i==1
  max_value=data(i); 
  min_value=data(i);
 end
 
 sum=sum + data(i);

 if data(i)>max_value
   max_value= data(i);
 end

 if data(i)  min_value=data(i);
 end
 fprintf('第%d筆資料=%d,讀取完畢\n',i,data(i))
 pause(1);
end
fprintf('-------------\n')
average_value=sum/n;
fprintf('平均值=%3.2f\n',average_value)
fprintf('最大值=%d\n',max_value)
fprintf('最大值=%d\n',min_value)

2013年4月14日 星期日

UltraSonicSensor應用-保護眼睛的守護神


NXT ,保護眼睛的守護神!
當超音波偵測到前方人體離電視太近的時候,系統發出Light光線及聲音警告。
   
[機構]

[程式]
 #define sonic_sensor IN_1
#define touch_sensor IN_2
#define light_sensor IN_3
#define touch SENSOR_2
#define MotorOut OUT_B
#define length 150

long tick;


void WaitSEC3()
{
   tick=CurrentTick();
   while(CurrentTick()<(tick+3000))
   {
       PlayTone(880,50);
       Wait(950);
   }
   Wait(1000);
}




task main()
{
    SetSensorTouch(touch_sensor);
    ResetTachoCount(MotorOut);
    SetVolume(4);
    SetSensorLight(light_sensor,false);
    SetSensorLowspeed(sonic_sensor);
    WaitSEC3();
}


task MotorRotateFn()
{
   Follows(main);
   while(touch==0)
   {
      RotateMotorPID(MotorOut,10,90,40,40,90);    //右轉
      Wait(100);
      RotateMotorPID(MotorOut,10,-170,40,40,90);  //左轉
      Wait(100);
      RotateMotorPID(MotorOut,10,80,40,40,90);    //右轉
   }
   Off(MotorOut);
   StopAllTasks();
}

task DetectFn()
{
   Follows(main);
   while(true)
   {
     if(SensorUS(sonic_sensor) <length{
       PlayTone(500,50);
       SetSensorLight(light_sensor,true);
       Wait(50);
       SetSensorLight(light_sensor,false);
       Wait(50);
     }
   }
}
[影片]                                  

2013年4月5日 星期五

齒輪組應用-nxt腳踏車

利用齒輪組原理,組裝的腳踏車。
後輪利用橡皮筋傳動。



齒輪組合可謂千變萬化,我個人設計時,先從後輪開始做起,先把後輪與腳踏傳動軸的橡皮筋先測試連動性。
確認後,再續完成前輪與龍頭等機構的連結。
最後為整合前後輪能藉由nxt馬達轉動,來帶動各部位的轉動,所以藉由齒輪組(三個)來傳遞給前輪及腳踏傳動軸。而腳踏傳動軸得到動能後,藉由橡皮筋的連動,使後輪轉動。

齒輪機構-玩玩

感謝探奇邱老師給予的資料(如參考資料)。
齒輪機構,有趣的地方在於透過齒輪之間的串合,可以有非常多的變化,因此被應用在馬達速度(差速)的變化。

齒輪比,藉由兩個齒輪串合,我們從經驗得知,大齒輪轉一圈,小齒輪轉動n圈,便可以做到差速的轉換。例如圖中:
與馬達串合在一起(同軸)的是8齒的小齒輪,8齒的小齒輪又與40齒的大齒輪咬合在一起。如此共構的齒輪組。我們知道:40齒的大齒輪轉動1圈,同時8齒的小齒輪已跑了5圈。

是以,馬達以150轉/分運轉,假設小齒輪轉150圈,那麼40齒的大齒輪,就是轉了30圈。所以以倍數的關係可知~大齒輪的轉速是30轉/分。

圖中另外一組是8齒小齒輪與24齒小齒輪,該8齒小齒輪與40齒同軸。
 8齒小齒輪與24齒小齒輪的齒輪比=1:3,所以可知8齒小輪轉3圈,24 齒中齒輪轉1圈。

所以整個齒輪組的組合,從馬達的輸入端傳動到24齒輸出端的葉片轉動,呈現轉動比為:
 (1/5)x(1/3)=1/15

換句話說,馬達轉15圈,輸出端的葉片僅轉動1圈,藉此達到轉速的變化!!!!

另外,齒輪組改成Worm Gear也很有趣:


參考資料:
1.http://www.education.rec.ri.cmu.edu/roboticscurriculum/curriculum/introductiontogears.htm
2.http://www.education.rec.ri.cmu.edu/roboticscurriculum/curriculum/gearsspeedtorque.htm

2012年7月8日 星期日

撲克牌洗牌機

久違了,好久沒有新的idea,今天寫一篇關於利用NXT做撲克牌發牌機。



基本上,把撲克牌放兩邊,模擬我們人的手洗牌的樣子。
而機構本身利用輪胎來推進撲克牌至中間的凹槽,馬達轉動的速度無需過快,以免撲克牌卡紙而破壞了牌紙。

且程式也止不過幾行,其中主要用以啟動馬達轉動的程式碼:

OnFwd(OUT_AB,50);

以下是洗牌機的影片片段:

2012年4月13日 星期五

使用matlab開啟Excel檔案,讀取數據資料

matlab當需要開啟外部資料,例如excel檔案時,使用的指令:
1. importdata('filename') -->filename就是你要指定的檔案名稱,包含副檔名
例如,欲打開一個檔名為data.xls,則指令為importdata('data.xls')
2. xlsread('filename')-->filename是你要指定的檔案名稱,副檔名預設為xls


有時操作者在程式執行期間,想切換開啟不同的xls檔案名稱,而不想重新啟動程式,可以使用input指令。下列為部分片段程式:
file_name=input('Open filename:')
file_data=xlsread(int2str(file_name))


如此,即可由操作者自行輸入檔案名稱,如果檔名以數字命名,記得做轉換為文字。

2012年2月17日 星期五

Matlab解聯立方程式

matlab功能強大,對於工程解題更是他的強項。多年來,我對matlab總有一份眷戀,畢竟真的很好用。

ok,回到正題,因想到解聯立解,所以找一找網路上對matlab解聯立解的方法,找到一個方法還不錯用:

假設一個聯立方程式:
x+y=2.....(1)
x-y=0.....(2)

以觀察法可以判斷找到x=1,y=1為其解。

而matlab的程式表示方法,假設等號左邊的x,y未知數之係數,看成一個矩陣A,且等號右邊的係數可以看成一個陣列C
簡化上述的表示式,以矩陣可以寫成
AX=C

所以:
A=[1 1
  1 -1]
C=[2
  0]

底下是matlab程式的寫法:
A=[1 1;1 -1];
C=[2;0];
X=A\C

以左除法,即可解出聯立解,其中X得到的答案就是x,y的解。

2011年12月16日 星期五

走迷宮找最短路徑至終點

前一篇的文章[篩選簡化路徑的Line Follower]談到:
『電腦鼠從起點到終點所經過的所有途徑,記錄所經過的座標之後,自動篩選及簡化路徑,進而尋找最短途逕從起點直至終點。』

本篇據此,經由nxt分析 最短途徑後,操作者將nxt電腦鼠再次放到起點處,預備讓電腦鼠可以依據最短途逕直至終點。不過程式需要增加一段,也是本篇的精華所在。



#define blue_tap1 3
#define blue_tap2 4
#define red_tap 9
#define factor 2


#define LMotor OUT_A
#define RMotor OUT_C
#define Motors OUT_AC

#define LightSensor1Port IN_1
#define LightSensor2Port IN_2
#define ColorSensorPort IN_4

int x[10];
int y[10];
int x_fix[10];
int y_fix[10];

int i,j,k=0;
int D;
int colornum;
int black,white,light1_value,light2_value;
int Lpower=0,Rpower=0;

long tick;
string code;


void WaitSEC3()
{
tick=CurrentTick();
while(CurrentTick()<(tick+3000))
{
PlayTone(880,50);
Wait(950);
}
Wait(1000);
}

void InitialLightSensor()
{
while(!ButtonPressed(BTNCENTER,false))
{
TextOut(0,LCD_LINE3,"Light at black..");
black=Sensor(LightSensor1Port);
}
ClearScreen();
Wait(1000);
while(!ButtonPressed(BTNCENTER,false))
{
TextOut(0,LCD_LINE3,"Light at white..");
white=Sensor(LightSensor1Port);
}
ClearScreen();
WaitSEC3();
}


void LoopAdjust()
{
for(i=0; i<ArrayLen(x); i++)
{
x_fix[k]=x[i];
y_fix[k]=y[i];
for(j=i; j<ArrayLen(x); j++)
{
if((x[j]==x[i])&&(y[j]==y[i]))
{
x_fix[i]=x[j];
y_fix[i]=y[j];
i=j;
}
}
k++;
}
}

void BotWalking()
{
light1_value=Sensor(LightSensor1Port);
Rpower=(light1_value-black)*factor;
Lpower=(white-light1_value)*factor;
OnFwd(LMotor,Lpower);
OnFwd(RMotor,Rpower);
}

void LightSensorTouchLine() //讓bot的兩個light往前推進一小步,直至壓線
{
tick=CurrentTick();
while(CurrentTick()<tick+800)
{
OnFwdSync(Motors,25,0);
}
}

void TireTouchLine(int n) //讓bot往前移動,直至前輪壓線
{
tick=CurrentTick();
while(CurrentTick()<tick+n)
{
OnFwd(LMotor,25);
OnFwd(RMotor,25);
}
}

void BotRightTurn() //讓bot右轉
{
LightSensorTouchLine();
Off(Motors);
Wait(SEC_1);
TireTouchLine(500);
tick=CurrentTick();
while(CurrentTick()<tick+2050)
{
OnFwd(LMotor,25);
OnFwd(RMotor,-25);
}
}

void BotLeftTurn() //讓bot左轉
{
LightSensorTouchLine();
Off(Motors);
Wait(SEC_1);
TireTouchLine(1400);
tick=CurrentTick();
while(CurrentTick()<tick+1600)
{
OnFwd(LMotor,-25);
OnFwd(RMotor,25);
}
}




void ShortLoopGo() //Result: (0,1)-->(-1,1)-->(-1,0)-->(-2,0)
{
string prev_axis="Y" ;
i=1;

while(i<=k)
{
colornum=SensorHTColorNum(ColorSensorPort);
//NumOut(0,LCD_LINE1,D);
if((colornum!=blue_tap1)||(colornum!=blue_tap2))
{
if(colornum==red_tap)
{
StopAllTasks();
}
BotWalking();
}

if((colornum==blue_tap1)||(colornum==blue_tap2))
{
Off(Motors);
Wait(SEC_1);
if((x_fix[i]-x_fix[i-1])!=0)
{
if(((x_fix[i]-x_fix[i-1])>0)&&(prev_axis=="Y"))
{
D=1;
}
if(((x_fix[i]-x_fix[i-1])>0)&&(prev_axis=="-Y"))
{
D=2;
}

if(((x_fix[i]-x_fix[i-1])<0)&&(prev_axis=="Y"))
{
D=3;
}
if(((x_fix[i]-x_fix[i-1])<0)&&(prev_axis=="-Y"))
{
D=4;
}

if(((x_fix[i]-x_fix[i-1])>0)&&(prev_axis=="-X"))
{
D=5;
}
if(((x_fix[i]-x_fix[i-1])<0)&&(prev_axis=="X"))
{
D=6;
}
}

if((y_fix[i]-y_fix[i-1])!=0)
{
if(((y_fix[i]-y_fix[i-1])>0)&&(prev_axis=="X"))
{
D=7;
}
if(((y_fix[i]-y_fix[i-1])>0)&&(prev_axis=="-X"))
{
D=8;
}

if(((y_fix[i]-y_fix[i-1])<0)&&(prev_axis=="X"))
{
D=9;
}
if(((y_fix[i]-y_fix[i-1])<0)&&(prev_axis=="-X"))
{
D=10;
}

if(((y_fix[i]-y_fix[i-1])>0)&&(prev_axis=="Y"))
{
D=11;
}

if(((y_fix[i]-y_fix[i-1])<0)&&(prev_axis=="-Y"))
{
D=12;
}
}
NumOut(0,LCD_LINE1,D);
switch(D)
{
case 1:
BotRightTurn();
prev_axis="-X";
break;
case 2:
BotLeftTurn();
prev_axis="-X";
break;
case 3:
BotLeftTurn();
prev_axis="X";
break;
case 4:
BotRightTurn();
prev_axis="X";
break;
case 5:
LightSensorTouchLine();
Off(Motors);
Wait(SEC_1);
TireTouchLine(500);
BotWalking();
prev_axis="-X";
break;
case 6:
LightSensorTouchLine();
Off(Motors);
Wait(SEC_1);
TireTouchLine(1400);
BotWalking();
prev_axis="X";
break;
case 7:
BotRightTurn();
prev_axis="Y";
break;
case 8:
BotLeftTurn();
prev_axis="Y";
break;
case 9:
BotLeftTurn();
prev_axis="-Y";
break;
case 10:
BotRightTurn();
prev_axis="-Y";
break;
case 11:
LightSensorTouchLine();
Off(Motors);
Wait(SEC_1);
TireTouchLine(500);
BotWalking();
prev_axis="Y";
break;
case 12:
LightSensorTouchLine();
Off(Motors);
Wait(SEC_1);
TireTouchLine(1400);
BotWalking();
prev_axis="-Y";
break;
}
i++;
}
}
Off(Motors);
}

task main()
{
SetSensorLowspeed(ColorSensorPort);
SetSensorLight(LightSensor1Port,true);
SetSensorLight(LightSensor2Port,true);
ArrayBuild(x,0,-1,-1,-1,-2,-2,-2,-1,-1,-2);
ArrayBuild(y,1, 1, 2, 3, 3, 2, 1, 1, 0, 0);
LoopAdjust();
InitialLightSensor();
while(!ButtonPressed(BTNCENTER,false));
ClearScreen();
ShortLoopGo();
}


●★●★●★●★●★●★●★●★●★●★
程式說明
1.LoopAdjust()函式-用以調整簡化最短路徑
2.BotWalking()函式-電腦鼠走黑線的副函式
3.LightSensorTouchLine()、TireTouchLine()-讓電腦鼠光感、輪胎在轉彎處修正其位置
4.BotRightTurn()-電腦鼠右轉副函式
5.BotLeftTurn()-電腦鼠左轉副函式
6.ShortLoopGo()-最短路徑副函式-本篇文章核心函式(Kernel Sub-Function)
(1)根據電腦鼠座標位置,於叉路轉彎,共有12個條件式
(2)依現行軌道,從起點處向上(或向前)Y為正,向下(或向後)Y為負;
(3)從起點處向左X為正,向右為負。
(4)前述2,3根據電腦鼠依現在座標、下一個駐點座標的二者地理位置座標,決定左右轉或前行,方向由使用者定義方向,於程式中設定之。

[執行結果]

2011年12月9日 星期五

篩選簡化路徑的Line Follower

續前一篇[具路徑規劃的Line Follower],當電腦鼠(nxt car)從起點走到終點後,根據前述的程式,我們是將所經過的路徑之x-y座標,存成檔案紀錄在nxt檔案夾中,可供我們事後觀測座標路徑正確與否。

其次,我們打算根據所走的x-y所有點,計算較短路徑。


(圖1 電腦鼠軌道)

程式的規劃,電腦鼠在路徑行走時,採右手法則(即遇到叉路時,以右轉優先,其次為直行,最後為左轉)。
從圖1,可以知道:
當電腦鼠走到(-1,1)時,以右手法則轉向右邊,途經(-1,2)、(-1,3)、(-2,3)、(-2,2)、(-2,1),最後又會到(-1,1)的點,之後右轉至(-1,0),再轉至終點(-2,0)。
這過程中,電腦鼠途經(-1,2)、(-1,3)、(-2,3)、(-2,2)、(-2,1)這些座標的點,對我們直觀的判斷,這些中途繞道的點,應該是多餘的。所以之後的程式,應該根據所有走過的座標,去篩選哪些是不必要再走的。

本篇文章,先設計一測試程式,將電腦鼠走過的座標,存成陣列,並逐步篩選以簡化路徑。

[程式]

(圖2 簡化路徑之程式)

圖2程式:
x[ ],y[ ]為原始數據,而x_fix[ ], y_fix[ ]為簡化後記錄的座標數據
程式從第一組元素(element)開始往後比對,i為參考組,j為比對組。
後面各組(j)若有與參考組(i)的座標雷同,則記錄該點至x_fix及y_fix。
(基本上,當電腦鼠會走回原來的地方,代表剛剛所經過的路徑必不是終點存在的區域,既然回到原來的地方,所以剛剛繞過的地方可捨去不用)


(圖3 電腦鼠走過的座標示意圖)

從圖3,籃框處中間的其他各點,為非必要的途徑,所以可捨去。
所以經過篩選後,最後的座標為:
(0,1)-->(-1,1)-->(-1,0)-->(-2,0)

2011年12月3日 星期六

具路徑紀錄之Line Follower

前些日子,採購了一顆具備辨色能力之hitechnic color sensor,並應用在Line Follower實務,在等距之處貼上色貼,刻劃橫坐標x以及縱座標y。


(圖1 硬體地圖配置)

一、硬體介紹
1.圖1每一個色貼間隔,盡可能讓bot有足夠空間可以迴轉。

2.起點設置在照片中車子停止的位置,硬體裝置使用三個感應器(light sensor x2、color sensor x1)。color sensor負責偵測前端是否為[色貼]標籤,做為後續判斷是否前進或左右轉彎的依據。

3.light sensor分置兩側,左邊light sensor(緊鄰color sensor),負責做沿線前進的功能;右邊的light sensor,負責判斷是否做轉彎的動作…

二、軟體程式

#define LMotor OUT_A
#define RMotor OUT_C
#define Motors OUT_AC

#define LightSensor1Port IN_1
#define LightSensor2Port IN_2
#define ColorSensorPort IN_4
#define factor 2

#define black_tap 0
#define blue_tap1 3
#define blue_tap2 4
#define red_tap 9


int colornum; //彩色感應器讀值
int black,white,light1_value,light2_value; //光感器讀值
int Lpower=0,Rpower=0;
long tick=0;

//紀錄車子移動方位

int x=0,y=0;
int D=1; //初始放在y軸上

byte fileHandle;
short bytesWritten;
string str_log;
string str_x;
string str_y;

void InitialLightSensor()
{
while(!ButtonPressed(BTNCENTER,false))
{
TextOut(0,LCD_LINE3,"Light at black..");
black=Sensor(LightSensor1Port);
}
ClearScreen();
Wait(1000);
while(!ButtonPressed(BTNCENTER,false))
{
TextOut(0,LCD_LINE3,"Light at white..");
white=Sensor(LightSensor1Port);
}
ClearScreen();
tick=CurrentTick();
while(CurrentTick()<(tick+3000))
{
PlayTone(880,50);
Wait(950);
}
Wait(1000);
}

void BotWalking()
{
light1_value=Sensor(LightSensor1Port);
Rpower=(light1_value-black)*factor;
Lpower=(white-light1_value)*factor;
OnFwd(LMotor,Lpower);
OnFwd(RMotor,Rpower);
}

void LightSensorTouchLine() //讓bot的兩個light往前推進一小步,直至壓線
{
tick=CurrentTick();
while(CurrentTick() {
OnFwdSync(Motors,25,0);
}
}

void TireTouchLine(int n) //讓bot往前移動,直至前輪壓線
{
tick=CurrentTick();
while(CurrentTick() {
OnFwd(LMotor,25);
OnFwd(RMotor,25);
}
}
void BotRightTurn() //讓bot右轉
{
tick=CurrentTick();
while(CurrentTick() {
OnFwd(LMotor,25);
OnFwd(RMotor,-25);
}
}

void BotLeftTurn() //讓bot左轉
{
tick=CurrentTick();
while(CurrentTick() {
OnFwd(LMotor,-25);
OnFwd(RMotor,25);
}
}


void BotTurning()
{
Off(Motors);
Wait(1000);
LightSensorTouchLine();
Off(Motors);
Wait(1000);

light1_value=Sensor(LightSensor1Port);
light2_value=Sensor(LightSensor2Port);
colornum=SensorHTColorNum(ColorSensorPort);

if(light1_value>light2_value) //可右轉
{
TireTouchLine(500);
BotRightTurn();
D=D+1;
if(D>4) D=1;
}
if(light1_value<=light2_value) //可左轉
{
if(colornum==black_tap) //彩色感應器偵測到前方有黑線,可前行
{
BotWalking();
D=D;
}
if(colornum!=black_tap)
{
TireTouchLine(1400);
BotLeftTurn();
D=D-1;
if(D<1) D=4;
}
}
}

void AxisRecord()
{
if(D==1)
{
y=y+1;
}

if(D==2)
{
x=x+1;
}

if(D==3)
{
y=y-1;
}

if(D==4)
{
x=x-1;
}
str_x=NumToStr(x);
str_y=NumToStr(y);
str_log=str_x+" "+str_y;
WriteLnString(fileHandle,str_log,bytesWritten);
}

void IfEndTask()
{
Off(Motors);
tick=CurrentTick();
while(CurrentTick() {
PlayTone(880,20);
Wait(450);
}
AxisRecord();
StopAllTasks();
}


task main()
{
DeleteFile("DataLog.txt");
CreateFile("DataLog.txt",10000,fileHandle);

SetSensorLowspeed(ColorSensorPort);
SetSensorLight(LightSensor1Port,true);
SetSensorLight(LightSensor2Port,true);
InitialLightSensor();
}

task BotWalkTask()
{
Follows(main);

while(true)
{
colornum=SensorHTColorNum(ColorSensorPort);
if((colornum!=blue_tap1)||(colornum!=blue_tap2)) //判斷是否遇到叉路
{
if(colornum==red_tap)
{
IfEndTask();
}
BotWalking();
}
if((colornum==blue_tap1)||(colornum==blue_tap2))
{
AxisRecord();
BotTurning();

}
}
}


三、執行結果:

2011年11月24日 星期四

Google App Inventor: 亂數產生器

亂數產生器,隨機產生一個或一組數字,在教室情境中很受歡迎。
當老師想要點名,卻又不想流於形式,亂數產生器得到的號碼,讓學生無法得知下一刻是誰被點到,那種急速上升刺激與快感,難以形容。

曾在Market找相關的軟體,卻未盡滿足我的需要,所以心中浮現用app inventor來開發,相信難度不高,且能客製化自己的需要來安排各種功能。

首先,我的軟體介面如下:

(圖1 軟體介面)

圖1中:
1.[亂數範圍]可由使用者自行決定起訖範圍。
2.[剔除不要的號碼]欄位,由使用者自行決定亂數產生時,以不出現此欄位指定的號碼為主。
3.當按下[隨機產生號碼]按鈕,即產生斗大的一個號碼於畫面中。

程式碼:

上述程式中:
1.StartNum及EndNum變數,分別指定為主畫面使用者輸入起訖號碼
2.RndNo變數,由[random integer函式],隨機產生一數字並指定回RndNo,範圍如上述1.
3.RemoveElementNum變數,使用者指定[剔除號碼]後,系統自動統計其個數,並指定給RemoveElementNum
4.for range迴圈:
檢視[隨機產生的數字]是否與[欲剔除的數字]相等?若相等,則重新產生一個新的數字。直至不重複為止。

2011年11月19日 星期六

Hitechnic Color Sensor 測試

一、硬體方面
color sensor 接在nxt主機上的IN_4。
二、軟體方面
根據[Third-party sensors: a review of some Hitechnic’s sensors]一文提到:
The new and totally redesigned HiTechnic Color Sensor Version 2 (V2) operates by using a single white LED (light emitting diode) to illuminate the target and analyses the color components of the light reflected by the target’s surface and calculates a Color Number that is returned to the NXT program.

Sensor Register Layout

AdressTypeContents
42HbyteColor number
43HbyteRed reading
44HbyteGreen reading
45HbyteBlue reading

Procedures are already available in Bricxcc to use the sensor:

  • SetSensorLowspeed() initializes the I2C communication with the sensor.
  • SensorHTColorNum(port) returns the value of Color number.
  • ReadSensorHTRawColor(port, rouge, vert, bleu) returns the RGB readings.
  • ReadSensorHTColor(port, index, rouge, vert, bleu) returns the value of Color number, and the RGB readings. See the code example at the end of the article ...
所以在NXC的程式基本採用的指令,包含二個:
1. SetSensorLowspeed(IN_4)
2. ReadSensorHTColor(IN_4,colorvalue,r,g,b)
其中,IN_4是彩色感應器接向IN_4,而colorvalue是經由color sensor回應的讀值,r,g,b分別為red,green,blue三原色的數值。

三、程式碼
#define ColorSensorPort IN_4

task main()
{

byte r,g,b;
byte colorvalue;
SetSensorLowspeed(ColorSensorPort);

while(true)
{
ReadSensorHTColor(ColorSensorPort, colorvalue,r,g,b);
NumOut(0,LCD_LINE3,colorvalue);
if (colorvalue==0) PlayTone(880,25);
Wait(25);
ClearScreen();
}
}

上述程式是說:
當color sensor讀值(colorvalue)=0,則PlayTone一個短音。
colorvalue=0-->黑色

2011年10月22日 星期六

Google App Inventor - 使用手機的語音控制

如果你的手機支援語音搜尋,那麼應該可以啟用語音辨識的操作。
這個功能可以替代手寫,英語的辨識率還算不錯,但中文辨識率不太高就是了。
(假如假設你發音正確,那麼應該可以顯示將你想說的語音轉成文字)

首先,我在手機介面上,設計如下的簡易畫面來進行測試:

(圖1)手機操作畫面

圖1中,我引用了App inventor的Other stuff中的[Speech recognizer]元件作語音控制。
而[按下後說話]的按鈕,是用來啟用speech recognizer,當你按下後即可說話。
簡單說了一段英文或中文語句,文字將顯示在圖中的Voice2TextResult文字欄位。

-------------------------------
其次,開啟Block Editor,進行程式編輯。
程式設計如下:

(圖2)程式內容

圖2中:
1. SpeechAfterPressedBtn-即按鈕,按下按鈕後,開始說話。
 call SpeechRecognizer1.GetText,呼叫語音辨識,取得文字。
2. When...SpeechRecognizer1.BeforeGettingText-
 當操作者還在說話時,介面上Voice2TextResult文字欄位的內容為空白
3. When...SpeechRecognizer1.AfterGettingText-
 將Voice2TextResult文字欄位指定為SpeechRecognizer1.Result
 即所說的內容,經過語音辨識後將文字呈現在Voice2TextResult文字欄位

--------------------------
有興趣的玩家,可以利用這樣的功能,實現在NXT的藍芽控制,當你說:
Go或是向前、Back或是向後、Left或是向左、Right或是向右,經過語音辨識,再結合
前述[Google App Inventor -手機藍芽遙控Segway]的方法,程式稍微修改一下就可
讓你的機器人用語音控制前進,後退、向左及向右了。

2011年10月15日 星期六

利用手機的指北針感應器,來做方位感測

前幾天利用手機的digital compass sensor (orientation sensor),拿來做為方位的度量。
設計的機構如下:


結果發現,這樣的機構,因為太靠近nxt motor,會產生磁場嚴重的干擾而使度量發生錯誤。
今天再改裝加高鷹架,機構如圖:


尚未測試,也許可以改善。測試的結果待續。