Skip to content

Commit 6592393

Browse files
feat: integrated bmp180 sensor in barometer instrument (#2806)
1 parent 43af902 commit 6592393

File tree

4 files changed

+688
-68
lines changed

4 files changed

+688
-68
lines changed

lib/communication/sensors/bmp180.dart

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
import 'dart:math';
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+
import '../../l10n/app_localizations.dart';
7+
import '../../providers/locator.dart';
8+
9+
class BMP180 {
10+
AppLocalizations appLocalizations = getIt.get<AppLocalizations>();
11+
12+
static const String tag = "BMP180";
13+
14+
static const int address = 0x77;
15+
16+
static const int ultraLowPower = 0;
17+
static const int standard = 1;
18+
static const int highRes = 2;
19+
static const int ultraHighRes = 3;
20+
21+
static const int calAC1 = 0xAA;
22+
static const int calAC2 = 0xAC;
23+
static const int calAC3 = 0xAE;
24+
static const int calAC4 = 0xB0;
25+
static const int calAC5 = 0xB2;
26+
static const int calAC6 = 0xB4;
27+
static const int calB1 = 0xB6;
28+
static const int calB2 = 0xB8;
29+
static const int calMB = 0xBA;
30+
static const int calMC = 0xBC;
31+
static const int calMD = 0xBE;
32+
static const int control = 0xF4;
33+
static const int tempData = 0xF6;
34+
static const int pressData = 0xF6;
35+
36+
static const int readTempCmd = 0x2E;
37+
static const int readPressureCmd = 0x34;
38+
39+
int mode = highRes;
40+
int oversampling = highRes;
41+
42+
static const int numPlots = 3;
43+
static const List<String> plotNames = ["Temperature", "Pressure", "Altitude"];
44+
static const String name = "Altimeter BMP180";
45+
46+
final I2C i2c;
47+
late int ac1, ac2, ac3, ac4, ac5, ac6, b1, b2, mb, mc, md;
48+
double temperature = 0.0;
49+
double pressure = 0.0;
50+
51+
static const double seaLevelPressure = 101325.0;
52+
53+
BMP180._(this.i2c);
54+
bool _validateCalibrationValues() {
55+
if (ac1 == 0 || ac2 == 0 || ac3 == 0 || ac4 == 0 || ac5 == 0 || ac6 == 0) {
56+
return false;
57+
}
58+
if (ac1 < -32768 || ac1 > 32767) return false;
59+
if (ac2 < -32768 || ac2 > 32767) return false;
60+
if (ac3 < -32768 || ac3 > 32767) return false;
61+
if (ac4 < 0 || ac4 > 65535) return false;
62+
if (ac5 < 0 || ac5 > 65535) return false;
63+
if (ac6 < 0 || ac6 > 65535) return false;
64+
if (b1 < -32768 || b1 > 32767) return false;
65+
if (b2 < -32768 || b2 > 32767) return false;
66+
if (mb < -32768 || mb > 32767) return false;
67+
if (mc < -32768 || mc > 32767) return false;
68+
if (md < -32768 || md > 32767) return false;
69+
return true;
70+
}
71+
72+
static Future<BMP180> create(I2C i2c, ScienceLab scienceLab) async {
73+
final bmp180 = BMP180._(i2c);
74+
await bmp180._initializeCalibrationValues(scienceLab);
75+
if (!bmp180._validateCalibrationValues()) {
76+
throw Exception('BMP180 calibration values are invalid or out of range.');
77+
}
78+
return bmp180;
79+
}
80+
81+
Future<void> _initializeCalibrationValues(ScienceLab scienceLab) async {
82+
if (!scienceLab.isConnected()) {
83+
throw Exception("ScienceLab not connected");
84+
}
85+
86+
try {
87+
ac1 = await readInt16(calAC1);
88+
ac2 = await readInt16(calAC2);
89+
ac3 = await readInt16(calAC3);
90+
ac4 = await readUInt16(calAC4);
91+
ac5 = await readUInt16(calAC5);
92+
ac6 = await readUInt16(calAC6);
93+
b1 = await readInt16(calB1);
94+
b2 = await readInt16(calB2);
95+
mb = await readInt16(calMB);
96+
mc = await readInt16(calMC);
97+
md = await readInt16(calMD);
98+
99+
logger.d(
100+
"Calibration values: [$ac1, $ac2, $ac3, $ac4, $ac5, $ac6, $b1, $b2, $mb, $mc, $md]");
101+
} catch (e) {
102+
logger.e("Error initializing BMP180 calibration values: $e");
103+
rethrow;
104+
}
105+
}
106+
107+
Future<int> readInt16(int registerAddress) async {
108+
try {
109+
List<int> data = await i2c.readBulk(address, registerAddress, 2);
110+
if (data.length < 2) {
111+
throw Exception(
112+
"Expected 2 bytes but got ${data.length} from register $registerAddress");
113+
}
114+
int value = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
115+
if (value >= 0x8000) value -= 0x10000;
116+
return value;
117+
} catch (e) {
118+
logger.e("Error reading int16 from register $registerAddress: $e");
119+
rethrow;
120+
}
121+
}
122+
123+
Future<int> readUInt16(int registerAddress) async {
124+
try {
125+
List<int> data = await i2c.readBulk(address, registerAddress, 2);
126+
if (data.length < 2) {
127+
throw Exception(
128+
"Expected 2 bytes but got ${data.length} from register $registerAddress");
129+
}
130+
return ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
131+
} catch (e) {
132+
logger.e("Error reading uint16 from register $registerAddress: $e");
133+
rethrow;
134+
}
135+
}
136+
137+
Future<int> readRawTemperature() async {
138+
try {
139+
await i2c.write(address, [readTempCmd], control);
140+
await Future.delayed(const Duration(milliseconds: 5));
141+
int raw = await readUInt16(tempData);
142+
return raw;
143+
} catch (e) {
144+
logger.e("Error reading raw temperature: $e");
145+
rethrow;
146+
}
147+
}
148+
149+
Future<double> readTemperature({int? rawTemp}) async {
150+
try {
151+
int ut = rawTemp ?? await readRawTemperature();
152+
153+
int x1 = ((ut - ac6) * ac5) >> 15;
154+
int x2 = (mc << 11) ~/ (x1 + md);
155+
int b5 = x1 + x2;
156+
temperature = ((b5 + 8) >> 4) / 10.0;
157+
158+
return temperature;
159+
} catch (e) {
160+
logger.e("Error reading temperature: $e");
161+
rethrow;
162+
}
163+
}
164+
165+
void setOversampling(int num) {
166+
oversampling = num;
167+
}
168+
169+
Future<int> readRawPressure() async {
170+
try {
171+
List<int> delays = [5, 8, 14, 26];
172+
int safeOversampling = oversampling.clamp(0, 3);
173+
await i2c.write(address, [readPressureCmd + (mode << 6)], control);
174+
await Future.delayed(Duration(milliseconds: delays[safeOversampling]));
175+
176+
List<int> data = await i2c.readBulk(address, pressData, 3);
177+
if (data.length < 3) {
178+
throw Exception(
179+
"Expected 3 bytes but got ${data.length} from pressure data");
180+
}
181+
int msb = data[0] & 0xFF;
182+
int lsb = data[1] & 0xFF;
183+
int xlsb = data[2] & 0xFF;
184+
185+
return ((msb << 16) + (lsb << 8) + xlsb) >> (8 - mode);
186+
} catch (e) {
187+
logger.e("Error reading raw pressure: $e");
188+
rethrow;
189+
}
190+
}
191+
192+
Future<double> readPressure({int? rawTemp}) async {
193+
try {
194+
int ut = rawTemp ?? await readRawTemperature();
195+
int up = await readRawPressure();
196+
197+
int x1 = ((ut - ac6) * ac5) >> 15;
198+
int x2 = (mc << 11) ~/ (x1 + md);
199+
int b5 = x1 + x2;
200+
201+
int b6 = b5 - 4000;
202+
x1 = (b2 * (b6 * b6) >> 12) >> 11;
203+
x2 = (ac2 * b6) >> 11;
204+
int x3 = x1 + x2;
205+
int b3 = (((ac1 * 4 + x3) << mode) + 2) ~/ 4;
206+
207+
x1 = (ac3 * b6) >> 13;
208+
x2 = (b1 * ((b6 * b6) >> 12)) >> 16;
209+
x3 = ((x1 + x2) + 2) >> 2;
210+
int b4 = (ac4 * (x3 + 32768)) >> 15;
211+
int b7 = (up - b3) * (50000 >> mode);
212+
213+
int p;
214+
if (b7 < 0x80000000) {
215+
p = (b7 * 2) ~/ b4;
216+
} else {
217+
p = (b7 ~/ b4) * 2;
218+
}
219+
220+
x1 = (p >> 8) * (p >> 8);
221+
x1 = (x1 * 3038) >> 16;
222+
x2 = (-7357 * p) >> 16;
223+
pressure = (p + ((x1 + x2 + 3791) >> 4)).toDouble();
224+
225+
return pressure;
226+
} catch (e) {
227+
logger.e("Error reading pressure: $e");
228+
rethrow;
229+
}
230+
}
231+
232+
double altitude() {
233+
return 44330.0 * (1 - pow(pressure / seaLevelPressure, 1 / 5.255));
234+
}
235+
236+
double seaLevel(double pressure, double altitude) {
237+
return pressure / pow(1 - (altitude / 44330.0), 5.255);
238+
}
239+
240+
Future<Map<String, double>> getRawData() async {
241+
try {
242+
int rawTemp = await readRawTemperature();
243+
temperature = await readTemperature(rawTemp: rawTemp);
244+
pressure = await readPressure(rawTemp: rawTemp);
245+
double alt = altitude();
246+
247+
return {
248+
'temperature': temperature,
249+
'pressure': pressure,
250+
'altitude': alt,
251+
};
252+
} catch (e) {
253+
logger.e("Error getting raw data: $e");
254+
rethrow;
255+
}
256+
}
257+
}

lib/l10n/app_localizations_en.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,7 @@ class AppLocalizationsEn extends AppLocalizations {
10841084
@override
10851085
String get fileDeleted => 'File deleted';
10861086

1087+
@override
10871088
String get soundmeterConfig => 'Soundmeter Configurations';
10881089

10891090
@override

0 commit comments

Comments
 (0)