├── Images ├── img1.jpg ├── img2.jpg ├── img3.jpg ├── img4.jpg └── photo ├── Lcd1_14driver.py ├── README.md ├── ST7789 Driver Pico Sense HAT ├── README.md ├── bme280.py ├── firmware.uf2 ├── pico_sense_hat_st7789.py ├── sgp40.py ├── sht31.py └── tcs34725.py ├── bme280.py ├── pico_sense_hat.py ├── sgp40.py ├── sht31.py └── tcs34725.py /Images/img1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbcshop/Pico-Sense-HAT/45b19d69b5e6c3bdfc80cc72814f0e449a117b86/Images/img1.jpg -------------------------------------------------------------------------------- /Images/img2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbcshop/Pico-Sense-HAT/45b19d69b5e6c3bdfc80cc72814f0e449a117b86/Images/img2.jpg -------------------------------------------------------------------------------- /Images/img3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbcshop/Pico-Sense-HAT/45b19d69b5e6c3bdfc80cc72814f0e449a117b86/Images/img3.jpg -------------------------------------------------------------------------------- /Images/img4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbcshop/Pico-Sense-HAT/45b19d69b5e6c3bdfc80cc72814f0e449a117b86/Images/img4.jpg -------------------------------------------------------------------------------- /Images/photo: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Lcd1_14driver.py: -------------------------------------------------------------------------------- 1 | from machine import Pin,SPI,PWM 2 | import framebuf 3 | import time 4 | 5 | DC = 8 6 | RST = 12 7 | MOSI = 11 8 | SCK = 10 9 | CS = 9 10 | 11 | 12 | class Lcd1_14(framebuf.FrameBuffer): 13 | def __init__(self): 14 | self.width = 240 15 | self.height = 135 16 | 17 | self.cs = Pin(CS,Pin.OUT) 18 | self.rst = Pin(RST,Pin.OUT) 19 | 20 | self.cs(1) 21 | self.spi = SPI(1) 22 | self.spi = SPI(1,1000_000) 23 | self.spi = SPI(1,10000_000,polarity=0, phase=0,sck=Pin(SCK),mosi=Pin(MOSI),miso=None) 24 | self.dc = Pin(DC,Pin.OUT) 25 | self.dc(1) 26 | self.buffer = bytearray(self.height * self.width * 2) 27 | super().__init__(self.buffer, self.width, self.height, framebuf.RGB565) #Red Green Blue (16-bit, 5+6+5) color format 28 | self.lcd_init_display() 29 | 30 | self.red = 0x07E0 31 | self.green = 0x001f 32 | self.blue = 0xf800 33 | self.white = 0xffff 34 | 35 | def lcd_write_cmd(self, cmd): 36 | self.cs(1) 37 | self.dc(0) 38 | self.cs(0) 39 | self.spi.write(bytearray([cmd])) 40 | self.cs(1) 41 | 42 | def lcd_write_data(self, buf): 43 | self.cs(1) 44 | self.dc(1) 45 | self.cs(0) 46 | self.spi.write(bytearray([buf])) 47 | self.cs(1) 48 | 49 | def lcd_init_display(self): 50 | """Initialize dispaly""" 51 | self.rst(1) 52 | self.rst(0) 53 | self.rst(1) 54 | 55 | self.lcd_write_cmd(0x36) 56 | self.lcd_write_data(0x70) 57 | 58 | self.lcd_write_cmd(0x3A) 59 | self.lcd_write_data(0x05) 60 | 61 | self.lcd_write_cmd(0xB2) 62 | self.lcd_write_data(0x0C) 63 | self.lcd_write_data(0x0C) 64 | self.lcd_write_data(0x00) 65 | self.lcd_write_data(0x33) 66 | self.lcd_write_data(0x33) 67 | 68 | self.lcd_write_cmd(0xB7) 69 | self.lcd_write_data(0x35) 70 | 71 | self.lcd_write_cmd(0xBB) 72 | self.lcd_write_data(0x19) 73 | 74 | self.lcd_write_cmd(0xC0) 75 | self.lcd_write_data(0x2C) 76 | 77 | self.lcd_write_cmd(0xC2) 78 | self.lcd_write_data(0x01) 79 | 80 | self.lcd_write_cmd(0xC3) 81 | self.lcd_write_data(0x12) 82 | 83 | self.lcd_write_cmd(0xC4) 84 | self.lcd_write_data(0x20) 85 | 86 | self.lcd_write_cmd(0xC6) 87 | self.lcd_write_data(0x0F) 88 | 89 | self.lcd_write_cmd(0xD0) 90 | self.lcd_write_data(0xA4) 91 | self.lcd_write_data(0xA1) 92 | 93 | self.lcd_write_cmd(0xE0) 94 | self.lcd_write_data(0xD0) 95 | self.lcd_write_data(0x04) 96 | self.lcd_write_data(0x0D) 97 | self.lcd_write_data(0x11) 98 | self.lcd_write_data(0x13) 99 | self.lcd_write_data(0x2B) 100 | self.lcd_write_data(0x3F) 101 | self.lcd_write_data(0x54) 102 | self.lcd_write_data(0x4C) 103 | self.lcd_write_data(0x18) 104 | self.lcd_write_data(0x0D) 105 | self.lcd_write_data(0x0B) 106 | self.lcd_write_data(0x1F) 107 | self.lcd_write_data(0x23) 108 | 109 | self.lcd_write_cmd(0xE1) 110 | self.lcd_write_data(0xD0) 111 | self.lcd_write_data(0x04) 112 | self.lcd_write_data(0x0C) 113 | self.lcd_write_data(0x11) 114 | self.lcd_write_data(0x13) 115 | self.lcd_write_data(0x2C) 116 | self.lcd_write_data(0x3F) 117 | self.lcd_write_data(0x44) 118 | self.lcd_write_data(0x51) 119 | self.lcd_write_data(0x2F) 120 | self.lcd_write_data(0x1F) 121 | self.lcd_write_data(0x1F) 122 | self.lcd_write_data(0x20) 123 | self.lcd_write_data(0x23) 124 | 125 | self.lcd_write_cmd(0x21) 126 | 127 | self.lcd_write_cmd(0x11) 128 | 129 | self.lcd_write_cmd(0x29) 130 | 131 | def lcd_show(self): 132 | self.lcd_write_cmd(0x2A) 133 | self.lcd_write_data(0x00) 134 | self.lcd_write_data(0x28) 135 | self.lcd_write_data(0x01) 136 | self.lcd_write_data(0x17) 137 | 138 | self.lcd_write_cmd(0x2B) 139 | self.lcd_write_data(0x00) 140 | self.lcd_write_data(0x35) 141 | self.lcd_write_data(0x00) 142 | self.lcd_write_data(0xBB) 143 | 144 | self.lcd_write_cmd(0x2C) 145 | 146 | self.cs(1) 147 | self.dc(1) 148 | self.cs(0) 149 | self.spi.write(self.buffer) 150 | self.cs(1) 151 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pico-Sense-HAT 2 | 3 | 4 | 5 | 6 | ## About the product 7 | * Pico sense hat have four sensors and these sensors have definate addresses 8 | * SGP40 Air quality sensor (addr=0x59) 9 | * SHT31 Temperature and Humidity sensor (addr=0x45) 10 | * BME280 Pressure sensor (0x76) 11 | * TCS34725 Color sensor (addr=0x29) 12 | 13 | 14 | ## Files in the folder 15 | ### In folder you see 6 files (except reabme.md file) 16 | * There are 5 libraries in this folder you need to save these libraries in the raspberry pi pico, 17 | 4 libraries of sensors and 1 library of lcd display 18 | * sgp40.py 19 | * sht31.py 20 | * bme280.py 21 | * tcs34725.py 22 | * Lcd1_14driver.py 23 | 24 | * One file is there in the folder which run the main code (this code display the sensor reading), 25 | this code import all the libraries of sensors and lcd display, 26 | * pico_sense_hat.py 27 | 28 | 29 | 30 | ## For setup the Board in thonny 31 | * Now connect USB Cable on USB Port of Pico. 32 | * Open Thonny IDE and Choose interpreter as MicroPython (Raspberry Pi pico). 33 | 34 | 35 | 36 | 37 | 38 | #### Now save the all the libraries inside the raspberry pi pico 39 | 40 | 41 | ### Rename the pico_sense_hat.py to main.py and save this also inside pico (main.py code automatically run when pico power on) 42 | 43 | 44 | 45 | # Working 46 | 47 | 48 | ### Pico Sense HAT Wiki Portal 49 | 50 | ## Pico Sence HAT Getting Started 51 | 52 | https://www.youtube.com/watch?v=j3DhHOlqDR0 53 | 54 | -------------------------------------------------------------------------------- /ST7789 Driver Pico Sense HAT/README.md: -------------------------------------------------------------------------------- 1 | ## Pico Sense HAT Run via ST7789 lcd driver 2 | 3 | ## Uploading the ST7789 Python Firmware (we already update in this repository, this library has many functions) 4 | * The firmware includes frozen python font files and pre-compiled objects with the st7789 C driver for a variety of devices. 5 | * The driver's library is provided as a single firmware.uf2 file, which is accessible here: 6 | https://github.com/russhughes/st7789_mpy/tree/master/firmware/RP2 7 | 8 | * Holding down the Pico's BOTSEL button while dragging this file into the mounted RP2 folder will allow you to load it(firmware.uf2). 9 | 10 | ## There are 4 libraries(sensors library) in this folder you need to save these libraries in the raspberry pi pico, 11 | * sgp40.py 12 | * sht31.py 13 | * bme280.py 14 | * tcs34725.py 15 | 16 | ## Run this file "pico_sense_hat_st7789.py" 17 | -------------------------------------------------------------------------------- /ST7789 Driver Pico Sense HAT/bme280.py: -------------------------------------------------------------------------------- 1 | from machine import I2C 2 | import time 3 | 4 | # BME280 default address. 5 | BME280_I2CADDR = 0x76 6 | 7 | # Operating Modes 8 | BME280_OSAMPLE_1 = 1 9 | BME280_OSAMPLE_2 = 2 10 | BME280_OSAMPLE_4 = 3 11 | BME280_OSAMPLE_8 = 4 12 | BME280_OSAMPLE_16 = 5 13 | 14 | # BME280 Registers 15 | 16 | BME280_REGISTER_DIG_T1 = 0x88 # Trimming parameter registers 17 | BME280_REGISTER_DIG_T2 = 0x8A 18 | BME280_REGISTER_DIG_T3 = 0x8C 19 | 20 | BME280_REGISTER_DIG_P1 = 0x8E 21 | BME280_REGISTER_DIG_P2 = 0x90 22 | BME280_REGISTER_DIG_P3 = 0x92 23 | BME280_REGISTER_DIG_P4 = 0x94 24 | BME280_REGISTER_DIG_P5 = 0x96 25 | BME280_REGISTER_DIG_P6 = 0x98 26 | BME280_REGISTER_DIG_P7 = 0x9A 27 | BME280_REGISTER_DIG_P8 = 0x9C 28 | BME280_REGISTER_DIG_P9 = 0x9E 29 | 30 | BME280_REGISTER_DIG_H1 = 0xA1 31 | BME280_REGISTER_DIG_H2 = 0xE1 32 | BME280_REGISTER_DIG_H3 = 0xE3 33 | BME280_REGISTER_DIG_H4 = 0xE4 34 | BME280_REGISTER_DIG_H5 = 0xE5 35 | BME280_REGISTER_DIG_H6 = 0xE6 36 | BME280_REGISTER_DIG_H7 = 0xE7 37 | 38 | BME280_REGISTER_CHIPID = 0xD0 39 | BME280_REGISTER_VERSION = 0xD1 40 | BME280_REGISTER_SOFTRESET = 0xE0 41 | 42 | BME280_REGISTER_CONTROL_HUM = 0xF2 43 | BME280_REGISTER_CONTROL = 0xF4 44 | BME280_REGISTER_CONFIG = 0xF5 45 | BME280_REGISTER_PRESSURE_DATA = 0xF7 46 | BME280_REGISTER_TEMP_DATA = 0xFA 47 | BME280_REGISTER_HUMIDITY_DATA = 0xFD 48 | 49 | 50 | class Device: 51 | """Class for communicating with an I2C device. 52 | 53 | Allows reading and writing 8-bit, 16-bit, and byte array values to 54 | registers on the device.""" 55 | 56 | def __init__(self, address, i2c): 57 | """Create an instance of the I2C device at the specified address using 58 | the specified I2C interface object.""" 59 | self._address = address 60 | self._i2c = i2c 61 | 62 | def writeRaw8(self, value): 63 | """Write an 8-bit value on the bus (without register).""" 64 | value = value & 0xFF 65 | self._i2c.writeto(self._address, value) 66 | 67 | def write8(self, register, value): 68 | """Write an 8-bit value to the specified register.""" 69 | b=bytearray(1) 70 | b[0]=value & 0xFF 71 | self._i2c.writeto_mem(self._address, register, b) 72 | 73 | def write16(self, register, value): 74 | """Write a 16-bit value to the specified register.""" 75 | value = value & 0xFFFF 76 | b=bytearray(2) 77 | b[0]= value & 0xFF 78 | b[1]= (value>>8) & 0xFF 79 | self.i2c.writeto_mem(self._address, register, value) 80 | 81 | def readRaw8(self): 82 | """Read an 8-bit value on the bus (without register).""" 83 | return int.from_bytes(self._i2c.readfrom(self._address, 1),'little') & 0xFF 84 | 85 | def readU8(self, register): 86 | """Read an unsigned byte from the specified register.""" 87 | return int.from_bytes( 88 | self._i2c.readfrom_mem(self._address, register, 1),'little') & 0xFF 89 | 90 | def readS8(self, register): 91 | """Read a signed byte from the specified register.""" 92 | result = self.readU8(register) 93 | if result > 127: 94 | result -= 256 95 | return result 96 | 97 | def readU16(self, register, little_endian=True): 98 | """Read an unsigned 16-bit value from the specified register, with the 99 | specified endianness (default little endian, or least significant byte 100 | first).""" 101 | result = int.from_bytes( 102 | self._i2c.readfrom_mem(self._address, register, 2),'little') & 0xFFFF 103 | if not little_endian: 104 | result = ((result << 8) & 0xFF00) + (result >> 8) 105 | return result 106 | 107 | def readS16(self, register, little_endian=True): 108 | """Read a signed 16-bit value from the specified register, with the 109 | specified endianness (default little endian, or least significant byte 110 | first).""" 111 | result = self.readU16(register, little_endian) 112 | if result > 32767: 113 | result -= 65536 114 | return result 115 | 116 | def readU16LE(self, register): 117 | """Read an unsigned 16-bit value from the specified register, in little 118 | endian byte order.""" 119 | return self.readU16(register, little_endian=True) 120 | 121 | def readU16BE(self, register): 122 | """Read an unsigned 16-bit value from the specified register, in big 123 | endian byte order.""" 124 | return self.readU16(register, little_endian=False) 125 | 126 | def readS16LE(self, register): 127 | """Read a signed 16-bit value from the specified register, in little 128 | endian byte order.""" 129 | return self.readS16(register, little_endian=True) 130 | 131 | def readS16BE(self, register): 132 | """Read a signed 16-bit value from the specified register, in big 133 | endian byte order.""" 134 | return self.readS16(register, little_endian=False) 135 | 136 | 137 | class BME280: 138 | def __init__(self, mode=BME280_OSAMPLE_1, address=BME280_I2CADDR, i2c=None, 139 | **kwargs): 140 | # Check that mode is valid. 141 | if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4, 142 | BME280_OSAMPLE_8, BME280_OSAMPLE_16]: 143 | raise ValueError( 144 | 'Unexpected mode value {0}. Set mode to one of ' 145 | 'BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or ' 146 | 'BME280_ULTRAHIGHRES'.format(mode)) 147 | self._mode = mode 148 | # Create I2C device. 149 | if i2c is None: 150 | raise ValueError('An I2C object is required.') 151 | self._device = Device(address, i2c) 152 | # Load calibration values. 153 | self._load_calibration() 154 | self._device.write8(BME280_REGISTER_CONTROL, 0x3F) 155 | self.t_fine = 0 156 | 157 | def _load_calibration(self): 158 | 159 | self.dig_T1 = self._device.readU16LE(BME280_REGISTER_DIG_T1) 160 | self.dig_T2 = self._device.readS16LE(BME280_REGISTER_DIG_T2) 161 | self.dig_T3 = self._device.readS16LE(BME280_REGISTER_DIG_T3) 162 | 163 | self.dig_P1 = self._device.readU16LE(BME280_REGISTER_DIG_P1) 164 | self.dig_P2 = self._device.readS16LE(BME280_REGISTER_DIG_P2) 165 | self.dig_P3 = self._device.readS16LE(BME280_REGISTER_DIG_P3) 166 | self.dig_P4 = self._device.readS16LE(BME280_REGISTER_DIG_P4) 167 | self.dig_P5 = self._device.readS16LE(BME280_REGISTER_DIG_P5) 168 | self.dig_P6 = self._device.readS16LE(BME280_REGISTER_DIG_P6) 169 | self.dig_P7 = self._device.readS16LE(BME280_REGISTER_DIG_P7) 170 | self.dig_P8 = self._device.readS16LE(BME280_REGISTER_DIG_P8) 171 | self.dig_P9 = self._device.readS16LE(BME280_REGISTER_DIG_P9) 172 | 173 | self.dig_H1 = self._device.readU8(BME280_REGISTER_DIG_H1) 174 | self.dig_H2 = self._device.readS16LE(BME280_REGISTER_DIG_H2) 175 | self.dig_H3 = self._device.readU8(BME280_REGISTER_DIG_H3) 176 | self.dig_H6 = self._device.readS8(BME280_REGISTER_DIG_H7) 177 | 178 | h4 = self._device.readS8(BME280_REGISTER_DIG_H4) 179 | h4 = (h4 << 24) >> 20 180 | self.dig_H4 = h4 | (self._device.readU8(BME280_REGISTER_DIG_H5) & 0x0F) 181 | 182 | h5 = self._device.readS8(BME280_REGISTER_DIG_H6) 183 | h5 = (h5 << 24) >> 20 184 | self.dig_H5 = h5 | ( 185 | self._device.readU8(BME280_REGISTER_DIG_H5) >> 4 & 0x0F) 186 | 187 | def read_raw_temp(self): 188 | """Reads the raw (uncompensated) temperature from the sensor.""" 189 | meas = self._mode 190 | self._device.write8(BME280_REGISTER_CONTROL_HUM, meas) 191 | meas = self._mode << 5 | self._mode << 2 | 1 192 | self._device.write8(BME280_REGISTER_CONTROL, meas) 193 | sleep_time = 1250 + 2300 * (1 << self._mode) 194 | 195 | sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 196 | sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 197 | time.sleep_us(sleep_time) # Wait the required time 198 | msb = self._device.readU8(BME280_REGISTER_TEMP_DATA) 199 | lsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 1) 200 | xlsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 2) 201 | raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4 202 | return raw 203 | 204 | def read_raw_pressure(self): 205 | """Reads the raw (uncompensated) pressure level from the sensor.""" 206 | """Assumes that the temperature has already been read """ 207 | """i.e. that enough delay has been provided""" 208 | msb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA) 209 | lsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 1) 210 | xlsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 2) 211 | raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4 212 | return raw 213 | 214 | def read_raw_humidity(self): 215 | """Assumes that the temperature has already been read """ 216 | """i.e. that enough delay has been provided""" 217 | msb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA) 218 | lsb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA + 1) 219 | raw = (msb << 8) | lsb 220 | return raw 221 | 222 | def read_temperature(self): 223 | """Get the compensated temperature in 0.01 of a degree celsius.""" 224 | adc = self.read_raw_temp() 225 | var1 = ((adc >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11) 226 | var2 = (( 227 | (((adc >> 4) - self.dig_T1) * ((adc >> 4) - self.dig_T1)) >> 12) * 228 | self.dig_T3) >> 14 229 | self.t_fine = var1 + var2 230 | return (self.t_fine * 5 + 128) >> 8 231 | 232 | def read_pressure(self): 233 | """Gets the compensated pressure in Pascals.""" 234 | adc = self.read_raw_pressure() 235 | var1 = self.t_fine - 128000 236 | var2 = var1 * var1 * self.dig_P6 237 | var2 = var2 + ((var1 * self.dig_P5) << 17) 238 | var2 = var2 + (self.dig_P4 << 35) 239 | var1 = (((var1 * var1 * self.dig_P3) >> 8) + 240 | ((var1 * self.dig_P2) >> 12)) 241 | var1 = (((1 << 47) + var1) * self.dig_P1) >> 33 242 | if var1 == 0: 243 | return 0 244 | p = 1048576 - adc 245 | p = (((p << 31) - var2) * 3125) // var1 246 | var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25 247 | var2 = (self.dig_P8 * p) >> 19 248 | return ((p + var1 + var2) >> 8) + (self.dig_P7 << 4) 249 | 250 | def read_humidity(self): 251 | adc = self.read_raw_humidity() 252 | # print 'Raw humidity = {0:d}'.format (adc) 253 | h = self.t_fine - 76800 254 | h = (((((adc << 14) - (self.dig_H4 << 20) - (self.dig_H5 * h)) + 255 | 16384) >> 15) * (((((((h * self.dig_H6) >> 10) * (((h * 256 | self.dig_H3) >> 11) + 32768)) >> 10) + 2097152) * 257 | self.dig_H2 + 8192) >> 14)) 258 | h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4) 259 | h = 0 if h < 0 else h 260 | h = 419430400 if h > 419430400 else h 261 | return h >> 12 262 | 263 | @property 264 | def temperature(self): 265 | "Return the temperature in degrees." 266 | t = self.read_temperature() 267 | ti = t // 100 268 | td = t - ti * 100 269 | return "{}.{:02d}C".format(ti, td) 270 | 271 | @property 272 | def pressure(self): 273 | "Return the temperature in hPa." 274 | p = self.read_pressure() // 256 275 | pi = p // 100 276 | pd = p - pi * 100 277 | return "{}.{:02d}".format(pi, pd) 278 | 279 | @property 280 | def humidity(self): 281 | "Return the humidity in percent." 282 | h = self.read_humidity() 283 | hi = h // 1024 284 | hd = h * 100 // 1024 - hi * 100 285 | return "{}.{:02d}%".format(hi, hd) -------------------------------------------------------------------------------- /ST7789 Driver Pico Sense HAT/firmware.uf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sbcshop/Pico-Sense-HAT/45b19d69b5e6c3bdfc80cc72814f0e449a117b86/ST7789 Driver Pico Sense HAT/firmware.uf2 -------------------------------------------------------------------------------- /ST7789 Driver Pico Sense HAT/pico_sense_hat_st7789.py: -------------------------------------------------------------------------------- 1 | import time,utime 2 | from machine import I2C, Pin, SPI 3 | from sgp40 import SGP40 4 | import bme280 5 | import tcs34725 6 | import sht31 7 | import st7789 8 | import vga1_bold_16x32 as font 9 | import vga1_8x16 as font1 10 | 11 | i2c = I2C(1,scl=Pin(7), sda=Pin(6), freq=40000)#all sensor connected through I2C 12 | 13 | rst = machine.Pin(3, machine.Pin.OUT)#GPIO 3(OUTPUT) pin to enable address of temperature and humidity sht21 sensor 14 | rst.value(1)#high GPIO 3 pin to enable address of temperature and humidity sht21 sensor 15 | 16 | spi = SPI(1, baudrate=40000000, sck=Pin(10), mosi=Pin(11)) 17 | tft = st7789.ST7789(spi,135,240,reset=Pin(12, Pin.OUT),cs=Pin(9, Pin.OUT),dc=Pin(8, Pin.OUT),backlight=Pin(26, Pin.OUT),rotation=1)#SPI interface for tft screen 18 | 19 | bme = bme280.BME280(i2c=i2c) #pressure,temperature and humidity sensor 20 | color = tcs34725.TCS34725(i2c)#color sensor 21 | air_quality = SGP40(i2c, 0x59)#air quality sensor 22 | temp_hum = sht31.SHT31(i2c, addr=0x45)#temperature and humidity 23 | 24 | def info(): 25 | tft.init() 26 | tft.fill(st7789.BLACK) 27 | time.sleep(0.5)#time delay 28 | tft.text(font1,"SB-COMPONENTS PICO SENSE HAT",5,5,st7789.RED) 29 | tft.text(font1,"SENSOR READING",70,25,st7789.RED) 30 | tft.text(font1,"PRESSURE : ",10,50,st7789.YELLOW) 31 | tft.text(font1,"TEMPERATURE :",10,65,st7789.YELLOW) 32 | tft.text(font1,"HUMIDITY : ",10,80,st7789.YELLOW) 33 | tft.text(font1,"AIR QUALITY :",10,95,st7789.YELLOW) 34 | tft.text(font1,"COLOR :",10,110,st7789.YELLOW) 35 | info() 36 | while True: 37 | #temp,hum,press = bme.temperature,bme.humidity,bme.pressure #uncomment this line for use of temperature and humidity 38 | pressure = bme.pressure # we use only pressure from BME sensor, you can also read temperature and humidity as ewll 39 | Temp_Humid = temp_hum.get_temp_humi() 40 | Temp_Humid = list(Temp_Humid) 41 | Air_quality = air_quality.measure_raw() 42 | Color = color.read('rgb') 43 | 44 | temperature = "{0}{1:.2f}C".format("", Temp_Humid[0]) 45 | humidity = "{0}{1:.2f}%".format("", Temp_Humid[1]) 46 | 47 | print("Prssure ",pressure) 48 | print("Temperature = ",temperature) 49 | print("humidity = ",humidity) 50 | print("Air quality = ",Air_quality) 51 | print("Color = ",Color)#R,G,B,C 52 | 53 | ''' 54 | # **** uncomment this if you need temperature in fahrenheit ******** 55 | 56 | fahrenheit = float(Temp_Humid[0]) * 1.8 + 32 57 | fahrenheit = "{:.2f}".format(fahrenheit) 58 | print("Temperature in fahrenheit = ",fahrenheit) 59 | ''' 60 | 61 | ''' 62 | # **** uncomment this if you need pressure in psi, mmhg and atm ******** 63 | 64 | press = pressure.split('h') 65 | kpa = float(press[0]) * 10 66 | psi = kpa / 6.89475729 67 | mmhg = kpa * 760 / 101.325 68 | atm = kpa / 101.325 69 | print("Pounds per square inch: %.2f psi" % (psi)) 70 | print("Millimeter of mercury: %.2f mmHg" % (mmhg)) 71 | print("Atmosphere pressure: %.2f atm." % (atm)) 72 | ''' 73 | 74 | tft.text(font1,pressure, 120,50,st7789.WHITE)# print on tft screen 75 | tft.text(font1,str(temperature), 120,65,st7789.WHITE)# print on tft screen 76 | tft.text(font1,str(humidity), 120,80,st7789.WHITE)# print on tft screen 77 | tft.text(font1,str(Air_quality), 120,95,st7789.WHITE)# print on tft screen 78 | tft.text(font1,str(Color), 120,110,st7789.WHITE)# print on tft screen 79 | 80 | time.sleep(0.1) 81 | 82 | tft.text(font1,pressure, 120,50,st7789.WHITE)# print on tft screen 83 | tft.text(font1,str(temperature), 120,65,st7789.WHITE)# print on tft screen 84 | tft.text(font1,str(humidity), 120,80,st7789.WHITE)# print on tft screen 85 | tft.text(font1,str(Air_quality), 120,95,st7789.WHITE)# print on tft screen 86 | tft.text(font1,str(Color), 120,110,st7789.WHITE)# print on tft screen 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /ST7789 Driver Pico Sense HAT/sgp40.py: -------------------------------------------------------------------------------- 1 | from machine import I2C 2 | import utime 3 | import struct 4 | import math 5 | 6 | class SGP40: 7 | 8 | class NotFoundException(Exception): 9 | pass 10 | 11 | class NotSupportedException(Exception): 12 | pass 13 | 14 | class CRCException(Exception): 15 | pass 16 | 17 | MEASUREMENT_RAW = 0x260f 18 | MEASUREMENT_TEST = 0x280e 19 | HEATER_OFF = 0x3615 20 | RESET = 0x0006 21 | 22 | GET_SERIAL_ID = 0x3682 23 | GET_FEATURESET = 0x202f 24 | 25 | # Generated using 26 | # crc_table = [] 27 | # for crc in range(256): 28 | # for crc_bit in range(8): 29 | # if crc & 0x80: 30 | # crc = (crc << 1) ^ CRC8_POLYNOMIAL; 31 | # else: 32 | # crc = (crc << 1); 33 | # crc = crc%256 34 | # crc_table.append(crc) 35 | 36 | CRC_TABLE = [ 37 | 0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, 38 | 67, 114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, 39 | 134, 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168, 40 | 197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235, 41 | 61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19, 42 | 126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, 43 | 187, 138, 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, 44 | 248, 201, 154, 171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214, 45 | 122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84, 46 | 57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23, 47 | 252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, 48 | 191, 142, 221, 236, 123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, 49 | 71, 118, 37, 20, 131, 178, 225, 208, 254, 207, 156, 173, 58, 11, 88, 105, 50 | 4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238, 121, 72, 27, 42, 51 | 193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239, 52 | 130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172 53 | ] 54 | 55 | def __init__(self, i2c, addr=0x59): 56 | self.i2c = i2c 57 | self.addr = addr 58 | if not addr in i2c.scan(): 59 | raise self.NotFoundException 60 | 61 | def measure_raw(self, humidity=50, temperature=25): 62 | paramh = struct.pack(">H", math.ceil(humidity * 0xffff / 100)) 63 | crch = self.__crc(paramh[0], paramh[1]) 64 | paramt = struct.pack(">H", math.ceil((temperature + 45) * 0xffff / 175)) 65 | crct = self.__crc(paramt[0], paramt[1]) 66 | data = paramh + bytes([crch]) + paramt + bytes([crct]) 67 | self.i2c.writeto_mem(self.addr, self.MEASUREMENT_RAW, data, addrsize=16) 68 | utime.sleep_ms(30) 69 | raw = self.i2c.readfrom(self.addr, 3) 70 | self.__check_crc(raw) 71 | return struct.unpack('>H', raw[:2])[0] 72 | 73 | def measure_test(self): 74 | raw = self.__read_bytes(self.MEASUREMENT_TEST, 3, 250000) 75 | self.__check_crc(raw) 76 | return struct.unpack('>H', raw[:2])[0] 77 | 78 | def reset(self): 79 | self.__write_command(self.RESET) 80 | 81 | def heater_off(self): 82 | self.__write_command(self.HEATER_OFF) 83 | 84 | def get_serial_id(self): 85 | data = self.__read_bytes(self.GET_SERIAL_ID, 6, 500) 86 | return data 87 | 88 | def __write_command(self, cmd): 89 | bcmd = struct.pack('>H', cmd) 90 | self.i2c.writeto(self.addr, bcmd) 91 | 92 | def __read_bytes(self, cmd, count, pause): 93 | self.__write_command(cmd) 94 | utime.sleep_us(pause) 95 | return self.i2c.readfrom(self.addr, count) 96 | 97 | def __check_crc(self, arr): 98 | assert (len(arr) == 3) 99 | if self.__crc(arr[0], arr[1]) != arr[2]: 100 | raise self.CRCException 101 | 102 | def __crc(self, msb, lsb): 103 | crc = 0xff 104 | crc ^= msb 105 | crc = self.CRC_TABLE[crc] 106 | if lsb is not None: 107 | crc ^= lsb 108 | crc = self.CRC_TABLE[crc] 109 | return crc 110 | 111 | -------------------------------------------------------------------------------- /ST7789 Driver Pico Sense HAT/sht31.py: -------------------------------------------------------------------------------- 1 | from machine import I2C 2 | import time 3 | 4 | R_HIGH = const(1) 5 | R_MEDIUM = const(2) 6 | R_LOW = const(3) 7 | 8 | class SHT31(object): 9 | """ 10 | This class implements an interface to the SHT31 temprature and humidity 11 | sensor from Sensirion. 12 | """ 13 | 14 | # This static map helps keeping the heap and program logic cleaner 15 | _map_cs_r = { 16 | True: { 17 | R_HIGH : b'\x2c\x06', 18 | R_MEDIUM : b'\x2c\x0d', 19 | R_LOW: b'\x2c\x10' 20 | }, 21 | False: { 22 | R_HIGH : b'\x24\x00', 23 | R_MEDIUM : b'\x24\x0b', 24 | R_LOW: b'\x24\x16' 25 | } 26 | } 27 | 28 | def __init__(self, i2c, addr=0x45): 29 | """ 30 | Initialize a sensor object on the given I2C bus and accessed by the 31 | given address. 32 | """ 33 | if i2c == None: 34 | raise ValueError('I2C object needed as argument!') 35 | self._i2c = i2c 36 | self._addr = addr 37 | 38 | def _send(self, buf): 39 | """ 40 | Sends the given buffer object over I2C to the sensor. 41 | """ 42 | self._i2c.writeto(self._addr, buf) 43 | 44 | def _recv(self, count): 45 | """ 46 | Read bytes from the sensor using I2C. The byte count can be specified 47 | as an argument. 48 | Returns a bytearray for the result. 49 | """ 50 | return self._i2c.readfrom(self._addr, count) 51 | 52 | def _raw_temp_humi(self, r=R_HIGH, cs=True): 53 | """ 54 | Read the raw temperature and humidity from the sensor and skips CRC 55 | checking. 56 | Returns a tuple for both values in that order. 57 | """ 58 | if r not in (R_HIGH, R_MEDIUM, R_LOW): 59 | raise ValueError('Wrong repeatabillity value given!') 60 | self._send(self._map_cs_r[cs][r]) 61 | time.sleep_ms(50) 62 | raw = self._recv(6) 63 | return (raw[0] << 8) + raw[1], (raw[3] << 8) + raw[4] 64 | 65 | def get_temp_humi(self, resolution=R_HIGH, clock_stretch=True, celsius=True): 66 | """ 67 | Read the temperature in degree celsius or fahrenheit and relative 68 | humidity. Resolution and clock stretching can be specified. 69 | Returns a tuple for both values in that order. 70 | """ 71 | t, h = self._raw_temp_humi(resolution, clock_stretch) 72 | if celsius: 73 | temp = -45 + (175 * (t / 65535)) 74 | else: 75 | temp = -49 + (315 * (t / 65535)) 76 | return temp, 100 * (h / 65535) 77 | -------------------------------------------------------------------------------- /ST7789 Driver Pico Sense HAT/tcs34725.py: -------------------------------------------------------------------------------- 1 | import time 2 | import ustruct 3 | 4 | #const = lambda x:x 5 | 6 | _COMMAND_BIT = const(0x80) 7 | 8 | _REGISTER_ENABLE = const(0x00) 9 | _REGISTER_ATIME = const(0x01) 10 | 11 | _REGISTER_AILT = const(0x04) 12 | _REGISTER_AIHT = const(0x06) 13 | 14 | _REGISTER_ID = const(0x12) 15 | 16 | _REGISTER_APERS = const(0x0c) 17 | 18 | _REGISTER_CONTROL = const(0x0f) 19 | 20 | _REGISTER_SENSORID = const(0x12) 21 | 22 | _REGISTER_STATUS = const(0x13) 23 | _REGISTER_CDATA = const(0x14) 24 | _REGISTER_RDATA = const(0x16) 25 | _REGISTER_GDATA = const(0x18) 26 | _REGISTER_BDATA = const(0x1a) 27 | 28 | _ENABLE_AIEN = const(0x10) 29 | _ENABLE_WEN = const(0x08) 30 | _ENABLE_AEN = const(0x02) 31 | _ENABLE_PON = const(0x01) 32 | 33 | _GAINS = (1, 4, 16, 60) 34 | _CYCLES = (0, 1, 2, 3, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60) 35 | 36 | 37 | class TCS34725: 38 | def __init__(self, i2c, address=0x29): 39 | self.i2c = i2c 40 | self.address = address 41 | self._active = False 42 | self.integration_time(2.4) 43 | sensor_id = self.sensor_id() 44 | if sensor_id not in (0x44, 0x10): 45 | raise RuntimeError("wrong sensor id 0x{:x}".format(sensor_id)) 46 | 47 | def _register8(self, register, value=None): 48 | register |= _COMMAND_BIT 49 | if value is None: 50 | return self.i2c.readfrom_mem(self.address, register, 1)[0] 51 | data = ustruct.pack('>8) & 0xFF 79 | self.i2c.writeto_mem(self._address, register, value) 80 | 81 | def readRaw8(self): 82 | """Read an 8-bit value on the bus (without register).""" 83 | return int.from_bytes(self._i2c.readfrom(self._address, 1),'little') & 0xFF 84 | 85 | def readU8(self, register): 86 | """Read an unsigned byte from the specified register.""" 87 | return int.from_bytes( 88 | self._i2c.readfrom_mem(self._address, register, 1),'little') & 0xFF 89 | 90 | def readS8(self, register): 91 | """Read a signed byte from the specified register.""" 92 | result = self.readU8(register) 93 | if result > 127: 94 | result -= 256 95 | return result 96 | 97 | def readU16(self, register, little_endian=True): 98 | """Read an unsigned 16-bit value from the specified register, with the 99 | specified endianness (default little endian, or least significant byte 100 | first).""" 101 | result = int.from_bytes( 102 | self._i2c.readfrom_mem(self._address, register, 2),'little') & 0xFFFF 103 | if not little_endian: 104 | result = ((result << 8) & 0xFF00) + (result >> 8) 105 | return result 106 | 107 | def readS16(self, register, little_endian=True): 108 | """Read a signed 16-bit value from the specified register, with the 109 | specified endianness (default little endian, or least significant byte 110 | first).""" 111 | result = self.readU16(register, little_endian) 112 | if result > 32767: 113 | result -= 65536 114 | return result 115 | 116 | def readU16LE(self, register): 117 | """Read an unsigned 16-bit value from the specified register, in little 118 | endian byte order.""" 119 | return self.readU16(register, little_endian=True) 120 | 121 | def readU16BE(self, register): 122 | """Read an unsigned 16-bit value from the specified register, in big 123 | endian byte order.""" 124 | return self.readU16(register, little_endian=False) 125 | 126 | def readS16LE(self, register): 127 | """Read a signed 16-bit value from the specified register, in little 128 | endian byte order.""" 129 | return self.readS16(register, little_endian=True) 130 | 131 | def readS16BE(self, register): 132 | """Read a signed 16-bit value from the specified register, in big 133 | endian byte order.""" 134 | return self.readS16(register, little_endian=False) 135 | 136 | 137 | class BME280: 138 | def __init__(self, mode=BME280_OSAMPLE_1, address=BME280_I2CADDR, i2c=None, 139 | **kwargs): 140 | # Check that mode is valid. 141 | if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4, 142 | BME280_OSAMPLE_8, BME280_OSAMPLE_16]: 143 | raise ValueError( 144 | 'Unexpected mode value {0}. Set mode to one of ' 145 | 'BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or ' 146 | 'BME280_ULTRAHIGHRES'.format(mode)) 147 | self._mode = mode 148 | # Create I2C device. 149 | if i2c is None: 150 | raise ValueError('An I2C object is required.') 151 | self._device = Device(address, i2c) 152 | # Load calibration values. 153 | self._load_calibration() 154 | self._device.write8(BME280_REGISTER_CONTROL, 0x3F) 155 | self.t_fine = 0 156 | 157 | def _load_calibration(self): 158 | 159 | self.dig_T1 = self._device.readU16LE(BME280_REGISTER_DIG_T1) 160 | self.dig_T2 = self._device.readS16LE(BME280_REGISTER_DIG_T2) 161 | self.dig_T3 = self._device.readS16LE(BME280_REGISTER_DIG_T3) 162 | 163 | self.dig_P1 = self._device.readU16LE(BME280_REGISTER_DIG_P1) 164 | self.dig_P2 = self._device.readS16LE(BME280_REGISTER_DIG_P2) 165 | self.dig_P3 = self._device.readS16LE(BME280_REGISTER_DIG_P3) 166 | self.dig_P4 = self._device.readS16LE(BME280_REGISTER_DIG_P4) 167 | self.dig_P5 = self._device.readS16LE(BME280_REGISTER_DIG_P5) 168 | self.dig_P6 = self._device.readS16LE(BME280_REGISTER_DIG_P6) 169 | self.dig_P7 = self._device.readS16LE(BME280_REGISTER_DIG_P7) 170 | self.dig_P8 = self._device.readS16LE(BME280_REGISTER_DIG_P8) 171 | self.dig_P9 = self._device.readS16LE(BME280_REGISTER_DIG_P9) 172 | 173 | self.dig_H1 = self._device.readU8(BME280_REGISTER_DIG_H1) 174 | self.dig_H2 = self._device.readS16LE(BME280_REGISTER_DIG_H2) 175 | self.dig_H3 = self._device.readU8(BME280_REGISTER_DIG_H3) 176 | self.dig_H6 = self._device.readS8(BME280_REGISTER_DIG_H7) 177 | 178 | h4 = self._device.readS8(BME280_REGISTER_DIG_H4) 179 | h4 = (h4 << 24) >> 20 180 | self.dig_H4 = h4 | (self._device.readU8(BME280_REGISTER_DIG_H5) & 0x0F) 181 | 182 | h5 = self._device.readS8(BME280_REGISTER_DIG_H6) 183 | h5 = (h5 << 24) >> 20 184 | self.dig_H5 = h5 | ( 185 | self._device.readU8(BME280_REGISTER_DIG_H5) >> 4 & 0x0F) 186 | 187 | def read_raw_temp(self): 188 | """Reads the raw (uncompensated) temperature from the sensor.""" 189 | meas = self._mode 190 | self._device.write8(BME280_REGISTER_CONTROL_HUM, meas) 191 | meas = self._mode << 5 | self._mode << 2 | 1 192 | self._device.write8(BME280_REGISTER_CONTROL, meas) 193 | sleep_time = 1250 + 2300 * (1 << self._mode) 194 | 195 | sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 196 | sleep_time = sleep_time + 2300 * (1 << self._mode) + 575 197 | time.sleep_us(sleep_time) # Wait the required time 198 | msb = self._device.readU8(BME280_REGISTER_TEMP_DATA) 199 | lsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 1) 200 | xlsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 2) 201 | raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4 202 | return raw 203 | 204 | def read_raw_pressure(self): 205 | """Reads the raw (uncompensated) pressure level from the sensor.""" 206 | """Assumes that the temperature has already been read """ 207 | """i.e. that enough delay has been provided""" 208 | msb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA) 209 | lsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 1) 210 | xlsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 2) 211 | raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4 212 | return raw 213 | 214 | def read_raw_humidity(self): 215 | """Assumes that the temperature has already been read """ 216 | """i.e. that enough delay has been provided""" 217 | msb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA) 218 | lsb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA + 1) 219 | raw = (msb << 8) | lsb 220 | return raw 221 | 222 | def read_temperature(self): 223 | """Get the compensated temperature in 0.01 of a degree celsius.""" 224 | adc = self.read_raw_temp() 225 | var1 = ((adc >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11) 226 | var2 = (( 227 | (((adc >> 4) - self.dig_T1) * ((adc >> 4) - self.dig_T1)) >> 12) * 228 | self.dig_T3) >> 14 229 | self.t_fine = var1 + var2 230 | return (self.t_fine * 5 + 128) >> 8 231 | 232 | def read_pressure(self): 233 | """Gets the compensated pressure in Pascals.""" 234 | adc = self.read_raw_pressure() 235 | var1 = self.t_fine - 128000 236 | var2 = var1 * var1 * self.dig_P6 237 | var2 = var2 + ((var1 * self.dig_P5) << 17) 238 | var2 = var2 + (self.dig_P4 << 35) 239 | var1 = (((var1 * var1 * self.dig_P3) >> 8) + 240 | ((var1 * self.dig_P2) >> 12)) 241 | var1 = (((1 << 47) + var1) * self.dig_P1) >> 33 242 | if var1 == 0: 243 | return 0 244 | p = 1048576 - adc 245 | p = (((p << 31) - var2) * 3125) // var1 246 | var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25 247 | var2 = (self.dig_P8 * p) >> 19 248 | return ((p + var1 + var2) >> 8) + (self.dig_P7 << 4) 249 | 250 | def read_humidity(self): 251 | adc = self.read_raw_humidity() 252 | # print 'Raw humidity = {0:d}'.format (adc) 253 | h = self.t_fine - 76800 254 | h = (((((adc << 14) - (self.dig_H4 << 20) - (self.dig_H5 * h)) + 255 | 16384) >> 15) * (((((((h * self.dig_H6) >> 10) * (((h * 256 | self.dig_H3) >> 11) + 32768)) >> 10) + 2097152) * 257 | self.dig_H2 + 8192) >> 14)) 258 | h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4) 259 | h = 0 if h < 0 else h 260 | h = 419430400 if h > 419430400 else h 261 | return h >> 12 262 | 263 | @property 264 | def temperature(self): 265 | "Return the temperature in degrees." 266 | t = self.read_temperature() 267 | ti = t // 100 268 | td = t - ti * 100 269 | return "{}.{:02d}C".format(ti, td) 270 | 271 | @property 272 | def pressure(self): 273 | "Return the temperature in hPa." 274 | p = self.read_pressure() // 256 275 | pi = p // 100 276 | pd = p - pi * 100 277 | return "{}.{:02d}hPa".format(pi, pd) 278 | 279 | @property 280 | def humidity(self): 281 | "Return the humidity in percent." 282 | h = self.read_humidity() 283 | hi = h // 1024 284 | hd = h * 100 // 1024 - hi * 100 285 | return "{}.{:02d}%".format(hi, hd) 286 | -------------------------------------------------------------------------------- /pico_sense_hat.py: -------------------------------------------------------------------------------- 1 | import time,utime 2 | from machine import I2C, Pin, SPI 3 | from sgp40 import SGP40 4 | import bme280 5 | import tcs34725 6 | import sht31 7 | import Lcd1_14driver#lcd driver 8 | 9 | LCD = Lcd1_14driver.Lcd1_14() 10 | LCD.fill(LCD.white) 11 | 12 | 13 | i2c = I2C(1,scl=Pin(7), sda=Pin(6), freq=40000)#all sensor connected through I2C 14 | 15 | rst = machine.Pin(3, machine.Pin.OUT)#GPIO 3(OUTPUT) pin to enable address of temperature and humidity sht21 sensor 16 | rst.value(1)#high GPIO 3 pin to enable address of temperature and humidity sht21 sensor 17 | 18 | bme = bme280.BME280(i2c=i2c) #pressure,temperature and humidity sensor 19 | color = tcs34725.TCS34725(i2c)#color sensor 20 | air_quality = SGP40(i2c, 0x59)#air quality sensor 21 | temp_hum = sht31.SHT31(i2c, addr=0x45)#temperature and humidity 22 | 23 | def info(): 24 | LCD.text("SB-COMPONENTS PICO SENSE HAT",5,5,LCD.red) 25 | LCD.text("SENSOR READING",70,25,LCD.red) 26 | LCD.text("PRESSURE : ",10,50,LCD.red) 27 | LCD.text("TEMPERATURE :",10,65,LCD.red) 28 | LCD.text("HUMIDITY : ",10,80,LCD.red) 29 | LCD.text("AIR QUALITY :",10,95,LCD.red) 30 | LCD.text("COLOR :",10,110,LCD.red) 31 | 32 | while True: 33 | #temp,hum,press = bme.temperature,bme.humidity,bme.pressure #uncomment this line for use of temperature and humidity 34 | info() 35 | pressure = bme.pressure # we use only pressure from BME sensor, you can also read temperature and humidity as ewll 36 | Temp_Humid = temp_hum.get_temp_humi() 37 | Temp_Humid = list(Temp_Humid) 38 | Air_quality = air_quality.measure_raw() 39 | Color = color.read('rgb') 40 | 41 | temperature = "{0}{1:.2f}C".format("", Temp_Humid[0]) 42 | humidity = "{0}{1:.2f}%".format("", Temp_Humid[1]) 43 | 44 | print("Prssure ",pressure) 45 | print("Temperature = ",temperature) 46 | print("humidity = ",humidity) 47 | print("Air quality = ",Air_quality) 48 | print("Color = ",Color)#R,G,B,C 49 | 50 | ''' 51 | # **** uncomment this if you need temperature in fahrenheit ******** 52 | 53 | fahrenheit = float(Temp_Humid[0]) * 1.8 + 32 54 | fahrenheit = "{:.2f}".format(fahrenheit) 55 | print("Temperature in fahrenheit = ",fahrenheit) 56 | ''' 57 | 58 | ''' 59 | # **** uncomment this if you need pressure in psi, mmhg and atm ******** 60 | 61 | press = pressure.split('h') 62 | kpa = float(press[0]) * 10 63 | psi = kpa / 6.89475729 64 | mmhg = kpa * 760 / 101.325 65 | atm = kpa / 101.325 66 | print("Pounds per square inch: %.2f psi" % (psi)) 67 | print("Millimeter of mercury: %.2f mmHg" % (mmhg)) 68 | print("Atmosphere pressure: %.2f atm." % (atm)) 69 | ''' 70 | 71 | LCD.text(pressure, 120,50,LCD.blue)# print on tft screen 72 | LCD.text(str(temperature), 120,65,LCD.blue)# print on tft screen 73 | LCD.text(str(humidity), 120,80,LCD.blue)# print on tft screen 74 | LCD.text(str(Air_quality), 120,95,LCD.blue)# print on tft screen 75 | LCD.text(str(Color), 120,110,LCD.blue)# print on tft screen 76 | LCD.lcd_show() 77 | 78 | time.sleep(0.2) 79 | 80 | LCD.text(pressure, 120,50,LCD.white)# print on tft screen 81 | LCD.text(str(temperature), 120,65,LCD.white)# print on tft screen 82 | LCD.text(str(humidity), 120,80,LCD.white)# print on tft screen 83 | LCD.text(str(Air_quality), 120,95,LCD.white)# print on tft screen 84 | LCD.text(str(Color), 120,110,LCD.white)# print on tft screen 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /sgp40.py: -------------------------------------------------------------------------------- 1 | from machine import I2C 2 | import utime 3 | import struct 4 | import math 5 | 6 | class SGP40: 7 | 8 | class NotFoundException(Exception): 9 | pass 10 | 11 | class NotSupportedException(Exception): 12 | pass 13 | 14 | class CRCException(Exception): 15 | pass 16 | 17 | MEASUREMENT_RAW = 0x260f 18 | MEASUREMENT_TEST = 0x280e 19 | HEATER_OFF = 0x3615 20 | RESET = 0x0006 21 | 22 | GET_SERIAL_ID = 0x3682 23 | GET_FEATURESET = 0x202f 24 | 25 | # Generated using 26 | # crc_table = [] 27 | # for crc in range(256): 28 | # for crc_bit in range(8): 29 | # if crc & 0x80: 30 | # crc = (crc << 1) ^ CRC8_POLYNOMIAL; 31 | # else: 32 | # crc = (crc << 1); 33 | # crc = crc%256 34 | # crc_table.append(crc) 35 | 36 | CRC_TABLE = [ 37 | 0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, 38 | 67, 114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, 39 | 134, 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168, 40 | 197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235, 41 | 61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19, 42 | 126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, 43 | 187, 138, 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, 44 | 248, 201, 154, 171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214, 45 | 122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84, 46 | 57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23, 47 | 252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, 48 | 191, 142, 221, 236, 123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, 49 | 71, 118, 37, 20, 131, 178, 225, 208, 254, 207, 156, 173, 58, 11, 88, 105, 50 | 4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238, 121, 72, 27, 42, 51 | 193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239, 52 | 130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172 53 | ] 54 | 55 | def __init__(self, i2c, addr=0x59): 56 | self.i2c = i2c 57 | self.addr = addr 58 | if not addr in i2c.scan(): 59 | raise self.NotFoundException 60 | 61 | def measure_raw(self, humidity=50, temperature=25): 62 | paramh = struct.pack(">H", math.ceil(humidity * 0xffff / 100)) 63 | crch = self.__crc(paramh[0], paramh[1]) 64 | paramt = struct.pack(">H", math.ceil((temperature + 45) * 0xffff / 175)) 65 | crct = self.__crc(paramt[0], paramt[1]) 66 | data = paramh + bytes([crch]) + paramt + bytes([crct]) 67 | self.i2c.writeto_mem(self.addr, self.MEASUREMENT_RAW, data, addrsize=16) 68 | utime.sleep_ms(30) 69 | raw = self.i2c.readfrom(self.addr, 3) 70 | self.__check_crc(raw) 71 | return struct.unpack('>H', raw[:2])[0] 72 | 73 | def measure_test(self): 74 | raw = self.__read_bytes(self.MEASUREMENT_TEST, 3, 250000) 75 | self.__check_crc(raw) 76 | return struct.unpack('>H', raw[:2])[0] 77 | 78 | def reset(self): 79 | self.__write_command(self.RESET) 80 | 81 | def heater_off(self): 82 | self.__write_command(self.HEATER_OFF) 83 | 84 | def get_serial_id(self): 85 | data = self.__read_bytes(self.GET_SERIAL_ID, 6, 500) 86 | return data 87 | 88 | def __write_command(self, cmd): 89 | bcmd = struct.pack('>H', cmd) 90 | self.i2c.writeto(self.addr, bcmd) 91 | 92 | def __read_bytes(self, cmd, count, pause): 93 | self.__write_command(cmd) 94 | utime.sleep_us(pause) 95 | return self.i2c.readfrom(self.addr, count) 96 | 97 | def __check_crc(self, arr): 98 | assert (len(arr) == 3) 99 | if self.__crc(arr[0], arr[1]) != arr[2]: 100 | raise self.CRCException 101 | 102 | def __crc(self, msb, lsb): 103 | crc = 0xff 104 | crc ^= msb 105 | crc = self.CRC_TABLE[crc] 106 | if lsb is not None: 107 | crc ^= lsb 108 | crc = self.CRC_TABLE[crc] 109 | return crc 110 | 111 | -------------------------------------------------------------------------------- /sht31.py: -------------------------------------------------------------------------------- 1 | from machine import I2C 2 | import time 3 | 4 | R_HIGH = const(1) 5 | R_MEDIUM = const(2) 6 | R_LOW = const(3) 7 | 8 | class SHT31(object): 9 | """ 10 | This class implements an interface to the SHT31 temprature and humidity 11 | sensor from Sensirion. 12 | """ 13 | 14 | # This static map helps keeping the heap and program logic cleaner 15 | _map_cs_r = { 16 | True: { 17 | R_HIGH : b'\x2c\x06', 18 | R_MEDIUM : b'\x2c\x0d', 19 | R_LOW: b'\x2c\x10' 20 | }, 21 | False: { 22 | R_HIGH : b'\x24\x00', 23 | R_MEDIUM : b'\x24\x0b', 24 | R_LOW: b'\x24\x16' 25 | } 26 | } 27 | 28 | def __init__(self, i2c, addr=0x45): 29 | """ 30 | Initialize a sensor object on the given I2C bus and accessed by the 31 | given address. 32 | """ 33 | if i2c == None: 34 | raise ValueError('I2C object needed as argument!') 35 | self._i2c = i2c 36 | self._addr = addr 37 | 38 | def _send(self, buf): 39 | """ 40 | Sends the given buffer object over I2C to the sensor. 41 | """ 42 | self._i2c.writeto(self._addr, buf) 43 | 44 | def _recv(self, count): 45 | """ 46 | Read bytes from the sensor using I2C. The byte count can be specified 47 | as an argument. 48 | Returns a bytearray for the result. 49 | """ 50 | return self._i2c.readfrom(self._addr, count) 51 | 52 | def _raw_temp_humi(self, r=R_HIGH, cs=True): 53 | """ 54 | Read the raw temperature and humidity from the sensor and skips CRC 55 | checking. 56 | Returns a tuple for both values in that order. 57 | """ 58 | if r not in (R_HIGH, R_MEDIUM, R_LOW): 59 | raise ValueError('Wrong repeatabillity value given!') 60 | self._send(self._map_cs_r[cs][r]) 61 | time.sleep_ms(50) 62 | raw = self._recv(6) 63 | return (raw[0] << 8) + raw[1], (raw[3] << 8) + raw[4] 64 | 65 | def get_temp_humi(self, resolution=R_HIGH, clock_stretch=True, celsius=True): 66 | """ 67 | Read the temperature in degree celsius or fahrenheit and relative 68 | humidity. Resolution and clock stretching can be specified. 69 | Returns a tuple for both values in that order. 70 | """ 71 | t, h = self._raw_temp_humi(resolution, clock_stretch) 72 | if celsius: 73 | temp = -45 + (175 * (t / 65535)) 74 | else: 75 | temp = -49 + (315 * (t / 65535)) 76 | return temp, 100 * (h / 65535) 77 | -------------------------------------------------------------------------------- /tcs34725.py: -------------------------------------------------------------------------------- 1 | import time 2 | import ustruct 3 | 4 | #const = lambda x:x 5 | 6 | _COMMAND_BIT = const(0x80) 7 | 8 | _REGISTER_ENABLE = const(0x00) 9 | _REGISTER_ATIME = const(0x01) 10 | 11 | _REGISTER_AILT = const(0x04) 12 | _REGISTER_AIHT = const(0x06) 13 | 14 | _REGISTER_ID = const(0x12) 15 | 16 | _REGISTER_APERS = const(0x0c) 17 | 18 | _REGISTER_CONTROL = const(0x0f) 19 | 20 | _REGISTER_SENSORID = const(0x12) 21 | 22 | _REGISTER_STATUS = const(0x13) 23 | _REGISTER_CDATA = const(0x14) 24 | _REGISTER_RDATA = const(0x16) 25 | _REGISTER_GDATA = const(0x18) 26 | _REGISTER_BDATA = const(0x1a) 27 | 28 | _ENABLE_AIEN = const(0x10) 29 | _ENABLE_WEN = const(0x08) 30 | _ENABLE_AEN = const(0x02) 31 | _ENABLE_PON = const(0x01) 32 | 33 | _GAINS = (1, 4, 16, 60) 34 | _CYCLES = (0, 1, 2, 3, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60) 35 | 36 | 37 | class TCS34725: 38 | def __init__(self, i2c, address=0x29): 39 | self.i2c = i2c 40 | self.address = address 41 | self._active = False 42 | self.integration_time(2.4) 43 | sensor_id = self.sensor_id() 44 | if sensor_id not in (0x44, 0x10): 45 | raise RuntimeError("wrong sensor id 0x{:x}".format(sensor_id)) 46 | 47 | def _register8(self, register, value=None): 48 | register |= _COMMAND_BIT 49 | if value is None: 50 | return self.i2c.readfrom_mem(self.address, register, 1)[0] 51 | data = ustruct.pack('