ラベル PIC の投稿を表示しています。 すべての投稿を表示
ラベル PIC の投稿を表示しています。 すべての投稿を表示

2014年5月28日水曜日

Arduinoでタッチセンサ

ちょこちょことググっていたらioポートをタッチセンサとして使えるってのを発見しました。
静電容量式タッチセンサで遊ぶ

何これ、面白うそうって事で
建築発明工作ゼミ2008さんの所からソースを頂いて早速動かしてみたところ

どうも触られる側、つまりセンサ及びマイコン側の環境で誤動作しやすかったので
色々と試して実用化できそうな気がしてきました。

一応現象としてはタッチを話した後に誤作動していたのでタッチ部に貯まった電荷が
逃げ切れていない為と思われるので一旦入力ピンを出力にして貯まった電荷を
逃しています。


まだ、課題としてタッチ側の面積を変えると誤動作もありましたので更に確認してみたところ、
タッチ部の面積と通常時の時間の長さが比例して伸びるだけで
タッチした時の時間はそれほど変化しませんでした。
つまり、コンデンサを並列に繋ぐようなものなので当たり前ですね。
そんなわけで自動キャリブレーション的な事もできないことはないと思いますが
タッチ面積を極端に大きくすると通常時の不安定さが増すだけだし
常識的なタッチ面積であれば実用には大丈夫だと思います。



通常時波形:緑=タッチコントロール出力 黄=タッチ入力




タッチ時波形:緑=タッチコントロール出力 黄=タッチ入力








//
//ioポート式タッチセンサ評価プログラム
//

#define LED_OUT  13     //LEDでタッチセンサのon/off表示
#define TOUCH_MON  12   //タッチセンサモニタ
#define TOUCH_OUT 11    //タッチセンサコントロール
#define TOUCH_IN  10    //タッチセンサ入力

#define TOUCH_AV  3     //移動平均回数
int touchLv=40;         //タッチ判定値
int touch=0;            //フィルタ用変数

int  touchMng(void)
{
  int aa=0;    //静電容量変化量の変数を用意
  unsigned long touchTm;    //タッチ時間保持

  pinMode(TOUCH_IN,INPUT);  //タッチ入力設定
  digitalWrite(TOUCH_OUT, HIGH);  //タッチ出力ピンをHIGHで出力
  digitalWrite(TOUCH_MON, HIGH);  //入力モニタ用出力
  //タッチ入力がHIGHになるまでをカウント
  //※HIGH→LOWの変化では検出不能でした
  touchTm = micros();
  while (digitalRead(TOUCH_IN)!=HIGH){
    if(micros()-touchTm > touchLv) {
      break;
    }
  }
  digitalWrite(TOUCH_MON, LOW);
  aa = micros()-touchTm;             //変化時間をμSecで取得
  digitalWrite(TOUCH_OUT, LOW);
  pinMode(TOUCH_IN,OUTPUT);    //入力を一旦出力にして貯まった電荷を逃します
  delay(1);

  Serial.print(touchLv);
  Serial.print(" \t");
  Serial.print(aa);
  Serial.print(" \t");
  Serial.print(touch);
  Serial.print(" \t");

  //加重移動平均
  //touch += aa-touch/TOUCH_AV;
  //return(touchLv*TOUCH_AV > touch ? 0 : -1);
  //単純移動平均
  touch += -touch/TOUCH_AV + aa;
  return(touchLv > touch/TOUCH_AV ? 0 : -1);
}


void  loop(void)
{
  if(touchMng() == 0) {
    Serial.println("    off");
    digitalWrite(LED_OUT, LOW);
  }
  else {
    Serial.println("on");
    digitalWrite(LED_OUT, HIGH);
  }
}


void setup(void)
{
  Serial.begin(9600);          //シリアルでモニター

  pinMode(TOUCH_OUT,OUTPUT);    //タッチ出力をデジタル出力
  pinMode(TOUCH_IN,INPUT);      //タッチ入力をデジタル入力
  pinMode(TOUCH_MON,OUTPUT);    //タッチ入力をモニタ出力
  pinMode(LED_OUT,OUTPUT);      //タッチ入力をモニタ出力
}



2014.06.19追記

専用IC使ったタッチセンサってどうなってんだ?
ってことで波形見てみました。



緑が通常状態で黄色がタッチしている状態。
2μSecぐらいのパルスを出して、触ると電圧が半分ぐらいに落ちてますね。

2017.11.20 追記
新たに「Arduinoでタッチセンサ その2」を書いてみました。
http://yuzumemo.blogspot.jp/2017/11/arduino.html

2009年1月30日金曜日

LEDのオートディマー

 点灯しているLEDに光が当たると、LEDの点灯が見えにくくなる。
って事でLEDを発光兼光センサとして暗い時には、暗く。明るい時には、明るく点灯させよう。
今回はPIC16F884を使用
点滅の機能とかオートディマー以外の機能も入っているけど面倒だから、殆どそのまま載せとく。

////////////////////////////////////////////
// 割込み処理
void interrupt(
void)
////////////////////////////////////////////
{
unsigned char tm;
int nn;

//タイマ1msec割り込み?
if (PIR1.TMR2IF) {
gTimer++; //フリーランニングカウント
TMR2 = DEF_TMRCUNT; //カウント値再設定
PIR1.TMR2IF = 0; //割込みフラグクリア

// LED点灯、点滅制御
tm = gTimer & led.dimmer;
if( tm == 0 ) {
//オートディマー処理
//▼ヒステリシスを追加する予定
nn = ADC_read(4); // ADC値の読み込み(AN4:10bits)
if( nn > 0x40 ) {
led.dimmer = 0xf; //デューティ15:1
}
else if( nn > 0x30 ) {
led.dimmer = 0x7; //デューティ7:1
}
else if( nn > 0x20 ) {
led.dimmer = 0x3; //デューティ3:1
}
else {
led.dimmer = 0x1; //デューティ1:1
}
//LEDフラッシュ
if( gTimer & 0x20 ) {
PORTA |= led.flash; //LED点滅の為に消す
}
//LED点灯
else {
PORTA = ~led.on; //点滅用LEDの点灯
}
PORTB = ~led.on >> 4; //常時点灯LEDの点灯
}
//LED受光量AD変換の為に一旦消す
else if( tm == led.dimmer ){
PORTA = 0x0f;
PORTB = 0x0f;
}
}
}

2009年1月9日金曜日

MikroCのConfiguration

MicroCって#pragmaでConfigurationを書けないのかな?<調べてないんだけどね
取り敢えず、機能だけ記録しておく


   MikroCでの名称   略称                 名称              
・INTRC_OSC_* FOSC: Oscillator Selection bits
  RA6とRA7をioとして使うか、CLKとして使うかの設定

・WDT_*      WDTE: Watchdog Timer Enable bit
  ウォッチドッグタイマを使用するか否か。(動作に影響しなかった気がする)

・PWRTE_*    PWRTE: Power-up Timer Enable bit
  パワーオンリセット後にちょいと時間を空けてから動き出すらしい
  リセット回路がちゃんとしていれば、どっちでも良いけどEnableにしといて損はない

・MCLRE_*    MCLRE: RE3/MCLR pin function select bit
  RE3をioとして使うか、MCLR(リセットの事)として使うかの設定

・CP_*       CP: Code Protection bit
  プログラム用Flashにプロテクト掛ける

・CPD_*      CPD: Data Code Protection bit
  データ用Flashにプロテクトを掛ける

・BOR_*      BOREN<1:0>: Brown-out Reset Selection bits
  ブラウンアウトリセット(電圧低下によるリセット)動作
  2.1vまたは4.0vでリセットさせるか機能しないか
  でもリセット中もioは保持されるっぽい

・IESO_*     IESO: Internal External Switchover bit
  内部、外部のクロックを

・FCMEN_*   FCMEN: Fail-Safe Clock Monitor Enabled bit

・LVP_*      LVP: Low Voltage Programming Enable bit

・           DEBUG: In-Circuit Debugger Mode bit

・WRT_*     WRT<1:0>: Flash Program Memory Self Write Enable bits

取り敢えず、今回は以下のように設定した
INTRC_OSC_NOCLKOUT RA6をioとしてしようする
WDT_ON プログラムでウォッチドッグタイマを有効にしているので、なくてもいいけど入れとく
PWRTE_ON 電源投入直後のリセット期間を有効にする
MCLRE_ON RE3をMCLREとする(デフォ)
CP_OFF Code Protectionはしない(デフォ)
CPD_OFF Data Code Protectionはしない(デフォ)
BOR_ON Brown out Reset ON(デフォ)
IESO_ON Internal/External Switchover mode is enabled(デフォ)
FCMEN_ON 外部クロック使用しないので関係ない(デフォ)
LVP_OFF RB3をioとして使用
BOR4.0V Brown-out 4.0v(デフォ)
WRT_OFF Write protection off(デフォ)

以下は変えてもConfigrationに変化無し
INTOSCIO,INTOSC
EXTRCIO,EXTRC

2008年12月26日金曜日

MikroCのヘルプより

  • 8 calls for PIC12 family,
  • 8 calls for PIC16 family,
  • 31 calls for PIC18 family.
  • 2008年12月25日木曜日

    MikroC

    なんで、MikroCなんだよ。名前が変だろ?ってのは置いといて、
    動作が、もっと変なので調べてみた。

    <構造体が変>
    コンパイラが吐き出すアセンブラソースを見るとソースを
    _main:
    CALL GlobalIniXXX
    なんてのを呼び出してConstantなデータをデータメモリに書いている
    で、気付いたが構造体だとバンク毎をデータを入れやがった。
    これは、ショボイ構造体以外使うなと言ってるようなものだね。

    <内部変数が変>
    内部変数を外部変数に変更したら、WDTがリセットできなくなったぞ??
    で、内部変数の割り当てを見てみたら・・・
    $00E7 cmdTask_cc_L0
    $00E7 getTimer_dd_L0
    $00E7 Usart_Init_tmp_L0
    へ~ェ、そんな割付するんだ

    で、WDTがおかしくなった理由は、

    つづく・・・

    2009.01.13追記
    まだ理由は、よく分かっていないけれど
    char stat = 0;
    てな、感じで変数を宣言した時点で初期化しまくれば期待通りに動くような感じ。