リスト1 測定した距離をキャラクタLCDに表示するe-ruler #include "mbed.h" #include "TextLCD.h" // キャラクタLCDの変数(オブジェクト)宣言 TextLCD lcd(p24, p26, p27, p28, p29, p30) ; // 距離センサからアナログ入力を取得するオブジェクトの宣言 AnalogIn in(p20); // ある時間ごとに関数を呼び出すためのオブジェクト Ticker input; // センサから読み込んだ値を一時的に保存する変数 float now, old = 0.0 ; // 関数のプロトタイプ宣言 void run(void); int main() { // 0.5秒ごとにrun関数を呼び出す input.attach(&run,0.5); // 無限ループ while(1) { } } // run関数で0.5秒ごとにセンサから値を取得し、距離に変換したものをLCDに表示している。 void run(void) { float data; // センサから得られる値が安定しないことがあるので、 // 前回取得した値をold変数に保持しておき、2回分の平均値を入力値としている。 old = now ; now = in ; data = (now +old)/2.0 ; lcd.locate(0,0) ; // 距離センサは、5〜80[cm]の距離に対しておよそ3.2〜0.4[V]の電圧が出力される。 // mbedは0〜3.3[V]の入力を0.0〜1.0に変換し内部で処理している。 // そこで、距離センサからの出力電圧を0.0〜1.0に変換すると // 0.121(=0.4/3.3)〜0.97(=3.2/3.3)になるので、この値に収まる場合は // 距離を求め、それ以外は測定範囲外(----)の表示をする。 if (0.121 <= data && data <= 0.970){ // 先ほど求めた出力電圧から距離を求める近似式を使用する // pow(x,y)はxのy乗を求める関数 float range = 25.33 * pow((data*3.3),-1.21); // LCDに小数点以下1桁で表示している。 lcd.printf("Range: %4.1f[cm]",range) ; }else{ // 測定範囲外の場合のLCD表示 lcd.printf("Range: ----[cm]"); } } --- リスト2 衝突検知システムのプログラムCollisionAvoidance #include "mbed.h" #include "TextLCD.h" // 距離センサからのアナログ入力を取得するオブジェクトの宣言 AnalogIn in(p20); // キャラクタLCDの変数(オブジェクト)宣言 TextLCD lcd(p24, p26, p27, p28, p29, p30) ; // 圧電スピーカを駆動するための変数 PwmOut out(p21); // 内蔵LEDを点灯するための変数 DigitalOut myled(LED1); // 一定時間ごとに関数を呼び出すオブジェクト Ticker input; Ticker output; // 点滅間隔を格納する変数 double flash; // 入力データを格納する変数 float data,now,old=0.0; // センサから入力データを読み込む関数 void run(){ // 一つ前のデータをold変数に保存しておく old = now; // センサからデータを読み込む now = in; // 古いデータと新しいデータの平均をデータとする。 // これは、データを安定させるための処理 data = ( now + old ) / 2.0; } void update(){ float range; lcd.locate(0,0); // ここでのしきい値は、適当に決めればよい if ( data < 0.208 ){ // 障害物が40cm以上離れている場合の処理 flash = 0.0 ; // 40cm => センサからの出力は 0.8[V] なので、0.686/3.3 = 0.208 lcd.printf(" Safty "); }else if ( data < 0.272){ // 障害物が 30cm <= data < 40cm の場合の処理 flash = 0.8 ; lcd.printf("Caution! "); }else if ( data < 0.389){ // 障害物が 20cm <= data < 30cm の場合の処理 flash = 0.4 ; lcd.printf("Caution! "); }else if ( data < 0.724){ // 障害物が 10cm <= data < 20cm の場合の処理 flash = 0.1 ; lcd.printf(" Danger! "); }else{ // 障害物が 10cm より近い場合の処理 flash = 0.05 ; lcd.printf(" Danger! "); } // 障害物までの距離を求める range = 25.33 * pow((data*3.3),-1.21); lcd.locate(0,1); // センサの出力電圧が 0.4[V](=0.12*3.3)より小さい場合は // RANGE OVERと表示する if ( data > 0.12) lcd.printf("RANGE %5.2f[cm]",range); else lcd.printf("RANGE OVER "); } int main() { // 0.2秒ごとにセンサの値を読む関数を実行する input.attach(&run,0.2); // 0.5秒ごとにキャラクタLCDの表示を更新する関数を実行する output.attach(&update,0.5); // ブザーを鳴らす周波数を1[kHz]に設定する out.period(0.001); // 無限ループ while(1){ out.write(0.0); if ( flash != 0.0 ){ // 40[cm]より近い場合は距離によって決められた間隔(flash)で // LEDを点滅させ音を鳴らす myled = !myled ; wait(flash) ; out.write(0.5); wait(flash); }else{ // 40[cm]以上離れている場合はLEDは消灯し、音も鳴らない myled = 0; out.write(0.0); } } } --- リスト3 なんちゃってテルミンImitationTheremin #include "mbed.h" #include "TextLCD.h" // プログラム内で使用している数学関数sin()やpow()はC言語ではmath.hをincludeしないと // 使えないが、mbedではmath.hをincludeする必要はない。 // #include "math.h" // 距離センサからのアナログ入力を取得するオブジェクトの宣言 AnalogIn in(p20); // キャラクタLCDの変数(オブジェクト)宣言 TextLCD lcd(p24, p26, p27, p28, p29, p30); // 音を出力するためのアナログ出力用の変数(オブジェクト)宣言 AnalogOut out(p18); // 一定時間ごとに関数を呼びだすオブジェクト Ticker input; Ticker output; // 出力する周波数を保存する変数 int freq; double t = 0.0 ; float data; // センサから入力データを読み込む関数 void run(){ // 距離センサから値を取得 data = in; } // 正弦波を出力する関数 void wave(){ float signal; // 距離-出力電圧のグラフから、0.4[V]より小さな値(80[cm]を超える)のときは // 周波数を0にして音を出さない。 // ここのif文で使用しているしきい値は適当に決めた値 // 使用する人が自分の感覚で適当な距離(値)を決めればよい。 if ( data < 0.1212){ // 0.4[V](=0.1212*3.3) 80[cm]を超える場合は音を出さない freq = 0; }else if ( data < 0.181){ // 0.597[V](=0.181*3.3) 50[cm] <= data < 80[cm] // 高いほうのドの周波数 freq = 2093; }else if ( data < 0.242){ // 0.799[V](=0.242*3.3) 35[cm] <= data < 50[cm] // シの周波数 freq = 1976; }else if ( data < 0.333){ // 1.098[V](=0.333*3.3) 25[cm] <= data < 35[cm] // ラの周波数 freq = 1760; }else if ( data < 0.394){ // 1.300[V](=0.394*3.3) 22[cm] <= data < 25[cm] // ソの周波数 freq = 1568; }else if ( data < 0.485){ // 1.600[V](=0.485*3.3) 15[cm] <= data < 22[cm] // ファの周波数 freq = 1397; }else if ( data < 0.697){ // 2.300[V](=0.697*3.3) 10[cm] <= data < 15[cm] // ミの周波数 freq = 1319; }else if ( data < 0.85 ){ // 2.805[V](=0.850*3.3) 7[cm] <= data < 10[cm] // レの周波数 freq = 1175; }else{ // ドの周波数 freq = 1046; // 5[cm] <= data < 7[cm] } if ( freq != 0 ){ // 正弦波を出力するための式 // V = Vm * sin(2*PI*freq*t) // Vm:波形の最大値, pi:3.1415, f:周波数, t:時間 // sin()の値は 1〜-1で変化するが、mbedは0.0〜1.0の範囲に対して0.0〜3.3[V]の電圧を出力。 // そこで、Vmを0.5倍し0.5〜-0.5の範囲で変化するようにして、最後に0.5を加えることで0.0〜1.0の // 範囲で変化するようにした。 signal =0.5*sin(2.0 * 3.1415 * freq * t )+0.5; out = signal; } // tが1を超えたら0に戻す if ( t > 1.0 ) t = 0.0 ; // tの値に50[us]だけ加算し時間を進める処理をしている。 // 時間(t)は、波形の瞬間の値をもとめるときに使用している。 t=t+0.00005 ; } int main() { // 0.5秒ごとにセンサから値を読み込む関数を呼び出す input.attach(&run,0.5); // 50[us]ごとに出力を更新する。 // あまり時間を短くすると時間内に処理が終わらないため、正常に動作しなくなる。 output.attach_us(&wave,50); // 無限ループ while(1){ lcd.locate(0,0); // キャラクタLCDにセンサの値と周波数の値を表示する lcd.printf("%5.3f %4d",data,freq); // センサの値から距離をもとめている lcd.locate(0,1); if ( 0.12 <= data){ float range = 25.33 * pow((data*3.3),-1.21); lcd.printf("RANGE %5.2f[cm]",range); }else{ lcd.printf("RANGE -----[cm]"); } lcd.locate(12,0); // 出力している音をキャラクタLCDに表示する lcd.putc('['); if ( freq == 0){ lcd.putc('-'); lcd.putc('-'); }else if ( freq == 2093){ // トと゛の表示 lcd.putc(0xC4); lcd.putc(0xDE); }else if (freq == 1976){ // レと (スペース)の表示 // 以下は同じ処理の繰り返し lcd.putc(0xBC); lcd.putc(0xFE); }else if ( freq == 1760){ lcd.putc(0xD7); lcd.putc(0xFE); }else if ( freq == 1568){ lcd.putc(0xBF); lcd.putc(0xFE); }else if ( freq == 1397){ lcd.putc(0xCC); lcd.putc(0xA7); }else if ( freq == 1319 ){ lcd.putc(0xD0); lcd.putc(0xFE); }else if ( freq == 1175){ lcd.putc(0xDA); lcd.putc(0xFE); }else{ lcd.putc(0xC4); lcd.putc(0xDE); } lcd.putc(']'); } }