├── .gitignore ├── Adafruit_HTU21D ├── HTU21D.py └── __init__.py ├── LICENSE ├── README.md ├── examples └── simpletest.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /Adafruit_HTU21D/HTU21D.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015-2017 Massimo Gaggero 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | """ 26 | HTU21D is a python library for the Adafruit HTU21D-F Humidity/Temperature 27 | sensor breakout board. 28 | """ 29 | 30 | import io 31 | import math 32 | import time 33 | import fcntl 34 | import logging 35 | 36 | 37 | # RPI-2/3 I2C DEFAULT BUS 38 | I2C_BUS = 1 39 | 40 | # RPI I2C SLAVE ADDRESS 41 | I2C_SLAVE = 0x0703 42 | 43 | # HTU21D default address 44 | HTU21D_I2CADDR = 0x40 45 | 46 | # Operating Modes 47 | HTU21D_HOLDMASTER = 0x00 48 | HTU21D_NOHOLDMASTER = 0x10 49 | 50 | # HTU21D Commands 51 | HTU21D_TRIGGERTEMPCMD = 0xE3 # Trigger Temperature Measurement 52 | HTU21D_TRIGGERHUMIDITYCMD = 0xE5 # Trigger Humidity Measurement 53 | HTU21D_WRITEUSERCMD = 0xE6 # Write user register 54 | HTU21D_READUSERCMD = 0xE7 # Read user register 55 | HTU21D_SOFTRESETCMD = 0xFE # Soft reset 56 | 57 | HTU21D_MAX_MEASURING_TIME = 100 # mSec 58 | 59 | # HTU21D Constants for Dew Point calculation 60 | HTU21D_A = 8.1332 61 | HTU21D_B = 1762.39 62 | HTU21D_C = 235.66 63 | 64 | 65 | class HTU21DException(Exception): 66 | pass 67 | 68 | 69 | class HTU21DBusProtocol(object): 70 | def __init__(self, busnum = I2C_BUS, address = HTU21D_I2CADDR): 71 | self._busnum = busnum 72 | self._address = address 73 | 74 | self._device_name = '/dev/i2c-{}'.format(self._busnum) 75 | 76 | self._read_handler = None 77 | self._write_handler = None 78 | 79 | def open(self): 80 | self._read_handler = io.open(self._device_name, 'rb', buffering=0) 81 | self._write_handler = io.open(self._device_name, 'wb', buffering=0) 82 | 83 | fcntl.ioctl(self._read_handler, I2C_SLAVE, self._address) 84 | fcntl.ioctl(self._write_handler, I2C_SLAVE, self._address) 85 | 86 | time.sleep(HTU21D_MAX_MEASURING_TIME/1000) 87 | 88 | def send_command(self, command): 89 | self._write_handler.write(command.to_bytes(1, 'big')) 90 | 91 | def read_bytes(self, len): 92 | return self._read_handler.read(len) 93 | 94 | def close(self): 95 | self._read_handler.close() 96 | self._write_handler.close() 97 | 98 | 99 | class HTU21D(object): 100 | def __init__(self, busnum=I2C_BUS, address=HTU21D_I2CADDR, mode=HTU21D_NOHOLDMASTER): 101 | self._logger = logging.getLogger('Adafruit_HTU21D.HTU21D') 102 | 103 | # Check that mode is valid. 104 | if mode not in [HTU21D_HOLDMASTER, HTU21D_NOHOLDMASTER]: 105 | raise ValueError('Unexpected mode value {0}. Set mode to one of HTU21D_HOLDMASTER, HTU21D_NOHOLDMASTER'.format(mode)) 106 | 107 | self._busnum = busnum 108 | self._address = address 109 | self._mode = mode 110 | 111 | # Create I2C device. 112 | self._htu_handler = HTU21DBusProtocol(self._busnum, self._address) 113 | 114 | def crc_check(self, msb, lsb, crc): 115 | remainder = ((msb << 8) | lsb) << 8 116 | remainder |= crc 117 | divsor = 0x988000 118 | 119 | for i in range(0, 16): 120 | if remainder & 1 << (23 - i): 121 | remainder ^= divsor 122 | divsor >>= 1 123 | 124 | if remainder == 0: 125 | return True 126 | else: 127 | return False 128 | 129 | def reset(self): 130 | """Reboots the sensor switching the power off and on again.""" 131 | self._htu_handler.open() 132 | 133 | self._htu_handler.send_command(HTU21D_SOFTRESETCMD & 0xFF) 134 | time.sleep(HTU21D_MAX_MEASURING_TIME/1000) 135 | self._htu_handler.close() 136 | 137 | return 138 | 139 | def read_raw_temp(self): 140 | """Reads the raw temperature from the sensor.""" 141 | self._htu_handler.open() 142 | 143 | self._htu_handler.send_command((HTU21D_TRIGGERTEMPCMD | self._mode) & 0xFF) 144 | time.sleep(HTU21D_MAX_MEASURING_TIME/1000) 145 | msb, lsb, chsum = self._htu_handler.read_bytes(3) 146 | 147 | self._htu_handler.close() 148 | 149 | if self.crc_check(msb, lsb, chsum) is False: 150 | raise HTU21DException("CRC Exception") 151 | 152 | raw = (msb << 8) + lsb 153 | raw &= 0xFFFC 154 | self._logger.debug('Raw temp 0x{0:X} ({1})'.format(raw & 0xFFFF, raw)) 155 | 156 | return raw 157 | 158 | def read_raw_humidity(self): 159 | """Reads the raw relative humidity from the sensor.""" 160 | self._htu_handler.open() 161 | 162 | self._htu_handler.send_command((HTU21D_TRIGGERHUMIDITYCMD | self._mode) & 0xFF) 163 | time.sleep(HTU21D_MAX_MEASURING_TIME/1000) 164 | msb, lsb, chsum = self._htu_handler.read_bytes(3) 165 | 166 | self._htu_handler.close() 167 | 168 | if self.crc_check(msb, lsb, chsum) is False: 169 | raise HTU21DException("CRC Exception") 170 | 171 | raw = (msb << 8) + lsb 172 | raw &= 0xFFFC 173 | self._logger.debug('Raw relative humidity 0x{0:04X} ({1})'.format(raw & 0xFFFF, raw)) 174 | 175 | return raw 176 | 177 | def read_temperature(self): 178 | """Gets the temperature in degrees celsius.""" 179 | v_raw_temp = self.read_raw_temp() 180 | v_real_temp = float(v_raw_temp)/65536 * 175.72 181 | v_real_temp -= 46.85 182 | self._logger.debug('Temperature {0:.2f} C'.format(v_real_temp)) 183 | return v_real_temp 184 | 185 | def read_humidity(self): 186 | """Gets the relative humidity.""" 187 | v_raw_hum = self.read_raw_humidity() 188 | v_real_hum = float(v_raw_hum)/65536 * 125 189 | v_real_hum -= 6 190 | self._logger.debug('Relative Humidity {0:.2f} %'.format(v_real_hum)) 191 | return v_real_hum 192 | 193 | def read_dewpoint(self): 194 | """Calculates the dew point temperature.""" 195 | # Calculation taken straight from datasheet. 196 | ppressure = self.read_partialpressure() 197 | humidity = self.read_humidity() 198 | den = math.log10(humidity * ppressure / 100) - HTU21D_A 199 | dew = -(HTU21D_B / den + HTU21D_C) 200 | self._logger.debug('Dew Point {0:.2f} C'.format(dew)) 201 | return dew 202 | 203 | def read_partialpressure(self): 204 | """Calculate the partial pressure in mmHg at ambient temperature.""" 205 | v_temp = self.read_temperature() 206 | v_exp = HTU21D_B / (v_temp + HTU21D_C) 207 | v_exp = HTU21D_A - v_exp 208 | v_part_press = 10 ** v_exp 209 | self._logger.debug('Partial Pressure {0:.2f} mmHg'.format(v_part_press)) 210 | return v_part_press 211 | 212 | # vim:ts=4:expandtab 213 | -------------------------------------------------------------------------------- /Adafruit_HTU21D/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Massimo Gaggero 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit_Python_HTU21D 2 | Python Library for the Adafruit HTU21D-F Humidity/Temperature sensor breakout board. 3 | 4 | Partially based on the code of the Adafruit_Python_BMP library written by Tony DiCola for Adafruit Industries. 5 | 6 | **Warning**: 7 | 8 | * ***Python 2.7*** is only partially supported; 9 | * "*Hold Master*" mode is not implemented; 10 | * **Beagle** boards (BeagleBoard, BeagleBone/Black) have not already been tested; 11 | * read/write user reg is not implemented. 12 | 13 | ## Currently supported platforms 14 | | Board | Options | 15 | | ---------------------- | --------------------------- | 16 | | Raspberry PI 1 Model B | ***busnum=0*** | 17 | | Raspberry PI 2 Model B | *busnum* default or ***1*** | 18 | | Raspberry PI 3 Model B | *busnum* default or ***1*** | 19 | 20 | ## Installation 21 | 22 | ### Setuptools 23 | The following commands install HTU21D library *system wide*: 24 | 25 | ~~~console 26 | git clone https://github.com/mgaggero/Adafruit_Python_HTU21D.git 27 | cd Adafruit_Python_HTU21D 28 | sudo python setup.py install 29 | ~~~ 30 | 31 | In order to install the library on the user's home directory, a *local installation* that not requires sudo/root privileges, the last command should be: 32 | 33 | ~~~console 34 | python setup.py install --user 35 | ~~~ 36 | 37 | And the library will be installed in the folder 38 | 39 | ~~~console 40 | $HOME/.local/lib/python3.6/site-packages/ 41 | ~~~ 42 | 43 | ### Pip 44 | 45 | The following commands install HTU21D library *system wide*: 46 | 47 | ~~~console 48 | git clone https://github.com/mgaggero/Adafruit_Python_HTU21D.git 49 | cd Adafruit_Python_HTU21D 50 | sudo pip install . 51 | ~~~ 52 | 53 | In order to install the library on the user's home directory, a *local installation* that not requires sudo/root privileges, the last command should be: 54 | 55 | ~~~console 56 | pip install . --user 57 | ~~~ 58 | 59 | And the library will be installed in the folder 60 | 61 | ~~~console 62 | $HOME/.local/lib/python3.6/site-packages/ 63 | ~~~ 64 | 65 | 66 | ## Permissions and privileges 67 | Accessing **I2C** devices usually requires root privileges or privileged group membership. These can be obtained with: 68 | 69 | * the use of `sudo` to run the program; 70 | * adding the user that runs the program to the I2C's device owning group; 71 | * creating an '**i2c**' group, assigning the i2c device to it and adding the user to that group. 72 | 73 | ### Creation of the 'i2c' group 74 | ~~~console 75 | sudo groupadd -r i2c # creates the 'i2c' group as a 'system' group 76 | sudo chgrp i2c /dev/i2c* # changes group ownership of the i2c device files 77 | sudo chmod g+rw /dev/i2c* # allow owning group to read/write to the devices 78 | sudo usermod -aG i2c $USER # add the current user to the 'i2c' group 79 | ~~~ 80 | Logout and re-login. 81 | 82 | ## Usage 83 | ~~~python 84 | >>> from Adafruit_HTU21D.HTU21D import HTU21D 85 | 86 | >>> h = HTU21D() 87 | 88 | >>> h.read_temperature() 89 | 24.117971191406248 90 | 91 | >>> h.read_humidity() 92 | 35.1224365234375 93 | 94 | >>> h.read_dewpoint() 95 | 7.783974941964999 96 | 97 | >>> h.reset() 98 | ~~~ 99 | 100 | ## Troubleshooting 101 | ### ArchLinux 102 | Before reporting any bugs or issues, make sure that: 103 | 104 | * the file */boot/config.txt* contains the line 105 | `dtparam=i2c_arm=on` 106 | Uncomment if necessary and reboot the board. 107 | 108 | 109 | * kernel module 110 | `i2c-dev` 111 | is loaded. Otherwise, load it with: 112 | `sudo modprobe i2c-dev` 113 | 114 | 115 | -------------------------------------------------------------------------------- /examples/simpletest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # BEGIN_COPYRIGHT 3 | # 4 | # The MIT License (MIT) 5 | # 6 | # Copyright (c) 2015-2017 Massimo Gaggero 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | # END_COPYRIGHT 27 | 28 | # Uncomment to enable debug output: 29 | #import logging 30 | #logging.basicConfig(level=logging.DEBUG) 31 | 32 | import Adafruit_HTU21D.HTU21D as HTU21D 33 | 34 | # Default constructor will pick a default I2C bus. 35 | # 36 | # For the Raspberry Pi this means you should hook up to the only exposed I2C bus 37 | # from the main GPIO header and the library will figure out the bus number based 38 | # on the Pi's revision. 39 | # 40 | # For the Beaglebone Black the library will assume bus 1 by default, which is 41 | # exposed with SCL = P9_19 and SDA = P9_20. 42 | sensor = HTU21D.HTU21D() 43 | 44 | # Optionally you can override the bus number: 45 | #sensor = HTU21D.HTU21D(busnum=2) 46 | 47 | # HTU21D communication mode can be set to one of HTU21D_HOLDMASTER and HTU21D_NOHOLDMASTER. 48 | # Actually only HTU21D_NOHOLDMASTER is supported. 49 | #sensor = HTU21D.HTU21D(mode=HTU21D.HTU21D_HOLDMASTER) 50 | 51 | print ('Temp = {0:0.2f} *C'.format(sensor.read_temperature())) 52 | print ('Humidity = {0:0.2f} %'.format(sensor.read_humidity())) 53 | print ('Dew Point = {0:0.2f} *C'.format(sensor.read_dewpoint())) 54 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) 2015-2017 Massimo Gaggero 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | 25 | from setuptools import setup, find_packages 26 | 27 | setup( 28 | name = 'Adafruit_HTU21D', 29 | version = '1.0.0', 30 | author = 'Massimo Gaggero', 31 | author_email = 'massimo.gaggero@crs4.it', 32 | description = 'Library for accessing the HTU21D-F humidity and temperature sensor on a Raspberry Pi or Beaglebone Black.', 33 | license = 'MIT', 34 | platforms = ["Linux"], 35 | url = 'https://github.com/mgaggero/Adafruit_Python_HTU21D/', 36 | packages = find_packages(), 37 | classifiers=[ 38 | 'Development Status :: 4 - Beta', 39 | 'Environment :: Console', 40 | 'Environment :: Other Environment', 41 | 'Intended Audience :: Developers', 42 | 'Intended Audience :: Education', 43 | 'Intended Audience :: Information Technology', 44 | 'Intended Audience :: Science/Research', 45 | 'License :: OSI Approved :: MIT License', 46 | 'Operating System :: POSIX :: Linux', 47 | 'Programming Language :: Python', 48 | 'Programming Language :: Python :: 2.7', 49 | 'Programming Language :: Python :: 3', 50 | 'Topic :: Education', 51 | 'Topic :: Home Automation', 52 | 'Topic :: Scientific/Engineering', 53 | 'Topic :: System :: Hardware :: Hardware Drivers', 54 | ], 55 | 56 | ) 57 | --------------------------------------------------------------------------------