Raspberry Pi + ruby + pi_piper+MCP 3208을 통한 SPI 통신/아날로그 입력

문제.


랩베리피는 ON/OFF만 판단할 수 있기 때문에 광센서 등 아날로그 센서는 직접 사용할 수 없다.
해결 방법으로는 AD 변환기를 사용하여 SPI 통신을 통해 아날로그 입력을 감지하는 방법이 있습니다.

준비물

  • 어떤 종류의 래퍼리피든 래퍼비안 형식으로 진행된다
  • AD 변환기(이곳은MCP3208-추월전자 300엔)
  • 어떤 시뮬레이션 센서(여기사운드 센서-추월전자는 690엔)
  • 동판
  • RaspberryPi로 SPI 통신 가능
  • 루비
  • 에 넣기

  • 삽입pi_piper
  • SPI 통신 유효성


    초기 상태에서 SPI 통신이 끊어졌기 때문에 SPI를 유효하게 하기 위해 sudo raspi-config 수행되었습니다.
    참고:raspi-config 공식 해설
    참조: raspi-config SPI 유효성에 대한 설명 8 Advanced Options부터 시작하다A5 SPI Enable/Disable automatic loading of SPI kernel module (needed for e.g. PiFace)를 참고하십시오.
    나중에 시동 걸어.
    $ sudo reboot
    
    다시 시작한 후 다음 명령으로spidev0을 진행합니다.0, 0.1 표시 여부를 확인합니다.bash
    $ ls /dev/spi*
    /dev/spidev0.0 /dev/spidev0.1
    위의 내용만 SPI를 사용할 수 없습니다.다음 블랙리스트 파일을 엽니다. spi-bcm2708의 줄에 주석이 없기 때문에 주석 출력spi-bcm2708을 블랙리스트에서 삭제=유효화
    sudo nano /etc/modprobe.d/raspi-blacklist.conf
    
    # blacklist spi and i2c by default (many users don't need them)
    
    #blacklist spi-bcm2708
    
    이후 다시 재부팅합니다.
    $ sudo reboot
    
    아래 명령을 실행하고 spi_bcm2708 를 표시하면 SPI 통신이 유효해집니다.
    $ lsmod | grep spi_
    

    배선 방법


    MCP 3208은 8개 채널 12비트다.8종의 아날로그 센서를 연결하고 12비트의 해상도=1111111111, 즉 아날로그 센서는 0에서 4095의 수치로 표현할 수 있다.
    더 적은 채널과 더 낮은 해상도의 AD 변환기도 있지만 가격은 거의 변하지 않는다.
    > 0b111111111111
    => 4095 
    > 4095.to_s(2)
    => "111111111111"
    > "111111111111".to_i(2)
    => 4095 
    > "0b111111111111".to_i(2)
    => 4095 
    
    MCP3208 핀 이름



    위에서 아래로의 순서대로 선을 긋는 말을 하다
  • 3.3V 사용
  • GND에 연결
  • 아날로그 센서의 출력을 MCP 3208용 CH0
  • 에 연결
  • GND에 연결
  • 3.3V
  • 에 연결
  • Vdd를 3.3V
  • 에 연결
  • Vref를 3.3V
  • 에 연결
  • AGND(아날로그 GND)를 GND
  • 에 연결
  • CLK(시계)를 SCLK
  • 에 연결
  • MISO에 Dout(디지털 출력) 연결
  • 딘(디지털 폭룡)을 MOSI
  • 에 연결
  • CS/SHDN을 CS0에 연결
  • DGND(디지털 GND)를 GND
  • 에 연결

    MCP 3208 데이터 시트 읽기


    AD 변환기는 다음 절차에 따라 데이터를 읽을 수 있습니다.
  • 원하는 채널의 데이터 전달 = RaspberryPi에서 AD 변환기로의 입력
  • 채널에 연결된 아날로그 센서의 값 = AD 변환기에서 RaspberryPi로 출력
  • 그게 다야.간단하지만 데이터 테이블 읽는 법을 알려주지 않으면 전혀 몰라요.

    RaspberryPi에서 AD 변환기로 가져오기


    MCP 3208 Data Sheet 14페이지 표表 5-2: MCP3208 の構成ビット에 1번 채널의 데이터를 얻는 설정 방법이 적혀 있다.이 표는 앞으로 설명할 자리가 서 있는지 안 서 있는지를 설명한다.
    * 참조: MCC3204 테이블의 "X"는 사용하지 않는 비트를 나타냅니다.
  • SINGLE/DIFF
  • D2
  • D1
  • D0
  • *SINGLE = 싱글 끝
    *DIFF = Differencial = 차동
    참조: 단일 입력
  • 이번 센서는 단일(아날로그 출력 1개)이므로 단일 단위로 "1"
  • 을 설정합니다.
  • CH0으로 사용, D2위는 "0"
  • CH0으로 사용, D1위는 "0"
  • CH0으로 사용, D0위는 "0"
  • 16페이지에 실제 위치를 어떻게 정하는지 적혀 있다.
    이 시계는 처음에는 전혀 뜻을 이해하지 못했다.원래는 CS(칩 선택),SCLK(시계) 등과 함께 데이터를 흘렸지만 pi피퍼가 잘하니까 데이터 입력 부분만 생각해서 OK.

    여기서 중요한 것은 8자리의 데이터를 배열 방식의 3가지 요소로 재생하는 것이다.

    CH0을 사용해서 이런 얘기를 하는 거죠.
            #開始ビット、シングルエンドビット、D2はビットなし
                 #D1,D0はビットなし
                             #最後の要素は常にゼロ
    [0b00000110, 0b00000000, 0b00000000]
    
    이것 괜찮아요?piper의 SPI 개체에 쓰기 가능 = AD 변환기에 입력

    AD 변환기에서 RaspberryPi로 출력


    입력에 오류가 없으면 바로 다음 출력으로 돌아갑니다.


    즉, 8비트 데이터가 어레이로 3가지 요소를 반환합니다.
    여기에는 B11에서 B0까지의 비트=12비트=0에서 4095까지의 해상도가 있음을 나타낸다.
    *참고: 해상도가 낮은 경우 데이터 테이블을 보면 배열은 2요소이고 비트수는 10등입니다.
    여기 질문은요.
  • 최초의 요소는 데이터가 없기 때문에 버릴 수 있다
  • 중간 요소 중 오른쪽에서 네 자리까지의 신뢰할 수 있는 데이터만 있음
  • 마지막 비트는 모두 데이터이지만 중간 요소를 결합시켜 고려하지 않으면 정확한 값이 없다
  • 이를 위해 중간의 비트를 처리하는 데 공을 들여야 하고, 중간의 비트와 마지막 비트를 더해야 한다.
    # 最初の要素は捨てる
    _, center, last = spi.write [.....]
    
    # centerが 10100011 だったとして
    #          00001111 をアンド演算すると
    #         ---------
    #          00000011 となり、綺麗に1から4ビット目だけのデータが取れる
    center = center & 0b00001111 # これによりゴミがある可能性のある、5から8ビット目は無視できる
    
    # centerは2バイト目のデータなのに、今のままでは1バイト目の数値
    # この為8ビット左にずらし、2バイト目の数値に変える
    # 例
    # 00000011 = 3 # center
    # 00000001 = 1 # last
    # 単純に centerとlastを足すと 4 になってしまうので、centerを8ビットずらし
    # 00000011 00000000 = 768 # center
    # lastと足せば
    # 00000011 00000001 = 769
    center = center << 8
    value = center + last
    
    나오는 값은 해상도에 대한 수치이기 때문에 해상도에 대해 백분율 계산을 해야 한다.이것을 통해 아날로그 센서가 얼마나 큰 반응을 보이는지 알 수 있다.
    RESOLUTION_AT_12BIT = 0b111111111111.to_f.freeze
    percentage = value / RESOLUTION_AT_12BIT * 100
    

    총결산

    require "pi_piper"
    
    RESOLUTION_AT_12BIT = 0b111111111111.to_f.freeze
    
    PiPiper::Spi.begin do |spi|
      loop do
        _, center, last = spi.write [0b00000110, 0b00000000, 0b00000000]
        center = center & 0b00001111
        center = center << 8
        value =  center + last
        percentage = value / RESOLUTION_AT_12BIT * 100
    
        puts "#{percentage} %"
        sleep 0.1
      end
    end
    
    참조: 다중 채널 버전
    require "pi_piper"
    
    RESOLUTION_AT_12BIT = 0b111111111111.to_f.freeze
    
    channels = {
      ch0: [0, 0, 0],
      ch1: [0, 0, 1],
    }
    
    PiPiper::Spi.begin do |spi|
      loop do
        channels.each do |channel_name, data|
          _, center, last = spi.write ["0b0000011#{data[0]}".to_i(2), "0b#{data[1]}#{data[2]}000000".to_i(2), 0b00000000]
          center = center & 0b00001111
          center = center << 8
          value =  center + last
          percentage = value / RESOLUTION_AT_12BIT * 100
    
          puts "#{channel_name}: #{percentage} %"
        end
        sleep 0.1
      end
    end
    

    기타 참조

  • Raspberry Pi GPIO Tutorial 3: Analog Inputs
  • AD 변환기와 사진 레지스터를 사용하여 방의 밝기를 얻습니다.
  • nterfacing an SPI ADC (MCP3008) chip to the Raspberry Pi using C++ (spidev)
  • SPI 모듈(Serial Peripheral InterfaceModule) 사용 방법
  • SPI Transfer Modes
  • 좋은 웹페이지 즐겨찾기