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


前回、基準電圧によるボタン動作を紹介しましたが、今回は基準電圧に1.65V、測定電 圧にライトセンサーの出力を試して見ます。
動作確認で使用する回路は以下の通りです。
使用したライトセンサーはNJL7502Lで470Kの抵抗で調整しています。



Cで書いた場合のコードは以下のようになります。
/*
 cc -o test6 test6.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
#define LED25    25      // rsp board pin:22

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);
    pinMode(LED25, OUTPUT);
    digitalWrite(LED25,0);

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

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

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

    exit(0);
}

ライトセンサーの出力と、基準電圧(1.65V)を比較し、暗くなればLEDを点灯します。
ちなみに、Pythonだともっと簡単です。
#!/usr/bin/env python

import RPi.GPIO as GPIO 
import signal
import sys

GPIO.setmode(GPIO.BCM) 
GPIO.setup(14, GPIO.IN, pull_up_down=GPIO.PUD_UP) 
GPIO.setup(25, GPIO.OUT)

def signal_handler(sig, frame):
    print('You pressed Ctrl+C')
    GPIO.cleanup()
    sys.exit(0)

def my_callback(channel):
    val=GPIO.input(channel)
    print('This is a edge event callback function!')
    print('Edge detected on channel=%s val=%d'%(channel,val))
    if val == 0:
        GPIO.output(25,True)
    else:
        GPIO.output(25,False)

# Set Interrupt
signal.signal(signal.SIGINT, signal_handler)
GPIO.add_event_detect(14, GPIO.BOTH, callback=my_callback)

print('Ready!!')
# A forever loop until user presses Ctrl+C
while 1:
    pass

今回は4CHのLM339を使いましたが、アナログ電圧が一定の出力以上かどうかだけを調べるのであれば、2CHのLM393で 十分です。
LM339(4CH)とLM393(2CH)は名前が似ていて紛らわしいです。
私もLM393(2CH)を買うつもりで、間違えてLM339(4CH)を買ってしまいました。

おしまい