

下記の様な電極を作ってみました。
---------------------------------------------------------------------
#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 | ||||||
この左図の電極1に触れればLED1
---------------------------------------------------------------------
#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.