# $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 .
#
##############################################################################
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 (){
$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 (){
$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
BBB_BMP180
Prerequesits
Module was developed for use with Beaglebone Black.
To create the device, run the following command on system console:
echo bmp085 0x77 > /sys/class/i2c-adapter/i2c-1/new_device
To check if successful:
dmesg | grep bmp
[ 76.989945] i2c i2c-1: new_device: Instantiated device bmp085 at 0x77
[ 77.040606] bmp085 1-0077: Successfully initialized bmp085!
Define
define <name> BBB_BMP180 [bus]
This module provides air pressure measurement by a BMP180 sensor connected to I2C bus.
Optional parameter [bus] defines number of I2C-bus in your hardware (default = 1).
Set-Commands
No set commands implemented.
Get-Commands
get <name> readValues
Update all values immediately.
Attributes
- bbbInterval - Interval for readings update (default = 300 seconds)
- bbbRoundPressure - If set to 1 = pressure value will be presented without decimals (default = 2 decimals)
- bbbRoundTemperatue - If set to 1 = temperature value will be presented without decimals (default = 1 decimal)
- readingFnAttributes
Generated Readings/Events:
- temperature - temperature at sensor
- pressure - pressure (absolute)
- pressure-nn - pressure (relative), global attribute altitude needed for calculation
Author's notes
=end html
=begin html_DE
BBB_BMP180
Sorry, keine deutsche Dokumentation vorhanden.
Die englische Doku gibt es hier: BBB_BMP180
=end html_DE
=cut