LM339(コンパレータ)を使う(その4)


前回までは測定電圧に応じてLEDを点灯しましたが、今回はこれを少し変更し、基準電圧によるボタン動作を試して見ます。
動作確認で使用する回路は以下の通りです。


OUT1(1番ピン)をPullUpし、OUT1をGPIOに接続すれば、GPIOの値を読むことで、
IN-側の電圧が1.65Vを超えているかどうかを知ることができます。
IN-側の電圧が1.65Vを超えていなければ、OUT1はPullUpされているので、GPIOの値はHIGHとなります。
IN-側の電圧が1.65Vを超えていれば、OUT1がGNDに落ちるので、GPIOの値はLOWとなります。

A/Dコンバータのようにずばりの値は分かりませんが、左側の抵抗値を変えることで、
アナログ出力が一定の出力以上かどうか、1本のGPIOだけで判定することができるので、
アナログ出力でON/OFF動作をしたい場合は、A/DコンバータよりもGPIOの数が少なくてすみます。

コードは以下のようになります。
/*
 cc -o test05 test05.c -lwiringPi
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include <signal.h>
#include <wiringPi.h>

// Define Pin
#define LM339    14      // rsp board pin:8

int semid;

//排他処理開始(ロック開始)
//自分よりも先にロックされていた場合にはロック解除されるまでスリープします
void lock(int semid){
    struct sembuf sb[1];
    sb[0].sem_num=0;
    sb[0].sem_op=-1;
    sb[0].sem_flg=0;
    if(EOF==semop(semid,sb,1)){
      printf("%s\n","lock ERR");
      exit(1);
    }
}

//排他処理終了(ロック解除)
void unlock(int semid){
    struct sembuf sb[1];
    sb[0].sem_num=0;
    sb[0].sem_op=1;
    sb[0].sem_flg=0;
    if(EOF==semop(semid,sb,1)){
      printf("%s\n","unlock ERR");
      exit(1);
    }
}

//セマフォ値のセット
void SemSetValue(int semid, int semnum, int semval) {
    union semun {
      int              val;     /* SETVAL の値 */
      struct semid_ds  *buf;    /* IPC_STAT, IPC_SET 用のバッファ */
      unsigned short   *array;  /* GETALL, SETALL 用の配列 */
    } ctl_arg;

    ctl_arg.val = semval;
    if((semctl(semid,semnum,SETVAL,ctl_arg))==EOF){
      printf("%s\n","semctl ERR");
      exit(1);
    }
}

//割り込み処理
void signal0(void){
    unlock(semid);
}

int main(int argc, char **argv) {
    int val;

    //セマフォを割り付けます
    semid=semget(IPC_PRIVATE,1,0666);
    if(semid==EOF){
      printf("%s\n","semget ERR");
      exit(1);
    }

    //セマフォに初期値を書き込みます
    SemSetValue(semid,0,0);

    if (wiringPiSetupGpio() == -1){
      printf("wiringPiSetup init error\n");
      exit(1);
    }
    pinMode(LM339, OUTPUT);

    //割り込みを設定します
    wiringPiISR( LM339, INT_EDGE_BOTH, signal0 );

    while(1){
      lock(semid); // Wait Unlock
      val=digitalRead(LM339);
      printf("val=%d\n",val);
      sleep(1);
    }

    //セマフォの削除
    if((semctl(semid,0,IPC_RMID,0))==EOF){
        printf("%s\n","semctl ERR");
        exit(1);
    }

    exit(0);
}

ボリュームをまわしてIN-側の電圧が1.65Vを超えると、割り込みが発生しロックが解除されます。
但し、アナログ出力がIN+側の基準電圧(1.65V)近辺のときは、頻繁に割り込みが発生しますので
今回はsleepで時間を稼いでいます。

次回は別のパターンを紹介します。