├── 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('