JavaScriptでわかる!組込みプログラミングの神髄

第1回 JavaScriptと組込みプログラミングは似ている!

この記事を読むのに必要な時間:およそ 3.5 分

最近は,組込みシステムという言葉もずいぶん一般的になりました。みなさんの中にも,すでに組込みシステムのプログラミングに挑戦したり,あるいはこれから挑戦してみたいと思っている方がたくさんいらっしゃると思います。

お手軽な学習キットや入門書もたくさん出ており,敷居はとても低くなりました。その一方で,組込みプログラミングに不安を持っていたり,あるいはすでに挑戦してみたけれどよくわからなかった,という人もいるかも知れません。

そこで本稿では,パソコン上で誰でも簡単に実行できるJavaScriptを使用して,組込みプログラミングの基礎について説明してみたいと思います。

古典的なプログラミングと,なにが違うのか

筆者は以前,Wikipediaに書き込みを行っているIPアドレスがいくつくらいあるのか知りたくなりました。これには更新ログをダウンロードして,IPアドレスを抽出し,種類を数えればOKです。次のようなコマンドラインになりました(実際は,100GB以上ある更新ログを置く場所がなかったので,アーカイバからパイプで入力しました)⁠調べたところ,日本語版Wikipediaの場合で,たしかIPアドレス総数が約100万,IPグループ総数が約10万でした。

awk '/*IPアドレスのみを抽出*/' < 更新ログ ¦ sort -u ¦ wc

筆者が子供のころ,プログラミングの入門書には「1から10までの整数の総和を求めよ」みたいな例題がたくさん出ていましたが,これも本質は同じです。つまり,入力データがあり,それをまとめて処理する,というプログラムです。

加速度センサーから入力されたデータを積分して,衝撃の強さを測定するプログラムはどうでしょうか。これもやはり考え方は同じです。データを入力して,処理して,結果を返します。

ではこのプログラムを,自動車のエアバッグ制御に使うことは可能でしょうか。

車が衝突したあとで,衝撃の強さを計算することはできます。その強さを見て,⁠この衝突ではエアバッグを動作させるべきです」と表示することもできます。しかしこれでは意味がありませんね。衝突が進行している途中で,エアバッグを起動するかどうかを判断する必要があります。このためにはまったく異なったプログラミングテクニックが必要になります。

さきほどのWikipediaのプログラムで考えてみましょう。追記される更新ログを追いかけて,ユニークIP数がちょうど100万になったときに警報を出すわけです。この場合も,まったく違ったプログラミングが必要になりますね。

「まとめて処理」だったのを「ちょっとずつ処理」にするのは大変なのですが,組込みプログラミングにはこの視点が絶対に必要です。逆にいえば,これが組込みプログラミングの難しいところでもあります。では,どうやればうまくできるのか,そのテクニックを見ていくことにしましょう。

10秒待とう

最初は簡単な例題です。スイッチを押して10秒たったらメッセージを表示する,というプログラムを考えてみましょう。

リスト1 wait10s.html

<HTMLM><HEAD><TITLE>wait10s</TITLE>
<SCRIPT type="text/javascript"><!--

function        press_button()
{
        var     start = new Date();

        for (;;) {
                var     now = new Date();

                if (now.getTime() > start.getTime() + 10000)
                        break;
        }
        document.getElementById("message").innerHTML = "ok!";
}

// --></SCRIPT>
</HEAD><BODY>
<H1>wait10s</H1>

<P><BIG><BIG>
<SPAN onmousedown="press_button()">[CLICK ME]</SPAN>
<SPAN id="message"></SPAN>
</BIG></BIG></P>

</BODY></HTML>

JavaScriptのプログラムをはじめて見る方には,少しわかりにくいかも知れません。このHTMLは以下の部分に分かれています。

  • </HEAD> より前の部分
  • <BODY> から後の部分

HEADの部分は,定義です。TITLE以外は画面に表示されません。基本的に,JavaScriptのプログラムはここに置きます。この例題では,press_button関数を定義しています。

BODYの部分は,表示です。画面に表示するものはここに書きます。

BODYの中に「onmousedown="press_button()"」という部分があります。これで,クリックされたときに関数を呼び出しています。

press_button関数の方では,new Date()を使って現在時刻を取得しています。現在時刻が10000ミリ秒(=10秒)だけ進んだら,ループを抜けて,メッセージを表示しています。オブジェクト指向プログラミングになじみのない方のためにC言語の範囲で説明しますと,new Date()という構文は,メモリを確保して構造体として初期化し,そのポインタを返します。now = new Date();としておき,now.getTime()とすると,構造体の中のgetTime()関数が呼びだされ,現在時刻が得られることになります。

本題ではありませんが,document.getElementById("message")というの部分は,<SPAN id="message">というタグに対応しています。innerHTMLは,このタグの中身と連動していますので,innerHTMLを更新すると,表示に反映されることになります。これはJavaScriptのDOMという機能です。

実行してみると

説明が長くなりました。では,実際にこのプログラムを実行してみましょう。⁠CLICK ME」のところをクリックすると,たしかに10秒後にメッセージが表示されました。しかし,10秒たつのをループで待っているため,CPU使用率が100%になってしまい,他の作業が進まなくなってしまいます。このようなやり方を,⁠ビジーループ」「ポーリング」と呼びます。

「クリックしたときに関数が呼ばれる」というのがピンとこない方は,次のようなプログラムを想像してください。これも同じ問題点を持っています。ちなみにこれはArduinoのプログラミングスタイルですが,関数からリターンしないと他の関数が呼びだされないのは,こういう構造になっているためです。

 void main()
 {
   for (;;) {
     if (クリック)
       press_button();
     if (キー入力)
       キー処理関数();
     if (データ受信)
       通信処理();
   }
 }

また,今回はボタンが1つですから問題ありませんが,もしボタンが2つ以上あったら,このプログラムでは並列的に処理することができません。キッチンタイマーを2つ用意しても,片方を使用中にもう片方が利用できないのでは,2つ用意した意味がありませんね。

JavaScriptではonmousedownの部分を「イベントハンドラ」と呼んでいます。組込みシステムでは「割り込み」と呼んでいます。例外的なケースを除いて,組込みプログラミングでも割り込み処理でビジーループを使ってはいけません。

著者プロフィール

木元峰之(きもとみねゆき)

独立系ソフトハウスに8年間勤務,パッケージソフトの開発や記事執筆などを行う。現在はフリーのコンサルタント。SWESTなどのワークショップで分科会のコーディネータを務める。デジタル回路設計歴30年,プログラミング歴27年。

きもと特急電子設計
URL:http://business.pa-i.org/

コメント

コメントの記入