正規のオンライン小売業者:

AMAZON
AMAZON
amzuk

紹介

レッスンでは、mcp3008を使用してフォトレジスタ(光センサー)のデータを読み取り、LEDの明るさを制御する方法を示します。

ハードウェアの準備

1 * Raspberry Pi
1 * ブレッドボード
1 * 10KΩ抵抗器
1 * フォトレジスタ
1 * LED
ジャンパーワイヤー
1 * T拡張ボード
1 * 40ピンケーブル

ソフトウェアの準備
注意:このレッスンでは、PCのPuTTyを介してラズベリーパイをリモートで制御します。ラズベリーパイの設定方法については、 lesson 1: getting started with raspberry piをご覧ください。

動作原理

フォトレジスタ は光制御可変抵抗器です。フォトレジスタの抵抗値は光の強度が増すにつれて減少します。

このプロジェクトでは、MCP3008 ADCを使用して、光によって変化するフォトレジスタの電圧値を読み取ります。MCP3008はアナログ電圧値をデジタル信号(バイナリ値)に変換し、それをPiに送信します。次に、PiはPWM入力値を変更して、LEDの明るさを制御します。


回路図:

 

ハードウェアの設定

サンプルコード

C言語ユーザーとPython言語ユーザー向けに2種類のコードを提供します。

C言語ユーザーの場合は、以下の手順を実行してください。


注意:wiringPiライブラリをインストールしていない場合は、Lesson 3に従ってインストールしてください。

1) 以下のコマンドを入力して、osoyooからサンプルコードをダウンロードしてください。

cd   ~

sudo  sudo  wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_11/lightsensor.c

注意:
サンプルコードファイルをカスタマイズする場合は、ターミナルで以下のコマンドを入力してnanoエディタを使用してソースコードを編集できます。

sudo nano  lightsensor.c

2) コードをコンパイルしてください

gcc  -Wall  -o  lightsensor  lightsensor.c  -lwiringPi

3) プログラムを実行してください。

A)プログラムを実行する前に、MOSI、MISO、SCLK(B10、B9、B11)の動作モードがALT0(代替機能)であることをターミナルコマンドで確認してください:gpio readall。モードがALTOでない場合は、以下のターミナルコマンドを実行してください。

gpio  -g  mode  9    alt0

gpio  -g  mode  10   alt0

gpio  -g  mode   11   alt0

B) プログラムを実行してください。

sudo  ./lightsensor

4) テスト結果

プログラムを実行すると、端末にはまずコードの印刷メッセージが表示され、その後、フォトレジスタADC値(電圧)が表示されます。フォトレジスタが遮られると、LEDの明るさが増加し、遮られなくなると、LEDの明るさが減少します。

サンプルコードと説明コメント

#include < unistd.h >
#include < stdint.h >
#include < string.h >
#include < errno.h >
#include < wiringPi.h >
#include < stdio.h > 
#include < stdlib.h >
#include < wiringPiSPI.h >

//pin 1(BCM GPIO 18) is PWM  port
#define  LEDPIN   1
//binary number 1000 (decimal 8) is analog channel prefix
#define CHAN_CONFIG_SINGLE  8

//About SPI channel, read https://osoyoo.com/ja/?p=7612
//since B8 connect to CS/SHDN pin, we need select SPI Channel to 0
#define SPICHANNEL          0 

//our light sensor connect to MCP3008 CH0, we set annanalog channel to 0
#define ANALOGCHANNEL       0
static int myFd ;

void spiSetup (int spiChannel)
{
    if ((myFd = wiringPiSPISetup (spiChannel, 10000)) < 0)
    {
        fprintf (stderr, "Can't open the SPI bus: %s\n", strerror (errno)) ;
        exit (EXIT_FAILURE) ;
    }
}

int myAnalogRead(int spiChannel,int channelConfig,int analogChannel)
{
    if(analogChannel7)
        return -1;
    unsigned char buffer[3] = {1}; // start bit
    buffer[1] = (channelConfig+analogChannel) << 4;
    wiringPiSPIDataRW(spiChannel, buffer, 3);
    return ( (buffer[1] & 3 ) << 8 ) + buffer[2]; // get last 10 bits
}

void print_info()
{
    printf("\n");
    printf("|************************************|\n");
    printf("|        MCP3008 read lightsensor    |\n");
    printf("|       -------------------------    |\n");
    printf("|       | ADC |           | Pi  |    |\n");
    printf("|       |-----|-----------|-----|    |\n");
    printf("|       | CS  | connect to| CE0 |    |\n");
    printf("|       | Din | connect to| MOSI|    |\n");
    printf("|       | Dout| connect to| MISO|    |\n");
    printf("|       | CLK | connect to| SCLK|    |\n");
    printf("|       | CH0 | connect to| 3.3V|    |\n");
    printf("|       | CH1 | connect to| GND |    |\n");
    printf("|************************************|\n");
    printf("|          LED connect to GPIO1      |\n");
    printf("|                              OSOYOO|\n");
    printf("|************************************|\n");
    printf("\n");

} 

int main()
{
  int adc;
  if(wiringPiSetup()<0)
    {
      printf("setup wiringPi failed!\n");
            printf("please check your setup\n");
            exit(1);
    } 
  spiSetup(SPICHANNEL);
  pinMode(LEDPIN,PWM_OUTPUT); 
  print_info();
  
  for(;;)
  {
      //read voltage value from analog CH0 pin data from SPI channel 0
      adc = myAnalogRead(SPICHANNEL,CHAN_CONFIG_SINGLE,ANALOGCHANNEL);
            printf("ADC = %d\n",adc);
      //adc is a value between 0 to 1023, 1023 means max vref value 3.3V
      pwmWrite(LEDPIN,1023-adc);
      delay(1000);
  }
  
}

  for(;;)
  {
      adc = myAnalogRead(SPICHANNEL,CHAN_CONFIG_SINGLE,ANALOGCHANNEL);
            printf("ADC = %d\n",adc);
      //USE pwmWrite function defined in  to control LED brightness
      pwmWrite(LEDPIN,1023-adc);
      delay(1000);
  }

Python ユーザーの場合は、次の手順を実行してください。


Python言語を使用してプログラムを作成する場合、通常、Rasbian Jessie OSに付属するGPIOライブラリであるRPi.GPIOを使用します。RPi.GPIOとPythonに関する詳細情報については、here をクリックしてください。

1) 以下のコマンドを入力して、osoyooからサンプルコードをダウンロードしてください。

cd  ~

sudo   wget http://osoyoo.com/driver/pi3_start_learning_kit_lesson_11/lightsensor.py

注意:
サンプルコードファイルをカスタマイズする場合は、ターミナルで以下のコマンドを入力してnanoエディタを使用してソースコードを編集できます。

sudo nano  lightsensor.py

2)以下のコマンドを入力してプログラムを実行してください。

sudo  python  ./lightsensor.py

3) 実行結果

プログラムを実行すると、端末にはまずコードの印刷メッセージが表示され、その後、光センサーのAD値が表示されます。フォトレジスタを覆うと、LEDの明るさが増加し、フォトレジスタに入射する光の強度が増すと、LEDの明るさが減少します。

Python サンプルコードと解説コメント

import time
import os
import RPi.GPIO as GPIO

# change these as desired - they're the pins connected from the
# SPI port on the ADC to the Cobbler
SPICLK = 11
SPIMISO = 9
SPIMOSI = 10
SPICS = 8
#set BCM_GPIO 18(GPIO1) as LED pin
LEDPIN = 18

analogChannel = 0

#setup function for some setup---custom function
def setup():
    global p
    GPIO.setwarnings(False)
    #set the gpio modes to BCM numbering
    GPIO.setmode(GPIO.BCM)
    # set up the SPI interface pins
    GPIO.setup(SPIMOSI, GPIO.OUT)
    GPIO.setup(SPIMISO, GPIO.IN)
    GPIO.setup(SPICLK, GPIO.OUT)
    GPIO.setup(SPICS, GPIO.OUT)
    #set all LedPin's mode to output,and initial level to HIGH(3.3V)
    GPIO.setup(LEDPIN,GPIO.OUT,initial=GPIO.LOW)
    #set LEDPIN as PWM output,and frequency=100Hz
    p = GPIO.PWM(LEDPIN,100)
    #set p begin with ualue 0
    p.start(0)
    pass

    
#print message at the begining ---custom function
def print_message():
    print ('|**********************************|')
    print ('|   MCP3008 read lightsensor   |')
    print ('|   -----------------------------  |')
    print ('|    | ADC |           | Pi  |     |')
    print ('|    |-----|-----------|-----|     |')
    print ('|    | CS  | connect to| CE0 |     |')
    print ('|    | Din | connect to| MOSI|     |')
    print ('|    | Dout| connect to| MISO|     |')
    print ('|    | CLK | connect to| SCLK|     |')
    print ('|    | CH0 | connect to| 3.3V|     |')
    print ('|    | CH1 | connect to| GND |     |')
    print ('| ********************************** |')
    print (' LED connect to GPIO1')
    print ('|                            OSOYOO|')
    print ('|**********************************|\n')
    print ('Program is running...')
    print ('Please press Ctrl+C to end the program...')

# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
        if ((adcnum > 7) or (adcnum < 0)):
                return -1
        GPIO.output(cspin, True)

        GPIO.output(clockpin, False)  # start clock low
        GPIO.output(cspin, False)     # bring CS low

        commandout = adcnum
        commandout |= 0x18  # start bit + single-ended bit
        commandout <<= 3    # we only need to send 5 bits here
        for i in range(5):
                if (commandout & 0x80):
                        GPIO.output(mosipin, True)
                else:
                        GPIO.output(mosipin, False)
                commandout <<= 1
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)

        adcout = 0
        # read in one empty bit, one null bit and 10 ADC bits
        for i in range(12):
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)
                adcout <<= 1 if (GPIO.input(misopin)): adcout |= 0x1 GPIO.output(cspin, True) adcout >>= 1       # first bit is 'null' so drop it
        return adcout

#main function
def main():
    while True:
        #print info
        print_message()
        adc = readadc(analogChannel, SPICLK, SPIMOSI, SPIMISO, SPICS)
        print ('LightSensor ADC = %d'%(adc))
        adc=(1023-adc)*100/1023
        p.ChangeDutyCycle(int(adc))
        time.sleep(1)

#define a destroy function for clean up everything after the script finished
def destroy():
    #stop p
    p.stop()
    #turn off led
    GPIO.output(LEDPIN,GPIO.LOW)
    #release resource
    GPIO.cleanup()
    
#
# if run this script directly ,do:
if __name__ == '__main__':
    setup()
    try:
            main()
    #when 'Ctrl+C' is pressed,child program destroy() will be executed.
    except KeyboardInterrupt:
        destroy()

        adc=(1023-adc)*100/1023
        p.ChangeDutyCycle(int(adc))