Skip to content

Commit d15d6ff

Browse files
feat: added sensors bh1750 & tsl2561 to complete Luxmeter (#2918)
Co-authored-by: Mario Behling <[email protected]>
1 parent 589775f commit d15d6ff

File tree

5 files changed

+399
-35
lines changed

5 files changed

+399
-35
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import 'package:pslab/communication/peripherals/i2c.dart';
2+
3+
class BH1750 {
4+
final String tag = "BH1750";
5+
6+
final int powerOn = 0x01;
7+
final int reset = 0x07;
8+
final int res1000mLx = 0x10;
9+
final int res500mLx = 0x11;
10+
final int res4000mLx = 0x13;
11+
12+
final I2C i2c;
13+
14+
final List<int> gainChoices = [0x11, 0x10, 0x13];
15+
final List<String> gainLiteralChoices = ["500mLx", "1000mLx", "4000mLx"];
16+
int gain = 0;
17+
final List<double> scaling = [2, 1, 0.25];
18+
19+
static const int numPlots = 1;
20+
static const List<String> plotNames = ["Lux"];
21+
final int address = 0x23;
22+
final String name = "Luminosity";
23+
24+
BH1750(this.i2c) {
25+
init();
26+
}
27+
28+
void init() {
29+
i2c.writeBulk(address, [res500mLx]);
30+
}
31+
32+
void setRange(String g) {
33+
int gainIndex = gainLiteralChoices.indexOf(g);
34+
if (gainIndex >= 0) {
35+
i2c.writeBulk(address, [gainChoices[gainIndex]]);
36+
}
37+
}
38+
39+
Future<List<int>> getVals(int numBytes) async {
40+
return await i2c.simpleRead(address, numBytes);
41+
}
42+
43+
Future<double> getRaw() async {
44+
List<int> vals = await getVals(2);
45+
if (vals.length == 3) {
46+
return ((vals[0] << 8) | vals[1]) / 1.2;
47+
} else {
48+
return 0.0;
49+
}
50+
}
51+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import 'dart:async';
2+
import 'package:pslab/communication/peripherals/i2c.dart';
3+
import 'package:pslab/communication/science_lab.dart';
4+
import 'package:pslab/others/logger_service.dart';
5+
6+
class TSL2561 {
7+
static const String tag = "TSL2561";
8+
9+
static const int commandBit = 0x80;
10+
static const int wordBit = 0x20;
11+
12+
static const int controlPowerOn = 0x03;
13+
static const int controlPowerOff = 0x00;
14+
15+
static const int registerControl = 0x00;
16+
static const int registerTiming = 0x01;
17+
static const int registerId = 0x0A;
18+
static const int registerChan0Low = 0x0C;
19+
static const int registerChan1Low = 0x0E;
20+
21+
static const int integrationTime13ms = 0x00;
22+
static const int integrationTime101ms = 0x01;
23+
static const int integrationTime402ms = 0x02;
24+
25+
static const int gain0x = 0x00;
26+
static const int gain16x = 0x10;
27+
28+
static const List<int> addresses = [0x39, 0x29, 0x49];
29+
30+
final I2C i2c;
31+
int address = 0x39;
32+
int timing = integrationTime13ms;
33+
int gain = gain16x;
34+
35+
TSL2561(this.i2c, ScienceLab scienceLab) {
36+
() async {
37+
if (scienceLab.isConnected()) {
38+
for (final addr in addresses) {
39+
address = addr;
40+
await disable();
41+
logger.d("$tag: Checking address 0x${address.toRadixString(16)}");
42+
try {
43+
int id = await i2c.readByte(address, registerId);
44+
if (id != 0xffffffff && (id & 0x0A) == 0x0A) {
45+
logger.d("$tag: TSL2561 found!");
46+
break;
47+
} else {
48+
logger.d("$tag: TSL2561 not found.");
49+
}
50+
} catch (e) {
51+
logger.e("$tag: Error reading ID: $e");
52+
}
53+
}
54+
await enable();
55+
await _wait();
56+
await i2c
57+
.writeBulk(address, [commandBit | registerTiming, timing | gain]);
58+
}
59+
}();
60+
}
61+
62+
Future<int> getID() async {
63+
try {
64+
List<int> idList = await i2c.readBulk(address, registerId, 1);
65+
if (idList.isEmpty) return -1;
66+
int id = int.parse(idList[0].toRadixString(16), radix: 16);
67+
logger.d("$tag: ID: $id");
68+
return id;
69+
} catch (e) {
70+
logger.e("$tag: Error getting ID: $e");
71+
rethrow;
72+
}
73+
}
74+
75+
Future<double?> getRaw() async {
76+
try {
77+
List<int> infraList = await i2c.readBulk(
78+
address, commandBit | wordBit | registerChan1Low, 2);
79+
List<int> fullList = await i2c.readBulk(
80+
address, commandBit | wordBit | registerChan0Low, 2);
81+
82+
if (infraList.isNotEmpty && fullList.isNotEmpty) {
83+
int full = ((fullList[1] & 0xff) << 8) | (fullList[0] & 0xff);
84+
int infra = ((infraList[1] & 0xff) << 8) | (infraList[0] & 0xff);
85+
return (full - infra).toDouble();
86+
} else {
87+
return 0.0;
88+
}
89+
} catch (e) {
90+
logger.e("$tag: Error reading raw values: $e");
91+
return 0.0;
92+
}
93+
}
94+
95+
Future<void> setGain(int gainValue) async {
96+
switch (gainValue) {
97+
case 1:
98+
gain = gain0x;
99+
break;
100+
case 16:
101+
gain = gain16x;
102+
break;
103+
default:
104+
gain = gain16x;
105+
}
106+
await i2c.writeBulk(address, [commandBit | registerTiming, gain | timing]);
107+
}
108+
109+
Future<void> enable() async {
110+
await i2c
111+
.writeBulk(address, [commandBit | registerControl, controlPowerOn]);
112+
}
113+
114+
Future<void> disable() async {
115+
await i2c
116+
.writeBulk(address, [commandBit | registerControl, controlPowerOff]);
117+
}
118+
119+
Future<void> _wait() async {
120+
switch (timing) {
121+
case integrationTime13ms:
122+
await Future.delayed(const Duration(milliseconds: 14));
123+
break;
124+
case integrationTime101ms:
125+
await Future.delayed(const Duration(milliseconds: 102));
126+
break;
127+
case integrationTime402ms:
128+
default:
129+
await Future.delayed(const Duration(milliseconds: 403));
130+
break;
131+
}
132+
}
133+
}

lib/providers/luxmeter_config_provider.dart

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
22
import 'dart:convert';
33
import 'package:shared_preferences/shared_preferences.dart';
44
import 'package:pslab/models/luxmeter_config.dart';
5+
import 'package:pslab/others/logger_service.dart';
56

67
class LuxMeterConfigProvider extends ChangeNotifier {
78
LuxMeterConfig _config = const LuxMeterConfig();
@@ -13,18 +14,30 @@ class LuxMeterConfigProvider extends ChangeNotifier {
1314
}
1415

1516
Future<void> _loadConfigFromPrefs() async {
16-
final prefs = await SharedPreferences.getInstance();
17-
final jsonString = prefs.getString('lux_config');
18-
if (jsonString != null) {
19-
final Map<String, dynamic> jsonMap = json.decode(jsonString);
20-
_config = LuxMeterConfig.fromJson(jsonMap);
17+
try {
18+
final prefs = await SharedPreferences.getInstance();
19+
final jsonString = prefs.getString('lux_config');
20+
if (jsonString != null) {
21+
final Map<String, dynamic> jsonMap = json.decode(jsonString);
22+
_config = LuxMeterConfig.fromJson(jsonMap);
23+
logger.d("Loaded LuxMeterConfig: ${_config.toJson()}");
24+
notifyListeners();
25+
}
26+
} catch (e) {
27+
logger.e("Error loading LuxMeterConfig from prefs: $e");
28+
_config = const LuxMeterConfig();
2129
notifyListeners();
2230
}
2331
}
2432

2533
Future<void> _saveConfigToPrefs() async {
26-
final prefs = await SharedPreferences.getInstance();
27-
await prefs.setString('lux_config', json.encode(_config.toJson()));
34+
try {
35+
final prefs = await SharedPreferences.getInstance();
36+
await prefs.setString('lux_config', json.encode(_config.toJson()));
37+
logger.d("Saved LuxMeterConfig: ${_config.toJson()}");
38+
} catch (e) {
39+
logger.e("Error saving LuxMeterConfig to prefs: $e");
40+
}
2841
}
2942

3043
void updateConfig(LuxMeterConfig newConfig) {
@@ -46,6 +59,11 @@ class LuxMeterConfigProvider extends ChangeNotifier {
4659
}
4760

4861
void updateActiveSensor(String activeSensor) {
62+
if (activeSensor != "In-built Sensor" &&
63+
activeSensor != "BH1750" &&
64+
activeSensor != "TSL2561") {
65+
activeSensor = "In-built Sensor";
66+
}
4967
_config = _config.copyWith(activeSensor: activeSensor);
5068
notifyListeners();
5169
_saveConfigToPrefs();

0 commit comments

Comments
 (0)