●A/D変換 を使ってみよう
PICではアナログ信号(電圧)をデジタルデータに変換するA/D変換機能が搭載されて おり、とても興味がありますので簡単な動作確認レベルで使ってみることにしました。 ・アナログ信号源(電圧データ)  可変抵抗の半固定ボリューム(10KΩ)を利用して、0V〜約5V(電源電圧)までの  範囲で、アナログ信号としての電圧データを発生させます。 ・A/D変換後の値を測定する  アナログ信号を入力してA/D変換実行後のデジタルデータ(測定値)を、EEPROM  に保存(記憶)させて、測定値の推移を調べます。
・ ・ ・ ・ ・
●配線図です。

■プログラムは・・・  サーボコントローラ 改良版1(SATBVB01 )を流用して、A/D変換処理部分を  追加する方法で作りました。   ------------------------------------------------------------------------------   ・SATBVD01( VER 0D.01 ) サーボコントローラ 改良版3    追加機能:A/D変換     A/D変換値をEEPROMに保存(記憶)する。   ------------------------------------------------------------------------------       【 PIC12F683 】       __________ __________       | V |      | |       3〜5V+ --+ 1 Vdd(+) | Vss(-) 8 +-- 0V      --+ 2 GP5 |OUT GP0 7 +--> サーボ       --+ 3 GP4 | GP1 6 +--< アナログ信号(電圧)      サーボ-->+ 4 GP3 IN | GP2 5 +--< SW.NEUTRAL       | |       +---------------------+
●A/D変換機能について  ■使用環境   ・基準電圧 : 約5V  ( 電源電圧を使用する )   ・測定電圧 : 0〜約5V( 基準電圧内で )   ・A/D変換値 : 10ビット ( 00 0000 0000 〜 11 1111 1111 )   ・変換段階数: 1023  ■A/D変換出力値   測定電圧(V)÷ 基準電圧(電源電圧)(V)X 1023(変換段階数) = A/D変換出力値  ■A/D変換出力値は、10ビットなので下記値の範囲内で表現される。   ・10ビットの表現(2進数) : 00 0000 0000 〜 11 1111 1111   ・10ビットの表現(10進数): 0 〜 1023   ・10ビットの表現(16進数): 0 00 〜 3 FF   *高精度値を求めないなら、上位8ビットを使用した方が扱いやすい感じがする。 ( 0 〜 1020 )  ■最小測定電圧(分解能)   基準電圧(電源電圧)(V)÷ 1023(変換段階数) = 最小測定電圧(分解能)(mV)    5V ÷ 1023段階数 = 約4.9 mV    最小約4.9 mVの分解能となるので、この単位が最小測定電圧となる。
●既存の初期設定に対して、A/D変換機能の設定を反映した部分です。 ;---A/D変換の(クロック・入力ピン)設定--- アナログ入力ピン(GP1のみ),他入力ピンはデジタルにする MOVLW B'00010010' ;Wレジスタ ← GP1のみアナログ入力ピンとして使う ;未使用 :ビット:7(0) ;A/D変換クロック選択(8Tosc):ビット:6-4(001) ;アナログ/デジタル選択(GP1) :ビット:3-0(0010) MOVWF ANSEL ;ANSELレジスタ ← Wレジスタ ;---入力ピン--- アナログ入力ピン(GP1のみ)、他入力ピンはデジタルI/O MOVLW B'00001110' ;Wレジスタ ← GP1、2、3を入力ピンとして使う MOVWF TRISIO ;TRISIOレジスタ ← Wレジスタ ;---A/D変換動作の設定--- MOVLW B'10000101' ;Wレジスタ ← A/D変換結果:左詰め,基準電圧:電源電圧 で使う ;A/D変換結果(右詰め):ビット7(1) ;基準電圧(電源電圧):ビット6(0) ;未使用 :ビット5-4(00) ;A/D変換のチャネル(AN1):ビット3-2(01) ;A/D変換状態(完了):ビット1(0) ;A/D変換状態(有効):ビット0(1) MOVWF ADCON0 ;ADCON0レジスタ ← Wレジスタ
・ ・ ・ ・ ・
●サンプリングコンデンサへの充電時間(アクイジション時間)について A/D変換の実行を開始するのに、前処理としてA/D変換準備の完了を待ちます。目的は アナログ信号(電圧)の情報源となるPIC内蔵コンデンサの充電が完了する必要があり、 この充電が完了する時間をアクィジション時間と言われています。 A/D変換のクロック指定は、PICを動作させるオシレータ(クロック)の周波数と、A NSELレジスタのADCS2〜0など、下記の設定で決めています。 ・オシレータ       :4MHz ・A/D変換のクロック指定:8Tosc( オシレータの1クロック<1サイクル> X 8 ) アクイジション時間は、2.0μ秒となり、入力の抵抗抵抗が10KΩですので、プログラ ム内で、時間調整処理を約20μ秒しており、この方法でA/D変換準備の完了判断してい ます。 ■しかしながら・・・ちょっと、変な対応? しちゃいましたです。(^^; 既存のサーボコントローラプログラムの中にA/D変換処理ステップを追加していますので プログラムロジック的に推奨されるアクイジション時間以上は確保できていますので、考慮 する必要はないのですが、A/D変換の実行条件を安定させたいので、適用するA/D変換 実行の直前にリセットもどきのダミー処理(A/D変換)を2回してから、アクイジション 時間の時間調整処理を約20μ秒しています。こんな方法で良いのかしら?
●A/D変換の実行処理したサブルーチン部分です。 ;****************************************************************************************** ;* A/D変換処理    * ;****************************************************************************************** ; ; @A/D変換(1回目):ダミー処理としてA/D変換を完了する ; AA/D変換(2回目):ダミー処理としてA/D変換を完了する ; BA/D変換(3回目):この処理のA/D変換を適用し、A/D変換結果(10ビット) を取得する ;  ・ADHSAV(A/D変換値上位):ADRESHレジスタ(A/D変換結果上位) をセットする ;  ・ADLSAV(A/D変換値下位):ADRESLレジスタ(A/D変換結果下位) をセットする ;---- ADHEN_RTN ;---- @A/D変換(1回目)これは、ダミー処理です ;---A/D変換を開始する (GOビットをON<1>にする) BSF ADCON0,GO ;ADCON0レジスタ(GOビット) ← 1 ;---A/D変換の完了を待つ(GOビットがOFF<0>になるまで) ADHEN_LOOP1 BTFSC ADCON0,GO ;ADCON0レジスタ(GOビット)=0の時 次の命令をスキップする     GOTO  ADHEN_LOOP1  ;ADHEN_LOOP1へ ジャンプする (A/D変換完了待ちループ) ;---- AA/D変換(2回目)これは、ダミー処理です ;---A/D変換を開始する (GOビットをON<1>にする) BSF ADCON0,GO ;ADCON0レジスタ(GOビット) ← 1 ;---A/D変換の完了を待つ(GOビットがOFF<0>になるまで) ADHEN_LOOP2 BTFSC ADCON0,GO ;ADCON0レジスタ(GOビット)=0の時 次の命令をスキップする GOTO ADHEN_LOOP2 ;ADHEN_LOOP2へ ジャンプする (A/D変換完了待ちループ) ;---- BA/D変換(3回目)この処理を適用する MOVLW 0 ;Wレジスタ ← 0(ゼロ) MOVWF ADHSAV ;ADHSAV (A/D変換値上位) ← Wレジスタ MOVWF ADLSAV ;ADLSAV (A/D変換値下位) ← Wレジスタ ;---A/D変換時間待ち(約20u秒)の判断 <ADHCNT=0:約20u秒オーバーになった状態> ;---PIC内蔵コンデンサの充電を待つ時間(20u秒)、入力抵抗が10KΩの時、約20μ秒要 MOVLW D'5' ;Wレジスタ  ← 5 MOVWF ADHCNT ;ADHCNT(A/D変換待ち時間カウント) ← Wレジスタ ADHEN_LOOP3 DECFSZ ADHCNT,1 ;(ADHCNT=ADHCNT−1)=0の時 次の命令をスキップする GOTO ADHEN_LOOP3 ;ADHEN_LOOP3へ ジャンプする (充電待ちループ) ;---A/D変換を開始する (GOビットをON<1>にする) BSF ADCON0,GO ;ADCON0レジスタ(GOビット) ← 1 ;---A/D変換の完了を待つ(GOビットがOFF<0>になるまで) ADHEN_LOOP31 BTFSC ADCON0,GO ;ADCON0レジスタ(GOビット)=0の時 次の命令をスキップする     GOTO  ADHEN_LOOP31 ;ADHEN_LOOP31へ ジャンプする (A/D変換完了待ちループ) ;---A/D変換結果の取得--- A/D変換出力値(10ビット) → ADRESHレジスタ(上位8ビット) ;-----ADHSAV(A/D変換値上位):ADRESHレジスタ(A/D変換結果上位) をセットする MOVF ADRESH,0 ;Wレジスタ  ← ADRESHレジスタ(A/D変換結果上位) MOVWF ADHSAV ;ADHSAV(A/D変換値上位)← Wレジスタ ;-----ADLSAV(A/D変換値下位):ADRESLレジスタ(A/D変換結果下位) をセットする BSF STATUS,RP0 ;■バンク1にする ( ステータスレジスタのRP0 ← 1 ) MOVF ADRESL,0 ;Wレジスタ  ← ADRESLレジスタ(A/D変換結果下位) BCF STATUS,RP0 ;■バンク0に戻す ( ステータスレジスタのRP0 ← 0 ) MOVWF ADLSAV ;ADLSAV(A/D変換値下位)← Wレジスタ ADHEN_END RETURN
・ ・ ・ ・ ・
●計算値を算出してから測定した値との比較です。 測定電圧 計算値 測定値 (V) (10進数)(10進数)  ・0.0   0 0  ・0.5  102 79  ・1.0  205 179  ・1.5  307 291  ・2.0  409 397  ・2.5  512 490  ・3.0  614 600  ・3.5  716 705  ・4.0  818 815  ・4.5  921 911  ・5.0 1023 1023 測定電圧(V)÷ 基準電圧(電源電圧)(5V)X 1023(変換段階数) = A/D変換出力値
●なんとなく、A/D変換出力値の測定ができた感じですが・・・ この環境下で測定すると、想定した値と違います。こんなものかしら? こんな小世界の測定は、まるで、ミクロの決死圏みたいだな (^^;
・ ・ ・ ・ ・