Last-modified: 2016-04-10 (日) 23:58:18
Raspberry Pi/フォトレジスタ

概要

Raspberry Pi2のGPIOで、フォトレジスタ(SPI)を使って、環境光の強度によってLEDを点灯/消灯します。
ADコンバータは、MCP3208を使います。
Raspberry Pi/ADコンバーターをベースに作りました。


MCP3208のデータシート
http://ww1.microchip.com/downloads/en/DeviceDoc/21298b.pdf

配線

000027.png
000001.jpg

手順

  1. vi gpio.h
    Everything is expanded.Everything is shortened.
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
    
    -
    |
    !
     
     
    -
    -
    -
    |
    !
    -
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    !
    |
    -
    |
    !
    |
    -
    |
    |
    !
    !
    !
    
    /**
     * @brief Raspberry PiのGPIO定義
     */
    #pragma once
     
    namespace paburica { namespace RaspberryPi {
    namespace GPIO {
        /**
    	 * @brief ピン番号(BCM)
    	 */
        namespace BCM {
            constexpr int SCL_0 = 1;
            constexpr int SDA_1 = 2;
            constexpr int SCL_1 = 3;
            constexpr int GPIO_7 = 4;
            constexpr int GPIO_21 = 5;
            constexpr int GPIO_22 = 6;
            constexpr int CE_1 = 7;
            constexpr int CE_0 = 8;
            constexpr int MISO = 9;
            constexpr int MOSI = 10;
            constexpr int SCLK = 11;
            constexpr int GPIO_26 = 12;
            constexpr int GPIO_23 = 13;
            constexpr int TXD = 14;
            constexpr int RXD = 15;
            constexpr int GPIO_27 = 16;
            constexpr int GPIO_0 = 17;
            constexpr int GPIO_1 = 18;
            constexpr int GPIO_24 = 19;
            constexpr int GPIO_28 = 20;
            constexpr int GPIO_29 = 21;
            constexpr int GPIO_3 = 22;
            constexpr int GPIO_4 = 23;
            constexpr int GPIO_5 = 24;
            constexpr int GPIO_6 = 25;
            constexpr int GPIO_25 = 26;
            constexpr int GPIO_2 = 27;
        };
     
        /**
    	 * @brief 信号の状態
    	 */
        enum class State : int
        {
            Low = 0,
            High = 1
        };
    };
    };};
  2. vi app.cpp
    Everything is expanded.Everything is shortened.
      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    
    -
    |
    |
    |
    |
    |
    !
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    -
    |
    |
    |
    |
    |
    |
    -
    |
    !
    |
    |
    -
    |
    !
    |
    -
    |
    |
    !
    |
    -
    |
    -
    |
    !
    |
    -
    |
    !
    |
    |
    !
    |
    -
    |
    |
    |
    |
    |
    !
    |
    -
    |
    -
    |
    !
    |
    -
    !
    |
    |
    |
    |
    -
    !
    |
    |
    |
    |
    !
    !
     
    -
    |
    |
    !
     
    -
    |
    -
    |
    |
    |
    |
    -
    |
    |
    |
    |
    !
    !
    |
    -
    |
    !
    |
    -
    |
    !
    |
    !
    
    /**
     * @brief フォトレジスタのサンプル 
     * ADコンバータはMCP3208を使う
     *
     * MCP3208のデータシート
     * http://ww1.microchip.com/downloads/en/DeviceDoc/21298b.pdf
     */
    #include <iostream>
    #include <stdexcept>
    #include <thread>
    #include <chrono>
    #include <type_traits>
    #include <array>
    #include <wiringPi.h>
    #include <wiringPiSPI.h>
    #include "gpio.h"
     
    using namespace std;
    namespace pgpio = paburica::RaspberryPi::GPIO;
     
    namespace
    {
        constexpr int SPICh = 0;
        constexpr int SPISpeedHz = 1000 * 1000;
        constexpr unsigned char ADCCh = 0;
        constexpr int WaitMicroSec = 100 * 1000;
        constexpr int LedThreshold = 2000;
     
        /**
    	 * @brief enum castヘルパ
    	 */
        template <class Enum>
        constexpr auto utype(Enum e) noexcept
        {
            return static_cast<underlying_type_t<Enum>>(e);
        }
     
        /**
    	 * @brief 初期化
    	 * 異常時に例外を投げます。
    	 */
        void initGpio()
        {
            if (wiringPiSPISetup(SPICh, SPISpeedHz) < 0)
            {
                throw runtime_error("Failed to wiringPiSPISetup");
            }
            if (wiringPiSetupGpio() == -1)
            {
                throw runtime_error("Failed to wiringPiSetupGpio");
            }
            pinMode(pgpio::BCM::CE_0, OUTPUT);
            pinMode(pgpio::BCM::GPIO_6, OUTPUT);
        }
     
        /**
    	 * @brief MCP3208でのADコンバート
    	 *
    	 * @param adcCh チャンネル番号(0 - 7)
    	 * 異常時に例外を投げます。
    	 * @return 結果
    	 */
        int getMCP3208ADC(unsigned char adcCh)
        {
            if (adcCh > 7)
            {
                throw invalid_argument("adcCh must be in the range of 0 to 7");
            }
     
            // コマンド生成
            array<unsigned char, 3> buf;
            buf[0] = 0b00000110 | (adcCh & 0b00000111) >> 7;
            buf[1] = (adcCh & 0b00000111) < 6;
            buf[2] = 0;
     
            // 送受信
            digitalWrite(pgpio::BCM::CE_0, utype(pgpio::State::Low));
            wiringPiSPIDataRW(SPICh, &buf[0], buf.size());
            digitalWrite(pgpio::BCM::CE_0, utype(pgpio::State::High));
            
            return ((buf[1] & 0b00001111) << 8) | buf[2];
        }
    };
     
    /**
     * @brief メイン
     * @return 常に0
     */
    int main()
    {
        try
        {
            initGpio();
            
            constexpr double rate = 3.3/4096;
            for (;;)
            {
                const int adc = getMCP3208ADC(ADCCh);
                digitalWrite(pgpio::BCM::GPIO_6, utype((adc > LedThreshold)? pgpio::State::Low : pgpio::State::High));
                cout << "raw=" << adc << ", val=" << (adc * rate) << "\n";
                this_thread::sleep_for(chrono::microseconds(WaitMicroSec));
            }
        }
        catch (exception& e)
        {
            cerr << e.what() << "\n";
        }
        catch (...)
        {
            cerr << "Unknown exception!\n";
        }
        return 0;
    }
  3. vi Makefile
    Everything is expanded.Everything is shortened.
      1
      2
      3
      4
    
     
     
     
     
    
    app: app.cpp
        g++ app.cpp -O2 -Wall -Wextra -std=gnu++1y -lwiringPi -oapp
    clean:
        rm -f *.o app
  4. ビルド/実行
    Everything is expanded.Everything is shortened.
      1
      2
    
     
     
    
    make
    sudo ./app

検証時の環境