PIC12F1822の基本動作から応用プログラムまでを学びます。

ホーム
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
    
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
PIC12F1822の(CPS)静電容量式センシングモジュール

12F1822 には、電極に指が触れると、指とグランド間の寄生容量を検知し、SWがONとなる静電容量式センシングモジュール”Capacitive Sensing (CPS) module"が組み込まれています。 このような非機械式入力装置をMicrochip社では mTouch と呼び、この CPSモジュールは mTouch の代表的な方法です。CPSは、複数の端子を切り替えるMUXと端子の容量により周波数が変化する発振器から構成されています。いろいろな形状の端子に対応できるよう、発振機の基準電圧をソフトウエアで変更できるようなっています。なお、端子の静電容量の変化を検知するため、一般的に端子には薄いフィルムなどで覆い、端子と指が直接接触することはありません。

*注意*
CPS端子に指定するI/Oピンは、以下の設定をします。

CPSRNG
<1:0>
CPSRM = 0 (Low レンジ)
内蔵の参照電圧を使う
CPSRM = 1 (High レンジ)
DAC とFVR を使う
オシレータ 充放電電流 オシレータ 充放電電流
00 OFF - ON 供給されない
01 ON 0.1 μA ON 9 μA
10 ON 1.2 μA ON 30 μA
11 ON 18 μA ON 100 μA

参照電圧と充放電電流の関連

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
CPSCON0 CPSON CPSRM CPSRNG1 CPSRNG0 CPSOUT T0XCS
CPSCON1 CPSCH1 CPSCH0
ANSELA ANSA4 ANSA2 ANSA1 ANSA0
TRISA TRISC5 TRISA4 TRISC3 TRISA2 TRISA1 TRISA0
WPUA WPUA5 WPUA4 WPUA3 WPUA2 WPUA1 WPUA0
レジスタ BIT 内容 1 0
CPSCON0 7 CPSON CPS モジュール イネーブル ON OFF
6 CPSRM 参照電圧モード 外部 内蔵
3 CPSRNG1 電流レンジ
01:Low 10:Medium 11:High
2 CPSRNG0
1 CPSOUT オシレータ ステータ (Read Only) 出力 入力
0 T0XCS Timer0 外部クロック源選択 CPS T0CKI
CPSCON1 4 CPSCH1 チャンネル選択
00 = CPS0 01 = CPS1 10 = CPS2 11 = CPS3
2 CPSCH0

CPSモジュールのプログラム例

2つのSWパッドを接続し、指が触れると端子に対応したLEDを点灯させるものです。

上記処理を、2つの端子に対して繰り返します。

<回路図>

<PIC内蔵モジュール関係図>

<CPSカウント計測手順>

<プログラム>

/*********************************************************************
 *  静電容量式センシング
 *            CPS電極に近づくとLEDが点灯  
 *
 *      1 VDD         8 VSS
 *  LED 2 RA5         7 RA0 TX
 * CPS3 3 RA4         6 RA1 LED
 *      4 MCLR        5 RA2 CPS2
 *
 * PIC12F1822  MPLAB X IDE with XC8 Ver1.32
 * Copyright (c) 2014 iwamoto All Rights Reserved
 *
 * *******************************************************************/

#define ch_0_IN    2      // CPS index0 Pad 接続 CPS 端子番号
#define ch_1_IN    3      // CPS index1 Pad 接続 CPS 端子番号
#define ch_0_OUT   LATA1  // CPS index0 LED 接続 ポート
#define ch_1_OUT   LATA5  // CPS index1 LED 接続 ポート
#define LED_ON     1
#define LED_OFF    0

#include <xc.h>

//******************* コンフィグレーション ****************************
#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = ON, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF
#pragma config WRT = OFF, PLLEN = OFF, STVREN = ON, BORV = LO, LVP = OFF
//
//******************* プロトタイプ ************************************
void CPSck(char);
unsigned int CPScnt(char);
void LEDout(char, char);

//******************* 共通変数 ****************************************
char ch_IN[] = {ch_0_IN, ch_1_IN};  // CPS 端子番号
unsigned int Avg[2];                // 通常時平均カウント
unsigned int swOn[]  = {180,180};   // ON  閾値カウント
unsigned int swOff[] = { 90, 90};   // OFF 閾値カウント

// ******************* main ******************************************
void main() {
    OSCCON = 0b01101010;            //  内部クロック4Mhz
    PORTA  = 0x00;
    TRISA  = 0b11011101;            // RA1,5:LED出力 他は入力
    ANSELA = 0b00010100;            // RA2,4:CPS, 他デジタル
    WPUA   = 0b00001001;            // RA0,3 弱プルアップ ON
    OPTION_REGbits.nWPUEN = 0;

    // Timer 0 設定 -------------------------------------------------
    //   8.2mSでオーバーフローし、CPSカウントのタイムベースとなる
    // --------------------------------------------------------------
    OPTION_REGbits.TMR0CS = 0;      // 内部クロックをカウント
    OPTION_REGbits.PSA = 0;         // プリスケラを使用する
    OPTION_REGbits.PS = 4;          // PS_1:32

    // Timer 1 設定 -------------------------------------------------
    //   Gate機能の シングルトグル モードでCPS をカウントする
    // --------------------------------------------------------------
    T1CON  = 0b11000001;       // CAPOSC, PS 1:1, OSC無効, 同期, ON
    T1GCON = 0b11110001;       // Gate有効,正極性,トグル,シングル,T0入力

    // CPS 設定 ------------------------------------------------------
    CPSCON0 = 0b10001000;      // CPS有効,内蔵参照電圧,Medium レンジ

    Avg[0] = CPScnt(0);        // 通常時平均カウントの初期設定
    Avg[1] = CPScnt(1);

    while(1){
        CPSck(0);              // CPS index0 の処理
        CPSck(1);              // CPS index1 の処理
    }
}

/*********************************************************************
 * 指定 CPS indexチャネルのカウントを計測し、平均カウントと比較
 *      ON 閾値より小さければ、LED ON
 *      OFF閾値より大きければ、LED OFF さらに平均値を更新
 *********************************************************************/
void CPSck(char ch){
    unsigned int raw;
    raw = CPScnt(ch);                        // チャネルのカウントを計測
    if(raw < (Avg[ch] - swOn[ch])){          // ON 閾値より小さければ
        LEDout(LED_ON, ch);                  //   LED ON
    }else if(raw > (Avg[ch] - swOff[ch])){   // OFF閾値より大きければ
        LEDout(LED_OFF, ch);                 //   LED OFF
                                             // 平均値を更新 (重み 1/16)
        Avg[ch] = Avg[ch] + ((long)raw - (long)Avg[ch])/ 16;
    }
}
/**********************************************************************
 * 指定 CPS indexチャネルのカウントを計測する
 *********************************************************************/
unsigned int CPScnt(char ch){
    CPSCON1 = ch_IN[ch];            // CPS indexチャネル指定
    TMR0 = 0xFE;                    //  Timer0 始動
    TMR1 = 0;                       //  Timer1 クリア
    T1GGO  = 1;                     // 計測を指示
    while(T1GGO);                   // 計測終了を待つ
    return TMR1;                    // Timer1読取
}
/**********************************************************************
 * 指定 CPS indexチャネルのLEDを ON / OFFする
 *********************************************************************/
void LEDout(char OnOff, char ch){
    switch(ch){
        case 0: ch_0_OUT = OnOff;break;
        case 1: ch_1_OUT = OnOff;break;
    }
}

CPSカウント値の評価方法

CPS端子は、使用するアプリケーションにより異なるため、指が離れている時の平均カウント値や、指で押さえたときのカウント値を吟味し、ON/OFFを判断する閾値を見つけ出す必要があります。 下図は、評価に必要な関係図を示します。

  • 現在のCPSカウント(青)
  • 通常時平均カウント(Avg)
  • ON 閾値 (swOn)
  • OFF 閾値 (swOff)

*注意*
閾値の swOn と swOff は平均値 Avg からの差で表します。

最新のCPSカウント値が
(Avg - swOn) 値より小さければ、LEDを点灯させ、
(Avg - swOff) 値より大きければ、LEDを消灯させます。
Avg は、指が離れている時の最新16サンプルの平均値を使います。

現在のCPSカウント値が、
(Avg - swOn) 値より小さければ、平均値には反映せず、
(Avg - swOff) 値より大ききければ、現在の平均値に反映させます。
最新16サンプルの平均値に反映するる方法は、今までの(旧)Avg を15/16 した値に、最新CPSカウント値を 1/16 した値を加えます。

実際にアプリケーションを設計するときは、設計する装置毎に、端子形状やPICから端子までの距離が異なるので、そのたびごとにON/OFF閾値を適切な値に変更することが求められます。 この目的のため平均カウントと、現在カウント値を外部接続したシリアル表示器に表示するプログラムを上記プログラムに追加しました。
使用したシリアル表示機は、このホームページで作成したものです。

ON/OFF閾値を検証するプログラム CPS_Cnt_Monitor.zip

<プログラムの使い方>
  CPS用PICのpin7(RA0)とシリアル表示器用PICのpin2(RA5)を接続します。ダウンロードしたプログラムは、
CPS index 1 (CPS3) のカウント値をLCDに表示します。
  LCD上段が平均カウント、下段が現在のカウントです。
CPS index 0 (CPS2) のカウント値を表示させるには、
  プログラム17行目を #define Enable_Dsp 0 とします。(下図赤丸内)

CPS_Cnt_Monitor.c