LoginSignup
24
25

More than 5 years have passed since last update.

Raspberry Pi + Ruby で A/Dコンバータ MCP3208 からデータロード

Last updated at Posted at 2014-04-13

pi_piper の example に入っていた MCP3008 向けのデータロードアプリを、読み書きのタイミングを秋月電子で購入した時についてきたデータシートを元に調整して、12bitの精度に修正したもの。

Raspberry Pi の PIN と MCP3208 の接続は下記のように接続してます。
(http://d.hatena.ne.jp/seinzumtode/20130918/1379501130 を参照しながら結線しました)
rpi_mcp3208.png

PI MCP3208
P1-01(3.3v) Vdd,Vref
GPIO 8 CS/SHDN
GPIO 9 D_OUT
GPIO10 D_IN
GPIO11 CLK
GND Agnd,Dgnd

測定したい CH を adc_chs[] に設定しておくと一度の計測で順次読み出しします。
基準電圧 3.3V として測定範囲を 0v 〜 3300mv と仮定して mvolts に MCP3208 のピン入力の電圧値を、rvolts に 100kΩ : 4.7kΩx2 で分圧したときの推定入力値を表示してますのでこのへんは自分の回路に合わせて変更してください。

実行部分を細工してあるので、このまま他のスクリプトから require なり load して関数部分だけ使えます。

ad_read_test.rb
# -*- coding: utf-8 -*-
# port of the Adafruit MCP3008 interface code found @ http://learn.adafruit.com/send-raspberry-pi-data-to-cosm/python-script
#
# adjast timing and resolution for MCP3208 (12bit)
# 

require 'pi_piper'

def read_adc(adc_pin, clockpin, adc_in, adc_out, cspin)
  cspin.on
  clockpin.off
  adc_in.off
  # clockpin が low の状態で cspin を立ち下げると SPI モード 0,0
  cspin.off

  command_out = adc_pin
  command_out |= 0x18
  command_out <<= 3

  (0..4).each do
    adc_in.update_value((command_out & 0x80) > 0)
    command_out <<= 1
    clockpin.on
    clockpin.off
  end
  result = 0

# 2clock skip (1clock gap(sampling end) + null bit)
  (0..1).each do
    clockpin.on
    clockpin.off
  end

# load data  
  (0..11).each do
    clockpin.on
    clockpin.off
    result <<= 1
    adc_out.read
    if adc_out.on?
      result |= 0x1
    end
  end

  cspin.on

  result >> 1
end




#---
# main when boot this script
#+++
if __FILE__ == $0


clock   = PiPiper::Pin.new :pin => 11, :direction => :out
adc_out = PiPiper::Pin.new :pin => 9
adc_in  = PiPiper::Pin.new :pin => 10, :direction => :out
cs      = PiPiper::Pin.new :pin => 8,  :direction => :out

# watch channels from 0 to 7(MCP3208) or 3(MCP3204)
adc_chs = [0, 1, 2]

# 12bit
RESOLUTION = 4096

loop do
  adc_chs.each do |adc_pin|
    value = read_adc(adc_pin, clock, adc_in, adc_out, cs)
    invert = RESOLUTION - 1 - value
    mvolts = value * (3300.0 / RESOLUTION.to_f)
    rbolts = value * 3.3 * 109.4 / 9.4 / RESOLUTION.to_f

    puts "#{Time.now.to_s}, CH:#{adc_pin}, Value = #{value}, invert = #{invert}, mvolts = #{mvolts.round(3)}, rvolts = #{rbolts.round(3)}"
  end
  sleep 1
end

end

ToDoとしては
・データシートなどなどから測定範囲を正確にする事
・計測間隔が sleep(sec) なのでどんどんずれていく事

24
25
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
25