pp.614ff.
今度は自動(再)コンフィギュレーションを実行してみる。
充放電電流設定値CDCがグローバルデフォルト値から大きくずれて、ベースライン値が初期値とはだいぶ違う値になった。下の実行例ではターゲットレベルを181 (左に2ビットシフトすると724)に設定していて、ベースラインは実際それに近い値になっている。
#define F_CPU 8000000UL #include <avr/io.h> #include <avr/interrupt.h> #include "USARTClass.h" #include "MPR121Class.h" MPR121Class pad(0x5A); // (I2Cスレーブアドレス)で実体化する。 // 全チャンネルのタッチステータスを端末に表示する函数。 void print_touch_status(){ usart.printString("Touch (Prox) Status[12:0]: "); usart.printBinaryWord(pad.get_touch_status()); usart.printString("\n"); } // (n)本のチャンネルの電極データを端末に表示する函数。 void print_filtered_data(uint8_t n){ usart.printString("Filtered Data: "); uint16_t buff_word[n]; pad.get_filtered_data(n, buff_word); for(int i=0; i<n; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printWord(buff_word[i]); usart.printString(", "); } usart.printString("\n"); } // (n)本のチャンネルのベースライン値を端末に表示する函数。 void print_baseline_val(uint8_t n){ usart.printString("Baseline Val : "); uint16_t buff_word[n]; pad.get_baseline_val(n, buff_word); for(int i=0; i<n; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printWord(buff_word[i]); usart.printString(", "); } usart.printString("\n"); } // (n)本のチャンネルのタッチ閾値を端末に表示する函数。 void print_touch_threshold(uint8_t n){ usart.printString("Touch Threshold: "); uint8_t buff[n]; pad.get_touch_threshold(n, buff); for(int i=0; i<n; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(buff[i]); usart.printString(", "); } usart.printString("\n"); } // (n)本のチャンネルのリリース閾値を端末に表示する函数。 void print_release_threshold(uint8_t n){ usart.printString("Release Threshold: "); uint8_t buff[n]; pad.get_release_threshold(n, buff); for(int i=0; i<n; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(buff[i]); usart.printString(", "); } usart.printString("\n"); } // (n)本のチャンネルのタッチ閾値、リリース閾値の両方を端末に表示する函数。 void print_both_threshold(uint8_t n){ usart.printString("Touch Threshold: "); uint8_t touch_buff[n]; uint8_t release_buff[n]; pad.get_both_threshold(n, touch_buff, release_buff); for(int i=0; i<n; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(touch_buff[i]); usart.printString(", "); } usart.printString("\n"); usart.printString("Release Threshold: "); for(int i=0; i<n; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(release_buff[i]); usart.printString(", "); } usart.printString("\n"); } // タッチ、リリース両方のディバウンス回数(全チャンネル共通)を端末に表示する函数。 void print_both_debounce_num(){ usart.printString("Touch Debounce#: "); usart.printByte(pad.get_touch_debounce_num()); usart.printString("\n"); usart.printString("Release Debounce#: "); usart.printByte(pad.get_release_debounce_num()); usart.printString("\n"); } // フィルターのサンプリング回数、グローバルCDC値、グローバルCDT値を端末に表示する函数。 void print_filter_global_cdc_cdt(){ usart.printString("First Filter# : "); usart.printByte(pad.get_ffi()); usart.printString("\n"); usart.printString("Global CDC (uA) : "); usart.printByte(pad.get_gloval_cdc()); usart.printString("\n"); usart.printString("Global CDT10 (0.1 us): "); usart.printByte(pad.get_gloval_cdt10()); usart.printString("\n"); usart.printString("Second Filter# : "); usart.printByte(pad.get_sfi()); usart.printString("\n"); usart.printString("Sample Interval (ms) : "); usart.printByte(pad.get_esi()); usart.printString("\n"); } // (n)本の各チャンネルの充放電電流設定値を端末に表示する函数。 void print_cdc(uint8_t n){ usart.printString("CDC (uA) : "); uint8_t buff[n]; pad.get_cdc(n, buff); for(int i=0; i<n; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(buff[i]); usart.printString(", "); } usart.printString("\n"); } // (n)本の各チャンネルの充放電時感設定値(10倍値)を端末に表示する函数。 void print_cdt10(uint8_t n){ usart.printString("CDT10 (0.1 us): "); uint8_t buff[n]; pad.get_cdt10(n, buff); for(int i=0; i<n; i++){ usart.printNibble(i); usart.printString("ch:"); usart.printByte(buff[i]); usart.printString(", "); } usart.printString("\n"); } // 自動(再)コンフィギュレーションを実行した結果、範囲外になったかどうかを端末に表示する函数。 void print_out_of_range_status_status(){ usart.printString("Out-Of-Range Status[12:0]: "); usart.printBinaryWord(pad.get_out_of_range_status()); usart.printString("\n"); } // 自動コンフィギュレーションに失敗したかどうかを端末に表示する函数。 void print_auto_config_failed(){ usart.printString("Auto Config Failed?: "); usart.printNibble(pad.auto_config_failed()); usart.printString("\n"); } // 自動再コンフィギュレーションに失敗したかどうかを端末に表示する函数。 void print_auto_reconfig_failed(){ usart.printString("Auto-ReConfig Failed?: "); usart.printNibble(pad.auto_reconfig_failed()); usart.printString("\n"); } const uint8_t n = 4; // 電極をn本使うことにする。 ISR(INT1_vect){ // 電極の状態が変化したら、 print_touch_status(); // 全チャンネルのタッチ状態を端末に表示し、 print_filtered_data(n); // 電極データを端末に表示し、 print_baseline_val(n); // ベースライン値を端末に表示する。 } int main(){ usart.init(); EIMSK |= (1 << INT1); // INT1 (外部割り込み要求1)を有効化する。 EICRA |= (1 << ISC11); // falling edgeで割り込む。 sei(); // グローバル割り込みを有効化する。 usart.printString("\n**********************************"); usart.printString("\n********** TOUCH SENSOR **********"); usart.printString("\n**********************************\n"); // ソフトリセットをかける。 pad.soft_reset(); // 自動(再)コンフィギュレーションの設定をする。 pad.set_up_side_limit(202); pad.set_low_side_limit(117); pad.set_target_level(181); pad.set_auto_config_0(6, 4, 1, 1); // (ffi=6,10,18,34回; retry=0,2,4,8回; are=1,0; ace=1,0); pad.set_auto_config_1(0, 1, 1, 1);// (scts=1,0; oorie=1,0; arfie=1,0; acfie=1,0); pad.set_baseline_tracking(2); // 初回電極データの上位5ビットを初期ベースライン値としてロードする。 pad.set_touch_debounce_num(3); // タッチ時のディバウンス回数(0~7)をセットする。 pad.set_release_debounce_num(2); // リリース時のディバウンス回数(0~7)をセットする。 for(int ch=0; ch<n; ch++){pad.set_touch_threshold(ch, 6);} // (チャンネル0~12)にタッチ閾値(0~255)をセットする。 for(int ch=0; ch<n; ch++){pad.set_release_threshold(ch, 1);} // (チャンネル0~12)にリリース閾値(0~255)をセットする。 pad.enable_touch(n); // (n)本の電極をタッチセンサーとして有効化する。 print_out_of_range_status_status(); // 自動(再)コンフィギュレーションの範囲外ステータスを端末に表示する。 print_auto_config_failed(); // 自動コンフィギュレーションに失敗したかどうかを端末に表示する。 //print_auto_reconfig_failed(); /* print_touch_threshold(n); // (n)本のチャンネルのタッチ閾値を端末に表示する。 print_release_threshold(n); // (n)本のチャンネルのリリース閾値を端末に表示する。 */ print_both_threshold(n); // (n)本のチャンネルのタッチ閾値、リリース閾値の両方を端末に表示する。 print_both_debounce_num(); // タッチ、リリース両方のディバウンス回数を端末に表示する。 print_filter_global_cdc_cdt(); // フィルターのサンプリング回数、グローバルCDC値、グローバルCDT値を端末に表示する。 print_cdc(n); // (n)本の各チャンネルの充放電電流値設定値を端末に表示する。 print_cdt10(n); // (n)本の各チャンネルの各充放電時間設定値(10倍値)を端末に表示する。 while(1); return 0; }
void MPR121Class::set_auto_config_0(uint8_t ffi, uint8_t retry, uint8_t are, uint8_t ace){ uint8_t ffi_n; // ffi回数を、レジスタに書き込む値に変換する。 switch(ffi){ case 6: ffi_n = 0; break; case 10: ffi_n = 1; break; case 18: ffi_n = 2; break; case 34: ffi_n = 3; break; default: ffi_n = 0; break; } uint8_t retry_n; // retry回数を、レジスタに書き込む値に変換する。 switch(retry){ case 0 : retry_n = 0; break; case 2 : retry_n = 1; break; case 4 : retry_n = 2; break; case 8 : retry_n = 3; break; default: retry_n = 0; break; } uint8_t auto0 = (ffi_n << 6) | (retry_n << 4) | (_CL << 2) | (are < 1) | ace; i2c.write(_SLA, AUTOCONFIG_CONTROL_0, auto0); } void MPR121Class::set_auto_config_1(uint8_t scts, uint8_t oorie, uint8_t arfie, uint8_t acfie){ uint8_t auto1 = (scts << 7) | (oorie << 2) | (arfie <<1) | acfie; i2c.write(_SLA, AUTOCONFIG_CONTROL_1, auto1); } void MPR121Class::set_up_side_limit(uint8_t usl){ i2c.write(_SLA, UP_SIDE_LIMIT, usl); } void MPR121Class::set_low_side_limit(uint8_t lsl){ i2c.write(_SLA, LOW_SIDE_LIMIT, lsl); } void MPR121Class::set_target_level(uint8_t tl){ i2c.write(_SLA, TARGET_LEVEL, tl); } uint16_t MPR121Class::get_out_of_range_status(){ uint8_t buff[2]; i2c.read(_SLA, OOR_STATUS, 2, buff); return ((uint16_t)(buff[1] & 0b11111) << 8) | buff[0]; } uint8_t MPR121Class::auto_config_failed(){ return (i2c.read(_SLA, OOR_STATUS + 1) >> 7) & 1; } uint8_t MPR121Class::auto_reconfig_failed(){ return (i2c.read(_SLA, OOR_STATUS + 1) >> 6) & 1; }