| # Copyright 2019 Google LLC |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Drivers for shared functionality provided by the Environment Bonnet.""" |
| |
| import os |
| import platform |
| from luma.core.interface.serial import noop, spi |
| from luma.oled.device import ssd1306 |
| |
| |
| def _get_path(sysfs_name): |
| search_path = '/sys/bus/iio/devices/' |
| try: |
| for fname in os.listdir(search_path): |
| with open(search_path + fname + '/name', 'r') as f: |
| if sysfs_name in f.read(): |
| return search_path + fname |
| return '' |
| except FileNotFoundError: |
| return '' |
| |
| |
| def _read_sysfs(path, retries=2): |
| try: |
| with open(path, 'r') as f: |
| # Allow multiple attempts in case sensor times out. |
| for _ in range(retries): |
| try: |
| data = f.read() |
| if data: |
| return float(data) |
| except: |
| pass |
| return None |
| except FileNotFoundError: |
| return None |
| |
| |
| class EnviroBoard(): |
| """ |
| An interface for all input and output modules on the Environmental Sensor Board. |
| """ |
| |
| def __init__(self): |
| # Obtain the full sysfs path of the IIO devices. |
| self._hdc2010 = _get_path('hdc20x0') |
| self._bmp280 = _get_path('bmp280') |
| self._opt3002 = _get_path('opt3001') |
| self._tla2021 = _get_path('ads1015') |
| # Create SSD1306 OLED instance, with SPI as the interface. |
| if 'mendel' in platform.platform(): |
| from .rpi_gpio_periphery import pGPIO |
| # Values for the Coral Dev Board (running Mendel Linux). |
| self._display = ssd1306(serial_interface=spi(gpio=pGPIO(), port=32766, device=0, gpio_DC=138, gpio_RST=140), |
| gpio=pGPIO(), height=32, rotate=2) |
| else: |
| # Default to RPi.GPIO in luma and defaults GPIO. |
| self._display = ssd1306(serial_interface=spi(), |
| gpio=noop(), height=32, rotate=2) |
| |
| @property |
| def temperature(self): |
| """ |
| Gets the current temperature, in Celsius. |
| """ |
| temperature = _read_sysfs(self._hdc2010 + '/in_temp_input') |
| if temperature is not None: |
| return temperature |
| temperature = _read_sysfs(self._bmp280 + '/in_temp_input') |
| # BMP280 reports as mC. |
| if temperature is not None: |
| return temperature / 1000.0 |
| return None |
| |
| @property |
| def humidity(self): |
| """ |
| Gets the current relative humidity, in percentage. |
| """ |
| return _read_sysfs(self._hdc2010 + '/in_humidityrelative_input') |
| |
| @property |
| def ambient_light(self): |
| """ |
| Gets the ambient light, in lux. |
| """ |
| return _read_sysfs(self._opt3002 + '/in_illuminance_input') |
| |
| @property |
| def pressure(self): |
| """ |
| Gets the current atmospheric pressure, in kPa. |
| """ |
| return _read_sysfs(self._bmp280 + '/in_pressure_input') |
| |
| @property |
| def grove_analog(self): |
| """ |
| Gets a raw value from a device connected to the board's analog Grove connector. |
| |
| .. note:: |
| ADC is set to +/- 6V range, independent of supply voltage (selected by jumper). |
| """ |
| return _read_sysfs(self._tla2021 + '/in_voltage0_raw') |
| |
| @property |
| def display(self): |
| """ |
| Gets an instance of :class:`luma.core.device.device` representing the board's OLED display. |
| |
| For example, you can write to the display using :class:`luma.core.render.canvas` |
| as follows:: |
| |
| enviro = EnviroBoard() |
| |
| update_display(enviro.display, "Hello world") |
| |
| def update_display(display, msg): |
| with canvas(display) as draw: |
| draw.text((0, 0), msg, fill='white') |
| """ |
| return self._display |