#Bosch BMP085/BMP180
class BarometerBMP
BMP_ADDRESS=0x77
OSS = 0
def initialize
@ac1 = read_int16( 0xAA )
@ac2 = read_int16( 0xAC )
@ac3 = read_int16( 0xAE )
@ac4 = read_uint16( 0xB0 )
@ac5 = read_uint16( 0xB2 )
@ac6 = read_uint16( 0xB4 )
@b1 = read_int16( 0xB6 )
@b2 = read_int16( 0xB8 )
@mb = read_int16( 0xBA )
@mc = read_int16( 0xBC )
@md = read_int16( 0xBE )
@temp = 0
@press = 0
#p "@ac1=#{@ac1}, @ac2=#{@ac2}, @ac3=#{@ac3}, "
end
def read_uint8( reg_addr )
$wire.beginTransmission( BMP_ADDRESS )
delay(10)
$wire.write( reg_addr )
delay(10)
$wire.endTransmission()
delay(10)
$wire.requestFrom( BMP_ADDRESS, 1 )
delay(10)
value = $wire.read
delay(10)
return value
end
def read_uint16( reg_addr )
hi = read_uint8( reg_addr )
delay(10)
lo = read_uint8( reg_addr + 1 )
value = hi*256 + lo
end
def read_int16( reg_addr )
value = read_uint16( reg_addr )
delay(10)
if value >= 32768
value = -( 65536 - value )
end
return value
end
def write_uint8( reg_addr, value )
$wire.beginTransmission( BMP_ADDRESS )
delay(10)
$wire.write( reg_addr )
delay(10)
$wire.write( value )
delay(10)
$wire.endTransmission()
end
def calc
#UT
write_uint8( 0xF4, 0x2E )
delay( 5 )
ut = read_uint16( 0xF6 )
#UP
write_uint8( 0xF4, 0x34 + (OSS<<6) )
delay( 2 + (3<<OSS) )
hi = read_uint8( 0xF6 )
mi = read_uint8( 0xF7 )
lo = read_uint8( 0xF8 )
up = hi * 65536 + mi * 256 + lo
up = up >> (8-OSS)
#p "ut=#{ut}, up=#{up}"
#tempereture
x1 = ( ut - @ac6 ) * @ac5 / 32768
x2 = @mc * 2048 / ( x1 + @md )
b5 = ( x1 + x2 ).to_i
t = ( b5 + 8 ) / 16
@temp = t.floor() / 10.0
#pressure
b6 = b5 - 4000
x1 = ( @b2 * ( b6 * b6 / 2**12 ) ) / 2**11
x2 = ( @ac2 * b6 ) / 2**11
x3 = x1 + x2
b3 = ( ( ( @ac1 * 4 + x3 ).to_i << OSS ) + 2 ) / 4
b3 = b3.to_i
#p "x1=#{x1}, x2=#{x2}, x3=#{x3}, b3=#{b3}"
x1 = ( @ac3 * b6 ) / 2**13
x2 = ( @b1 * ( b6 * b6 / 2**12 ) ) / 2**16
x3 = ( ( x1 + x2 ) + 2 ) / 2**2
b4 = ( @ac4 * ( x3 + 32768 ) ) / 2**15
b4 = b4.to_i
#p "x1=#{x1}, x2=#{x2}, x3=#{x3}, b4=#{b4}"
b7 = ( up - b3 ) * ( 50000 >> OSS )
b7 = b7.to_i
#p "b7=#{b7}"
if ( b7 < 0x80000000 )
p = ( b7 * 2 ) / b4
else
p = ( b7 / b4 ) * 2
end
x1 = ( p / 2**8 ) * ( p / 2**8 )
x1 = ( x1 * 3038 ) / 2**16
x2 = ( -7357 * p ) / 2**16
p += ( x1 + x2 + 3791 ) / 2**4
@press = p.to_i
return true
end
def tempereture
return @temp
end
def pressure
return @press
end
end
# HIH6130
class HumidityHIH6130
HIH6130_ADDRESS = 0x27
def initialize
@temp = 0
@humidity = 0
@status = 0
end
def calc
# wake up
#puts 'HIH6130 MR'
$wire.beginTransmission( HIH6130_ADDRESS )
delay( 10 )
$wire.endTransmission()
delay( 10 )
# read registers
#puts 'HIH6130 DF'
$wire.requestFrom( HIH6130_ADDRESS, 4 )
h_hi = $wire.read
h_lo = $wire.read
t_hi = $wire.read
t_lo = $wire.read
#$wire.endTransmission()
#normalize
@status = ( h_hi >> 6 ) & 3
h_hi = h_hi & 0x3f
t = ( t_hi*256 + t_lo ) >> 2
h = h_hi*256 + h_lo
@temp = t/( 2**14 - 2 )*165.0 - 40.0
@humidity = h/( 2**14 -2 )*100.0
return true
end
def tempereture
return @temp
end
def humidity
return @humidity
end
def status
return @status
end
end
class Thermistor
B = 3452.0 # 25-100 deg.
RC = 1000.0 # Series constant R
RS = 10000.0 # thermistor R at 25 deg.
def initialize
@temp = 0
end
def calc
av = analogRead( A0 )
vs = av * 3.3 / 1024.0
# RS:RC = vs:(3.3-vs)
# so RS = RC*vs/( 3.3 - vs )
rs = RC * vs / ( 3.3 - vs )
#puts "vs=#{vs}, rs=#{rs}"
@temp = 1.0 / ( 1.0 / ( 273.0 + 25.0 ) + 1.0 / B * Math.log( rs / RS ) ) - 273.0
return true
end
def tempereture
return @temp
end
end
class GpsNmea
#NMEA
# ref. http://blog.lojic.com/2009/04/08/use-ruby-to-parse-nmea-sentences-from-your-gps/
def initialize
@lon = 0
@lat = 0
@utc = ''
@available = false
@sp = Serial.new(9600)
end
def calc
result = parse( getline )
if result
@available = true
end
return result
end
def getline
s = ''
while true
c = getch
if c == "\n"
break
end
if s.length and c == '$'
s = ''
end
s += c
end
return s.strip
end
def getch
until @sp.available
end
i = 256
while i >= 256
i = @sp.read
end
return i.chr
end
def longitude
return @lon
end
def latitude
return @lat
end
def available?
return @available
end
def utc
return @utc
end
# lat is of the form 4807.038 where the first 2 digits are degrees and
# the remainder is minutes.
# dir is either 'N' or 'S'
def convert_lat lat, dir
degrees = lat[0..1].to_f + (lat[2..-1].to_f / 60.0)
dir == 'N' ? degrees : -degrees
end
# lon is of the form 01131.000 where the first 3 digits are degrees and
# the remainder is minutes.
# dir is either 'E', or 'W'
def convert_lon lon, dir
degrees = lon[0..2].to_f + (lon[3..-1].to_f / 60.0)
dir == 'E' ? degrees : -degrees
end
def parse( line )
# puts "parse() : #{line}"
if line.length > 6 and line[0..5] == '$GPGGA'
fix = line.split( ',' )
if fix.length >= 7 and fix[6].length and ( fix[6] == '1' or fix[6] == '2' )
@utc = fix[1]
@lat = convert_lat( fix[2], fix[3] )
@lon = convert_lon( fix[4], fix[5] )
return true
end
end
return false
end
end
def main
puts "create wire..."
$wire = Wire.new( 0x0, Wire::DutyCycle_2 )
puts "OK"
puts "create gps..."
gps = GpsNmea.new
puts "OK"
gps.calc
prev_ms = millis
puts "create hum..."
hum = HumidityHIH6130.new
puts "OK"
hum.calc
puts "create bar..."
bar = BarometerBMP.new
puts "OK"
bar.calc
puts "loop begin"
loop do
begin
# calc : every time
gps.calc
delay(10)
hum.calc
delay(10)
bar.calc
rescue => exc
#Exception
p exc
else # when can be calculated
# print result : every 5sec.
if ( millis - prev_ms ) < 5000
next
end
puts '[GPS]'
if gps.available?
puts "UTC = #{gps.utc}"
puts gps.longitude
puts gps.latitude
else
puts 'No data'
end
puts '[HUM]'
puts "#{hum.tempereture}"
puts "#{hum.humidity}"
puts '[BAR]'
puts "#{bar.tempereture}"
puts "#{bar.pressure}"
prev_ms = millis
ensure
#
end
end
end
# exec main
main