Source code for PyExpLabSys.drivers.ccs811
""" Driver for CCS811 enviromental sensor """
import smbus
import time
[docs]class CCS811(object):
"""
Class for reading approximate values of eCO2 TVOC
from a CC811 environmental sensor
"""
[docs] def __init__(self):
self.bus = smbus.SMBus(1)
self.device_address = 0x5A
self.status = {}
self.status['error'] = []
self.data = {
'eCO2': -1,
'TVOC': -1,
'current': -1,
'voltage': -1,
'resistance': -1,
}
if not self.verify_id():
raise Exception('Not an CCS811!')
self._activate() # Todo, check for True
self._set_drive_mode()
def _activate(self):
""" Take the device out of firmware update mode """
self.bus.write_byte(self.device_address, 0xF4)
meas_mode = self.bus.read_byte_data(self.device_address, 0x01)
return meas_mode == 0
def _set_drive_mode(self):
"""
Set the sensor MEAS_MODE
This could be done more sofisticated, but basically
the preffered mode is always mode 1 (read once pr second)
"""
self.bus.write_byte_data(self.device_address, 0x01, 0x00)
time.sleep(1)
meas_mode = self.bus.read_byte_data(self.device_address, 0x01)
self.bus.write_byte_data(self.device_address, 0x01, 0x18)
return None
[docs] def hw_version(self):
""" Read hardware version """
hw_version = self.bus.read_byte_data(self.device_address, 0x21)
return hex(hw_version)
[docs] def verify_id(self):
""" Verify that this is indeed a CCS811 """
hw_id = self.bus.read_byte_data(self.device_address, 0x20)
return hw_id == 0x81
def update_status(self, status=None, error=None):
if not status:
status = self.bus.read_byte_data(self.device_address, 0x00)
bit_values = bin(status)[2:].zfill(8)
if bit_values[-8] == '1':
self.status['Firmware mode'] = 'Application mode'
else:
self.status['Firmware mode'] = 'Boot mode'
if bit_values[-5] == '1':
self.status['Firmware status'] = 'Firmware loaded'
else:
self.status['Firmware mode'] = 'Firmware not loaded'
self.status['Data ready'] = bit_values[-4] == '1'
if bit_values[-1] == '1':
self.read_error(error)
else:
self.status['error'] = []
return self.status
def read_error(self, error=None):
if not error:
error = self.bus.read_byte_data(self.device_address, 0xE0)
bit_values = bin(error)[2:].zfill(8)
error = []
if bit_values[-1] == '1':
error.append('Invalid write')
if bit_values[-2] == '1':
error.append('Invalid read')
if bit_values[-3] == '1':
error.append('Invalid MEAS_MODE')
if bit_values[-4] == '1':
error.append('Resistance too high, sensor not working')
if bit_values[-5] == '1':
error.append('Heater current error, sensor not working')
if bit_values[-6] == '1':
error.append('Heater voltage error, sensor not working')
return self.status
[docs] def update_data(self):
""" Read data and update internal state """
data = self.bus.read_i2c_block_data(self.device_address, 0x02, 8)
self.data['eCO2'] = 256 * data[0] + data[1]
self.data['TVOC'] = 256 * data[2] + data[3]
raw_bits = bin(data[6])[2:].zfill(8) + bin(data[7])[2:].zfill(8)
self.data['current'] = int(raw_bits[0:6], 2)
self.data['voltage'] = int(raw_bits[6:16], 2) * 1.65 / 1023
self.data['resistance'] = int(
1000000 * self.data['voltage'] / self.data['current']
)
return self.data
[docs] def set_environmental_data(self, humidity, temperature):
"""
Set the environmental conditions to allow for correct
compensation in the device
"""
humidity_byte = ''
for i in range(0, 16):
bit_val = 64.0 / 2 ** i
if humidity > bit_val:
humidity_byte += '1'
humidity -= bit_val
else:
humidity_byte += '0'
hum_val = int(humidity_byte, 2)
hum_bytes = hum_val.to_bytes(2, byteorder='big')
temperature_byte = ''
for i in range(0, 16):
bit_val = 64.0 / 2 ** i
if temperature + 25 > bit_val:
temperature_byte += '1'
temperature -= bit_val
else:
temperature_byte += '0'
temperature_val = int(temperature_byte, 2)
temp_bytes = temperature_val.to_bytes(2, byteorder='big')
env_data = [hum_bytes[0], hum_bytes[1], temp_bytes[0], temp_bytes[1]]
print(env_data)
self.bus.wri2te_block_data(self.device_address, 0x05, env_data)
time.sleep(0.5)
if __name__ == '__main__':
sensor = CCS811()
time.sleep(5)
for i in range(0, 2000):
time.sleep(0.1)
status = sensor.update_status()
print(status)
if status['Data ready']:
print(sensor.update_data())
sensor.set_environmental_data(45.4, 27.3)