--------------------------------------------------------------------- #include <xc.h> #include <stdlib.h> #include "skMonitorLCD.h" // LCDモニター用 #define _XTAL_FREQ 16000000 // delay用に必要(クロック16MHzを指定) // コンフィギュレーションの設定(ここの記述に無い設定はデフォルト値での動作) // 外部クロックは使用しない(PRICLKEN_OFF) // 動作クロックを4倍では動作させない(PLLCFG_OFF):内部クロックを使用する(INTIO67) #pragma config PRICLKEN=OFF,PLLCFG=OFF,FOSC=INTIO67 // CONFIG1H // 電源電圧降下常時監視機能ON(BOREN_NOSLP):監視電圧は(2.85V)に設定 // 電源ONから後65.6msにプログラムを開始する(PWRTEN_ON) #pragma config BOREN=NOSLP,BORV=285,PWRTEN=ON // CONFIG2L // ウオッチドッグタイマー無し(WDTEN_OFF) #pragma config WDTEN=OFF // CONFIG2H // 外部リセット信号は使用せずにデジタル入力(RE3)ピンとする(MCLRE_INTMCLR) // オシレータが安定するのを待ってシステムクロックを供給する(HFOFST_OFF) #pragma config MCLRE=INTMCLR,HFOFST=OFF // CONFIG3H // 低電圧プログラミング機能使用しない(LVP_OFF) #pragma config LVP=OFF // CONFIG4L // 指定した時間(num x 10ms)だけウエイトを行う処理関数 void Wait(unsigned int num) { int i ; // numで指定した回数だけ繰り返す for (i=0 ; i<num ; i++) { __delay_ms(10) ; // 10msプログラムの一時停止 } } // 電極の電圧値を読み取る処理 int CTM_ReadRobe() { unsigned long temp ; unsigned int cap , i ; temp = 0 ; for (i=0 ; i < 10 ; i++) { // ゼロ電位から開始させる為に電荷を放電させる CTMUCONHbits.IDISSEN = 1 ; __delay_us(125) ; CTMUCONHbits.IDISSEN = 0 ; // 電極に充電を行う CTMUCONLbits.EDG2STAT = 0 ; CTMUCONLbits.EDG1STAT = 1 ; __delay_us(20) ; CTMUCONLbits.EDG1STAT = 0 ; // 電極の電圧(AN0)を読み取る GO_nDONE = 1 ; // アナログ値読取り開始指示 while(GO_nDONE) ; // 読取り完了まで待つ cap = ADRESH ; cap = ( cap << 8 ) | ADRESL ; temp = temp + cap ; } return temp/10 ; // 10回の平均値を返す } // メインの処理 void main() { char s[8] ; unsigned int cap ; OSCCON = 0b01110010 ; // 内部クロックとする(16MHz) ANSELA = 0b00000001 ; // AN0のみアナログ、他のAN1-4はデジタルI/Oに割当 ANSELB = 0b00000000 ; // AN8-13アナログは使用しない、デジタルI/Oに割当 ANSELC = 0b00000000 ; // AN14-19アナログは使用しない、デジタルI/Oに割当 TRISA = 0b00000001 ; // RA0のみ入力、他は全て出力に設定、、1で入力 0で出力 TRISB = 0b00000000 ; // RB0-RB7全て出力に設定 TRISC = 0b00000000 ; // RC0-RC7全て出力に設定 PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) PORTB = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) PORTC = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) // アナログ入力の設定 ADCON1 = 0b00000000 ; // VDDをリファレンスとする ADCON2 = 0b10010101 ; // 読取値は右寄せ、A/D変換クロックはFOSC/16、4TAD後に変換開始 ADCON0 = 0b00000001 ; // アナログ変換情報設定(AN0から読込む) __delay_us(8) ; // アナログ変換情報が設定されるまでとりあえず待つ // CTMU(充電時間計測ユニット)の設定 CTMUICON = 0b00000010 ; // 電流ソースは5.5uA(調整は無) CTMUCONL = 0b00000000 ; // エッジ制御ロジックは未使用 CTMUCONH = 0b10000000 ; // CTMUの開始 MonitorInit() ; // LCDモニターに送信出来る様に初期化する while(1) { // 電極の電圧(AN0)を読み込む cap = CTM_ReadRobe() ; // 読んだ値をLCDモニターに表示する MonitorPutc(0x11) ; // モニターの表示位置を設定する MonitorPuts(" ") ; // 表示を消す MonitorPutc(0x11) ; // モニターの表示位置を設定する utoa(s,cap,10) ; // カウント値を文字列に変換する MonitorPuts(s) ; // 表示する // 500ms後に繰り返す Wait(50) ; } } ---------------------------------------------------------------------このプログラムにはデバッグモニタープログラム「skMonitorLCD.c」「skMonitorLCD.h」が必要です。
電極 | 触れていない時 | 触れた時 | 0.5mmの青アクリル裏 から触れた時 |
リードジャンプワイヤー (充電時間 20us) |
733〜734位 | 545〜595位 | − |
20mm x 20mm x 0.3mm の銅板 (充電時間 20us) |
706〜709位 | 547〜605位 | 632〜645位 |
20mm x 20mm x 0.3mm の銅板 (充電時間 10us) |
366〜369位 | 280〜320位 | 320〜332位 |
ビッ ト | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
機能 | CTMUEN | CTMUSIDL | TGEN | EDGEN |
EDGSEQEN | IDISSEN | CTTRIG |
ビッ ト | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
機能 | EDG2POL | EDG2SEL | EDG1POL | EDG1SEL | EDG2STAT | EDG1STAT |
ビッ ト | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
機能 | ITRIM | IRNG |
--------------------------------------------------------------------- #include <xc.h> #define _XTAL_FREQ 16000000 // delay用に必要(クロック16MHzを指定) #define ANALOG_NUMBER 20 // アナログ端子のピン実装個数(AN0-AN19) // CTMU用データ unsigned int CTM_data[3][ANALOG_NUMBER] = {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} ; // コンフィギュレーションの設定(ここの記述に無い設定はデフォルト値での動作) // 外部クロックは使用しない(PRICLKEN_OFF) // 動作クロックを4倍では動作させない(PLLCFG_OFF):内部クロックを使用する(INTIO67) #pragma config PRICLKEN=OFF,PLLCFG=OFF,FOSC=INTIO67 // CONFIG1H // 電源電圧降下常時監視機能ON(BOREN_NOSLP):監視電圧は(2.85V)に設定 // 電源ONから後65.6msにプログラムを開始する(PWRTEN_ON) #pragma config BOREN=NOSLP,BORV=285,PWRTEN=ON // CONFIG2L // ウオッチドッグタイマー無し(WDTEN_OFF) #pragma config WDTEN=OFF // CONFIG2H // 外部リセット信号は使用せずにデジタル入力(RE3)ピンとする(MCLRE_INTMCLR) // オシレータが安定するのを待ってシステムクロックを供給する(HFOFST_OFF) #pragma config MCLRE=INTMCLR,HFOFST=OFF // CONFIG3H // 低電圧プログラミング機能使用しない(LVP_OFF) #pragma config LVP=OFF // CONFIG4L // 指定した時間(num x 10ms)だけウエイトを行う処理関数 void Wait(unsigned int num) { int i ; // numで指定した回数だけ繰り返す for (i=0 ; i<num ; i++) { __delay_ms(10) ; // 10msプログラムの一時停止 } } // 電極の電圧値を読み取る処理 int CTM_ReadRobe() { unsigned long temp ; unsigned int cap , i ; temp = 0 ; for (i=0 ; i < 10 ; i++) { // ゼロ電位から開始させる為に電荷を放電させる CTMUCONHbits.IDISSEN = 1 ; __delay_us(500) ; // 500usの時間だけ放電させる CTMUCONHbits.IDISSEN = 0 ; // 電極に充電を行う CTMUCONLbits.EDG2STAT = 0 ; CTMUCONLbits.EDG1STAT = 1 ; __delay_us(20) ; // 20usの時間だけ充電させる CTMUCONLbits.EDG1STAT = 0 ; // 電極の電圧を読み取る GO_nDONE = 1 ; // アナログ値読取り開始指示 while(GO_nDONE) ; // 読取り完了まで待つ cap = ADRESH ; cap = ( cap << 8 ) | ADRESL ; temp = temp + cap ; } return temp/10 ; // 10回の平均値を返す } // CTMUに接続されている電極の初期値を読み込む処理 void CTM_Init() { int i ; // 接続している電極の分だけ繰り返す for (i=0 ; i<ANALOG_NUMBER ; i++) { if (CTM_data[0][i] == 1) { ADCON0bits.CHS = i ; // アナログ変換を行うチャンネルの設定 __delay_us(8) ; // アナログ変換情報が設定されるまでとりあえず待つ CTM_data[1][i] = CTM_ReadRobe() ; // 電極の電圧値を読む } else CTM_data[1][i] = 0 ; CTM_data[2][i] = 0 ; } } // CTMUに接続されている電極の現在値を読み込む処理 void CTM_ScanRobe() { unsigned int cap ; int i ; // 接続している電極の分だけ繰り返す for (i=0 ; i<ANALOG_NUMBER ; i++) { if (CTM_data[0][i] == 1) { ADCON0bits.CHS = i ; // アナログ変換を行うチャンネルの設定 __delay_us(8) ; // アナログ変換情報が設定されるまでとりあえず待つ cap = CTM_ReadRobe() ; // 電極の電圧値を読む if (cap <= (CTM_data[1][i]*0.92)) { // 現在値が初期値の92%以内ならONとする CTM_data[2][i] = cap ; // ONとする } else { CTM_data[2][i] = 0 ; // OFFとする CTM_data[1][i] = cap ; // 初期値とする } } } } // CTMUに接続されている電極の状態を調べる処理 // num : 調べる電極のアナログ番号を指定する int CTM_StateRobe(int num) { if (num >= ANALOG_NUMBER) return( -1 ) ; // 数値指定エラー if (CTM_data[0][num] != 1) return( -1 ) ; // 数値指定エラー if (CTM_data[2][num] == 0) return( 0 ) ; // 電極に触れていない else return( 1 ) ; // 電極に触れている } /******************************************************************************* * メインの処理 * *******************************************************************************/ void main() { OSCCON = 0b01110010 ; // 内部クロックとする(16MHz) ANSELA = 0b00000011 ; // AN0/1のみアナログ、他のAN2-4はデジタルI/Oに割当 ANSELB = 0b00000000 ; // AN8-13アナログは使用しない、デジタルI/Oに割当 ANSELC = 0b00000000 ; // AN14-19アナログは使用しない、デジタルI/Oに割当 TRISA = 0b00000011 ; // RA0/1のみ入力、他は全て出力に設定、1で入力 0で出力 TRISB = 0b00000000 ; // RB0-RB7全て出力に設定 TRISC = 0b00000000 ; // RC0-RC7全て出力に設定 PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) PORTB = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) PORTC = 0b00000000 ; // 出力ピンの初期化(全てLOWにする) // アナログ入力の設定 ADCON1 = 0b00000000 ; // VDDをリファレンスとする ADCON2 = 0b10010101 ; // 読取値は右寄せ、A/D変換クロックはFOSC/16、4TAD後に変換開始 ADCON0 = 0b00000001 ; // アナログ変換情報設定(AN0から読込む) __delay_us(8) ; // アナログ変換情報が設定されるまでとりあえず待つ // CTMU(充電時間計測ユニット)の設定 CTMUICON = 0b00000010 ; // 電流ソースは5.5uA(調整は無) CTMUCONL = 0b00000000 ; // エッジ制御ロジックは未使用 CTMUCONH = 0b10000000 ; // CTMUの開始 // 電極の初期値を読み込む CTM_Init() ; while(1) { // 電極の現在値を読み込む CTM_ScanRobe() ; // 電極1(AN0)の状態でLED1を点灯させる処理 if (CTM_StateRobe(0) == 1) LATB7 = 1 ; // LED1を点灯 else LATB7 = 0 ; // LED1を消灯 // 電極2(AN1)の状態でLED2を点灯させる処理 if (CTM_StateRobe(1) == 1) LATB6 = 1 ; // LED2を点灯 else LATB6 = 0 ; // LED2を消灯 } } ---------------------------------------------------------------------プログラムについて
#define ANALOG_NUMBER 20 // アナログ端子のピン実装個数(AN0-AN19) // CTMU用データ unsigned int CTM_data[3][ANALOG_NUMBER] = {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} ;ANALOG_NUMBERはAN0-AN19までアナログが有るので20とします。
#define ANALOG_NUMBER 20 // アナログ端子のピン実装個数(AN0-AN19) // CTMU用データ unsigned int CTM_data[3][ANALOG_NUMBER] = {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0} ;
if (cap <= (CTM_data[0][i]*0.92)) {と有るので0.92を変更して下さい、0.92を上げれば感度も良くなります。
while(1) { CTM_ScanRobe() ; }とこんな感じですね。
void interrupt InterTimer( void ) { if (TMR0IF == 1) { // タイマー0の割込み発生か? TMR0 = ???? ; // タイマー0の初期化 CTM_ScanRobe() ; TMR0IF = 0 ; // タイマー0割込フラグをリセット } }とこんな感じですね。
リンクの見直し(*2) 2017/01/13
"skMonitorLCD.c"変更により"実験1"のプログラム変更(*1) 2014/02/01
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.