マイクロマウスの市販組み立てキットを完成させた北上くんとえみちゃん。サンプルのソースコードに頼らず、オリジナルプログラムをイチから組もうと奮闘中。今回は、“壁の有無”や“壁までの距離”を検知する「センサー」の値を取得する方法についてだ。
組み込み技術者に要求される要素が“ギュッ”と詰まった「マイクロマウス」。北上くんと新入社員のえみちゃんは、スキルアップを兼ねてマイクロマウスの開発を始めることにしました。「階層構造」を意識したオリジナルプログラムを開発することになったえみちゃんは、北上くんの指導の下、スイッチやブザーの制御を着々とこなしてきました(前回の記事へ)。
――ピンポーン! (チャイムの音)
こんにちはー!
おぉ、いらっしゃい!!
センパイ、今日は「センサーの処理をする」って言ってましたけど、一体どんなことをやるんですか〜?
マイクロマウスに搭載されている「センサー」の値を取得して、PCのモニターに表示させるんだよ。
あれ?
それって確かマイクロマウスのハードウェアを組み立てた後にやりましたよね?
うん。でもあの時は、サンプルのソースコードを使ったよね。今度は、自分のプログラムでやるんだよ!! ここを自分の手でやっておけば、「A/D変換」と「シリアル通信」の方法が理解できるはずだよ。
A/D変換? シリアル通信? う〜ん。聞いたことはあるけど、何だっけ……?
とにかく、いつものように始めよう!
まずは、センサーの値をA/D変換して、取り込んでみようか。
はーい!
今回は、“壁の有無”や“壁までの距離”を検知する「センサー」についてです。通常、センサーを使って測定した値をマイコンに取り込む場合、アナログ値をデジタル値に変換する処理「A/D変換」が必要です。また、その値をユーザーが読み取るには、「シリアル通信」を使って、PCのモニターに表示させなければなりません。マイコンプログラミングをする上で、このA/D変換とシリアル通信は、避けて通れません。今回の内容でA/D変換について、そして、次回の内容でシリアル通信について詳しく解説していきます。えみちゃんと一緒に、理解を深めていきましょう!!
では、本題に入る前に、ここでマイクロマウスの市販組み立てキット「Pi:Co Classic」に搭載されているセンサーの概要を説明します。
Pi:Co Classicは、前方に4つのセンサー(赤外線LEDとフォトトランジスタ)を搭載しています(画像1)。発光器であるLEDは、指向性の高いものが採用されており、これをパルス発光させることで、通常よりも遠くまで光を照射します。また、発光量を大きくすることで外乱光の影響を受けにくくしています。
受光器であるフォトトランジスタも同様に指向性の高いものが採用されています。フォトトランジスタの受光部がLEDから放たれた赤外線を受けると、エミッタ−コレクタ間に電流が流れます(画像2)。この値を取得することで、光量を測定できます。
光量はアナログ値ですから、マイコンに取り込むには、デジタル値に変換しなければなりません。Pi:Co Classicに搭載されているマイコン「SH7125」には、逐次比較方式の10ビット A/D変換器が内蔵されています。Pi:Co Classicは、このA/D変換器により、外部から入力されたアナログ値をデジタル値に変換して、マイコンに取り込みます。
近ごろ、コンピュータ技術が進化し、世の中が「デジタル化」していると言われますが、私たちの身の回りの音・温度・湿度・光などは、昔も今も変わらずアナログ値なのです。ここで紹介したように、A/D変換器でアナログ値を、コンピュータが扱えるデジタル値に変換することで、これらデータをデジタル機器などに取り込み、利用できるのです。
関連記事: | |
---|---|
⇒ | デジタル信号、アナログ信号って何? |
マイクロマウスに搭載されているセンサーの仕組みを理解したところで、いつものように、プログラミングに必要な情報をデータシートでチェックしておきましょう(表1、画像3、画像4、画像5)。
「アナログ」と「デジタル」か〜。正直、これまであまり意識したことなかったです。
組み込み開発をする上では「必須」と言える知識だね。
うーん。マイコンを扱うには、プログラミング以外にもいろいろな知識が必要なんですねぇ!
実際にモノを制御するわけだからね。まぁ、そこが組み込み開発、マイコン制御プログラミングの面白さだと思うよ!! それじゃあ、早速、センサー処理のプログラムを書いてみよう!
はいっ!!
それでは、いつものようにプログラムを作成していきましょう。まずは「init.h」に、A/D変換の設定に関する記述を追加します(ソースコード1)。
void init_adc(void); //A/D変換 初期化
続いて「init.c」のI/Oポートの初期化部分に、センサーLEDのポート出力設定(ソースコード2)を追加し、A/D変換の初期化(ソースコード3)を新たに記述します。
void init_io(void) { ……(中略)…… //センサーLED PFC.PAIORL.BIT.B6 = 1; //PA6を出力に設定(左) PFC.PAIORL.BIT.B7 = 1; //PA7を出力に設定(右) PFC.PAIORL.BIT.B8 = 1; //PA8を出力に設定(前左) PFC.PAIORL.BIT.B9 = 1; //PA9を出力に設定(前右) }
void init_adc(void) { STB.CR4.BIT._AD0 = 0; //AD0のスタンバイを解除 STB.CR4.BIT._AD1 = 0; //AD1のスタンバイを解除 // AD0.ADCR.BIT.ADST = 0; //AD停止 AD0.ADCSR.BIT.ADF = 0; //ADFフラグクリア AD0.ADCSR.BIT.ADIE = 0; //割込み禁止 AD0.ADCSR.BIT.TRGE = 0; //トリガイネーブル無効 AD0.ADCSR.BIT.CONADF = 0; //ADFコントロール(独立ADF) AD0.ADCSR.BIT.STC = 0; //ステートコントロール(50ステート) AD0.ADCSR.BIT.CKSL = 3; //周辺動作クロックPφ AD0.ADCSR.BIT.ADM = 0; //シングルスキャン AD0.ADCSR.BIT.ADCS = 0; //サイクルスキャンしない AD0.ADCSR.BIT.CH = 0; //AD0-ch0選択 // AD1.ADCR.BIT.ADST = 0; //AD停止 AD1.ADCSR.BIT.ADF = 0; //ADFフラグクリア AD1.ADCSR.BIT.ADIE = 0; //割込み禁止 AD1.ADCSR.BIT.TRGE = 0; //トリガイネーブル無効 AD1.ADCSR.BIT.CONADF = 0; //ADFコントロール(独立ADF) AD1.ADCSR.BIT.STC = 0; //ステートコントロール(50ステート) AD1.ADCSR.BIT.CKSL = 3; //周辺動作クロックPφ AD1.ADCSR.BIT.ADM = 0; //シングルスキャン AD1.ADCSR.BIT.ADCS = 0; //サイクルスキャンしない AD1.ADCSR.BIT.CH = 0; //AD1-ch0選択 }
A/D変換では3種類のレジスタにアクセスし、初期設定を行います。項目は多いですが、CKSL(クロックセレクト)以外は初期値で問題ありません(表2)。CKSLは、「3」を指定すると周辺動作クロック(Pφ)になります。
全てのハードウェアの初期化を行うinit_all関数に、A/D変換の初期化を追加します(ソースコード4)。
void init_all(void) { ……(中略)…… init_adc(); //ADCの初期化 }
これで、A/D変換の準備ができました。
Copyright © ITmedia, Inc. All Rights Reserved.