#!/usr/bin/env python # # Distributed with a free-will license. # Use it any way you want, profit or free, provided it fits in the licenses of its associated works. # BME280 # This code is designed to work with the BME280_I2CS I2C Mini Module available from ControlEverything.com. # https://www.controleverything.com/content/Humidity?sku=BME280_I2CS#tabs-0-product_tabset-2 # ''' ### Notes: Inspired on P3Hi video https://www.youtube.com/watch?v=VeyR_STkiT8 See example code for websockets https://websockets.readthedocs.io/en/stable/ NodeRed : sudo-apt-get install nodered install websockets with command: sudo pip3 install websockets install smbus2 with command : sudo pip3 install smbus2 # see https://pypi.org/project/smbus2/0.2.1/#description ''' # import asyncio import grovepi #from smbus2 import SMBus import smbus import time import datetime from threading import Thread, Lock import websockets import traceback # Get I2C bus #b us = SMBus(1) bus = smbus.SMBus(1) async def sendBME280Values(values): async with websockets.connect('ws://127.0.0.1:18189/bme280') as websocket: await websocket.send(values) async def sendFCA33Values(values): async with websockets.connect('ws://127.0.0.1:18189/fca33') as websocket: await websocket.send(values) class oneFCA33(Thread): mutex = Lock() port = 4 values = "" resultString="" stopIt = False def stop(self): self.stopIt = True def __init__(self, sensor): Thread.__init__(self) self.daemon = True self.port = sensor self.start() def run(self): self.stopIt = False print("Start fca33 port:" + "{}".format(self.port)) now = datetime.datetime.now() curMinut = now.minute curHour = now.hour curDay = now.day prevValue = -1 value = 0 countMinut = 0 countHour = 0 countDay = 0 countMinutAvr = -1 countHourAvr = -1 countDayAvr = -1 grovepi.pinMode(self.port,"INPUT") while self.stopIt == False: # Sensor returns HIGH on a black surface and LOW on a white surface now = datetime.datetime.now() value = grovepi.digitalRead(self.port) if curMinut != now.minute: curMinut = now.minute countHour = countHour + countMinut countMinutAvr = self.__calcAvr(countMinutAvr, countMinut) self.resultString = "{}".format(countMinut)+":"+"{0:.1f}".format(countMinutAvr) # print("fca33 countMinut:" + self.resultString) countMinut = 0 if curHour != now.hour: curHour = now.hour countDay = countDay + countHour countHourAvr = self.__calcAvr(countHourAvr, countHour) self.resultString = self.resultString + ";" + "{}".format(countHour)+":"+"{0:.1f}".format(countHourAvr) # print("fca33 countHour:" + self.resultString) countHour = 0 if curDay != now.day: curDay = now.day countDayAvr = self.__calcAvr(countDayAvr, countDay) self.resultString = self.resultString + ";" + "{}".format(countDay)+":"+"{0:.1f}".format(countDayAvr) # print("fca33 countDay:" + self.resultString) countDay = 0 self.mutex.acquire() self.values = '%s' % self.resultString self.mutex.release() if prevValue != value: if value == 1: countMinut = countMinut + 1 prevValue = value time.sleep(0.01) print ("exit fra33.run loop !!") def __calcAvr(self, avr, count): if avr < 0.0: avr = count avr = 0.8 * avr + 0.2 * count return avr def getValues(self): self.mutex.acquire() result = '%s' % self.values self.values = "" self.mutex.release() return result ################################ def oncePerMinuteBME280(): try: # BME280 address, 0x76(118) # Read data back from 0x88(136), 24 bytes b1 = bus.read_i2c_block_data(0x76, 0x88, 24) # Convert the data # Temp coefficients dig_T1 = b1[1] * 256 + b1[0] dig_T2 = b1[3] * 256 + b1[2] if dig_T2 > 32767 : dig_T2 -= 65536 dig_T3 = b1[5] * 256 + b1[4] if dig_T3 > 32767 : dig_T3 -= 65536 # Pressure coefficients dig_P1 = b1[7] * 256 + b1[6] dig_P2 = b1[9] * 256 + b1[8] if dig_P2 > 32767 : dig_P2 -= 65536 dig_P3 = b1[11] * 256 + b1[10] if dig_P3 > 32767 : dig_P3 -= 65536 dig_P4 = b1[13] * 256 + b1[12] if dig_P4 > 32767 : dig_P4 -= 65536 dig_P5 = b1[15] * 256 + b1[14] if dig_P5 > 32767 : dig_P5 -= 65536 dig_P6 = b1[17] * 256 + b1[16] if dig_P6 > 32767 : dig_P6 -= 65536 dig_P7 = b1[19] * 256 + b1[18] if dig_P7 > 32767 : dig_P7 -= 65536 dig_P8 = b1[21] * 256 + b1[20] if dig_P8 > 32767 : dig_P8 -= 65536 dig_P9 = b1[23] * 256 + b1[22] if dig_P9 > 32767 : dig_P9 -= 65536 # BME280 address, 0x76(118) # Read data back from 0xA1(161), 1 byte dig_H1 = bus.read_byte_data(0x76, 0xA1) # BME280 address, 0x76(118) # Read data back from 0xE1(225), 7 bytes b1 = bus.read_i2c_block_data(0x76, 0xE1, 7) # Convert the data # Humidity coefficients dig_H2 = b1[1] * 256 + b1[0] if dig_H2 > 32767 : dig_H2 -= 65536 dig_H3 = (b1[2] & 0xFF) dig_H4 = (b1[3] * 16) + (b1[4] & 0xF) if dig_H4 > 32767 : dig_H4 -= 65536 dig_H5 = (b1[4] / 16) + (b1[5] * 16) if dig_H5 > 32767 : dig_H5 -= 65536 dig_H6 = b1[6] if dig_H6 > 127 : dig_H6 -= 256 # BME280 address, 0x76(118) # Select control humidity register, 0xF2(242) # 0x01(01) Humidity Oversampling = 1 bus.write_byte_data(0x76, 0xF2, 0x01) # BME280 address, 0x76(118) # Select Control measurement register, 0xF4(244) # 0x27(39) Pressure and Temperature Oversampling rate = 1 # Normal mode bus.write_byte_data(0x76, 0xF4, 0x27) # BME280 address, 0x76(118) # Select Configuration register, 0xF5(245) # 0xA0(00) Stand_by time = 1000 ms bus.write_byte_data(0x76, 0xF5, 0xA0) time.sleep(0.5) # BME280 address, 0x76(118) # Read data back from 0xF7(247), 8 bytes # Pressure MSB, Pressure LSB, Pressure xLSB, Temperature MSB, Temperature LSB # Temperature xLSB, Humidity MSB, Humidity LSB data = bus.read_i2c_block_data(0x76, 0xF7, 8) # Convert pressure and temperature data to 19-bits adc_p = ((data[0] * 65536) + (data[1] * 256) + (data[2] & 0xF0)) / 16 adc_t = ((data[3] * 65536) + (data[4] * 256) + (data[5] & 0xF0)) / 16 # Convert the humidity data adc_h = data[6] * 256 + data[7] # Temperature offset calculations var1 = ((adc_t) / 16384.0 - (dig_T1) / 1024.0) * (dig_T2) var2 = (((adc_t) / 131072.0 - (dig_T1) / 8192.0) * ((adc_t)/131072.0 - (dig_T1)/8192.0)) * (dig_T3) t_fine = (var1 + var2) cTemp = (var1 + var2) / 5120.0 fTemp = cTemp * 1.8 + 32 # Pressure offset calculations var1 = (t_fine / 2.0) - 64000.0 var2 = var1 * var1 * (dig_P6) / 32768.0 var2 = var2 + var1 * (dig_P5) * 2.0 var2 = (var2 / 4.0) + ((dig_P4) * 65536.0) var1 = ((dig_P3) * var1 * var1 / 524288.0 + ( dig_P2) * var1) / 524288.0 var1 = (1.0 + var1 / 32768.0) * (dig_P1) p = 1048576.0 - adc_p p = (p - (var2 / 4096.0)) * 6250.0 / var1 var1 = (dig_P9) * p * p / 2147483648.0 var2 = p * (dig_P8) / 32768.0 pressure = (p + (var1 + var2 + (dig_P7)) / 16.0) / 100 # Humidity offset calculations var_H = ((t_fine) - 76800.0) var_H = (adc_h - (dig_H4 * 64.0 + dig_H5 / 16384.0 * var_H)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * var_H * (1.0 + dig_H3 / 67108864.0 * var_H))) humidity = var_H * (1.0 - dig_H1 * var_H / 524288.0) if humidity > 100.0 : humidity = 100.0 elif humidity < 0.0 : humidity = 0.0 # Output data to screen # print ("Temperature Celsius : %.1f C" %cTemp) # print ("Temperature in Fahrenheit : %.1f F" %fTemp) # print ("Pressure : %.1f mbar" %pressure) # print ("Relative Humidity : %.0f %%" %humidity) # print ("") # Output data to the websocket asyncio.get_event_loop().run_until_complete(sendBME280Values("{0:.1f};{1:.1f};{2:.0f}".format(cTemp, pressure, humidity))) except: print("Exception in oncePerMinute") # Create a thread as follows try: fca33 = oneFCA33(4) sendString = "" while True: time.sleep(20.0) sendString = fca33.getValues() # print ("Sendstring: "+sendString) if sendString != "": # print("send ["+sendString+"]") asyncio.get_event_loop().run_until_complete(sendFCA33Values(sendString)) oncePerMinuteBME280() sendString = "" except: traceback.print_exc() finally: fca33.stop()