Skip to content

Commit dba9600

Browse files
committed
Merge branch 'mlx90614' of https://github.com/rahul31124/pslab-android into mlx90614
2 parents 6c7f3f9 + 9ded205 commit dba9600

7 files changed

Lines changed: 634 additions & 13 deletions

File tree

assets/images/ccs811.jpg

81.4 KB
Loading
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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 CCS811 {
7+
static const String tag = "CCS811";
8+
static const int address = 0x5A;
9+
10+
static const int algResultData = 0x02;
11+
static const int hwId = 0x20;
12+
static const int fwBootVersion = 0x23;
13+
static const int fwAppVersion = 0x24;
14+
static const int measMode = 0x01;
15+
static const int hwVersion = 0x21;
16+
static const int appStart = 0xF4;
17+
18+
static const int driveMode1Sec = 0x01;
19+
20+
final I2C i2c;
21+
22+
CCS811._(this.i2c);
23+
24+
static Future<CCS811> create(I2C i2c, ScienceLab scienceLab) async {
25+
final ccs811 = CCS811._(i2c);
26+
if (scienceLab.isConnected()) {
27+
await ccs811._initialize();
28+
}
29+
return ccs811;
30+
}
31+
32+
Future<void> _initialize() async {
33+
try {
34+
await _fetchID();
35+
await _appStart();
36+
await Future.delayed(const Duration(milliseconds: 100));
37+
await _disableInterrupt();
38+
await _setMeasMode();
39+
} catch (e) {
40+
logger.e("$tag Error initializing: $e");
41+
rethrow;
42+
}
43+
}
44+
45+
Future<void> _setMeasMode() async {
46+
int config = (1 << 2) | (driveMode1Sec << 4);
47+
await i2c.write(address, [config], measMode);
48+
}
49+
50+
Future<void> _disableInterrupt() async {
51+
int config = (1 << 2) | (3 << 4);
52+
await i2c.write(address, [config], measMode);
53+
}
54+
55+
Future<void> _fetchID() async {
56+
try {
57+
List<int> hwIdData = await i2c.readBulk(address, hwId, 1);
58+
await Future.delayed(const Duration(milliseconds: 20));
59+
60+
List<int> hwVerData = await i2c.readBulk(address, hwVersion, 1);
61+
await Future.delayed(const Duration(milliseconds: 20));
62+
63+
List<int> bootVerData = await i2c.readBulk(address, fwBootVersion, 2);
64+
await Future.delayed(const Duration(milliseconds: 20));
65+
66+
List<int> appVerData = await i2c.readBulk(address, fwAppVersion, 2);
67+
await Future.delayed(const Duration(milliseconds: 20));
68+
69+
if (hwIdData.isNotEmpty) {
70+
logger.d("$tag Hardware ID: ${hwIdData[0] & 0xFF}");
71+
}
72+
if (hwVerData.isNotEmpty) {
73+
logger.d("$tag Hardware Version: ${hwVerData[0] & 0xFF}");
74+
}
75+
if (bootVerData.length >= 2) {
76+
logger
77+
.d("$tag Boot Version: ${(bootVerData[0] << 8) | bootVerData[1]}");
78+
}
79+
if (appVerData.length >= 2) {
80+
logger.d("$tag App Version: ${(appVerData[0] << 8) | appVerData[1]}");
81+
}
82+
} catch (e) {
83+
logger.e("$tag Error fetching IDs: $e");
84+
}
85+
}
86+
87+
Future<void> _appStart() async {
88+
await i2c.write(address, [], appStart);
89+
}
90+
91+
String _decodeError(int error) {
92+
String e = "";
93+
if ((error & 1) > 0) e += ", Invalid register address ID";
94+
if ((error & (1 << 1)) > 0) e += ", Invalid mailbox ID";
95+
if ((error & (1 << 2)) > 0) e += ", Unsupported mode to MEAS_MODE";
96+
if ((error & (1 << 3)) > 0) {
97+
e += ", Resistance measurement max range reached";
98+
}
99+
if ((error & (1 << 4)) > 0) e += ", Heater current out of range";
100+
if ((error & (1 << 5)) > 0) e += ", Heater voltage applied incorrectly";
101+
102+
return e.isNotEmpty ? "Error: ${e.substring(2)}" : "Unknown error";
103+
}
104+
105+
Future<Map<String, int>> getRawData() async {
106+
try {
107+
List<int> data = await i2c.readBulk(address, algResultData, 8);
108+
if (data.length < 8) {
109+
throw Exception("Expected 8 bytes but got ${data.length}");
110+
}
111+
112+
int eCO2 = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
113+
int tvoc = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
114+
int errorId = data[5] & 0xFF;
115+
116+
if (errorId > 0) {
117+
logger.e("$tag ${_decodeError(errorId)}");
118+
}
119+
120+
return {
121+
'eCO2': eCO2,
122+
'TVOC': tvoc,
123+
};
124+
} catch (e) {
125+
logger.e("$tag Error getting raw data: $e");
126+
rethrow;
127+
}
128+
}
129+
}

lib/l10n/app_en.arb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,5 +766,11 @@
766766
"gauss" : "Gauss",
767767
"mlx90614" : "MLX90614",
768768
"objectTemperature" : "Object Temp",
769-
"ambientTemperature" : "Ambient Temp"
769+
"ambientTemperature" : "Ambient Temp",
770+
"i2cError" : "Check I2C wiring.",
771+
"ccs811" : "CCS811",
772+
"eco2" : "eCO2",
773+
"tvoc" : "TVOC",
774+
"ppb" : "ppb",
775+
"concentrationPpm" : "Concentration (PPM)"
770776
}

lib/providers/barometer_state_provider.dart

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class BarometerStateProvider extends ChangeNotifier {
4444
bool get isRecording => _isRecording;
4545
bool get isPlayingBack => _isPlayingBack;
4646
bool get isPlaybackPaused => _isPlaybackPaused;
47+
int? _playbackStartTimestamp;
4748

4849
StreamSubscription? _barometerSubscription;
4950

@@ -60,10 +61,12 @@ class BarometerStateProvider extends ChangeNotifier {
6061

6162
Position? currentPosition;
6263
StreamSubscription? _locationStream;
64+
int _currentUpdatePeriod = 1000;
6365

6466
BarometerStateProvider(this._configProvider) {
6567
_configProvider.addListener(_onConfigChanged);
6668
_currentSensorType = _configProvider.config.activeSensor;
69+
_currentUpdatePeriod = _configProvider.config.updatePeriod;
6770
}
6871

6972
Future<void> _startGeoLocationUpdates() async {
@@ -101,11 +104,16 @@ class BarometerStateProvider extends ChangeNotifier {
101104
}
102105

103106
void _onConfigChanged() {
107+
if (_isPlayingBack) return;
108+
104109
final newSensorType = _configProvider.config.activeSensor;
105-
if (_currentSensorType != newSensorType) {
106-
logger
107-
.d("Sensor type changed from $_currentSensorType to $newSensorType");
110+
final newUpdatePeriod = _configProvider.config.updatePeriod;
111+
112+
if (_currentSensorType != newSensorType ||
113+
_currentUpdatePeriod != newUpdatePeriod) {
108114
_currentSensorType = newSensorType;
115+
_currentUpdatePeriod = newUpdatePeriod;
116+
109117
_reinitializeSensors();
110118
}
111119
}
@@ -141,14 +149,16 @@ class BarometerStateProvider extends ChangeNotifier {
141149

142150
try {
143151
_startTime = DateTime.now().millisecondsSinceEpoch / 1000.0;
144-
_timeTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
145-
_currentTime =
146-
(DateTime.now().millisecondsSinceEpoch / 1000.0) - _startTime;
147-
if (_sensorAvailable) {
152+
_timeTimer = Timer.periodic(
153+
Duration(milliseconds: _currentUpdatePeriod),
154+
(timer) {
155+
_currentTime =
156+
(DateTime.now().millisecondsSinceEpoch / 1000.0) - _startTime;
157+
148158
_updateData();
149-
}
150-
notifyListeners();
151-
});
159+
notifyListeners();
160+
},
161+
);
152162

153163
if (_currentSensorType == 'In-built Sensor') {
154164
_initializeBuiltInSensor();
@@ -286,7 +296,8 @@ class BarometerStateProvider extends ChangeNotifier {
286296
}
287297

288298
void startPlayback(List<List<dynamic>> data) {
289-
if (data.length <= 1) return;
299+
if (data.length <= 2) return;
300+
_playbackStartTimestamp = int.tryParse(data[2][0].toString())?.toInt();
290301

291302
_isPlayingBack = true;
292303
_isPlaybackPaused = false;
@@ -320,7 +331,10 @@ class BarometerStateProvider extends ChangeNotifier {
320331
if (currentRow.length > 3) {
321332
_currentAltitude = double.tryParse(currentRow[3].toString());
322333
}
323-
_currentTime = (_playbackIndex - 1).toDouble();
334+
final timestamp = int.tryParse(currentRow[0].toString())?.toInt();
335+
if (timestamp != null && _playbackStartTimestamp != null) {
336+
_currentTime = (timestamp - _playbackStartTimestamp!) / 1000.0;
337+
}
324338
_updateData();
325339
_playbackIndex++;
326340
notifyListeners();
@@ -364,6 +378,7 @@ class BarometerStateProvider extends ChangeNotifier {
364378
Future<void> stopPlayback() async {
365379
_isPlayingBack = false;
366380
_isPlaybackPaused = false;
381+
_playbackStartTimestamp = null;
367382
_playbackTimer?.cancel();
368383
_playbackData = null;
369384
_playbackIndex = 0;

0 commit comments

Comments
 (0)