glasermrk
Posts: 1
Joined: Thu Jul 07, 2016 6:32 pm

Need help with Python Library T6713 CO2 Sensor - I2C

Thu Jul 07, 2016 6:44 pm

I am working on getting my Raspberry Pi 3 (Jessie FULL) to read CO2 levels from a T6713 CO2 I2C Sensor. The only resource for Python available is from an Intel source code http://iotdk.intel.com/docs/master/upm/ ... ml#COMMAND

Code: Select all

# This file was automatically generated by SWIG (http://www.swig.org).
# Version 3.0.8
#
# Do not make changes to this file unless you know what you are doing--modify
# the SWIG interface file instead.





from sys import version_info
if version_info >= (2, 6, 0):
    def swig_import_helper():
        from os.path import dirname
        import imp
        fp = None
        try:
            fp, pathname, description = imp.find_module('_pyupm_t6713', [dirname(__file__)])
        except ImportError:
            import _pyupm_t6713
            return _pyupm_t6713
        if fp is not None:
            try:
                _mod = imp.load_module('_pyupm_t6713', fp, pathname, description)
            finally:
                fp.close()
            return _mod
    _pyupm_t6713 = swig_import_helper()
    del swig_import_helper
else:
    import _pyupm_t6713
del version_info
try:
    _swig_property = property
except NameError:
    pass  # Python < 2.2 doesn't have 'property'.


def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
    if (name == "thisown"):
        return self.this.own(value)
    if (name == "this"):
        if type(value).__name__ == 'SwigPyObject':
            self.__dict__[name] = value
            return
    method = class_type.__swig_setmethods__.get(name, None)
    if method:
        return method(self, value)
    if (not static):
        if _newclass:
            object.__setattr__(self, name, value)
        else:
            self.__dict__[name] = value
    else:
        raise AttributeError("You cannot add attributes to %s" % self)


def _swig_setattr(self, class_type, name, value):
    return _swig_setattr_nondynamic(self, class_type, name, value, 0)


def _swig_getattr_nondynamic(self, class_type, name, static=1):
    if (name == "thisown"):
        return self.this.own()
    method = class_type.__swig_getmethods__.get(name, None)
    if method:
        return method(self)
    if (not static):
        return object.__getattr__(self, name)
    else:
        raise AttributeError(name)

def _swig_getattr(self, class_type, name):
    return _swig_getattr_nondynamic(self, class_type, name, 0)


def _swig_repr(self):
    try:
        strthis = "proxy of " + self.this.__repr__()
    except Exception:
        strthis = ""
    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)

try:
    _object = object
    _newclass = 1
except AttributeError:
    class _object:
        pass
    _newclass = 0



_pyupm_t6713.T6713_COMMAND_RESET_swigconstant(_pyupm_t6713)
T6713_COMMAND_RESET = _pyupm_t6713.T6713_COMMAND_RESET

_pyupm_t6713.T6713_COMMAND_STATUS_swigconstant(_pyupm_t6713)
T6713_COMMAND_STATUS = _pyupm_t6713.T6713_COMMAND_STATUS

_pyupm_t6713.T6713_COMMAND_GET_FIRMWARE_REVISION_swigconstant(_pyupm_t6713)
T6713_COMMAND_GET_FIRMWARE_REVISION = _pyupm_t6713.T6713_COMMAND_GET_FIRMWARE_REVISION

_pyupm_t6713.T6713_COMMAND_GET_GAS_PPM_swigconstant(_pyupm_t6713)
T6713_COMMAND_GET_GAS_PPM = _pyupm_t6713.T6713_COMMAND_GET_GAS_PPM

_pyupm_t6713.ERROR_CONDITION_swigconstant(_pyupm_t6713)
ERROR_CONDITION = _pyupm_t6713.ERROR_CONDITION

_pyupm_t6713.FLASH_ERROR_swigconstant(_pyupm_t6713)
FLASH_ERROR = _pyupm_t6713.FLASH_ERROR

_pyupm_t6713.CALIBRATION_ERROR_swigconstant(_pyupm_t6713)
CALIBRATION_ERROR = _pyupm_t6713.CALIBRATION_ERROR

_pyupm_t6713.WARMUP_MODE_swigconstant(_pyupm_t6713)
WARMUP_MODE = _pyupm_t6713.WARMUP_MODE

_pyupm_t6713.SINGLE_POINT_CALIBRATION_swigconstant(_pyupm_t6713)
SINGLE_POINT_CALIBRATION = _pyupm_t6713.SINGLE_POINT_CALIBRATION

_pyupm_t6713.RS232_swigconstant(_pyupm_t6713)
RS232 = _pyupm_t6713.RS232

_pyupm_t6713.I2C_swigconstant(_pyupm_t6713)
I2C = _pyupm_t6713.I2C

_pyupm_t6713.RS485_swigconstant(_pyupm_t6713)
RS485 = _pyupm_t6713.RS485

class COMMAND(_object):
    """Proxy of C++ upm::t6713_co2::COMMAND class."""

    __swig_setmethods__ = {}
    __setattr__ = lambda self, name, value: _swig_setattr(self, COMMAND, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, COMMAND, name)
    __repr__ = _swig_repr
    __swig_setmethods__["function_code"] = _pyupm_t6713.COMMAND_function_code_set
    __swig_getmethods__["function_code"] = _pyupm_t6713.COMMAND_function_code_get
    if _newclass:
        function_code = _swig_property(_pyupm_t6713.COMMAND_function_code_get, _pyupm_t6713.COMMAND_function_code_set)
    __swig_setmethods__["register_address_msb"] = _pyupm_t6713.COMMAND_register_address_msb_set
    __swig_getmethods__["register_address_msb"] = _pyupm_t6713.COMMAND_register_address_msb_get
    if _newclass:
        register_address_msb = _swig_property(_pyupm_t6713.COMMAND_register_address_msb_get, _pyupm_t6713.COMMAND_register_address_msb_set)
    __swig_setmethods__["register_address_lsb"] = _pyupm_t6713.COMMAND_register_address_lsb_set
    __swig_getmethods__["register_address_lsb"] = _pyupm_t6713.COMMAND_register_address_lsb_get
    if _newclass:
        register_address_lsb = _swig_property(_pyupm_t6713.COMMAND_register_address_lsb_get, _pyupm_t6713.COMMAND_register_address_lsb_set)
    __swig_setmethods__["input_registers_to_read_msb"] = _pyupm_t6713.COMMAND_input_registers_to_read_msb_set
    __swig_getmethods__["input_registers_to_read_msb"] = _pyupm_t6713.COMMAND_input_registers_to_read_msb_get
    if _newclass:
        input_registers_to_read_msb = _swig_property(_pyupm_t6713.COMMAND_input_registers_to_read_msb_get, _pyupm_t6713.COMMAND_input_registers_to_read_msb_set)
    __swig_setmethods__["input_registers_to_read_lsb"] = _pyupm_t6713.COMMAND_input_registers_to_read_lsb_set
    __swig_getmethods__["input_registers_to_read_lsb"] = _pyupm_t6713.COMMAND_input_registers_to_read_lsb_get
    if _newclass:
        input_registers_to_read_lsb = _swig_property(_pyupm_t6713.COMMAND_input_registers_to_read_lsb_get, _pyupm_t6713.COMMAND_input_registers_to_read_lsb_set)

    def __init__(self):
        """__init__(upm::t6713_co2::COMMAND self) -> COMMAND"""
        this = _pyupm_t6713.new_COMMAND()
        try:
            self.this.append(this)
        except Exception:
            self.this = this
    __swig_destroy__ = _pyupm_t6713.delete_COMMAND
    __del__ = lambda self: None

COMMAND_swigregister = _pyupm_t6713.COMMAND_swigregister
COMMAND_swigregister(COMMAND)

class RESPONSE(_object):
    """Proxy of C++ upm::t6713_co2::RESPONSE class."""

    __swig_setmethods__ = {}
    __setattr__ = lambda self, name, value: _swig_setattr(self, RESPONSE, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, RESPONSE, name)
    __repr__ = _swig_repr
    __swig_setmethods__["function_code"] = _pyupm_t6713.RESPONSE_function_code_set
    __swig_getmethods__["function_code"] = _pyupm_t6713.RESPONSE_function_code_get
    if _newclass:
        function_code = _swig_property(_pyupm_t6713.RESPONSE_function_code_get, _pyupm_t6713.RESPONSE_function_code_set)
    __swig_setmethods__["byte_count"] = _pyupm_t6713.RESPONSE_byte_count_set
    __swig_getmethods__["byte_count"] = _pyupm_t6713.RESPONSE_byte_count_get
    if _newclass:
        byte_count = _swig_property(_pyupm_t6713.RESPONSE_byte_count_get, _pyupm_t6713.RESPONSE_byte_count_set)
    __swig_setmethods__["status_msb"] = _pyupm_t6713.RESPONSE_status_msb_set
    __swig_getmethods__["status_msb"] = _pyupm_t6713.RESPONSE_status_msb_get
    if _newclass:
        status_msb = _swig_property(_pyupm_t6713.RESPONSE_status_msb_get, _pyupm_t6713.RESPONSE_status_msb_set)
    __swig_setmethods__["status_lsb"] = _pyupm_t6713.RESPONSE_status_lsb_set
    __swig_getmethods__["status_lsb"] = _pyupm_t6713.RESPONSE_status_lsb_get
    if _newclass:
        status_lsb = _swig_property(_pyupm_t6713.RESPONSE_status_lsb_get, _pyupm_t6713.RESPONSE_status_lsb_set)

    def __init__(self):
        """__init__(upm::t6713_co2::RESPONSE self) -> RESPONSE"""
        this = _pyupm_t6713.new_RESPONSE()
        try:
            self.this.append(this)
        except Exception:
            self.this = this
    __swig_destroy__ = _pyupm_t6713.delete_RESPONSE
    __del__ = lambda self: None

RESPONSE_swigregister = _pyupm_t6713.RESPONSE_swigregister
RESPONSE_swigregister(RESPONSE)


_pyupm_t6713.READ_INPUT_REGISTERS_swigconstant(_pyupm_t6713)
READ_INPUT_REGISTERS = _pyupm_t6713.READ_INPUT_REGISTERS

_pyupm_t6713.WRITE_SINGLE_COIL_swigconstant(_pyupm_t6713)
WRITE_SINGLE_COIL = _pyupm_t6713.WRITE_SINGLE_COIL

_pyupm_t6713.WRITE_SINGLE_HOLDING_REGISTER_swigconstant(_pyupm_t6713)
WRITE_SINGLE_HOLDING_REGISTER = _pyupm_t6713.WRITE_SINGLE_HOLDING_REGISTER

class T6713(_object):
    """Proxy of C++ upm::T6713 class."""

    __swig_setmethods__ = {}
    __setattr__ = lambda self, name, value: _swig_setattr(self, T6713, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, T6713, name)
    __repr__ = _swig_repr

    def __init__(self, bus):
        """
        __init__(upm::T6713 self, int bus) -> T6713

        Parameters
        ----------
        bus: int

        """
        this = _pyupm_t6713.new_T6713(bus)
        try:
            self.this.append(this)
        except Exception:
            self.this = this
    __swig_destroy__ = _pyupm_t6713.delete_T6713
    __del__ = lambda self: None

    def getModuleName(self):
        """
        getModuleName(T6713 self) -> char const *

        Parameters
        ----------
        self: upm::T6713 *

        """
        return _pyupm_t6713.T6713_getModuleName(self)

    def getPpm(self):
        """
        getPpm(T6713 self) -> uint16_t

        Parameters
        ----------
        self: upm::T6713 *

        """
    def getFirmwareRevision(self):
        """
        getFirmwareRevision(T6713 self) -> uint16_t

        Parameters
        ----------
        self: upm::T6713 *

        """
        return _pyupm_t6713.T6713_getFirmwareRevision(self)

T6713_swigregister = _pyupm_t6713.T6713_swigregister
T6713_swigregister(T6713)

# This file is compatible with both classic and new-style classes.
        return _pyupm_t6713.T6713_getPpm(self)
I am still a beginner at coding. How would I use this source code to create a Python library as well as a code to read and print the CO2 levels? The PWM output of the sensor is in GPIO18.



There was another python library that someone made but could not get it to work, probably because it was serial to USB. https://github.com/arcenik/t67xx_co2reader

edwardsnick
Posts: 8
Joined: Sat Sep 19, 2015 12:15 am

Re: Need help with Python Library T6713 CO2 Sensor - I2C

Sun Oct 16, 2016 4:16 am

I struggled with this one too as the typical smbus python library won't work with this chip. It uses Modbus protocol over the I2C. I managed to get it to work using the pigpio library but it was a mess and only worked when I slowed down the baudrate due to a delayed clock tick which the raspberry pi didn't respond properly to (if I remember, it was a while ago now).
Anyway good news is I came across this:
viewtopic.php?f=44&t=76688
when I was trying to get my humidity sensor working which is perfect for the Telaire CO2 sensor so I rewrote my driver and it works perfectly, sorry it's not properly commented and there's a few functions I could still add; enjoy:
It's a fantastic sensor btw.

Code: Select all

#!/usr/bin/python
import math, struct, array, time, io, fcntl

bus = 1
addressT6713 = 0x15
I2C_SLAVE=0x0703

class i2c(object):
	def __init__(self, device, bus):

		self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
		self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

		# set device address

		fcntl.ioctl(self.fr, I2C_SLAVE, device)
		fcntl.ioctl(self.fw, I2C_SLAVE, device)

	def write(self, bytes):
		self.fw.write(bytes)

	def read(self, bytes):
		return self.fr.read(bytes)

	def close(self):
		self.fw.close()
		self.fr.close()

class T6713(object):
	def __init__(self):
		self.dev = i2c(addressT6713, bus)

	def status(self):
		buffer = array.array('B', [0x04, 0x13, 0x8a, 0x00, 0x01])
		self.dev.write(buffer)
		time.sleep(0.1)
		data = self.dev.read(4)
		buffer = array.array('B', data)
		return buffer[2]*256+buffer[3]

	def gasPPM(self):
		buffer = array.array('B', [0x04, 0x13, 0x8b, 0x00, 0x01])
		self.dev.write(buffer)
		time.sleep(0.1)
		data = self.dev.read(4)
		buffer = array.array('B', data)
		return buffer[2]*256+buffer[3]

	def checkABC(self):
		buffer = array.array('B', [0x04, 0x03, 0xee, 0x00, 0x01])
		self.dev.write(buffer)
		time.sleep(0.1)
		data = self.dev.read(4)
		buffer = array.array('B', data)
		return buffer[2]*256+buffer[3]

	def calibrate(self):
		buffer = array.array('B', [0x05, 0x03, 0xec, 0xff, 0x00])
		self.dev.write(buffer)
		time.sleep(0.1)
		data = self.dev.read(5)
		buffer = array.array('B', data)
		return buffer[3]*256+buffer[3]
             
if __name__ == "__main__":
	obj = T6713()
	print "Status: ", bin(obj.status())
	print "PPM: ", obj.gasPPM()
	print "ABC State: ", obj.checkABC()

edwardsnick
Posts: 8
Joined: Sat Sep 19, 2015 12:15 am

Re: Need help with Python Library T6713 CO2 Sensor - I2C

Sun Oct 16, 2016 8:41 pm

Just realized the new code also needs the slow bus speed to work, looks like the ACK is too long and messes with the rest of the conversation, the RPI should delay the conversation but I believe this is a known bug. my trouble is it's messing with my IR sensor which doesn't like the slow bus, going to have to try find a middle ground.
Set your baudrate for the i2c as follows:

sudo nano /boot/config.txt

find this line and change from 100kHz to 10kHz to make the above code work:
dtparam=i2c_baudrate=100000
change to 10000 for CO2 sensor

reboot the Pi

User avatar
joan
Posts: 14274
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Need help with Python Library T6713 CO2 Sensor - I2C

Sun Oct 16, 2016 9:18 pm

edwardsnick wrote:Just realized the new code also needs the slow bus speed to work, looks like the ACK is too long and messes with the rest of the conversation, the RPI should delay the conversation but I believe this is a known bug. my trouble is it's messing with my IR sensor which doesn't like the slow bus, going to have to try find a middle ground.
Set your baudrate for the i2c as follows:

sudo nano /boot/config.txt

find this line and change from 100kHz to 10kHz to make the above code work:
dtparam=i2c_baudrate=100000
change to 10000 for CO2 sensor

reboot the Pi
You can bit bang I2C with pigpio. That should support clock stretching.

http://abyz.co.uk/rpi/pigpio/python.html#bb_i2c_open

edwardsnick
Posts: 8
Joined: Sat Sep 19, 2015 12:15 am

Re: Need help with Python Library T6713 CO2 Sensor - I2C

Sun Oct 16, 2016 9:24 pm

could; but want to avoid installing / running extra processes if possible. They working fine at 50kHz, reading the datasheet of the IR sensor it's minimum is 10kHz so 15kHz will probably work fine too

NemesisN800
Posts: 1
Joined: Wed Jul 31, 2019 4:00 am

Re: Need help with Python Library T6713 CO2 Sensor - I2C

Wed Jul 31, 2019 4:04 am

edwardsnick wrote:
Sun Oct 16, 2016 4:16 am
I struggled with this one too as the typical smbus python library won't work with this chip. It uses Modbus protocol over the I2C. I managed to get it to work using the pigpio library but it was a mess and only worked when I slowed down the baudrate due to a delayed clock tick which the raspberry pi didn't respond properly to (if I remember, it was a while ago now).
Anyway good news is I came across this:
https://www.raspberrypi.org/forums/view ... 44&t=76688
when I was trying to get my humidity sensor working which is perfect for the Telaire CO2 sensor so I rewrote my driver and it works perfectly, sorry it's not properly commented and there's a few functions I could still add; enjoy:
It's a fantastic sensor btw.

Code: Select all

#!/usr/bin/python
import math, struct, array, time, io, fcntl

bus = 1
addressT6713 = 0x15
I2C_SLAVE=0x0703

class i2c(object):
	def __init__(self, device, bus):

		self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
		self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

		# set device address

		fcntl.ioctl(self.fr, I2C_SLAVE, device)
		fcntl.ioctl(self.fw, I2C_SLAVE, device)

	def write(self, bytes):
		self.fw.write(bytes)

	def read(self, bytes):
		return self.fr.read(bytes)

	def close(self):
		self.fw.close()
		self.fr.close()

class T6713(object):
	def __init__(self):
		self.dev = i2c(addressT6713, bus)

	def status(self):
		buffer = array.array('B', [0x04, 0x13, 0x8a, 0x00, 0x01])
		self.dev.write(buffer)
		time.sleep(0.1)
		data = self.dev.read(4)
		buffer = array.array('B', data)
		return buffer[2]*256+buffer[3]

	def gasPPM(self):
		buffer = array.array('B', [0x04, 0x13, 0x8b, 0x00, 0x01])
		self.dev.write(buffer)
		time.sleep(0.1)
		data = self.dev.read(4)
		buffer = array.array('B', data)
		return buffer[2]*256+buffer[3]

	def checkABC(self):
		buffer = array.array('B', [0x04, 0x03, 0xee, 0x00, 0x01])
		self.dev.write(buffer)
		time.sleep(0.1)
		data = self.dev.read(4)
		buffer = array.array('B', data)
		return buffer[2]*256+buffer[3]

	def calibrate(self):
		buffer = array.array('B', [0x05, 0x03, 0xec, 0xff, 0x00])
		self.dev.write(buffer)
		time.sleep(0.1)
		data = self.dev.read(5)
		buffer = array.array('B', data)
		return buffer[3]*256+buffer[3]
             
if __name__ == "__main__":
	obj = T6713()
	print "Status: ", bin(obj.status())
	print "PPM: ", obj.gasPPM()
	print "ABC State: ", obj.checkABC()
Hi , I'm very new to Python and raspberry pi. I have used your code and tried to run but i'm getting the following errors, can you kindly help me?
Thanks in advance.
Traceback (most recent call last):
File "/home/pi/CIRT/T6713Sensor/Test/Wiringtest.py", line 66, in <module>
obj = T6713()
File "/home/pi/CIRT/T6713Sensor/Test/Wiringtest.py", line 31, in __init__
self.dev = i2c(addressT6713, bus)
File "/home/pi/CIRT/T6713Sensor/Test/Wiringtest.py", line 11, in __init__
self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'

It was working fine earlier , when i changed baud rate to 100 in boot/config.txt, this started giving problems.

ghp
Posts: 1413
Joined: Wed Jun 12, 2013 12:41 pm
Location: Stuttgart Germany
Contact: Website

Re: Need help with Python Library T6713 CO2 Sensor - I2C

Thu Aug 01, 2019 4:50 am

Check with raspi-config that I2C is enabled.
When enabled, use 'ls /dev/i2c*' in a terminal to check if the device is available.
I2C should be independent from baud rate settings ? What did you change exactly in config.txt ?

Return to “Python”