51_I2C_BH1750.pm 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. # $Id: 51_I2C_BH1750.pm 12274 2016-10-05 09:45:28Z arnoaugustin $
  2. ##############################################################################
  3. #
  4. # 51_I2C_BH1750.pm
  5. #
  6. # This file is part of FHEM.
  7. #
  8. # Fhem is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation, either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # BDKM is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with FHEM. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. # Written by Arno Augustin
  22. ##############################################################################
  23. package main;
  24. use strict;
  25. use warnings;
  26. use Time::HiRes qw(tv_interval);
  27. # BH1750 chip constants
  28. use constant
  29. {
  30. # I2C addresses
  31. BH1750_ADDR_DEFAULT => 0x23,
  32. BH1750_ADDR_OTHER => 0x5C,
  33. # I2C registers
  34. BH1750_RAW_VALUE => 0x00,
  35. BH1750_POWER_DOWN => 0x00,
  36. BH1750_POWER_ON => 0x01,
  37. BH1750_RESET => 0x07,
  38. BH1750_H_MODE => 0x10,
  39. BH1750_H_MODE2 => 0x11,
  40. BH1750_L_MODE => 0x13,
  41. BH1750_H_MODE_ONCE => 0x20,
  42. BH1750_H_MODE2_ONCE => 0x21,
  43. BH1750_L_MODE_ONCE => 0x23,
  44. BH1750_MT_MIN => 31,
  45. BH1750_MT_DEFAULT => 69,
  46. BH1750_MT_MAX => 254,
  47. };
  48. #state
  49. use constant
  50. {
  51. BH1750_STATE_DEFINED => 'Defined',
  52. BH1750_STATE_I2C_ERROR => 'I2C Error',
  53. BH1750_STATE_SATURATED => 'Saturated',
  54. BH1750_STATE_OK => 'Ok'
  55. };
  56. # PollState
  57. use constant
  58. {
  59. BH1750_POLLSTATE_IDLE => 0,
  60. BH1750_POLLSTATE_START_MEASURE => 1,
  61. BH1750_POLLSTATE_PRE_LUX_WAIT => 2,
  62. BH1750_POLLSTATE_PRE_LUX_DONE => 3,
  63. BH1750_POLLSTATE_LUX_WAIT => 4,
  64. BH1750_POLLSTATE_LUX_DONE => 5
  65. };
  66. # chip parameter selection for different LUX values
  67. # BH1750 has the following limitations:
  68. # MODE_L, MT= 31, LUX 0-121556, res. >8 LUX
  69. # MODE_L, MT= 69, LUX 0- 54612, res. >4 LUX
  70. # MODE2_H, MT= 31, LUX 0- 60778, res. >1 LUX
  71. # MODE2_H, MT= 69, LUX 0- 27306, res. >0.5 LUX
  72. # MODE2_H, MT=254, LUX 0- 7417, res. >0.11 LUX
  73. my @I2C_BH1750_ranges=(
  74. # RAWVAL MT MODE
  75. [ 3000, 254, BH1750_H_MODE2_ONCE],
  76. [ 6000, 127, BH1750_H_MODE2_ONCE],
  77. [ 12000, 69, BH1750_H_MODE2_ONCE],
  78. [ 26000, 31, BH1750_H_MODE2_ONCE]
  79. # else use 31, BH1750_L_MODE_ONCE
  80. );
  81. sub I2C_BH1750_Initialize($);
  82. sub I2C_BH1750_Define($$);
  83. sub I2C_BH1750_Attr(@);
  84. sub I2C_BH1750_Poll($);
  85. sub I2C_BH1750_Restart_Measure($$);
  86. sub I2C_BH1750_Set($@);
  87. sub I2C_BH1750_Get($);
  88. sub I2C_BH1750_Undef($$);
  89. sub I2C_BH1750_Initialize($)
  90. {
  91. my ($hash) = @_;
  92. $hash->{STATE} = "Init";
  93. $hash->{DefFn} = "I2C_BH1750_Define";
  94. $hash->{UndefFn} = "I2C_BH1750_Undef";
  95. $hash->{InitFn} = "I2C_BH1750_IoInit";
  96. $hash->{AttrFn} = "I2C_BH1750_Attr";
  97. $hash->{SetFn} = "I2C_BH1750_Set";
  98. $hash->{I2CRecFn} = 'I2C_BH1750_I2CRec';
  99. $hash->{AttrList} = "poll_interval:0.1,0.2,0.5,1,2,5,10,20,30,60 IODev percentdelta correction ".
  100. $readingFnAttributes;
  101. $hash->{VERSION} = '$Id: 51_I2C_BH1750.pm 12274 2016-10-05 09:45:28Z arnoaugustin $';
  102. }
  103. sub I2C_BH1750_Define($$)
  104. {
  105. my ($hash, $def) = @_;
  106. my @a = split(/\s+/, $def);
  107. my $name = shift(@a);
  108. my $device=0;
  109. my $usage=sprintf "usage: \"define <devicename> I2C_BH1750 [devicename] [0x%x|0x%x]\"\n",
  110. BH1750_ADDR_DEFAULT,BH1750_ADDR_OTHER;
  111. $hash->{I2C_Address}=BH1750_ADDR_DEFAULT; # default
  112. Log3 ($hash, 3, $hash->{NAME} . ': ' . "define $def");
  113. shift(@a);
  114. @a > 1 and return $usage;
  115. if(defined ($_=$a[0])) {
  116. /0x(5c|23)/i or return $usage;
  117. $hash->{I2C_Address}=hex($_);
  118. }
  119. $hash->{BASEINTERVAL} = 0;
  120. $hash->{RESTARTDELAY} = 10;
  121. $hash->{DELTA} = 0;
  122. $hash->{PollState} = BH1750_POLLSTATE_IDLE;
  123. $hash->{CORRECTION} = 1;
  124. readingsSingleUpdate($hash, 'state', BH1750_STATE_DEFINED, 1);
  125. my $ret = undef;
  126. if ($main::init_done) {
  127. eval {I2C_BH1750_IoInit($hash, \@a);};
  128. if($@) {
  129. $ret = I2C_BH1750_Catch($@);
  130. Log3 ($hash, 1, $hash->{NAME} . ': ' . $ret);
  131. }
  132. }
  133. return $ret;
  134. }
  135. sub I2C_BH1750_IoInit($$)
  136. {
  137. my ($hash, $args) = @_;
  138. my $name = $hash->{NAME};
  139. eval { AssignIoPort($hash, AttrVal($hash->{NAME},"IODev",undef)); };
  140. $@ and return I2C_BH1750_Catch($@);
  141. return undef;
  142. }
  143. sub I2C_BH1750_Catch($)
  144. {
  145. my $exception = shift;
  146. if ($exception) {
  147. $exception =~ /^(.*)( at.*FHEM.*)$/;
  148. return $1;
  149. }
  150. return undef;
  151. }
  152. sub I2C_BH1750_Attr (@)
  153. {
  154. my ($cmd,$name,$attr,$val) = @_;
  155. my $hash = $defs{$name};
  156. my $error = "$name: ERROR attribute $attr ";
  157. my $del = $cmd =~ /del/;
  158. local $_;
  159. Log3 $name, 3, "$name I2C_BH1750_Attr $cmd,$name,$attr,$val";
  160. if ($attr eq "correction") {
  161. if($del) {
  162. $val = 1; # default
  163. } else {
  164. $val =~ /^(12|[012]+\.[0-9]+)$/ and $val >= 0.5
  165. and $val <=2 or return $error."needs numeric value between 0.5 and 2";
  166. }
  167. $hash->{CORRECTION} = $val;
  168. } elsif ($attr eq "percentdelta") {
  169. if($del) {
  170. $val = 0; # default
  171. } else {
  172. $val =~ /^([0-9]+|[0-9]+\.?[0.9]+)$/ or return $error."needs numeric value";
  173. }
  174. $hash->{DELTA} = $val/100;
  175. } elsif ($attr eq "poll_interval") {
  176. RemoveInternalTimer($hash);
  177. if($del) {
  178. $hash->{BASEINTERVAL} = 0;
  179. $hash->{PollState} = BH1750_POLLSTATE_IDLE;
  180. } else {
  181. if($val !~ /^\d+/) {
  182. return $error."needs numeric value";
  183. } else {
  184. $hash->{BASEINTERVAL} = 60*$val;
  185. I2C_BH1750_Restart_Measure($hash,$hash->{RESTARTDELAY});
  186. }
  187. }
  188. } elsif ($attr eq "IODev") {
  189. eval {
  190. if ($main::init_done and (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $val)) {
  191. my @def = split (' ',$hash->{DEF});
  192. return I2C_BH1750_IoInit($hash,\@def);
  193. };
  194. };
  195. }
  196. return undef;
  197. }
  198. sub I2C_BH1750_Restart_Measure($$)
  199. {
  200. my ($hash,$delay) = @_;
  201. my $name = $hash->{NAME};
  202. RemoveInternalTimer($hash);
  203. $hash->{PollState} = BH1750_POLLSTATE_IDLE;
  204. I2C_BH1750_i2cwrite($hash, BH1750_POWER_DOWN);
  205. $delay and InternalTimer(gettimeofday() + $delay, 'I2C_BH1750_Poll', $hash, 0);
  206. }
  207. sub I2C_BH1750_Poll($)
  208. {
  209. my ($hash) = @_;
  210. my $name = $hash->{NAME};
  211. Log3 $name, 4, "$name I2C_BH1750_Poll ".gettimeofday()." PollState=$hash->{PollState}";
  212. RemoveInternalTimer($hash);
  213. my $delay=$hash->{BASEINTERVAL};
  214. $hash->{PollState} == BH1750_POLLSTATE_IDLE and $hash->{PollState}++;
  215. my $state = $hash->{PollState};
  216. if ($state == BH1750_POLLSTATE_START_MEASURE) {
  217. I2C_BH1750_i2cwrite($hash, BH1750_POWER_ON);
  218. # check in lowest resolution first
  219. $delay = I2C_BH1750_start_measure($hash,BH1750_MT_MIN,BH1750_L_MODE_ONCE);
  220. $hash->{PollState} = BH1750_POLLSTATE_PRE_LUX_WAIT;
  221. } elsif($state == BH1750_POLLSTATE_PRE_LUX_WAIT) {
  222. I2C_BH1750_request_measure($hash);
  223. } elsif($state == BH1750_POLLSTATE_PRE_LUX_DONE) {
  224. my $raw=$hash->{RAWVAL};
  225. if($hash->{RAWVAL} == 0xFFFF) {
  226. $hash->{SATURATED} = 1;
  227. } else {
  228. $hash->{SATURATED} = 0;
  229. }
  230. my $i;
  231. for($i=0; $i<@I2C_BH1750_ranges; $i++) {
  232. $raw <= $I2C_BH1750_ranges[$i][0] and last;
  233. }
  234. if($i == @I2C_BH1750_ranges) {
  235. # no finer resolution possible, no further poll
  236. $hash->{PollState} = BH1750_POLLSTATE_LUX_DONE;
  237. return I2C_BH1750_Poll($hash);
  238. } else {
  239. # do finer reading
  240. my (undef,$mt,$mode)=@{$I2C_BH1750_ranges[$i]};
  241. Log3 $name, 4, "$name I2C_BH1750_Poll using mt=$mt, mode=$mode";
  242. $delay=I2C_BH1750_start_measure($hash,$mt,$mode);
  243. $hash->{PollState} = BH1750_POLLSTATE_LUX_WAIT;
  244. }
  245. } elsif($state == BH1750_POLLSTATE_LUX_WAIT) {
  246. I2C_BH1750_request_measure($hash);
  247. } elsif($state == BH1750_POLLSTATE_LUX_DONE) {
  248. if($hash->{SATURATED}) {
  249. readingsSingleUpdate($hash, 'state', BH1750_STATE_SATURATED, 1);
  250. Log3 $hash, 4, "$name sensor saturated ";
  251. } else {
  252. readingsSingleUpdate($hash, 'state', BH1750_STATE_OK, 1);
  253. }
  254. I2C_BH1750_update_lux($hash);
  255. $hash->{PollState} = BH1750_POLLSTATE_IDLE;
  256. I2C_BH1750_i2cwrite($hash, BH1750_POWER_DOWN);
  257. } else {
  258. Log3 $name, 1, "$name I2C_BH1750_Poll wrong state state=$state";
  259. $hash->{PollState} = BH1750_POLLSTATE_IDLE;
  260. }
  261. $delay and InternalTimer(gettimeofday() + $delay, 'I2C_BH1750_Poll', $hash, 0);
  262. return undef;
  263. }
  264. sub I2C_BH1750_Set($@)
  265. {
  266. my ( $hash, @args ) = @_;
  267. my $name = $hash->{NAME};
  268. my $cmd = $args[1];
  269. if($cmd eq "update") {
  270. RemoveInternalTimer($hash);
  271. $hash->{PollState} = BH1750_POLLSTATE_START_MEASURE;
  272. I2C_BH1750_Poll($hash);
  273. } elsif($cmd eq "deleteminmax") {
  274. delete($hash->{READINGS}{minimum});
  275. delete($hash->{READINGS}{maximum});
  276. } else {
  277. return "Unknown argument ".$cmd.", choose one of update deleteminmax";
  278. }
  279. return undef;
  280. }
  281. sub I2C_BH1750_Undef($$)
  282. {
  283. my ($hash, $arg) = @_;
  284. RemoveInternalTimer($hash);
  285. return undef;
  286. }
  287. sub I2C_BH1750_i2cread($$$)
  288. {
  289. my ($hash, $reg, $nbyte) = @_;
  290. my $name = $hash->{NAME};
  291. Log3 $name, 5, "$name I2C_BH1750_i2cread $reg,$nbyte";
  292. if (defined (my $iodev = $hash->{IODev})) {
  293. eval {
  294. CallFn($iodev->{NAME}, "I2CWrtFn", $iodev,
  295. {
  296. direction => "i2cread",
  297. i2caddress => $hash->{I2C_Address},
  298. reg => $reg,
  299. nbyte => $nbyte
  300. });
  301. };
  302. my $sendStat = $hash->{$iodev->{NAME}.'_SENDSTAT'};
  303. if (defined($sendStat) && $sendStat eq 'error') {
  304. readingsSingleUpdate($hash, 'state', BH1750_STATE_I2C_ERROR, 1);
  305. Log3 ($hash, 3, $hash->{NAME} . ": i2cread on $iodev->{NAME} failed");
  306. return 0;
  307. }
  308. } else {
  309. Log3 ($hash, 1, $hash->{NAME} . ': ' . "no IODev assigned to '$hash->{NAME}'");
  310. return 0;
  311. }
  312. return 1;
  313. }
  314. sub I2C_BH1750_i2cwrite
  315. {
  316. my ($hash, $reg, @data) = @_;
  317. my $name = $hash->{NAME};
  318. Log3 $name, 5, "$name I2C_BH1750_i2write $reg,@data";
  319. if (defined (my $iodev = $hash->{IODev})) {
  320. eval {
  321. CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, {
  322. direction => "i2cwrite",
  323. i2caddress => $hash->{I2C_Address},
  324. reg => $reg,
  325. data => join (' ',@data),
  326. });
  327. };
  328. my $sendStat = $hash->{$iodev->{NAME}.'_SENDSTAT'};
  329. if (defined($sendStat) && $sendStat eq 'error') {
  330. readingsSingleUpdate($hash, 'state', BH1750_STATE_I2C_ERROR, 1);
  331. Log3 ($hash, 3, $hash->{NAME} . ": i2cwrite on $iodev->{NAME} failed");
  332. return 0;
  333. }
  334. } else {
  335. Log3 ($hash, 1, $hash->{NAME} . ': ' . "no IODev assigned to '$hash->{NAME}'");
  336. return 0;
  337. }
  338. return 1;
  339. }
  340. sub I2C_BH1750_I2CRec ($$)
  341. {
  342. my ($hash, $clientmsg) = @_;
  343. my $name = $hash->{NAME};
  344. Log3 $name, 5, "$name I2C_BH1750_i2Rec";
  345. my $pname = undef;
  346. my $phash = $hash->{IODev};
  347. $pname = $phash->{NAME};
  348. while (my ( $k, $v ) = each %$clientmsg) {
  349. $hash->{$k} = $v if $k =~ /^$pname/;
  350. Log3 $name, 5, "$name I2C_BH1750_i2Rec $k $v";
  351. }
  352. if($clientmsg->{$pname . "_SENDSTAT"} ne "Ok") {
  353. Log3 $name, 3, "$name I2C_BH1750_i2Rec bad sendstat: ".$clientmsg->{$pname."_SENDSTAT"};
  354. if($clientmsg->{direction} eq "i2cread" or $clientmsg->{reg}) {
  355. # avoid recoursion on power down, power down has $clientmsg->{reg} == 0
  356. I2C_BH1750_Restart_Measure($hash,$hash->{RESTARTDELAY});
  357. }
  358. return undef;
  359. }
  360. if ( $clientmsg->{direction} eq "i2cread" && defined($clientmsg->{received})) {
  361. my $register = $clientmsg->{reg};
  362. Log3 $hash, 4, "$name RX register $register, $clientmsg->{nbyte} byte: $clientmsg->{received}";
  363. my @raw = split(" ", $clientmsg->{received});
  364. if ($register == BH1750_RAW_VALUE && $clientmsg->{nbyte} == 2) {
  365. my $word = $raw[0] << 8 | $raw[1];
  366. $hash->{RAWVAL}=$word;
  367. Log3 $name, 4, "$name I2C_BH1750_I2CRec: rawval=$word";
  368. if($hash->{PollState} == BH1750_POLLSTATE_PRE_LUX_WAIT ||
  369. $hash->{PollState} == BH1750_POLLSTATE_LUX_WAIT) {
  370. $hash->{PollState}++;
  371. I2C_BH1750_Poll($hash);
  372. }
  373. }
  374. }
  375. return undef;
  376. }
  377. sub I2C_BH1750_update_lux
  378. {
  379. my($hash)=@_;
  380. my $name=$hash->{NAME};
  381. my $lux;
  382. my $delta=$hash->{DELTA};
  383. # lux calculation see manual manual:
  384. $lux = $hash->{RAWVAL}/1.2*(69/$hash->{MT_VAL})/$hash->{MODE};
  385. $lux *= $hash->{CORRECTION};
  386. if($delta) { # update only if delta large enough
  387. my $lastlux=ReadingsNum($name,"luminosity",1000000);
  388. $lux == $lastlux and return; # no delta, no update
  389. # check if we have too less delta and return
  390. if($lastlux > $lux) {
  391. ($lastlux-$lastlux*$delta < $lux) and return;
  392. } else {
  393. ($lastlux+$lastlux*$delta > $lux) and return;
  394. }
  395. }
  396. # round value
  397. if($lux < 100) {
  398. $lux = int($lux*10+0.5)/10;
  399. } elsif($lux < 1000) {
  400. $lux=int($lux+0.5);
  401. } elsif($lux < 10000) {
  402. $lux=int($lux/10+0.5); $lux *= 10;
  403. } elsif($lux < 100000) {
  404. $lux=int($lux/100+0.5); $lux *= 100;
  405. } else {
  406. $lux=int($lux/1000+0.5); $lux *= 1000;
  407. }
  408. Log3 $name, 4, "$name I2C_BH1750_update_lux: luminosity=$lux";
  409. readingsBeginUpdate($hash);
  410. readingsBulkUpdate($hash, "luminosity", $lux);
  411. $lux < ReadingsNum($name,"minimum", 1000000) and readingsBulkUpdate($hash, "minimum", $lux);
  412. $lux > ReadingsNum($name,"maximum",-1000000) and readingsBulkUpdate($hash, "maximum", $lux);
  413. readingsEndUpdate($hash, 1);
  414. }
  415. sub I2C_BH1750_request_measure
  416. {
  417. my ($hash) = @_;
  418. I2C_BH1750_i2cread($hash,BH1750_RAW_VALUE,2);
  419. }
  420. sub I2C_BH1750_start_measure
  421. {
  422. my ($hash,$mt,$mode)=@_;
  423. my $name = $hash->{NAME};
  424. $hash->{MT_VAL} = $mt;
  425. $hash->{MODE} = ($mode == BH1750_H_MODE2 || $mode == BH1750_H_MODE2_ONCE) ? 2 : 1;
  426. my $hi=($mt>>5) | 0x40;
  427. my $lo=($mt&0x1F) | 0x60;
  428. I2C_BH1750_i2cwrite($hash,BH1750_RESET);
  429. I2C_BH1750_i2cwrite($hash,$hi); # set MT value
  430. I2C_BH1750_i2cwrite($hash,$lo);
  431. I2C_BH1750_i2cwrite($hash,$mode);
  432. my $mindelay = ($mode == BH1750_L_MODE || $mode == BH1750_L_MODE_ONCE) ? 24 : 180;
  433. $mindelay = $mindelay * ($mt/BH1750_MT_DEFAULT);
  434. Log3 $name, 5, "$name I2C_BH1750_start_measure: duration ".int($mindelay)."ms";
  435. $mindelay /=1000; # seconds
  436. return $mindelay;
  437. }
  438. sub I2C_BH1750_sleep
  439. {
  440. select(undef, undef, undef, $_[0]);
  441. }
  442. 1;
  443. =pod
  444. =item device
  445. =item summary support for the BH1750 I2C light sensor
  446. =item summary_DE Unterst&uuml;tzung f&uuml;r den BH1750 I2C Lichtsensor
  447. =begin html
  448. <a name="I2C_BH1750"></a>
  449. <h3>I2C_BH1750</h3>
  450. <ul>
  451. <a name="I2C_BH1750"></a>
  452. <p>
  453. Module for the I<sup>2</sup>C BH1750 light sensor.
  454. The BH1750 sensor supports a luminous flux from 0 up to 120k lx
  455. and a resolution up to 0.11lx.
  456. It supports different modes to be able to cover this large range of
  457. data. <br>
  458. The I2C_BH1750 module tries always to get
  459. the luminosity data from the sensor as good as possible. To achieve
  460. this the module first reads flux data in the least sensitive mode and then
  461. decides which mode to take to get best results.
  462. <br><br>
  463. For the I<sup>2</sup>C bus the same things are valid as described in the
  464. <a href="#I2C_TSL2561">I2C_TSL2561</a> &nbsp;
  465. module.<br>
  466. <b>Define</b>
  467. <ul>
  468. <code>define BH1750 I2C_BH1750 [I2C address]</code><br><br>
  469. I2C address must be 0x23 or 0x5C (if omitted default address 0x23 is used)
  470. <br>
  471. Examples:
  472. <pre>
  473. # define IO-Module:
  474. define I2C_2 RPII2C 2
  475. # Use IODev I2C_2 with default i2c address 0x23
  476. # set poll interval to 1 min
  477. # generate luminosity value only if difference to last value is at least 10%
  478. define BH1750 I2C_BH1750
  479. attr BH1750 IODev I2C_2
  480. attr BH1750 poll_interval 1
  481. attr BH1750 percentdelta 10
  482. </pre>
  483. </ul>
  484. <b>Set</b>
  485. <ul>
  486. <li><code>set &lt;device name&gt; update</code><br>
  487. Force immediate illumination measurement and restart a
  488. new poll_interval.
  489. Note that the new readings are not yet available after set returns
  490. because the
  491. measurement is performed asynchronously. Depending on the flux value
  492. this may require more than one second to complete.<br>
  493. </li>
  494. <li><code>set &lt;device name&gt; deleteminmax</code><br>
  495. Delete the minimum maximum readings to start new
  496. min/max measurement
  497. </li>
  498. </ul>
  499. <p>
  500. <b>Readings</b>
  501. <ul>
  502. <li>luminosity<br>
  503. Illumination measurement in the range of 0 to 121557 lx.<br>
  504. The generated luminosity value is stored with up to one
  505. fractional digit for values below 100 and
  506. rounded to 3 significant digits for all other values.
  507. Compared with the accuracy of the sensor it makes no
  508. sense to store the values with more precision.
  509. </li>
  510. <li>minimum<br>
  511. minimum of measured luminosity
  512. </li>
  513. <li>maximum<br>
  514. maximum of measured luminosity
  515. </li>
  516. <li>state<br>
  517. Default: Defined, Ok, Saturated, I2C Error
  518. </li>
  519. </ul>
  520. <p>
  521. <a name="I2C_BH1750attr"></a>
  522. <b>Attributes</b>
  523. <ul>
  524. <li>IODev<br>
  525. Set the name of an IODev module like RPII2C<br>
  526. Default: undefined<br>
  527. </li>
  528. <li>poll_interval<br>
  529. Set the polling interval in minutes to query the sensor for new measured values.
  530. By changing this attribute a new illumination measurement will be triggered.<br>
  531. valid values: 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 30, 60<br>
  532. </li>
  533. <li>percentdelta<br>
  534. If set a luminosity reading is only generated if
  535. the difference between the current luminosity value and the last reading is
  536. at least percentdelta percents.<br>
  537. </li>
  538. <li>correction<br>
  539. Linear correction factor to be applied to the sensor value.
  540. Compared with a commercial light meter it seems that the values for my
  541. BH1750 are about 25% to low in day light (correction 1.25).
  542. The TLS2561 compares much better with the light meter but has the disadvantage
  543. that it saturates at about 40k lux.<br>
  544. The correction factor can also be used if your sensor is behind an opal glass.<br>
  545. valid range: 0.5 to 2.0<br>
  546. </li>
  547. </ul>
  548. <p>
  549. <br>
  550. </ul>
  551. =end html
  552. =cut