# $Id: 51_BBB_BMP180.pm 4929 2014-02-15 03:26:20Z betateilchen $ ############################################################################## # # 51_BBB_BMP180.pm # # An FHEM Perl module to retrieve pressure data from a BMP085/BMP180 # sensor connected to I2C bus # # Copyright: betateilchen ® # e-mail : fhem.development@betateilchen.de # # This file is part of fhem. # # Fhem is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # Fhem is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with fhem. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## package main; use strict; use warnings; use feature qw/say switch/; use Time::HiRes qw(gettimeofday); sub BBB_BMP180_Initialize($){ my ($hash) = @_; $hash->{DefFn} = "BBB_BMP180_Define"; $hash->{UndefFn} = "BBB_BMP180_Undefine"; $hash->{GetFn} = "BBB_BMP180_Get"; $hash->{AttrFn} = "BBB_BMP180_Attr"; $hash->{NotifyFn} = "BBB_BMP180_Notify"; $hash->{ShutdownFn} = "BBB_BMP180_Shutdown"; $hash->{AttrList} = "bbbRoundPressure:0,1 ". "bbbRoundTemperature:0,1 ". "bbbInterval ". $readingFnAttributes; } sub BBB_BMP180_Define($$){ my ($hash, $def) = @_; my $name = $hash->{NAME}; my @a = split("[ \t][ \t]*", $def); Log3($name, 3, "BBB_BMP180 $name: created"); readingsSingleUpdate($hash, "state", "active",1); $hash->{helper}{i2cbus} = '1'; $hash->{helper}{i2cbus} = $a[2] if(defined($a[2])); # check sensor presence my $bmpTest = '/sys/bus/i2c/drivers/bmp085/'.$hash->{helper}{i2cbus}.'-0077/pressure0_input'; return 'BBB_BMP180: sensor not found!' unless -e $bmpTest; $bmpTest = '/sys/bus/i2c/drivers/bmp085/'.$hash->{helper}{i2cbus}.'-0077/temp0_input'; return 'BBB_BMP180: sensor not found!' unless -e $bmpTest; if( $init_done ) { delete $modules{openweathermap}->{NotifyFn}; bbb_getValues($hash,0); } else { readingsSingleUpdate($hash, "state", "defined",1); } return undef; } sub BBB_BMP180_Undefine($$){ my($hash, $name) = @_; RemoveInternalTimer($hash); return; } sub BBB_BMP180_Shutdown($) { my ($hash) = @_; my $name = $hash->{NAME}; Log3 ($name,4,"BBB_BMP180 $name: shutdown requested"); return undef; } sub BBB_BMP180_Get($@){ my ($hash, @a) = @_; my $name = $hash->{NAME}; my ($cmd) = $a[1]; my $usage = "Unknown argument $cmd, choose one of readValues:noArg"; return $usage if($cmd eq "?"); given($cmd) { when("readValues") { bbb_getValues($hash,1); } default {return} } return; } sub BBB_BMP180_Attr($@){ my @a = @_; my $hash = $defs{$a[1]}; my (undef, $name, $attrName, $attrValue) = @a; given($attrName){ when("bbbInterval"){ RemoveInternalTimer($hash); my $next = gettimeofday()+$attrValue; InternalTimer($next, "bbb_getValues", $hash, 0); break; } default {$attr{$name}{$attrName} = $attrValue;} } return ""; } sub BBB_BMP180_Notify($$) { my ($hash,$dev) = @_; if( grep(m/^INITIALIZED$/, @{$dev->{CHANGED}}) ) { delete $modules{BBB_BMP180}->{NotifyFn}; foreach my $d (keys %defs) { next if($defs{$d}{TYPE} ne "openweathermap"); bbb_getValues($hash,0); } } } sub bbb_getValues($$){ my ($hash,$local) = @_; my $name = $hash->{NAME}; my $a = AttrVal('global','altitude',undef); my $t = bbb_temp($hash); my $pa = bbb_absDruck($hash); my $pr = bbb_relDruck($hash,$a) if(defined($a)); if(AttrVal($name,'bbbRoundPressure',undef)){ $pa = sprintf("%.0f", $pa); $pr = sprintf("%.0f", $pr) if(defined($a)); } else { $pa = sprintf("%.2f", $pa); $pr = sprintf("%.2f", $pr) if(defined($a)); } if(AttrVal($name,'bbbRoundTemperature',undef)){ $t = sprintf("%.0f", $t); } else { $t = sprintf("%.1f", $t); } my $s = "T: $t P: $pa"; $s .= " P-nn: $pr" if(defined($a)); readingsBeginUpdate($hash); readingsBulkUpdate($hash, 'temperature', $t); readingsBulkUpdate($hash, 'pressure', $pa); readingsBulkUpdate($hash, 'pressure-nn', $pr) if(defined($a)); readingsBulkUpdate($hash, 'state', $s) if(defined($a)); readingsEndUpdate($hash, 1); my $next = gettimeofday()+AttrVal($name,'bbbInterval',300); InternalTimer($next, "bbb_getValues", $hash, 0) unless $local; return; } sub bbb_temp($){ my ($hash) = @_; my $bmpT = '/sys/bus/i2c/drivers/bmp085/'.$hash->{helper}{i2cbus}.'-0077/temp0_input'; my $temp; open (IN,"<$bmpT"); while (<IN>){ $temp = $_; last; } close IN; $temp = substr($temp,0,length($temp)-1); return $temp/10; } sub bbb_absDruck($){ my ($hash) = @_; my $bmpP = '/sys/bus/i2c/drivers/bmp085/'.$hash->{helper}{i2cbus}.'-0077/pressure0_input'; my $p; open (IN,"<$bmpP"); while (<IN>){ $p = $_; last; } close IN; $p = substr($p,0,length($p)-1); return $p/100; } sub bbb_relDruck($$){ my($hash,$Alti) = @_; my $Pa = bbb_absDruck($hash); my $Temp = bbb_temp($hash); # Konstanten my $g0 = 9.80665; my $R = 287.05; my $T = 273.15; my $Ch = 0.12; my $a = 0.065; my $E = 0; if($Temp < 9.1){ $E = 5.6402*(-0.0916 + exp(0.06 * $Temp)); } else { $E = 18.2194*(1.0463 - exp(-0.0666 * $Temp)); } my $xp = $Alti * $g0 / ($R*($T+$Temp + $Ch*$E + $a*$Alti/2)); my $Pr = $Pa*exp($xp); return $Pr; } 1; =pod not to be translated =begin html <a name="BBB_BMP180"></a> <h3>BBB_BMP180</h3> <ul> <b>Prerequesits</b> <ul> <br/> Module was developed for use with Beaglebone Black.<br/><br/> To create the device, run the following command on system console:<br/><br/> <code>echo bmp085 0x77 > /sys/class/i2c-adapter/i2c-1/new_device</code><br/><br/> To check if successful:<br/><br/> <code> dmesg | grep bmp<br/> [ 76.989945] i2c i2c-1: new_device: Instantiated device bmp085 at 0x77<br/> [ 77.040606] bmp085 1-0077: Successfully initialized bmp085!<br/> </code> <br/> </ul> <br/><br/> <a name="BBB_BMP180define"></a> <b>Define</b> <ul> <br/> <code>define <name> BBB_BMP180 [bus]</code> <br/><br/> This module provides air pressure measurement by a BMP180 sensor connected to I2C bus.<br/> Optional parameter [bus] defines number of I2C-bus in your hardware (default = 1).<br/> <br/> </ul> <br/><br/> <a name="BBB_BMP180set"></a> <b>Set-Commands</b><br/> <ul> <br/> No set commands implemented.<br/> <br/> </ul> <br/><br/> <a name="BBB_BMP180get"></a> <b>Get-Commands</b><br/> <ul> <br/> <code>get <name> readValues</code> <br/><br/> <ul> Update all values immediately. </ul> </ul> <br/><br/> <a name="BBB_BMP180attr"></a> <b>Attributes</b><br/><br/> <ul> <li><b>bbbInterval</b> - Interval for readings update (default = 300 seconds)</li> <li><b>bbbRoundPressure</b> - If set to 1 = pressure value will be presented without decimals (default = 2 decimals)</li> <li><b>bbbRoundTemperatue</b> - If set to 1 = temperature value will be presented without decimals (default = 1 decimal)</li> <li><a href="#readingFnAttributes">readingFnAttributes</a></li> </ul> <br/><br/> <b>Generated Readings/Events:</b> <br/><br/> <ul> <li><b>temperature</b> - temperature at sensor</li> <li><b>pressure</b> - pressure (absolute)</li> <li><b>pressure-nn</b> - pressure (relative), global attribute altitude needed for calculation</li> </ul> <br/><br/> <b>Author's notes</b><br/><br/> <ul> <li>Have fun!</li><br/> </ul> </ul> =end html =begin html_DE <a name="BBB_BMP180"></a> <h3>BBB_BMP180</h3> <ul> Sorry, keine deutsche Dokumentation vorhanden.<br/><br/> Die englische Doku gibt es hier: <a href='http://fhem.de/commandref.html#BBB_BMP180'>BBB_BMP180</a><br/> </ul> =end html_DE =cut