SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

たった5つのルールではじめるC言語開発

マジカルボックスのプログラムを読み解く 1


  • X ポスト
  • このエントリーをはてなブックマークに追加

ダウンロード サンプルソース (44.7 KB)

プログラムを読んでみよう② ―― 間隔計測masure.c

 関数はひとつ、MeasureIntervals()だけです。

 プログラムの説明の前に、どんなふうに間隔を計測するのかについて説明します。図2をご覧ください。これはスプーンをたたいた時、音検出回路の接続された入力ポートにどんな信号が入力されるかを示しています。

図2:スプーン音で入力ポートに加えられる信号
図2:スプーン音で入力ポートに加えられる信号

 無音時は入力ポートは1になっています。スプーンをたたくと、入力ポートに0のパルスが入力されます。この幅は数十ミリ秒~最大50ミリ秒くらいです。

 これに対し、ソフトウェアではまず図3のように①無音の間待って、②最初の音信号が来たところでストップ・ウォッチ(タイマー)をスタートさせます。

図3:最初のスプーン音で時間計測を開始する
図3:最初のスプーン音で時間計測を開始する

 次に図4の③~⑥のように、無音の確認と音信号の確認を繰り返し、2発目と3発目をやりすごします。

図4:2発目3発目を確認しつつ時間計測を続ける
図4:2発目3発目を確認しつつ時間計測を続ける

 最後に図5の⑦~⑧で4発目の音を確認したところでストップウォッチを止めます。計測した時間は4回スプーンをたたいた時間であり、これを3で割ることでスプーンを打った平均間隔時間が求められます。

図5:4発目で時間計測を終える。3で割ると平均時間がわかる
図5:4発目で時間計測を終える。3で割ると平均時間がわかる

 それでは処理プログラムの説明に移ります。

 まず22行目でWaitInactive()を呼んで無音状態を確認します。引数にNOCHEK_TIMEを渡しているのは、タイムアウト(時間切れ)処理をせず、いつまでも無音になるのを待てという指示です。

 無音を確認したら、24行目でWaitSound()を呼んで、今度は最初の1音を待ちます。これも引数にNOCHECK_TIMEを指定していて、スプーンが叩かれるまで永遠に待ちます。音が検出されるとWaitSound()から帰ってきますので、ここでStartTimer()を呼んで時間計測を開始します。本来ならWintSound()の処理の中で、ポートの変化(音の検出)と同時にタイマをスタートさせるほうがより正確ですが、ここでは制御の順番のわかりやすさを優先しています。27行目では1番目のLEDを点灯します。1番目のLEDというのが実際はどのランプなのかはここではわかりません。先に述べたように、それはデバイスドライバの中で解決しています。ここでは「1番目のLED」を灯すという抽象的動作にしてあるのです。

 図5からわかるように、2番目から4番目の音までは同じ処理、つまり「無音を確認して次の音を待つ」という動作を繰り返します。繰り返しということはループ制御文の出番ということで、ここではfor文を使っています。繰り返し回数は変数iで制御していて、2(番目)から4(番目)まで繰り返すよう記述してあります。

 30行目からが繰り返す処理の内容です。最初に1ミリ秒単位の時間待ち関数Wait1msec()を呼んで50ミリ秒待っています。これは、スプーンを1回叩くと、最長で40~50ミリ秒の信号が発生するためです。音信号が消えたころを見計らって、31行目でWaitInactive()を呼んで無音状態に戻るのを待ちます。ここでは引数にCHECK_TIMEを指定して、一定時間以上無音が確認できないときにはタイムアウトしてエラーで帰ります。

 無音状態が正常に確認できたら(33行目)、34行目でスプーン音を待ちます。ここも一定時間音が来なければタイムアウトしてエラーが返ります。音が確認できたら、36行目で対応するLEDを点灯します。for文の回数制御変数iの値を、音が「何番目か」に合わせてあるので、点灯させるLED番号にはiを渡すことで対応LEDを指定できます。

 40行目は無音確認~音確認までの一連の処理でエラー(タイムアウト)があったかをチェックをしています。エラーがあった場合は、41行目でタイマを止めて、ERRORで帰ります。

 こうして正常に4回目の音まで検出しおわると、for文を終了し、46行目でReadTimer()を呼んでタイマ値を読みます。47行目で1/3することで、スプーンを打つ間隔の平均値を求めています。この値があまりに小さいとき(今回のプログラムでは100ミリ秒未満)は、計測に失敗した異常値とみなしてエラーにしています(51行目)。

 前後しますが、49行目でタイマを止め、正常時はスプーンをたたいた間隔の平均時間を持って帰ります。

次のページ
プログラムを読んでみよう③ ―― サンプリングsampling.c

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
たった5つのルールではじめるC言語開発連載記事一覧

もっと読む

この記事の著者

舘 伸幸(タチ ノブユキ)

NECマイクロシステム株式会社 勤務NPO法人SESSAME 所属開発ツールのソフトウェア開発を経て組込みソフトウェア開発に従事。プライベートにも半田ごては手放さない。2006年からSESSAME に参加。若い世代に物を作る楽しさを伝えていきたい。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3732 2009/03/26 17:23

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング