2010年9月21日 星期二

千里共嬋娟

千里共嬋娟

中秋節快到了,
聽些應景的音樂吧。

明月幾時有,把酒問青天。
不知天上宮闕,今夕是何年。
我欲乘風歸去,又恐瓊樓玉宇,高處不勝寒。
起舞弄清影,何似在人間。
轉朱閣,低綺戶,照無眠。
不應有恨,何事長向別時圓。
人有悲歡離合,月有陰晴圓缺,此事古難全。
但願人長久,千里共嬋娟。

歌詠月亮,
自蘇軾這首水調歌頭詞以降,餘詞盡廢。
這類「倚天既出,誰與爭鋒」的作品,讓後世擊節讚賞之餘,
更讓創作者感嘆,為何不是出於己手!

梁弘志為此詞譜了「但願人長久」,藉由鄧麗君輕柔的歌聲,
勾起了無數中國人的悲歡離合、陰晴圓缺。
後來王菲翻唱此曲,現代感多了點,韻味倒也不減。

蘇芮「一樣的月光」對冷酷無情的世界發出吶喊,
而許美靜「城裏的月光」,卻在冷漠的現代都會中,
添加一股幸福的溫暖。

王心凌「月光」像小仙女的金粉,灑在年輕戀人身上,
隨著愛情喜悅的念頭,飛翔在夜晚的風中。
啊!最好也不要長大,大人世界煩惱多。

貝多芬第 14 號鋼琴奏鳴曲第一樂章
一改往常的使用慢板,
在大半輩子與命運抗爭的音樂風格中,
流露出鐵漢柔情的一面,
於是有貝多芬在月光下為少女彈琴的穿鑿附會之說。

在音樂領域,德布西的鋼琴曲集貝加馬斯克組曲中的「月光」
或許是讓後世歌詠月亮餘音盡廢的作品。
「印象樂派」一詞是由繪畫界而來,
兩者發展出來的語法都特別適合描述「光影的動態變化」。
能掌握這種語法的音樂家不多,德布西可說是前無古人。
本曲也被改編成管絃樂版本,
波士頓流行管絃樂團有張專輯 Adagios,要與「卡拉揚---慢板」互別苗頭,
第一首就是這首「月光」,這整張專輯很值得一聽

迪士尼卡通「幻想曲」也把此曲的管絃樂版配在一段動畫中,
描述一隻天鵝優雅的穿梭在夜晚的森林中,
皎潔的月色,倒影在林中小溪,天鵝起舞所泛起的水波,
更讓光影迷離,配上音樂真是恰如其份。
不過當初電影上映時,本段被剪掉了,
幸好,兩年前重新出版的DVD收錄了這一段


中國街頭藝人華彥鈞(人稱瞎子阿炳),
身世坎坷,貧病悲苦,以一曲「二泉映月」揚名國際,
「二泉」指的是有天下第二泉之稱的無錫惠山泉,
華彥鈞以二胡淒涼的音色,借景抒情,
悲世態之炎涼,寄豪情於山水。
美國在1985年評選本曲為十大外國名曲之一,
華彥鈞壯志得申,不知能否含笑九泉?
有人將其改編為小提琴版本,讓不會二胡的眾多小提琴手也能演奏,
音色比起二胡漂亮許多,但味道就是差了一截。
我聽過華彥鈞本人拉的二胡獨奏版,
雖然年代久遠,錄音技術不佳,
但那種「眾人皆醉而我獨醒」的感慨,
那副「追尋社會正義公理」的渴望,
再爛的錄音器材都補捉的到!


真是的,
在這團圓的日子裏,
幹麻搞得這麼悲情?
記得以前的音樂課本也收錄了像「中秋怨」、「桐淚滴中秋」這類藝術歌曲,
要是現在音樂課本還這樣編,
肯定在網路上要被批得狗血淋頭了。

找首幸福的歌來做Ending。

只有月亮當然就覺得孤單,
冷月伴孤星也好不到哪兒去,
滿天星星就可愛多了,
有月亮就不能沒有星星,
莫札特 KV265「小星星」鋼琴變奏曲
敲出中秋好心情 ^_^

2010年7月30日 星期五

小隻轉魔方

小隻的很喜歡玩Lego NXT,
在看到網路上有人用NXT轉魔方之後,
他對魔方也感興趣,
我趁機教他轉,
本來以為他應該學不會,
不過他幾天後真的學會了,
而且還比我快。

最近我已經忘了怎麼解,
但他還是記得。

小犬即興 2

這次即興的曲子有點日本風,
起承轉合四句,很有邏輯,
只是第三句「轉」得不夠好。
不知他哪兒學的?


大隻的不甘勢弱,說也要來點中國風,
我覺得很像搖籃曲。

2010年6月3日 星期四

使用NXC撰寫NXT程式---第八章 再探循跡車

使用NXC撰寫NXT程式---第八章 再探循跡車


我們在第六章有寫過循跡車的程式如下:

//簡易循跡車
#define _LIGHT 45
#define _POWER 50
#define _TURN_TIME 100
task main()
{
  SetSensorLight(IN_3); //或用 S3
  while (true)
  {
    if (SENSOR_3<=_LIGHT) //左轉修正
    {
      NumOut(5,20,SENSOR_3,true);
      Off(OUT_C);
      OnFwd(OUT_B, _POWER); 
      Wait(_TURN_TIME);
    }
    else //右轉修正
    {
      NumOut(5,20,SENSOR_3,true);
      Off(OUT_B);
      OnFwd(OUT_C, _POWER); 
      Wait(_TURN_TIME);
    }
  } //end while
}

這個程式差強人意,走起路來歪七扭八怪彆扭的,我們接下來要使用PID控制的方式來讓循跡車走的更優雅。

關於PID控制,請先閱讀這篇 J. Sluka 所寫的文章,底下的作法仍根據這篇說明而來。

我們假設光感在全白的底色上所讀到的數據是50,而在黑色軌跡上的讀數是40,
上述程式的做法,是以這兩者的平均值45為判斷標準,
若機器人是沿黑線的左邊行進,小於等於45,表示偏向黑色軌跡,機器人需往左修正;
反之則以反方向修正。

不是左轉,就是右轉,以45為判斷的標準,典型的二元論。

難道沒有模糊地帶?

要讓機器人更聰明,必需讓它了解不僅只有這兩種情況。

假設我們的光感在不同的狀態下所讀到的數據如下:






至少現在我們可以有三種選擇:
1.小於45且大於等於40:向左修正
2.大於45且小於等於50:向右修正
3.等於45:直線前進

機器人現在多了一項反應了。

仔細一想,我們可以加入更多的情況讓機器人辨示,以做出更多不同的反應。




如上圖,我們現在可以有五種選擇:
1.在40到42之間:向左修正,且要修正大一點
2.在42到45之間:向左修正,但修正小一點即可
3.等於45:直線前進
4.在45到48之間:向右修正,但修正小一點即可
5.在48到50之間:向右修正,且要修正大一點

修正角度的大小,可以用馬達的輸出馬力來控制。

以此細分下去,我們可以讓光感讀到的數據,對映一個馬達輸出的馬力,
最簡單的算法,就是以線性等比例的方式來換算。

我們設定當光感讀數是45時,B、C馬達皆以50%的馬力輸出(即走直線),
而在兩個極端點(即光感讀數為50及40時),B、C兩個馬達的輸出為100%及0(或0及100%),
我們可以畫出底下的函數圖形:





這條線的方程式為:
Power=10*(Light-45)+50
10即為斜率,在PID領域有個術語,稱為比例常數。

如果上面的函數圖形代表C馬達,
那我們可以讓B馬達的斜率為負,如下圖。



現在我們可以寫程式了。



//有比例控制的循跡車
//-----------------------------------------------
//請依您的情況調整Kp、offset與Tp值
//我的情況是Kp=2 、 offset=47 、 Tp=80 時走的最快
//而Kp=1 、 offset=47 、 Tp=50 時走的最平順
//-----------------------------------------------


task main()
{

    int Kp = 10;//比例常數,調小此數值會走的比較平順
    int offset = 45;//不修正時的光感值,依實際情況設定
    int Tp = 50;//不修正時的馬力,愈大愈快,但要配合Kp

    int Light;//光感讀數
    int PowerB, PowerC;//B、C馬達的輸出馬力

    SetSensorLight(IN_3); //或用 S3

    while (true)
    {

      Light = SENSOR_3 ;//讀取光感數據
      PowerC = (Kp*(Light-offset))+Tp;//代入方程式
      PowerB = (-Kp*(Light-offset))+Tp;//另一個馬達的斜率是負的
      TextOut(5,40,NumToStr(Light),true);
      TextOut(5,20,NumToStr(PowerB));
      TextOut(75,20,NumToStr(PowerC));

      OnFwd(OUT_B,PowerB);
      OnFwd(OUT_C,PowerC);

    }

}


有可能在您調整參數的過程中,或是光感也有可能偵測到小於40或大於50的情況下,讓PowerC或PowerC大於100或小於0。雖然NXT對馬達的Power有自我保護,且NXC對小於0的Power值會自動逆轉,但程式師應該要對任何可能發生的意外負責,仔細考慮各種可能情況,否則,就會像福音戰士中的初號機一樣「暴走」,導致不可預期的失控。當然設計越複雜,就越難保證不失控。但從小事養成謹慎的態度是很好且必要的。我們的輸出入設計只限制在一個合理的範圍:在40<=Light<=50時,-100<=Power<=100。(Power為負值時逆轉)其他情況我們並沒有設計讓機器人如何反應,所以,我們要在程式碼中,好好的規範一下。底下是較有保障的程式。
註:
由於小弟偷懶,事隔1年半才又著手寫這篇文章,之前的程式不曉得誤了多少人,幸好不會讓NXT暴走或壞掉。可見寫網路文章也得戒慎恐懼啊!




//有比例控制且較穩定的循跡車
//-----------------------------------------------
//請依您的情況調整Kp、offset與Tp值
//我的情況是Kp=2 、 offset=47 、 Tp=80 時走的最快
//而Kp=1 、 offset=47 、 Tp=50 時走的最平順
//-----------------------------------------------


task main()
{
    int LightMax = 50;//光感讀入的最大值
    int LightMin = 40;//光感讀入的最小值
    int PowerMax = 100;//Power的最大值
    int PowerMin = -100;//Power的最小值
    int Kp = 10;//比例常數,調小此數值會走的比較平順
    int offset = (LightMax+LightMin)/2;//不修正時的光感值,依實際情況設定
    int Tp = 50;//不修正時的馬力,愈大愈快,但要配合Kp

    int Light;//光感讀數
    int PowerB, PowerC;//B、C馬達的輸出馬力

    SetSensorLight(IN_3); //或用 S3

    while (true)
    {
      Light = SENSOR_3 ;//讀取光感數據
      //限制輸入 Light 在比例控制的範圍
      if (Light < LightMin)
        Light=LightMin;

      else if (Light > LightMax)
        Light=LightMax;


      PowerC = (Kp*(Light-offset))+Tp;//代入方程式
      PowerB = (-Kp*(Light-offset))+Tp;//另一個馬達的斜率是負的
      //限制輸出 Power 在比例控制的範圍
      if (PowerC < PowerMin)
        PowerC=PowerMin;

      else if (PowerC > PowerMax)
        PowerC=PowerMax;


      if (PowerB < PowerMin)
        PowerB=PowerMin;

      else if (PowerB > PowerMax)
        PowerB=PowerMax;


      TextOut(5,40,NumToStr(Light),true);
      TextOut(5,20,NumToStr(PowerB));
      TextOut(75,20,NumToStr(PowerC));

      OnFwd(OUT_B,PowerB);
      OnFwd(OUT_C,PowerC);

    }

}



(未完待續...)

2010年5月31日 星期一

使用NXC撰寫NXT程式---第六章 從感應器抓取資料

使用NXC撰寫NXT程式---第六章 從感應器抓取資料

一、Touch Sensor

//讓機器人撞到東西後會後退轉彎
task main()
{
    SetSensorTouch(IN_1);//設定 port 1接到碰觸感應器,IN_1 也可以用 S1取代
    OnFwd(OUT_BC, 80);
    while (true)
    {
      if (SENSOR_1==1)// port 1讀到的數值會存在SENSOR_1中
      {
        OnRev(OUT_BC, 80); Wait(300);
        OnFwd(OUT_B, 80); Wait(500);
        OnFwd(OUT_BC, 80);

      } //end if

    } //end while

}



二、Light Sensor

//簡易循跡車
#define _LIGHT 45
#define _POWER 50
#define _TURN_TIME 100
task main()
{
    SetSensorLight(IN_3); //或用 S3
    while (true)
    {
      if (SENSOR_3<=_LIGHT)//左轉修正
      {
        NumOut(5,20,SENSOR_3,true);
        Off(OUT_C);
        OnFwd(OUT_B, _POWER); Wait(_TURN_TIME);

      }
      else //右轉修正
      {
        NumOut(5,20,SENSOR_3,true);
        Off(OUT_B);
        OnFwd(OUT_C, _POWER); Wait(_TURN_TIME);

      }

    } //end while

}



三、Sound Sensor
(未完待續...)

四、Ultra sonic Sensor


五、角度 Sensor


六、進階用法

使用NXC撰寫NXT程式---第五章 將程式模組化

使用NXC撰寫NXT程式---第五章 將程式模組化

一、程序
sub 程序名(參數1,參數2,...)
{
    //程式碼...

}

//將轉彎的功能以程序包裝起來,要用時再呼叫。
sub turning(int power)
{
    OnRev(OUT_BC, power);//B、C反轉
    Wait(3000);
    OnFwd(OUT_C, power); //C正轉,B繼續反轉
    Wait(500);

}

task main()
{
    OnFwd(OUT_BC, 80);
    Wait(1000);
    turning(30); //呼叫turning,傳入30%的動力
    OnFwd(OUT_BC, 80);
    Wait(2000);
    turning(50); //呼叫turning,傳入50%的動力
    Off(OUT_BC);

}

二、函式 (function)
傳回值型別 函式名(參數1, 參數2,…)
{
//…
return 傳回值;
}

與程序主要的不同點在於:
函式可有傳回值,若無則傳回值型別以 void 表示。


//隨機傳回x~y的任一數
int myRand(int x, int y)
{
    int result;
    result = (x+ Random(y+1-x)); //隨機取 x~y
    return result;

}

task main()
{
    int time,power;
    time= myRand(2,5)*1000; //隨機取2~5秒
    NumOut(5,20,time,true);
    OnFwd(OUT_BC,80);
    Wait(time); //隨機等待2~5秒

    power= myRand(3,5)*10 ; //隨機取30、40或50
    NumOut(5,10,power);
    OnRev(OUT_C,power); //隨機以30%、40%或50%動力輸出
    Wait(time); //隨機等待2~5秒
    Off(OUT_BC);

}



三、inline function
inline 傳回值型別 函式名(參數1, 參數2,…)
{
    //…
    return 傳回值;

}

與函式之不同處在於:
程式在編譯前,會先行內擴展(就是取代啦!),
將函式中的程式碼直接複製一份在呼叫的程式中,
直接執行函式中的指令,並非以呼叫的方式來調用函式,
因此,使用inline function會使程式碼大小增加,
但因省掉函式呼叫時,位址與記憶空間需保留的堆疊運算,
執行效率會比較高。

如果您的程式很大,NXT記憶體寸土寸金,
當然就不適合使用inline function了。

2010年5月26日 星期三

使用NXC撰寫NXT程式---第四章 流程控制

使用NXC撰寫NXT程式---第四章 流程控制

一、迴圈
1. repeat(n) {...} //執行{ }中的程式碼n次

//讓機器人走一個正方形
#define _GO_STRAIGHT_TIME 3000
#define _TURN_TIME 700
#define _GO_STRAIGHT_POWER 80
#define _TURN_POWER 50

task main()
{
    repeat(4){

      OnFwd(OUT_BC,_GO_STRAIGHT_POWER);
      Wait(_GO_STRAIGHT_TIME);
      OnRev(OUT_C,_TURN_POWER);
      Wait(_TURN_TIME);

    }
    Off(OUT_BC);

}


2. while(條件) {...} //當條件成立時執行{ }中的程式碼

//讓機器人走一個正方形
#define _GO_STRAIGHT_TIME 3000
#define _TURN_TIME 700
#define _GO_STRAIGHT_POWER 80
#define _TURN_POWER 50

task main()
{
    int i=0;
    while(i < 4){
      OnFwd(OUT_BC,_GO_STRAIGHT_POWER);
      Wait(_GO_STRAIGHT_TIME);
      OnRev(OUT_C,_TURN_POWER);
      Wait(_TURN_TIME);
      i++;

    }
    Off(OUT_BC);

}



3. do {...} while(條件) ; //本迴圈至少會執行一次

4. for(初始設定;條件;每次迭代最後要執行的指令) {...}

//讓機器人走一個正方形
#define _GO_STRAIGHT_TIME 3000
#define _TURN_TIME 700
#define _GO_STRAIGHT_POWER 80
#define _TURN_POWER 50

task main()
{
    int i;
    for(i=0; i < 4; i++){
      OnFwd(OUT_BC,_GO_STRAIGHT_POWER);
      Wait(_GO_STRAIGHT_TIME);
      OnRev(OUT_C,_TURN_POWER);
      Wait(_TURN_TIME);

    }
    Off(OUT_BC);

}



二、條件判斷
1. if(條件){...} else {...}

//讓機器人隨意散步
task main()
{

    int run_time = 0; //宣告一個整數變數,名為run_time,其初值為0
    while (true){
      run_time = (3+ Random(6-3)); //隨機取 3~5
      NumOut(5,20,run_time,true);
      TextOut(5,10,"Go Straight!");
      OnFwd(OUT_BC,80); //設定B、C port 的馬達以80%的Power正轉。
      Wait(run_time*1000); //等待 run_time 秒
      if (run_time % 2 ==0){ //右轉
        NumOut(5,20,run_time,true);
        TextOut(5,10,"Turn Right!");
        OnRev(OUT_C,80); //設定C port 的馬達以80%的Power後退。
        Wait(run_time*1000); //等待 run_time 秒

      }
      else { //左轉
        NumOut(5,20,run_time,true);
        TextOut(5,10,"Turn Left!");
        OnRev(OUT_B,80); //設定B port 的馬達以80%的Power後退。
        Wait(run_time*1000); //等待 run_time 秒

      }

    } //end while

}


2.switch(條件){...}

switch(x)
{

    case 1:
      // 撰寫x==1 時要做的事...
      break; //跳出switch

    case 2:
    case 3:
      // 撰寫x==2或3時要做的事...
      break; //跳出switch

    default:
      // 撰寫當x不是1, 2, 3 時要做的事...
      break; //跳出switich

}
註:NXC的 switch 可以使用 string 型別來判斷喔!

2010年5月7日 星期五

使用NXC撰寫NXT程式---第三章 變數

使用NXC撰寫NXT程式---第三章 變數

一、變數命名規則
英文字母或_(底線)開頭

二、資料型別




資料型別說明範圍

bool

8位元無號數

0~255

byte

unsigned char

8位元無號數0~255
char8位元有號數-128~127
unsigned int16位元無號數0~65535

short

int

16位元有號數-32768~32767
unsigned long32位元無號數0~4294967295
long32位元有號數-2147483648~2147483647
mutex互斥程式碼
string字串
struct自訂結構
Arrays陣列


注意 : NXT 不支援 float 與 double 等浮點數型別

修正 :
感謝 探奇自然科學教室 指正


NXT 1.0x版本的韌體的確不支援浮點數,但是1.2x版的韌體就已經支援浮點運算。

在新版BricxCC的編譯選項選擇"Automatic firmware version" 或 "NXT 2.0 compatible firmware"就可以使用浮點運算。

請參考http://forums.nxtasy.org/index.php?showtopic=5093&view=findpost&p=38693


三、運算子
    1.算數運算子:

符號功能C++運算式數學意義

+

a = x + y

a = 5 + 3

-a = x - ya = 5 - 3
*a = x * ya = 5 * 3
/a = x / yfloat a;
a = 5 / 3; (結果a=1)
a = 5.0/3;
%取餘數a = x % ya = 5 / 3 的餘數
++遞增a = x++(先指派再遞增)
a = ++x(先遞增再指派)
a = 5++ (=6)
--遞減a = x--
a = --x
a = 5-- (=4)


    2.指定運算子:

運算子

功能

實例

結果

=

指定

i = 2

變數i的值為2

+=

相加後再指定

i +=2 相當於(i=i+2)

變數i的值為7

-=

相減後再指定

i -=2相當於(i=i-2)

變數i的值為3

*=

相乘後再指定

i *=2相當於(i=i*2)

變數i的值為10

/=

相除後再指定

i /=2相當於(i=i/2)

變數i的值為2.5

%=

餘數除法後再指定

i %=2相當於(i=i%2)

變數i的值為1

^=

做XOR運算後再指定(逐位元)

i ^=2相當於(i=i^2)

&=

做AND運算後再指定(逐位元)

i &=2相當於(i=i&2)

=

做OR運算後再指定(逐位元)

i =2相當於(i=i2)

<<=

左移指定運算

i<<=2相當於(i=i<<2)

>>=

右移指定運算

i>>=2相當於(i=i>>2)



其餘請參考 BricxCC安裝目錄中的Documentation\NXC_Guide.pdf

四、讓您的NXT隨意散步

task main()
{

    int run_time = 0; //宣告一個整數變數,名為run_time,其初值為0
    string name = "simfonia";
    run_time = (3+ Random(6-3))*1000; //隨機取 3~5秒
    OnFwd(OUT_BC,80); //設定B、C port 的馬達以80%的Power正轉。
    Wait(run_time); //等待 run_time 秒

    run_time = (1+ Random(4-1))*1000; //隨機取 1~3秒
    OnRev(OUT_C,80); //設定C port 的馬達以80%的Power反轉。
    Wait(run_time); //等待 run_time 秒

    run_time = (3+ Random(6-3))*1000; //隨機取 3~5秒
    OnFwd(OUT_BC,80); //設定B、C port 的馬達以80%的Power正轉。
    Wait(run_time); //等待 run_time 秒


    Off(OUT_BC); //關掉B、C port 的馬達電力,並剎車。

}


關於 Random(x) 函式:
Random(x)是NXC API 中的一個數學函式,它隨機傳回 0 ~ x 之整數值(可等於零,但小於 x )。
0 <= Random(x) < x
=> 0 <= Random(y-x) < y-x 同加上 x
=> x <= x + Random(y-x) < y => 可隨機傳回 x ~ y (小於y)之整數

2010年5月6日 星期四

使用NXC撰寫NXT程式---第二章 讓 NXT 動起來

使用NXC撰寫NXT程式---第二章 讓 NXT 動起來

一、讓 NXT 前進

task main()
{

    OnFwd(OUT_A,80); //設定A port 的馬達前進,以80%的Power。
    OnFwd(OUT_B,80); //設定B port 的馬達前進,以80%的Power。
    Wait(3000); //等待3秒
    Off(OUT_AB); //關掉A、B port 的馬達電力,並剎車。

}


相關函式及常數

OnRev(port,power) //反轉
OUT_AB, OUT_ABC, OUT_BC, ...




練習:讓您的NXT車子可以轉彎。



二、使用 #define 定義常數

#define _TURN_TIME 700 //#為前置處理,不屬於語言範圍,故不加";"
task main()
{

    OnFwd(OUT_BC,80);
    Wait(3000); //前進3秒
    OnRev(OUT_C,80);
    Wait(_TURN_TIME); //轉彎時間
    OnFwd(OUT_BC,80);
    Wait(3000); //前進3秒
    Off(OUT_BC);

}



練習:
一、把上述程式中的字面常數以#define定義。
二、讓您的NXT機器人走出一個正方形。

2010年5月4日 星期二

使用NXC撰寫NXT程式---第一章 Hello NXC

一、安裝BricxCC
Bricx Command Center (BricxCC)是一個整合開發環境(IDE),可讓我們用NXC(Not eXactly C,類似C/C++的語法)來撰寫程式,並透過NBC(Next Byte Codes )來編譯成rxe的NXT可執行檔。



所以說,
NBC是編譯器,
NXC是程式語言,
BricxCC是IDE。

請至下列網址下載並安裝。
test release版本可支援NXT 2.0的顏色感應器,
latest version版本為最新穩定版。

http://bricxcc.sourceforge.net/

二、啟動BricxCC
在啟動畫面中挑選如下設定


或啟動BricxCC後,執行 Tools/Find Brick 亦可與NXT連線。



三、介面環境說明及常用設定




1.開新檔案

2.輸入位置行列數

3.Download program,下載程式至NXT

4.Edit/Preferences/Compiler/Common,將使用語言改成NXC。

5.Edit/Preferences/Options/,將Code completion的Hot key改成 Ctrl+Alt+Space,以免與中文輸入法衝突。

6.程式碼書籤,在某行程式使用Shift+Ctrl+0~9可設定書籤,再按一次可清除該書籤,Ctrl+0~9可跳到該書籤。


四、Hello world!



task main() //程式可由多個task組成,但main是程式進入點
{

    ClearScreen(); //清除螢幕
    TextOut(10,2,"Hello world!"); //在 (10,2)的位置(第一象限)輸出 Hello world! 字串
    Wait(2000); //等候2秒

}

將上述程式碼存成nxc檔,經NBC編譯成rxe後,下載至NXT中執行即可。

以上寫程式的過程您也可以不透過BricxCC 這個IDE,
步驟如下:
1.用您喜歡的文字編輯器(如記事本、UltraEdit...等)撰寫程式碼。
2.存檔至BricxCC安裝的資料夾(預設是C:\Program Files\BricxCC),假設檔名為 hello.nxc
3.按 開始/執行 , 輸入 cmd 後按 Enter 。
4.在 Console 中,切換工作目錄: cd C:\Program Files\BricxCC
5.編譯程式碼,請輸入 nbc hello.nxc -O=hello.rxe >log.txt
6.在NXT-G 中,把hello.rxe下載至NXT中即可。

2010年3月26日 星期五

大隻的小犬音樂創作

小五音樂課中的創作,
開頭應該是來自貝多芬【月光】的靈感。

他自己這樣描述他的創作:
「我這首在描寫月光,第一段音比較高,比喻皎潔的月亮,
第二段音較低,比喻被月光照到的街道,很好聽喔!」

我覺的還不錯。

2010年3月19日 星期五

小隻的小犬即興彈琴

這隻小的從小就會一直亂哼亂唱,
只要興致一來,就可以不間斷的哼個半小時。

最近他開始會在鋼琴上亂彈,
真的是想也不想的即興亂彈,
我要是沒有用手勢叫他停止,他會沒完沒了。

雖然只是用了兩三個和弦,但還是讓我很驚訝!
尤其是他的曲子與樂句是有結構的。

2010年3月10日 星期三

Jupiter

最近大隻的小犬剛從三天兩夜的天文營回來,
這是他第一次離開父母獨自在外過夜,
所以我就問他有沒有想爸爸媽媽而哭泣?
他說沒有,但是第二天有哭。
我想果然父母在這小子的心中還是很重要的,
第一天一定是強忍淚水,真是難為他了。
就抱著他故意問他為什麼哭?
他說:「因為我想到,明天活動完畢就要回家了,
我好想不要結束哦!所以就哭了。」

好吧!我承認在小孩的心目中,星星的魅力是無法擋的。
我拉他到戶外,
要他講一顆星星的故事給我聽。

他指著月亮旁,一顆最亮的星星說:
那是木星,天體中第四亮的星星,
旁邊那顆是它的衛星,但其實它還有好多個衛星...
他嘩啦啦的講了一大堆,
我接著說:兒子啊,關於木星,
我也可以給你講個故事...

英國作曲家霍爾斯特在1916年作了一首「行星組曲」,
共有七個樂章,各有一個標題和副題,分別如下:

Mars, The Bringer of War 火星,戰爭之神
Venus, the Bringer of Peace 金星,和平之神
Mercury, the Winged Messenger 水星,飛翔之神
Jupiter, the Bringer of Jollity 木星,快樂之神
Saturn, the Bringer of Old Age 土星,老年之神
Uranus, the Magician 天王星,魔術之神
Neptune, the Mystic 海王星,神秘之神

扣除地球之外,還少了冥王星,
不是因為霍爾斯特有先見之明,
在當時就把它從九大行星中除名,
而是因為冥王星是在1930年才被發現,後來命名為Pluto,
羅馬神話中的冥界之王,也是米奇的好朋友。

霍爾斯特自己說,雖然曲子有標題,
但它們不是標題音樂,欣賞時把副題延伸想像即可。
這意味著,在聽「木星」時,
你不用去找它的大紅斑,
或是比「土星」暗的環到底在音樂的哪一段。

這曲子的第四首「木星」是最受世人喜愛的,
Jupiter是羅馬神話中的天神之王,相當於希臘神話中的宙斯。
曲中充滿歡樂的氣氛,由四個主題構成:
A:




A-B過門


B:


C:


D:

行星組曲最有名的是木星,而大家喜愛它的原因就是衝著這一段。
由A-B過門的音樂演變而來,神聖莊嚴,
後來霍爾斯特乾脆把這樂段獨立寫成一首愛國歌曲,
讓大家朗朗上口之餘,也能激起愛國情操。
2003年日本平原綾香改以日文重新填詞翻唱,
大家可到YouTube聽看看。


樂曲後半就把前四個主題再濃縮、變型、混合演奏一次,
然後花火燦爛中結束。


如果多聽幾次,你會發現,
A-B過門這段音樂其實是最重要的,
整首曲子幾乎都是它變成的。


另外,值得一提的是,如果你是六年級生,
我們當時瘋狂的港劇大多是來自香港年代影視,
這公司的片頭音樂就是取自這首「木星」的中間及結尾。


莫札特的最後一首交響曲第41號也叫Jupiter,
雖不是莫札特自己加上的,
但這位天才以圓熟的作曲技法而呈現出莊嚴恢宏的氣度,
這標題倒也當之無愧。

第一樂章,奏鳴曲式。
呈示部:
第一主題


第二主題


結束句



發展部由結束句的音樂開始發展:


轉小調的變化是我最喜歡的莫札特手法,
然後第一主題也加入短暫發展後,進入再現部。
據我觀察,
莫札特很喜歡用結束句來當作發展部的開頭,
這點值得注意。

第二樂章,也是奏鳴曲式。
呈示部:
第一主題


過門


第二主題


結束句



猜猜這次發展部用哪個段落開始?



第三樂章,小步舞曲,ABA三段體。
A段由兩小段組成:
a

這一段是非常工整的「44224句型」,
有時間再和大家介紹這種句型。

b



B段也由兩小段組成:
c


d


第四樂章,奏鳴曲式。
這首曲子稱作「Jupiter」應該是這個樂章的原因。
莫札特用完美的賦格作曲技巧,把這個樂章寫得光輝燦爛。

呈示部:
第一主題
a


b

由帶附點的三個音導出,後面接一組下行音階,
在往後的發展中,有時下行音階會變成上行音階。

第二主題

這段是弱起拍開頭,所以若你有打拍子的習慣,可能在中間會覺得怪怪的,
只要把這段的第二個音當成第一拍來打,就完全順暢啦。
注意聽,除了新的第二主題音樂外,
你也可以聽到低音管在下方、而長笛在上方吹奏著第一主題b段中的音樂哦,
這種多線進行的賦格曲風,可是天才莫札特的拿手好戲呢!

結束句

以b段當結束句,小提琴在此把三個附點音後的下行音階改成上行了,
但這個版本的指揮把重點放在木管部分,
所以你很難聽得出來,
讓我們換個版本聽聽:


這個版本快了許多,但仔細聽可以聽到小提琴真的把b段反行了。
這裏也可以說明在不同版本間所造成的差異,又是另一番樂趣了。

發展部
又是延續結束句,
以a段的前四音和b段開始發展。
如果剛剛聽不出小提琴把b段上行,
現在這裏你一定可以清楚聽到木管的這個變形(第13秒後)。


之後莫札特把b段,用弦樂四部與木管群來作五聲部賦格,
由於速度很快,我們其實不需要,也不可能仔細去聽出每一聲部,
只要放鬆,讓整個音響流進耳中,
感受這「眾響交融」的衝擊效果即可。


再現部
第一主題a、b與第二主題再度出現後,樂曲進入結尾(Coda)

Coda
來來來!好酒沉甕底!
如果第四樂章是這闕交響曲的精華,
那麼,這段Coda就是精華中的精華。
請注意,莫札特之後就沒機會再寫交響曲了,
這是最後一段,你可能要站著聽:



請仔細多聽幾次,再往下看。



第18秒後進入三重賦格。
三重賦格和發展部的五聲部賦格不一樣,
五聲部賦格用的是同一個主題(b段)來對位,
五條線前後出現同一個主題;
三重賦格是把之前的a、b與第二主題這三個主題同時出現來對位,
單一主題的對位已經夠難了,三個主題要怎麼寫啊?
幸好這世界有天才,讓我們坐享可望而不可及的完美。

請再聽一次,在第18秒後看看你能不能聽出之前我們聽過的那三個主題。
當然,我再提醒一次,
聽出每一個聲部與主題是附帶的要求,不是主要的,
享受這整體繽紛壯麗的聲響,才是莫札特留給我們這珍寶的目的。

第49秒後進入大合奏,直到終了。

你一定意猶未盡,
現在知道為什麼有那麼多人希望莫札特多活幾年的原因了吧!

莫札特只以不到二個月的時間寫下他的最後三首交響曲,
包括這首第41號交響曲。平均一首用不到20天。
而根據考證,莫札特直到去逝前,這三首交響曲並沒有首演,
也就是說,
莫札特可能沒聽過他自己的這三首傑作。
我每次聽莫札特的作品,想到他這位天才的生世,
都會為之鼻酸。

喜歡莫札特這種對位音樂型式的人,
可試試「c小調彌撒曲K427」與「d小調安魂彌撒曲K626」,
前者聽說是莫札特為感念上帝讓他娶到康絲坦彩的「還願」之作,
後者則是莫札特以生命換來而未竟全功的「天鵝之歌」,
皆是上上乘之作品。

錄音部分:
霍爾斯特的行星組曲可以購買全曲,
但除了木星外,其他六曲可能不見得你會喜歡,
所以介紹一片我認為還不錯的合輯,
裏面有收錄「木星」一曲,
其他的曲子也都適合入門者聆聽,
請參考看看。
http://www.books.com.tw/exep/cdfile.php?item=0020086742

至於莫札特第41號交響曲,
版本眾多,選擇你喜歡的即可。