amazonで電子部品をあさっているとき、16キー構成の静電容量タッチキーモジュールが目についたのでついでに購入 (199円)。赤外線リモコンの操作部にいいかなと思って、さっそく5V動作のArduino PRO MINI (The Simple) につないでみることにした。
TonTouch™ IC TTP229
TonTouch™ IC のTTP229-BSF (8229BSF)が載っている。 TonTouch™ ICというのは台湾のTonTek社が商標をもつ静電容量タッチパッドの制御用ICのようである。
インドにある sunrom社のページからデータシートをダウンロード可能。今回購入した製品は、このICのデモ用基板として用意されたもののようで、同社のサイトから回路図もダウンロード可能だった。
サフィックス違いのTTP229-Lが外部インタフェースとしてI2Cを備えているのに対し、この基板に載っているTTP229-Bは独自の2線式シリアルインタフェースをもっている。なのでI2Cのライブラリを使った接続はできないから、データシートを読むときにはデバイス名のサフィックスに注意が必要だろう。
この基板はTTP229-BというICのデモ用で、実用的な16キーのタッチキーモジュールというより、ICの機能の確認用として設計されており、わざわざ12ピンのピンヘッダが用意されている。このうちの8ピン(OUT1~OUT8)は、9~16と印字されている8つキーの状態(オンかオフか)を直接マイコンのIOポートで読むために用いるようだ。キー1~8については、SCLとSDOの2ピンを使ったシリアル通信で読めるようになっている。電源ピン(VCC)には、+2.4~+5.5Vを与えることが可能で、IC内部のレギュレータによって必要な電圧を生成しているとのこと。
基板上のジャンパエリア(P1、P2)にはICのTP0~TP7が引き出されており、出荷時にはすべてオープン状態となっている。ジャンパすると1MΩの抵抗を介してGNDに接続される。電源投入時のTP0~TP7の状態(オープン=1, クローズ=0) によってICの挙動を設定可能で、16個のキーすべてをシリアル通信で読んだり、通信時の論理を反転したり、キースキャンのレートを変更したりすることができる。詳しくはデータシートを参照のこと。
ジャンパエリア周辺を拡大したところ。右側のICがTTP229B、左側のR1とR2が1MΩの集合抵抗、左端のR3とD1はLEDおよび直列抵抗(1KΩ)。
今回は出荷時のままの状態で、シリアル通信を使って8つのキー(キー1~キー8) を読み取って、タッチされたキーの番号をシリアルモニタに表示することを目標とした。次の段階では、ジャンパエリアにヘッダを立てて設定変更できるようにし、なおかつArduino のスリープモードと組み合わせる予定。
回路図
+5V、16MHz動作のArduino PRO MINI( The Simple) に、USB-シリアル変換用のAE-FT231Xを接続し、PRO MINIのD2をSDO、D4をSCLに接続した。OUT1~OUT8は使わない。
PRO MINIおよびTTP229タッチキーモジュールの電源は、AE-FT231Xから(つまりPCのUSBから)もらうことにした。動作時の全体の消費電流は約20mAだった。今回使ったArduino PRO MINIは、裏にThe Simpleと書かれた安いヤツで、以前POWER ON LED用の直列抵抗を外したもの。
TTP229BのSDOは、キータッチを検出しデータを送出する準備ができるとアクティブレベルになる(アクティブLかアクティブHかは、ジャンパで変更可能。出荷状態ではアクティブL)。SDOをArduino のD2につないだのは、エッジセンスかレベルセンスの割込み要因として用いることを意図したから(今回は割り込みは使わない)。
こういった構成になった。タッチキーモジュールの裏には何かのデバイスが入っていた静電防止袋をセロテープで貼り付けてある。
プログラム
今回のスケッチはTTP229Bからもらったキーの内容をシリアルモニタに表示するだけなので、TTP229Bとのシリアル通信の確認が主眼になっている。
シリアル通信のタイミングチャート
シリアル通信時のタイミング(アクティブL出力、8キー出力)は以下のようになっている。出荷時設定のアクティブL出力を使う場合、TTP229は初期化後SDO == Hを出力する。マイコン側(Arduino側)も初期化時にSCL == H としておく。
- DV (Data Valid) : 1キー分のデータが用意できると、約90μ秒の期間、アクティブ状態となる(図ではLレベル)。これを検出したら、Tw(10μsec min.) 後からSCLの駆動を開始する。
- F_SCL : SCLの周波数を表しており、1KHz (min.)~512KHz (max.)となっている。1周期の時間に直すと 1msec~2μsec の範囲のクロックを与える。
- Tout : SCL==Hの期間がTout (2msec) 以上の場合、TTP229はシリアル通信をやめてスタンバイ(キータッチ待ち)状態に戻るとのこと。
- SDOには タッチされているキーが”0″となった8ビットのデータがキー1(LSB)から順に出力される(出荷状態の、アクティブL、シングルキー、8キー出力構成時)。データシートを見ても、各キーのデータが確定するタイミングが明確には読み取れないのだけど、上図のようにSCLの立上りで読めば良さそうである。
- 上図は、1と書いてあるキーを押した場合の波形の概略を示しているが、LSBから何番目のビットが0かによって押下されているキーがわかる。ビット0が0ならばキー1,ビット7が0ならばキー8ということになる。
タッチされたキーを確認するスケッチ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#define LED 13 #define TTP_SDO 2 #define TTP_SCL 4 #define READ_SDO() (PIND & B00000100) #define SET_SCL() (PORTD |= B00010000) #define RESET_SCL() (PORTD &= B11101111) void setup() { delay(500); Serial.begin(115200); Serial.println("start"); pinMode(LED, OUTPUT); pinMode(TTP_SDO, INPUT); pinMode(TTP_SCL, OUTPUT); SET_SCL(); // default H } bool read_keydata() { RESET_SCL(); delayMicroseconds(5); SET_SCL(); int n = READ_SDO(); delayMicroseconds(5); return n != 0; } void loop() { int n = READ_SDO(); if (n == 0) { delayMicroseconds(100); int i; unsigned int tpp_data = 0; int key_no = 0; for(i = 0; i < 8; i++) { tpp_data >>= 1; bool f = read_keydata(); tpp_data |= f ? 0x80 : 0; if (!f) key_no = i + 1; } tpp_data |= 0xff00; // if (tpp_data != 0xffff) { Serial.print(tpp_data, 16); Serial.print(" : "); Serial.println(key_no); // } delay(2); // keep SCL==H for 2msec. } } |
同期クロックを生成する必要があるので、I/Oピンの上げ下げのオーバーヘッドを減らすため、digitalRead(), digitalWrite() の代わりに PORTDのレジスタに直接作用するためのマクロを用意した。
void setup()
TPP229Bは、電源投入時の初期化や安定化のために0.5秒間必要ということなのでdelay(500)している。そしてI/Oポートの動作モードを設定し、SCL==Hとしている。
void loop()
READ_SDO()により、ポートD2が”L”になったらTw(10μsec)分の遅延のあとから、read_keydata() を8回呼び出すことで8ビットのデータを得ている。変数tpp_dataには受信した8ビットデータを、key_noには押下されたキー番号が格納し、それらをシリアルモニタに出力する。
キーから指を離したときには0xffを受信する。これは全キーオフを表しているのだろう。シリアルモニタに出力する部分を、 // if (tpp_data != 0xffff) { というコメントにしたifブロックで囲んでいるが、キーを離した場合を無視するならば、”//” を外す。
また、キーの上にずっと指を置いていてもキー・リピートは発生しないし、複数のキーに指を置いた場合も2つ目以降のタッチは無視される。
bool read_keydata()
SCLを下げ上げし、SDOの内容を1ビット読む。
SCLは初期化時からHなので、この関数でLとして5μsec待ってからHとしてまた5μsec待つ。なので、F_SCL = 100KHzといったところ。SCLをHとしたタイミングでSDO(D2)の値を読み取っている。関数は、読み取ったビットがHレベルならばtrueを返す。
シリアルモニタ出力
なんの芸もないのだが、キー1からキー8までを順にタッチして離すを繰り返した場合、シリアルモニタには以下のように表示される。
tpp_data == 0xfffeならばビット0が0でキー1がオン、0xff7fならばビット7が0でキー8がオンということを表している。
何か表示デバイスでもあれば、動画にできてサマになるのだが。
きょうのまとめ
静電容量タッチキーモジュールの利用は実に簡単。消費電力も少ない。ブレッドボード工作用にはピンヘッダが下向きにつけてくれるか、パターンだけでピンヘッダ無しの方がよかった。何か役に立つものに使おうと思ったら、ピンヘッダは自分で外すことになるだろう。
ジャンパエリアにヘッダを立てて、簡単に設定変更できるようしてから他の機能も試してみる予定。
追記
見直してみると、TTP229 を TPP299と書いているところが多かったので修正した。スケッチ内の変数名は変更せず。