2013年6月13日木曜日

ruby gem 'arduino_firmata' の sysex を使ってMPL115A2使用の圧力モジュールから値を取得する

2013/06/14-18:11JST u2sで負の値の求め方の間違いを修正(緑色)

気圧の値も妥当なものになった(と思う).
2013/06/14-13:30JST 返り値のバイト数が要求バイト数と合っていないことがあるのでその場合スキップするように修正(青色)
2013/06/13-16:10JST ADT7410(温度)/"arduino.sysex I2C_REQUEST, [ADDRESS_ADT7410, _WRITE, 0x03, 0x00, 0x00, 0x001]"で16bit-modeで動くこともあるが, ケースによっては13bitのままだったりする.

  • 0.1度の中に複数の計測点があるので16bit modeであることがわかる.
  • 気圧/MPL115A2側はパスコン入れたら安定した
2013/06/13-15:36JST ADT7410(温度)/16bit mode指定がやっぱり正しく動いてないので削除
2013/06/13-15:06JST ADT7410(温度)/16bit mode指定の間違いを訂正
結果:

ブレッドボードをMBPの上からおろしたらみるみる温度が下がっていく図.
気圧が安定していない…やっぱりなにか間違っているのかもしれない.

これを使って,やってみた.のでメモ.
#!/usr/bin/env ruby -Ku
require 'rubygems'
require 'arduino_firmata'
$stdout.sync = true

STRING_DATA= 0x71
I2C_REQUEST= 0x76
I2C_REPLY= 0x77
I2C_CONFIG= 0x78

_WRITE= 0x00
_READ= 0x08

ADDRESS_ADT7410= 0x48
ADDRESS_MPL115A2= 0x60

#MPL115A2 coefficients
a0= b1= b2= c12= 0.0

def readData(data, shift)
  msb= data[4+4*shift]+data[5+4*shift]*128
  lsb= data[6+4*shift]+data[7+4*shift]*128
  return (msb<<8)+lsb
end

def readDataS(data, shift)
  v= readData(data, shift)
  return (v<(1<<15)) ? v : v-(1<<15)*2
end

def data2string(data)
  i=0
  msg= ''
  while i+1<data.length
    msg+= data[i].chr
    i+= 2
  end
  return msg;
end

arduino = ArduinoFirmata.connect ENV["ARDUINO"], :nonblock_io => true

arduino.on :sysex do |command, data|
  puts "command : #{command}"
  puts "data    : #{data.inspect}"
  if command == I2C_REPLY
    if data[0] == ADDRESS_ADT7410
      if data.length == 8
        tout= readDataS(data, 0)/(1<<7).to_f
        puts "気温 #{tout} ℃"
      end
    elsif data[0] == ADDRESS_MPL115A2
      if data[2] == 0x04
        if data.length == 20
          a0 = readDataS(data, 0)/(1<<3).to_f
          b1 = readDataS(data, 1)/(1<<13).to_f
          b2 = readDataS(data, 2)/(1<<14).to_f
          c12= readDataS(data, 3)/(1<<24).to_f
        end
      elsif data[2] == 0x00
        if data.length == 12
          padc= readData(data, 0)>>6
          tadc= readData(data, 1)>>6
          pcomp= a0 + ( b1 + c12 * tadc ) * padc + b2 * tadc
          pout= pcomp * 650.0/1023.0 + 500.0
          puts "気圧 #{pout} hPa"
        end
      end
    end
  else
    if command == STRING_DATA
      p data2string(data);
    end
  end
end

#i2c enable
arduino.sysex I2C_CONFIG, [0x00, 0x00]

#MPL115A2 coefficients
arduino.sysex I2C_REQUEST, [ADDRESS_MPL115A2, _READ, 0x04, 0x00, 0x08, 0x00]

loop do
  arduino.sysex I2C_REQUEST, [ADDRESS_ADT7410, _READ, 0x00, 0x00, 0x02, 0x00]

  arduino.sysex I2C_REQUEST, [ADDRESS_MPL115A2, _WRITE, 0x12, 0x00, 0x01, 0x00]
  sleep 0.02
  arduino.sysex I2C_REQUEST, [ADDRESS_MPL115A2, _READ, 0x00, 0x00, 0x04, 0x00]

  sleep 1
end
  • 前の記事の最後に書いた,「うまくいかない.」の原因は,1バイト(8ビット)の内容を送るのにも7bitの通信なので2バイト(7ビットのバイト+1ビットのバイト)送らないといけない(受信も)という点を全く理解していなかったのに挑んでいたのが原因.…だったと思っている(結局よくわかっていない).

0 件のコメント: