├── .gitignore ├── Adafruit_I2C └── Adafruit_I2C.py ├── Adafruit_Python_BMP ├── .gitignore ├── Adafruit_BMP │ ├── BMP085.py │ ├── BMP280.py │ └── __init__.py ├── LICENSE ├── README.md ├── examples │ ├── google_spreadsheet.py │ ├── simpletest.py │ └── simpletest_280.py ├── ez_setup.py ├── munin │ ├── i2c_pressure │ └── i2c_temperature └── setup.py ├── Adafruit_Python_GPIO ├── .gitignore ├── Adafruit_GPIO │ ├── FT232H.py │ ├── GPIO.py │ ├── I2C.py │ ├── MCP230xx.py │ ├── PWM.py │ ├── Platform.py │ ├── SPI.py │ └── __init__.py ├── LICENSE ├── README.md ├── ez_setup.py ├── setup.py └── test │ ├── MockGPIO.py │ ├── test_GPIO.py │ ├── test_I2C.py │ ├── test_PWM.py │ ├── test_Platform.py │ └── test_SPI.py ├── Adafruit_Python_SSD1306 ├── .github │ ├── ISSUE_TEMPLATE.md │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── Adafruit_SSD1306 │ ├── SSD1306.py │ └── __init__.py ├── LICENSE ├── README.md ├── dist │ └── Adafruit_SSD1306-1.6.0-py2.7.egg ├── examples │ ├── animate.py │ ├── happycat_oled_32.ppm │ ├── happycat_oled_64.ppm │ ├── image.py │ └── shapes.py ├── ez_setup.py └── setup.py ├── GroveWeatherPi.py ├── MySQLFiles └── GroveWeatherPi.sql ├── README.md ├── RTC_SDL_DS3231 ├── README.md ├── SDL_DS3231.py └── testSDL_DS3231.py ├── RaspberryPi-AS3935 ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── RPi_AS3935 │ ├── RPi_AS3935.py │ └── __init__.py ├── demo.py ├── requirements.txt ├── requirements │ ├── base.txt │ ├── flake8.txt │ └── pep8.txt ├── setup.cfg ├── setup.py ├── tests │ ├── conftest.py │ ├── test_disp_lco.py │ ├── test_disturbers.py │ ├── test_indoors.py │ ├── test_min_strikes.py │ └── test_noise_floor.py └── tox.ini ├── SDL_Adafruit_ADS1x15 ├── Adafruit_I2C.py ├── SDL_Adafruit_ADS1x15.py ├── ads1x15_ex_comparator.py ├── ads1x15_ex_differential.py └── ads1x15_ex_singleended.py ├── SDL_Pi_AM2315 ├── .gitignore ├── AM2315.py ├── LICENSE ├── README.md ├── adasmbus.py └── testAM2315.py ├── SDL_Pi_FRAM ├── README.md ├── SDL_Pi_FRAM.py └── testSDL_Pi_FRAM.py ├── SDL_Pi_HDC1000 ├── .gitignore ├── README.md ├── SDL_Pi_HDC1000.py └── testHDC1000.py ├── SDL_Pi_INA3221 ├── .gitignore ├── README.md ├── SDL_Pi_INA3221.py └── testSDL_Pi_INA3221.py ├── SDL_Pi_SI1145 ├── .gitignore ├── README.md ├── SDL_Pi_SI1145.py ├── SI1145Lux.py └── simpletest.py ├── SDL_Pi_SSD1306 ├── README.md ├── SDL_animate.py ├── SDL_image.py ├── SDL_shapes.py ├── happycat_oled_32.ppm └── happycat_oled_64.ppm ├── SDL_Pi_TCA9545 ├── .gitignore ├── README.md ├── SDL_Pi_TCA9545.py └── testSDL_Pi_TCA9545.py ├── SDL_Pi_WeatherRack ├── .gitignore ├── NoWPAConfig.py ├── README.md ├── SDL_Pi_WeatherRack.py └── SDL_Pi_WeatherRackTest.py ├── Scroll_SSD1306.py ├── WeatherPiSQL └── WeatherPiStructure.sql ├── WeatherUnderground.py ├── config.py ├── crcpython2.py ├── doAllGraphs.py ├── graphs ├── BarometerLightningGraph.py ├── PowerCurrentGraph.py ├── PowerVoltageGraph.py ├── TemperatureHumidityGraph.py └── testTemp.py ├── htu21dflib ├── .gitignore ├── LICENSE ├── README.md ├── build.sh ├── dweetio ├── dweetio.c ├── htu21dflib ├── htu21dflib.c ├── htu21dflib.h ├── mqtt └── mqtt.c ├── pclogging.py ├── sendemail.py ├── startserver.sh ├── state.py ├── state ├── SunAirPlusStats.txt ├── WeatherCommand.txt └── WeatherStats.txt ├── static ├── BarometerLightningGraph.png ├── PowerCurrentGraph.png ├── PowerVoltageGraph.png └── TemperatureHumidityGraph.png ├── testAM2315.py ├── testAS3935.py ├── testBlynk.py ├── testSI1145.py ├── updateBlynk.py └── util.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | tx* 3 | .*.swp 4 | *.xml 5 | *.temp 6 | *.test 7 | nohup.out 8 | .*DS_Store 9 | conflocal.py 10 | state/EnglishMetric.txt 11 | -------------------------------------------------------------------------------- /Adafruit_I2C/Adafruit_I2C.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import re 3 | import smbus 4 | 5 | # =========================================================================== 6 | # Adafruit_I2C Class 7 | # =========================================================================== 8 | 9 | class Adafruit_I2C(object): 10 | 11 | @staticmethod 12 | def getPiRevision(): 13 | "Gets the version number of the Raspberry Pi board" 14 | # Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History 15 | try: 16 | with open('/proc/cpuinfo', 'r') as infile: 17 | for line in infile: 18 | # Match a line of the form "Revision : 0002" while ignoring extra 19 | # info in front of the revsion (like 1000 when the Pi was over-volted). 20 | match = re.match('Revision\s+:\s+.*(\w{4})$', line) 21 | if match and match.group(1) in ['0000', '0002', '0003']: 22 | # Return revision 1 if revision ends with 0000, 0002 or 0003. 23 | return 1 24 | elif match: 25 | # Assume revision 2 if revision ends with any other 4 chars. 26 | return 2 27 | # Couldn't find the revision, assume revision 0 like older code for compatibility. 28 | return 0 29 | except: 30 | return 0 31 | 32 | @staticmethod 33 | def getPiI2CBusNumber(): 34 | # Gets the I2C bus number /dev/i2c# 35 | return 1 if Adafruit_I2C.getPiRevision() > 1 else 0 36 | 37 | def __init__(self, address, busnum=-1, debug=False): 38 | self.address = address 39 | # By default, the correct I2C bus is auto-detected using /proc/cpuinfo 40 | # Alternatively, you can hard-code the bus version below: 41 | # self.bus = smbus.SMBus(0); # Force I2C0 (early 256MB Pi's) 42 | # self.bus = smbus.SMBus(1); # Force I2C1 (512MB Pi's) 43 | self.bus = smbus.SMBus(busnum if busnum >= 0 else Adafruit_I2C.getPiI2CBusNumber()) 44 | self.debug = debug 45 | 46 | def reverseByteOrder(self, data): 47 | "Reverses the byte order of an int (16-bit) or long (32-bit) value" 48 | # Courtesy Vishal Sapre 49 | byteCount = len(hex(data)[2:].replace('L','')[::2]) 50 | val = 0 51 | for i in range(byteCount): 52 | val = (val << 8) | (data & 0xff) 53 | data >>= 8 54 | return val 55 | 56 | def errMsg(self): 57 | print "Error accessing 0x%02X: Check your I2C address" % self.address 58 | return -1 59 | 60 | def write8(self, reg, value): 61 | "Writes an 8-bit value to the specified register/address" 62 | try: 63 | self.bus.write_byte_data(self.address, reg, value) 64 | if self.debug: 65 | print "I2C: Wrote 0x%02X to register 0x%02X" % (value, reg) 66 | except IOError, err: 67 | return self.errMsg() 68 | 69 | def write16(self, reg, value): 70 | "Writes a 16-bit value to the specified register/address pair" 71 | try: 72 | self.bus.write_word_data(self.address, reg, value) 73 | if self.debug: 74 | print ("I2C: Wrote 0x%02X to register pair 0x%02X,0x%02X" % 75 | (value, reg, reg+1)) 76 | except IOError, err: 77 | return self.errMsg() 78 | 79 | def writeRaw8(self, value): 80 | "Writes an 8-bit value on the bus" 81 | try: 82 | self.bus.write_byte(self.address, value) 83 | if self.debug: 84 | print "I2C: Wrote 0x%02X" % value 85 | except IOError, err: 86 | return self.errMsg() 87 | 88 | def writeList(self, reg, list): 89 | "Writes an array of bytes using I2C format" 90 | try: 91 | if self.debug: 92 | print "I2C: Writing list to register 0x%02X:" % reg 93 | print list 94 | self.bus.write_i2c_block_data(self.address, reg, list) 95 | except IOError, err: 96 | return self.errMsg() 97 | 98 | def readList(self, reg, length): 99 | "Read a list of bytes from the I2C device" 100 | try: 101 | results = self.bus.read_i2c_block_data(self.address, reg, length) 102 | if self.debug: 103 | print ("I2C: Device 0x%02X returned the following from reg 0x%02X" % 104 | (self.address, reg)) 105 | print results 106 | return results 107 | except IOError, err: 108 | return self.errMsg() 109 | 110 | def readU8(self, reg): 111 | "Read an unsigned byte from the I2C device" 112 | try: 113 | result = self.bus.read_byte_data(self.address, reg) 114 | if self.debug: 115 | print ("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" % 116 | (self.address, result & 0xFF, reg)) 117 | return result 118 | except IOError, err: 119 | return self.errMsg() 120 | 121 | def readS8(self, reg): 122 | "Reads a signed byte from the I2C device" 123 | try: 124 | result = self.bus.read_byte_data(self.address, reg) 125 | if result > 127: result -= 256 126 | if self.debug: 127 | print ("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" % 128 | (self.address, result & 0xFF, reg)) 129 | return result 130 | except IOError, err: 131 | return self.errMsg() 132 | 133 | def readU16(self, reg, little_endian=True): 134 | "Reads an unsigned 16-bit value from the I2C device" 135 | try: 136 | result = self.bus.read_word_data(self.address,reg) 137 | # Swap bytes if using big endian because read_word_data assumes little 138 | # endian on ARM (little endian) systems. 139 | if not little_endian: 140 | result = ((result << 8) & 0xFF00) + (result >> 8) 141 | if (self.debug): 142 | print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg) 143 | return result 144 | except IOError, err: 145 | return self.errMsg() 146 | 147 | def readS16(self, reg, little_endian=True): 148 | "Reads a signed 16-bit value from the I2C device" 149 | try: 150 | result = self.readU16(reg,little_endian) 151 | if result > 32767: result -= 65536 152 | return result 153 | except IOError, err: 154 | return self.errMsg() 155 | 156 | if __name__ == '__main__': 157 | try: 158 | bus = Adafruit_I2C(address=0) 159 | print "Default I2C bus is accessible" 160 | except: 161 | print "Error accessing default I2C bus" 162 | -------------------------------------------------------------------------------- /Adafruit_Python_BMP/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | *.egg-info 4 | *.pyc 5 | -------------------------------------------------------------------------------- /Adafruit_Python_BMP/Adafruit_BMP/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/Adafruit_Python_BMP/Adafruit_BMP/__init__.py -------------------------------------------------------------------------------- /Adafruit_Python_BMP/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Adafruit_Python_BMP/README.md: -------------------------------------------------------------------------------- 1 | Adafruit Python BMP 2 | =================== 3 | 4 | Python library for accessing the BMP series pressure and temperature sensors like the BMP085/BMP180 on a Raspberry Pi or Beaglebone Black. 5 | 6 | Designed specifically to work with the Adafruit BMP085/BMP180 pressure sensors ----> https://www.adafruit.com/products/1603 7 | 8 | To install, download the library by clicking the download zip link to the right and unzip the archive somewhere on your Raspberry Pi or Beaglebone Black. Then execute the following command in the directory of the library: 9 | 10 | ```` 11 | sudo python setup.py install 12 | ```` 13 | 14 | Make sure you have internet access on the device so it can download the required dependencies. 15 | 16 | See examples of usage in the examples folder. 17 | 18 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 19 | 20 | Written by Tony DiCola for Adafruit Industries. 21 | MIT license, all text above must be included in any redistribution 22 | -------------------------------------------------------------------------------- /Adafruit_Python_BMP/examples/google_spreadsheet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Google Spreadsheet BMP Sensor Data-logging Example 4 | 5 | # Depends on the 'gspread' package being installed. If you have pip installed 6 | # execute: 7 | # sudo pip install gspread 8 | 9 | # Copyright (c) 2014 Adafruit Industries 10 | # Author: Tony DiCola 11 | 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to deal 14 | # in the Software without restriction, including without limitation the rights 15 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | # copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | 19 | # The above copyright notice and this permission notice shall be included in all 20 | # copies or substantial portions of the Software. 21 | 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | # SOFTWARE. 29 | import sys 30 | import time 31 | import datetime 32 | 33 | import Adafruit_BMP.BMP085 as BMP085 34 | import gspread 35 | 36 | # Google Docs account email, password, and spreadsheet name. 37 | GDOCS_EMAIL = 'your google docs account email address' 38 | GDOCS_PASSWORD = 'your google docs account password' 39 | GDOCS_SPREADSHEET_NAME = 'your google docs spreadsheet name' 40 | 41 | # How long to wait (in seconds) between measurements. 42 | FREQUENCY_SECONDS = 30 43 | 44 | 45 | def login_open_sheet(email, password, spreadsheet): 46 | """Connect to Google Docs spreadsheet and return the first worksheet.""" 47 | try: 48 | gc = gspread.login(email, password) 49 | worksheet = gc.open(spreadsheet).sheet1 50 | return worksheet 51 | except: 52 | print 'Unable to login and get spreadsheet. Check email, password, spreadsheet name.' 53 | sys.exit(1) 54 | 55 | 56 | # Create sensor instance with default I2C bus (On Raspberry Pi either 0 or 57 | # 1 based on the revision, on Beaglebone Black default to 1). 58 | bmp = BMP085.BMP085() 59 | 60 | print 'Logging sensor measurements to {0} every {1} seconds.'.format(GDOCS_SPREADSHEET_NAME, FREQUENCY_SECONDS) 61 | print 'Press Ctrl-C to quit.' 62 | worksheet = None 63 | while True: 64 | # Login if necessary. 65 | if worksheet is None: 66 | worksheet = login_open_sheet(GDOCS_EMAIL, GDOCS_PASSWORD, GDOCS_SPREADSHEET_NAME) 67 | 68 | # Attempt to get sensor readings. 69 | temp = bmp.read_temperature() 70 | pressure = bmp.read_pressure() 71 | altitude = bmp.read_altitude() 72 | 73 | print 'Temperature: {0:0.1f} C'.format(temp) 74 | print 'Pressure: {0:0.1f} Pa'.format(pressure) 75 | print 'Altitude: {0:0.1f} m'.format(altitude) 76 | 77 | # Append the data in the spreadsheet, including a timestamp 78 | try: 79 | worksheet.append_row((datetime.datetime.now(), temp, pressure, altitude)) 80 | except: 81 | # Error appending data, most likely because credentials are stale. 82 | # Null out the worksheet so a login is performed at the top of the loop. 83 | print 'Append error, logging in again' 84 | worksheet = None 85 | time.sleep(FREQUENCY_SECONDS) 86 | continue 87 | 88 | # Wait 30 seconds before continuing 89 | print 'Wrote a row to {0}'.format(GDOCS_SPREADSHEET_NAME) 90 | time.sleep(FREQUENCY_SECONDS) 91 | -------------------------------------------------------------------------------- /Adafruit_Python_BMP/examples/simpletest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright (c) 2014 Adafruit Industries 3 | # Author: Tony DiCola 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | # Can enable debug output by uncommenting: 24 | #import logging 25 | #logging.basicConfig(level=logging.DEBUG) 26 | 27 | import Adafruit_BMP.BMP085 as BMP085 28 | 29 | # Default constructor will pick a default I2C bus. 30 | # 31 | # For the Raspberry Pi this means you should hook up to the only exposed I2C bus 32 | # from the main GPIO header and the library will figure out the bus number based 33 | # on the Pi's revision. 34 | # 35 | # For the Beaglebone Black the library will assume bus 1 by default, which is 36 | # exposed with SCL = P9_19 and SDA = P9_20. 37 | sensor = BMP085.BMP085() 38 | 39 | # Optionally you can override the bus number: 40 | #sensor = BMP085.BMP085(busnum=2) 41 | 42 | # You can also optionally change the BMP085 mode to one of BMP085_ULTRALOWPOWER, 43 | # BMP085_STANDARD, BMP085_HIGHRES, or BMP085_ULTRAHIGHRES. See the BMP085 44 | # datasheet for more details on the meanings of each mode (accuracy and power 45 | # consumption are primarily the differences). The default mode is STANDARD. 46 | #sensor = BMP085.BMP085(mode=BMP085.BMP085_ULTRAHIGHRES) 47 | 48 | print 'Temp = {0:0.2f} *C'.format(sensor.read_temperature()) 49 | print 'Pressure = {0:0.2f} Pa'.format(sensor.read_pressure()) 50 | print 'Altitude = {0:0.2f} m'.format(sensor.read_altitude()) 51 | print 'Sealevel Pressure = {0:0.2f} Pa'.format(sensor.read_sealevel_pressure()) 52 | -------------------------------------------------------------------------------- /Adafruit_Python_BMP/examples/simpletest_280.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Author: Bastien Wirtz 3 | 4 | # Can enable debug output by uncommenting: 5 | #import logging 6 | #logging.basicConfig(level=logging.DEBUG) 7 | 8 | import Adafruit_BMP.BMP280 as BMP280 9 | 10 | sensor = BMP280.BMP280() 11 | 12 | print 'Temp = {0:0.2f} *C'.format(sensor.read_temperature()) 13 | print 'Pressure = {0:0.2f} Pa'.format(sensor.read_pressure()) 14 | print 'Altitude = {0:0.2f} m'.format(sensor.read_altitude()) 15 | print 'Sealevel Pressure = {0:0.2f} Pa'.format(sensor.read_sealevel_pressure()) 16 | -------------------------------------------------------------------------------- /Adafruit_Python_BMP/munin/i2c_pressure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # coding: utf-8 3 | 4 | from Adafruit_BMP085 import BMP085 5 | import sys 6 | 7 | # =========================================================================== 8 | # Munin Plugin - Pressure 9 | # =========================================================================== 10 | 11 | # Initialise the BMP085 and use STANDARD mode (default value) 12 | # bmp = BMP085(0x77, debug=True) 13 | bmp = BMP085(0x77) 14 | 15 | # To specify a different operating mode, uncomment one of the following: 16 | # bmp = BMP085(0x77, 0) # ULTRALOWPOWER Mode 17 | # bmp = BMP085(0x77, 1) # STANDARD Mode 18 | # bmp = BMP085(0x77, 2) # HIRES Mode 19 | # bmp = BMP085(0x77, 3) # ULTRAHIRES Mode 20 | 21 | temp = bmp.readTemperature() 22 | 23 | # Read the current barometric pressure level 24 | pressure = bmp.readPressure() 25 | 26 | is_config = len(sys.argv) == 2 and sys.argv[1] == "config" 27 | 28 | if is_config: 29 | print "graph_title Pressure (I2C)" 30 | print "graph_vlabel mBar" 31 | print "graph_category sensors" 32 | print "graph_scale no" 33 | print "graph_args -A -Y" 34 | print "pressure.label Pressure (mBar)" 35 | else: 36 | print "pressure.value %.4f" % (pressure / 100.0) 37 | -------------------------------------------------------------------------------- /Adafruit_Python_BMP/munin/i2c_temperature: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # coding: utf-8 3 | 4 | from Adafruit_BMP085 import BMP085 5 | import sys 6 | 7 | # =========================================================================== 8 | # Munin Plugin - Temperature 9 | # =========================================================================== 10 | 11 | # Initialise the BMP085 and use STANDARD mode (default value) 12 | # bmp = BMP085(0x77, debug=True) 13 | bmp = BMP085(0x77) 14 | 15 | # To specify a different operating mode, uncomment one of the following: 16 | # bmp = BMP085(0x77, 0) # ULTRALOWPOWER Mode 17 | # bmp = BMP085(0x77, 1) # STANDARD Mode 18 | # bmp = BMP085(0x77, 2) # HIRES Mode 19 | # bmp = BMP085(0x77, 3) # ULTRAHIRES Mode 20 | 21 | temp = bmp.readTemperature() 22 | 23 | # Read the current barometric pressure level 24 | pressure = bmp.readPressure() 25 | 26 | is_config = len(sys.argv) == 2 and sys.argv[1] == "config" 27 | 28 | if is_config: 29 | print "graph_title Temperatur (I2C)" 30 | print "graph_vlabel °C" 31 | print "graph_category sensors" 32 | #print "graph_scale no" 33 | #print "graph_args -A -Y" 34 | print "temperature.label Temperatur (°C)" 35 | else: 36 | print "temperature.value %.4f" % temp 37 | -------------------------------------------------------------------------------- /Adafruit_Python_BMP/setup.py: -------------------------------------------------------------------------------- 1 | from ez_setup import use_setuptools 2 | use_setuptools() 3 | from setuptools import setup, find_packages 4 | 5 | setup(name = 'Adafruit_BMP', 6 | version = '1.5.0', 7 | author = 'Tony DiCola', 8 | author_email = 'tdicola@adafruit.com', 9 | description = 'Library for accessing the BMP series pressure and temperature sensors like the BMP085/BMP180 on a Raspberry Pi or Beaglebone Black.', 10 | license = 'MIT', 11 | url = 'https://github.com/adafruit/Adafruit_Python_BMP/', 12 | dependency_links = ['https://github.com/adafruit/Adafruit_Python_GPIO/tarball/master#egg=Adafruit-GPIO-0.6.5'], 13 | install_requires = ['Adafruit-GPIO>=0.6.5'], 14 | packages = find_packages()) 15 | -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | *.egg-info 4 | *.pyc 5 | setuptools* 6 | 7 | .idea -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/Adafruit_GPIO/PWM.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import Adafruit_GPIO.Platform as Platform 22 | 23 | 24 | class RPi_PWM_Adapter(object): 25 | """PWM implementation for the Raspberry Pi using the RPi.GPIO PWM library.""" 26 | 27 | def __init__(self, rpi_gpio, mode=None): 28 | self.rpi_gpio = rpi_gpio 29 | # Suppress warnings about GPIO in use. 30 | rpi_gpio.setwarnings(False) 31 | # Set board or BCM pin numbering. 32 | if mode == rpi_gpio.BOARD or mode == rpi_gpio.BCM: 33 | rpi_gpio.setmode(mode) 34 | elif mode is not None: 35 | raise ValueError('Unexpected value for mode. Must be BOARD or BCM.') 36 | else: 37 | # Default to BCM numbering if not told otherwise. 38 | rpi_gpio.setmode(rpi_gpio.BCM) 39 | # Store reference to each created PWM instance. 40 | self.pwm = {} 41 | 42 | def start(self, pin, dutycycle, frequency_hz=2000): 43 | """Enable PWM output on specified pin. Set to intiial percent duty cycle 44 | value (0.0 to 100.0) and frequency (in Hz). 45 | """ 46 | if dutycycle < 0.0 or dutycycle > 100.0: 47 | raise ValueError('Invalid duty cycle value, must be between 0.0 to 100.0 (inclusive).') 48 | # Make pin an output. 49 | self.rpi_gpio.setup(pin, self.rpi_gpio.OUT) 50 | # Create PWM instance and save a reference for later access. 51 | self.pwm[pin] = self.rpi_gpio.PWM(pin, frequency_hz) 52 | # Start the PWM at the specified duty cycle. 53 | self.pwm[pin].start(dutycycle) 54 | 55 | def set_duty_cycle(self, pin, dutycycle): 56 | """Set percent duty cycle of PWM output on specified pin. Duty cycle must 57 | be a value 0.0 to 100.0 (inclusive). 58 | """ 59 | if dutycycle < 0.0 or dutycycle > 100.0: 60 | raise ValueError('Invalid duty cycle value, must be between 0.0 to 100.0 (inclusive).') 61 | if pin not in self.pwm: 62 | raise ValueError('Pin {0} is not configured as a PWM. Make sure to first call start for the pin.'.format(pin)) 63 | self.pwm[pin].ChangeDutyCycle(dutycycle) 64 | 65 | def set_frequency(self, pin, frequency_hz): 66 | """Set frequency (in Hz) of PWM output on specified pin.""" 67 | if pin not in self.pwm: 68 | raise ValueError('Pin {0} is not configured as a PWM. Make sure to first call start for the pin.'.format(pin)) 69 | self.pwm[pin].ChangeFrequency(frequency_hz) 70 | 71 | def stop(self, pin): 72 | """Stop PWM output on specified pin.""" 73 | if pin not in self.pwm: 74 | raise ValueError('Pin {0} is not configured as a PWM. Make sure to first call start for the pin.'.format(pin)) 75 | self.pwm[pin].stop() 76 | del self.pwm[pin] 77 | 78 | 79 | class BBIO_PWM_Adapter(object): 80 | """PWM implementation for the BeagleBone Black using the Adafruit_BBIO.PWM 81 | library. 82 | """ 83 | 84 | def __init__(self, bbio_pwm): 85 | self.bbio_pwm = bbio_pwm 86 | 87 | def start(self, pin, dutycycle, frequency_hz=2000): 88 | """Enable PWM output on specified pin. Set to intiial percent duty cycle 89 | value (0.0 to 100.0) and frequency (in Hz). 90 | """ 91 | if dutycycle < 0.0 or dutycycle > 100.0: 92 | raise ValueError('Invalid duty cycle value, must be between 0.0 to 100.0 (inclusive).') 93 | self.bbio_pwm.start(pin, dutycycle, frequency_hz) 94 | 95 | def set_duty_cycle(self, pin, dutycycle): 96 | """Set percent duty cycle of PWM output on specified pin. Duty cycle must 97 | be a value 0.0 to 100.0 (inclusive). 98 | """ 99 | if dutycycle < 0.0 or dutycycle > 100.0: 100 | raise ValueError('Invalid duty cycle value, must be between 0.0 to 100.0 (inclusive).') 101 | self.bbio_pwm.set_duty_cycle(pin, dutycycle) 102 | 103 | def set_frequency(self, pin, frequency_hz): 104 | """Set frequency (in Hz) of PWM output on specified pin.""" 105 | self.bbio_pwm.set_frequency(pin, frequency_hz) 106 | 107 | def stop(self, pin): 108 | """Stop PWM output on specified pin.""" 109 | self.bbio_pwm.stop(pin) 110 | 111 | 112 | def get_platform_pwm(**keywords): 113 | """Attempt to return a PWM instance for the platform which the code is being 114 | executed on. Currently supports only the Raspberry Pi using the RPi.GPIO 115 | library and Beaglebone Black using the Adafruit_BBIO library. Will throw an 116 | exception if a PWM instance can't be created for the current platform. The 117 | returned PWM object has the same interface as the RPi_PWM_Adapter and 118 | BBIO_PWM_Adapter classes. 119 | """ 120 | plat = Platform.platform_detect() 121 | if plat == Platform.RASPBERRY_PI: 122 | import RPi.GPIO 123 | return RPi_PWM_Adapter(RPi.GPIO, **keywords) 124 | elif plat == Platform.BEAGLEBONE_BLACK: 125 | import Adafruit_BBIO.PWM 126 | return BBIO_PWM_Adapter(Adafruit_BBIO.PWM, **keywords) 127 | elif plat == Platform.UNKNOWN: 128 | raise RuntimeError('Could not determine platform.') 129 | -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/Adafruit_GPIO/Platform.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | import platform 22 | import re 23 | 24 | # Platform identification constants. 25 | UNKNOWN = 0 26 | RASPBERRY_PI = 1 27 | BEAGLEBONE_BLACK = 2 28 | 29 | 30 | def platform_detect(): 31 | """Detect if running on the Raspberry Pi or Beaglebone Black and return the 32 | platform type. Will return RASPBERRY_PI, BEAGLEBONE_BLACK, or UNKNOWN.""" 33 | # Handle Raspberry Pi 34 | pi = pi_version() 35 | if pi is not None: 36 | return RASPBERRY_PI 37 | 38 | # Handle Beaglebone Black 39 | # TODO: Check the Beaglebone Black /proc/cpuinfo value instead of reading 40 | # the platform. 41 | plat = platform.platform() 42 | if plat.lower().find('armv7l-with-debian') > -1: 43 | return BEAGLEBONE_BLACK 44 | elif plat.lower().find('armv7l-with-ubuntu') > -1: 45 | return BEAGLEBONE_BLACK 46 | elif plat.lower().find('armv7l-with-glibc2.4') > -1: 47 | return BEAGLEBONE_BLACK 48 | 49 | # Couldn't figure out the platform, just return unknown. 50 | return UNKNOWN 51 | 52 | 53 | def pi_revision(): 54 | """Detect the revision number of a Raspberry Pi, useful for changing 55 | functionality like default I2C bus based on revision.""" 56 | # Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History 57 | with open('/proc/cpuinfo', 'r') as infile: 58 | for line in infile: 59 | # Match a line of the form "Revision : 0002" while ignoring extra 60 | # info in front of the revsion (like 1000 when the Pi was over-volted). 61 | match = re.match('Revision\s+:\s+.*(\w{4})$', line, flags=re.IGNORECASE) 62 | if match and match.group(1) in ['0000', '0002', '0003']: 63 | # Return revision 1 if revision ends with 0000, 0002 or 0003. 64 | return 1 65 | elif match: 66 | # Assume revision 2 if revision ends with any other 4 chars. 67 | return 2 68 | # Couldn't find the revision, throw an exception. 69 | raise RuntimeError('Could not determine Raspberry Pi revision.') 70 | 71 | 72 | def pi_version(): 73 | """Detect the version of the Raspberry Pi. Returns either 1, 2 or 74 | None depending on if it's a Raspberry Pi 1 (model A, B, A+, B+), 75 | Raspberry Pi 2 (model B+), or not a Raspberry Pi. 76 | """ 77 | # Check /proc/cpuinfo for the Hardware field value. 78 | # 2708 is pi 1 79 | # 2709 is pi 2 80 | # Anything else is not a pi. 81 | with open('/proc/cpuinfo', 'r') as infile: 82 | cpuinfo = infile.read() 83 | # Match a line like 'Hardware : BCM2709' 84 | match = re.search('^Hardware\s+:\s+(\w+)$', cpuinfo, 85 | flags=re.MULTILINE | re.IGNORECASE) 86 | if not match: 87 | # Couldn't find the hardware, assume it isn't a pi. 88 | return None 89 | if match.group(1) == 'BCM2708': 90 | # Pi 1 91 | return 1 92 | elif match.group(1) == 'BCM2709': 93 | # Pi 2 94 | return 2 95 | else: 96 | # Something else, not a pi. 97 | return None 98 | -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/Adafruit_GPIO/__init__.py: -------------------------------------------------------------------------------- 1 | from GPIO import * -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/README.md: -------------------------------------------------------------------------------- 1 | Adafruit Python GPIO Library 2 | ============================ 3 | 4 | Library to provide a cross-platform GPIO interface on the Raspberry Pi and Beaglebone Black using the [RPi.GPIO](https://pypi.python.org/pypi/RPi.GPIO) and [Adafruit_BBIO](https://pypi.python.org/pypi/Adafruit_BBIO) libraries. 5 | 6 | The library is currently in an early stage, but you can see how its used in the [Adafruit Nokia LCD library](https://github.com/adafruit/Adafruit_Nokia_LCD) to write Python code that is easily portable between the Raspberry Pi and Beaglebone Black. 7 | -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/setup.py: -------------------------------------------------------------------------------- 1 | from ez_setup import use_setuptools 2 | use_setuptools() 3 | from setuptools import setup, find_packages 4 | 5 | import sys 6 | 7 | # Define required packages. 8 | requires = [] 9 | # Assume spidev is required on non-windows & non-mac platforms (i.e. linux). 10 | if sys.platform != 'win32' and sys.platform != 'darwin': 11 | requires.append('spidev') 12 | 13 | setup(name = 'Adafruit_GPIO', 14 | version = '0.8.0', 15 | author = 'Tony DiCola', 16 | author_email = 'tdicola@adafruit.com', 17 | description = 'Library to provide a cross-platform GPIO interface on the Raspberry Pi and Beaglebone Black using the RPi.GPIO and Adafruit_BBIO libraries.', 18 | license = 'MIT', 19 | url = 'https://github.com/adafruit/Adafruit_Python_GPIO/', 20 | install_requires = requires, 21 | packages = find_packages()) 22 | -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/test/MockGPIO.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | 22 | import Adafruit_GPIO as GPIO 23 | 24 | 25 | class MockGPIO(GPIO.BaseGPIO): 26 | def __init__(self): 27 | self.pin_mode = {} 28 | self.pin_written = {} 29 | self.pin_read = {} 30 | 31 | def setup(self, pin, mode): 32 | self.pin_mode[pin] = mode 33 | 34 | def output(self, pin, bit): 35 | self.pin_written.setdefault(pin, []).append(1 if bit else 0) 36 | 37 | def input(self, pin): 38 | if pin not in self.pin_read: 39 | raise RuntimeError('No mock GPIO data to read for pin {0}'.format(pin)) 40 | return self.pin_read[pin].pop(0) == 1 41 | -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/test/test_PWM.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | 22 | import unittest 23 | 24 | from mock import Mock, patch 25 | 26 | import Adafruit_GPIO.PWM as PWM 27 | 28 | 29 | class TestRPi_PWM_Adapter(unittest.TestCase): 30 | def test_setup(self): 31 | rpi_gpio = Mock() 32 | pwm = PWM.RPi_PWM_Adapter(rpi_gpio) 33 | pwm.start(1, 50) 34 | rpi_gpio.PWM.assert_called_with(1, 2000) 35 | 36 | def test_set_duty_cycle_valid(self): 37 | rpi_gpio = Mock() 38 | pwm = PWM.RPi_PWM_Adapter(rpi_gpio) 39 | pwm.start(1, 50) 40 | pwm.set_duty_cycle(1, 75) 41 | # Implicit verification that no assertion or other error thrown. 42 | 43 | def test_set_duty_cycle_invalid(self): 44 | rpi_gpio = Mock() 45 | pwm = PWM.RPi_PWM_Adapter(rpi_gpio) 46 | pwm.start(1, 50) 47 | self.assertRaises(ValueError, pwm.set_duty_cycle, 1, 150) 48 | self.assertRaises(ValueError, pwm.set_duty_cycle, 1, -10) 49 | 50 | def test_set_frequency(self): 51 | rpi_gpio = Mock() 52 | pwm = PWM.RPi_PWM_Adapter(rpi_gpio) 53 | pwm.start(1, 50) 54 | pwm.set_frequency(1, 1000) 55 | # Implicit verification that no assertion or other error thrown. 56 | 57 | 58 | class TestBBIO_PWM_Adapter(unittest.TestCase): 59 | def test_setup(self): 60 | bbio_pwm = Mock() 61 | pwm = PWM.BBIO_PWM_Adapter(bbio_pwm) 62 | pwm.start('P9_16', 50) 63 | bbio_pwm.start.assert_called_with('P9_16', 50, 2000) 64 | 65 | def test_set_duty_cycle_valid(self): 66 | bbio_pwm = Mock() 67 | pwm = PWM.BBIO_PWM_Adapter(bbio_pwm) 68 | pwm.start('P9_16', 50) 69 | pwm.set_duty_cycle('P9_16', 75) 70 | bbio_pwm.set_duty_cycle.assert_called_with('P9_16', 75) 71 | 72 | def test_set_duty_cycle_invalid(self): 73 | bbio_pwm = Mock() 74 | pwm = PWM.BBIO_PWM_Adapter(bbio_pwm) 75 | pwm.start('P9_16', 50) 76 | self.assertRaises(ValueError, pwm.set_duty_cycle, 'P9_16', 150) 77 | self.assertRaises(ValueError, pwm.set_duty_cycle, 'P9_16', -10) 78 | 79 | def test_set_frequency(self): 80 | bbio_pwm = Mock() 81 | pwm = PWM.BBIO_PWM_Adapter(bbio_pwm) 82 | pwm.start('P9_16', 50) 83 | pwm.set_frequency('P9_16', 1000) 84 | bbio_pwm.set_frequency.assert_called_with('P9_16', 1000) 85 | 86 | 87 | class TestGetPlatformPWM(unittest.TestCase): 88 | @patch.dict('sys.modules', {'RPi': Mock(), 'RPi.GPIO': Mock()}) 89 | @patch('platform.platform', Mock(return_value='Linux-3.10.25+-armv6l-with-debian-7.4')) 90 | def test_raspberrypi(self): 91 | pwm = PWM.get_platform_pwm() 92 | self.assertIsInstance(pwm, PWM.RPi_PWM_Adapter) 93 | 94 | @patch.dict('sys.modules', {'Adafruit_BBIO': Mock(), 'Adafruit_BBIO.PWM': Mock()}) 95 | @patch('platform.platform', Mock(return_value='Linux-3.8.13-bone47-armv7l-with-debian-7.4')) 96 | def test_beagleboneblack(self): 97 | pwm = PWM.get_platform_pwm() 98 | self.assertIsInstance(pwm, PWM.BBIO_PWM_Adapter) 99 | 100 | @patch('platform.platform', Mock(return_value='Darwin-13.2.0-x86_64-i386-64bit')) 101 | def test_otherplatform(self): 102 | self.assertRaises(RuntimeError, PWM.get_platform_pwm) 103 | -------------------------------------------------------------------------------- /Adafruit_Python_GPIO/test/test_Platform.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import unittest 22 | 23 | from mock import Mock, patch 24 | 25 | import Adafruit_GPIO.Platform as Platform 26 | 27 | 28 | class TestPlatformDetect(unittest.TestCase): 29 | @patch('platform.platform', Mock(return_value='Linux-3.10.25+-armv6l-with-debian-7.4')) 30 | def test_raspberry_pi(self): 31 | result = Platform.platform_detect() 32 | self.assertEquals(result, Platform.RASPBERRY_PI) 33 | 34 | @patch('platform.platform', Mock(return_value='Linux-3.8.13-bone47-armv7l-with-debian-7.4')) 35 | def test_beaglebone_black(self): 36 | result = Platform.platform_detect() 37 | self.assertEquals(result, Platform.BEAGLEBONE_BLACK) 38 | 39 | @patch('platform.platform', Mock(return_value='Darwin-13.2.0-x86_64-i386-64bit')) 40 | def test_unknown(self): 41 | result = Platform.platform_detect() 42 | self.assertEquals(result, Platform.UNKNOWN) 43 | 44 | 45 | class TestPiRevision(unittest.TestCase): 46 | def test_revision_1(self): 47 | with patch('__builtin__.open') as mock_open: 48 | handle = mock_open.return_value.__enter__.return_value 49 | handle.__iter__.return_value = iter(['Revision : 0000']) 50 | rev = Platform.pi_revision() 51 | self.assertEquals(rev, 1) 52 | with patch('__builtin__.open') as mock_open: 53 | handle = mock_open.return_value.__enter__.return_value 54 | handle.__iter__.return_value = iter(['Revision : 0002']) 55 | rev = Platform.pi_revision() 56 | self.assertEquals(rev, 1) 57 | with patch('__builtin__.open') as mock_open: 58 | handle = mock_open.return_value.__enter__.return_value 59 | handle.__iter__.return_value = iter(['Revision : 0003']) 60 | rev = Platform.pi_revision() 61 | self.assertEquals(rev, 1) 62 | 63 | def test_revision_2(self): 64 | with patch('__builtin__.open') as mock_open: 65 | handle = mock_open.return_value.__enter__.return_value 66 | handle.__iter__.return_value = iter(['Revision : 000e']) 67 | rev = Platform.pi_revision() 68 | self.assertEquals(rev, 2) 69 | 70 | def test_unknown_revision(self): 71 | with patch('__builtin__.open') as mock_open: 72 | handle = mock_open.return_value.__enter__.return_value 73 | handle.__iter__.return_value = iter(['foobar']) 74 | self.assertRaises(RuntimeError, Platform.pi_revision) 75 | 76 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Python library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Python/Raspberry Pi projects check these very common issues to ensure they don't apply**: 17 | 18 | - If you are receiving an **ImportError: No module named...** error then a 19 | library the code depends on is not installed. Check the tutorial/guide or 20 | README to ensure you have installed the necessary libraries. Usually the 21 | missing library can be installed with the `pip` tool, but check the tutorial/guide 22 | for the exact command. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and power in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | If you're sure this issue is a defect in the code and checked the steps above 33 | please fill in the following fields to provide enough troubleshooting information. 34 | You may delete the guideline and text above to just leave the following details: 35 | 36 | - Platform/operating system (i.e. Raspberry Pi with Raspbian operating system, 37 | Windows 32-bit, Windows 64-bit, Mac OSX 64-bit, etc.): **INSERT PLATFORM/OPERATING 38 | SYSTEM HERE** 39 | 40 | - Python version (run `python -version` or `python3 -version`): **INSERT PYTHON 41 | VERSION HERE** 42 | 43 | - Error message you are receiving, including any Python exception traces: **INSERT 44 | ERROR MESAGE/EXCEPTION TRACES HERE*** 45 | 46 | - List the steps to reproduce the problem below (if possible attach code or commands 47 | to run): **LIST REPRO STEPS BELOW** 48 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.egg-info 3 | *.pyc 4 | setuptools-* 5 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/Adafruit_SSD1306/__init__.py: -------------------------------------------------------------------------------- 1 | from .SSD1306 import * 2 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/README.md: -------------------------------------------------------------------------------- 1 | Adafruit Python SSD1306 2 | ======================= 3 | 4 | Python library to use SSD1306-based 128x64 or 128x32 pixel OLED displays with a Raspberry Pi or Beaglebone Black. 5 | 6 | Designed specifically to work with the Adafruit SSD1306-based OLED displays ----> https://www.adafruit.com/categories/98 7 | 8 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 9 | 10 | Written by Tony DiCola for Adafruit Industries. 11 | MIT license, all text above must be included in any redistribution 12 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/dist/Adafruit_SSD1306-1.6.0-py2.7.egg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/Adafruit_Python_SSD1306/dist/Adafruit_SSD1306-1.6.0-py2.7.egg -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/examples/animate.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import math 22 | import time 23 | 24 | import Adafruit_GPIO.SPI as SPI 25 | import Adafruit_SSD1306 26 | 27 | from PIL import Image 28 | from PIL import ImageFont 29 | from PIL import ImageDraw 30 | 31 | 32 | # Raspberry Pi pin configuration: 33 | RST = 24 34 | # Note the following are only used with SPI: 35 | DC = 23 36 | SPI_PORT = 0 37 | SPI_DEVICE = 0 38 | 39 | # Beaglebone Black pin configuration: 40 | # RST = 'P9_12' 41 | # Note the following are only used with SPI: 42 | # DC = 'P9_15' 43 | # SPI_PORT = 1 44 | # SPI_DEVICE = 0 45 | 46 | # 128x32 display with hardware I2C: 47 | disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) 48 | 49 | # 128x64 display with hardware I2C: 50 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) 51 | 52 | # 128x32 display with hardware SPI: 53 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 54 | 55 | # 128x64 display with hardware SPI: 56 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 57 | 58 | # Initialize library. 59 | disp.begin() 60 | 61 | # Get display width and height. 62 | width = disp.width 63 | height = disp.height 64 | 65 | # Clear display. 66 | disp.clear() 67 | disp.display() 68 | 69 | # Create image buffer. 70 | # Make sure to create image with mode '1' for 1-bit color. 71 | image = Image.new('1', (width, height)) 72 | 73 | # Load default font. 74 | font = ImageFont.load_default() 75 | 76 | # Alternatively load a TTF font. Make sure the .ttf font file is in the same directory as this python script! 77 | # Some nice fonts to try: http://www.dafont.com/bitmap.php 78 | # font = ImageFont.truetype('Minecraftia.ttf', 8) 79 | 80 | # Create drawing object. 81 | draw = ImageDraw.Draw(image) 82 | 83 | # Define text and get total width. 84 | text = 'SSD1306 ORGANIC LED DISPLAY. THIS IS AN OLD SCHOOL DEMO SCROLLER!! GREETZ TO: LADYADA & THE ADAFRUIT CREW, TRIXTER, FUTURE CREW, AND FARBRAUSCH' 85 | maxwidth, unused = draw.textsize(text, font=font) 86 | 87 | # Set animation and sine wave parameters. 88 | amplitude = height/4 89 | offset = height/2 - 4 90 | velocity = -2 91 | startpos = width 92 | 93 | # Animate text moving in sine wave. 94 | print('Press Ctrl-C to quit.') 95 | pos = startpos 96 | while True: 97 | # Clear image buffer by drawing a black filled box. 98 | draw.rectangle((0,0,width,height), outline=0, fill=0) 99 | # Enumerate characters and draw them offset vertically based on a sine wave. 100 | x = pos 101 | for i, c in enumerate(text): 102 | # Stop drawing if off the right side of screen. 103 | if x > width: 104 | break 105 | # Calculate width but skip drawing if off the left side of screen. 106 | if x < -10: 107 | char_width, char_height = draw.textsize(c, font=font) 108 | x += char_width 109 | continue 110 | # Calculate offset from sine wave. 111 | y = offset+math.floor(amplitude*math.sin(x/float(width)*2.0*math.pi)) 112 | # Draw text. 113 | draw.text((x, y), c, font=font, fill=255) 114 | # Increment x position based on chacacter width. 115 | char_width, char_height = draw.textsize(c, font=font) 116 | x += char_width 117 | # Draw the image buffer. 118 | disp.image(image) 119 | disp.display() 120 | # Move position for next frame. 121 | pos += velocity 122 | # Start over if text has scrolled completely off left side of screen. 123 | if pos < -maxwidth: 124 | pos = startpos 125 | # Pause briefly before drawing next frame. 126 | time.sleep(0.1) 127 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/examples/happycat_oled_32.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/Adafruit_Python_SSD1306/examples/happycat_oled_32.ppm -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/examples/happycat_oled_64.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/Adafruit_Python_SSD1306/examples/happycat_oled_64.ppm -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/examples/image.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import time 22 | 23 | import Adafruit_GPIO.SPI as SPI 24 | import Adafruit_SSD1306 25 | 26 | from PIL import Image 27 | 28 | 29 | # Raspberry Pi pin configuration: 30 | RST = 24 31 | # Note the following are only used with SPI: 32 | DC = 23 33 | SPI_PORT = 0 34 | SPI_DEVICE = 0 35 | 36 | # Beaglebone Black pin configuration: 37 | # RST = 'P9_12' 38 | # Note the following are only used with SPI: 39 | # DC = 'P9_15' 40 | # SPI_PORT = 1 41 | # SPI_DEVICE = 0 42 | 43 | # 128x32 display with hardware I2C: 44 | disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) 45 | 46 | # 128x64 display with hardware I2C: 47 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) 48 | 49 | # 128x32 display with hardware SPI: 50 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 51 | 52 | # 128x64 display with hardware SPI: 53 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 54 | 55 | # Initialize library. 56 | disp.begin() 57 | 58 | # Clear display. 59 | disp.clear() 60 | disp.display() 61 | 62 | # Load image based on OLED display height. Note that image is converted to 1 bit color. 63 | if disp.height == 64: 64 | image = Image.open('happycat_oled_64.ppm').convert('1') 65 | else: 66 | image = Image.open('happycat_oled_32.ppm').convert('1') 67 | 68 | # Alternatively load a different format image, resize it, and convert to 1 bit color. 69 | #image = Image.open('happycat.png').resize((disp.width, disp.height), Image.ANTIALIAS).convert('1') 70 | 71 | # Display image. 72 | disp.image(image) 73 | disp.display() 74 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/examples/shapes.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import time 22 | 23 | import Adafruit_GPIO.SPI as SPI 24 | import Adafruit_SSD1306 25 | 26 | from PIL import Image 27 | from PIL import ImageDraw 28 | from PIL import ImageFont 29 | 30 | 31 | # Raspberry Pi pin configuration: 32 | RST = 24 33 | # Note the following are only used with SPI: 34 | DC = 23 35 | SPI_PORT = 0 36 | SPI_DEVICE = 0 37 | 38 | # Beaglebone Black pin configuration: 39 | # RST = 'P9_12' 40 | # Note the following are only used with SPI: 41 | # DC = 'P9_15' 42 | # SPI_PORT = 1 43 | # SPI_DEVICE = 0 44 | 45 | # 128x32 display with hardware I2C: 46 | disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) 47 | 48 | # 128x64 display with hardware I2C: 49 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) 50 | 51 | # Note you can change the I2C address by passing an i2c_address parameter like: 52 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, i2c_address=0x3C) 53 | 54 | # Alternatively you can specify an explicit I2C bus number, for example 55 | # with the 128x32 display you would use: 56 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, i2c_bus=2) 57 | 58 | # 128x32 display with hardware SPI: 59 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 60 | 61 | # 128x64 display with hardware SPI: 62 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 63 | 64 | # Alternatively you can specify a software SPI implementation by providing 65 | # digital GPIO pin numbers for all the required display pins. For example 66 | # on a Raspberry Pi with the 128x32 display you might use: 67 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, sclk=18, din=25, cs=22) 68 | 69 | # Initialize library. 70 | disp.begin() 71 | 72 | # Clear display. 73 | disp.clear() 74 | disp.display() 75 | 76 | # Create blank image for drawing. 77 | # Make sure to create image with mode '1' for 1-bit color. 78 | width = disp.width 79 | height = disp.height 80 | image = Image.new('1', (width, height)) 81 | 82 | # Get drawing object to draw on image. 83 | draw = ImageDraw.Draw(image) 84 | 85 | # Draw a black filled box to clear the image. 86 | draw.rectangle((0,0,width,height), outline=0, fill=0) 87 | 88 | # Draw some shapes. 89 | # First define some constants to allow easy resizing of shapes. 90 | padding = 2 91 | shape_width = 20 92 | top = padding 93 | bottom = height-padding 94 | # Move left to right keeping track of the current x position for drawing shapes. 95 | x = padding 96 | # Draw an ellipse. 97 | draw.ellipse((x, top , x+shape_width, bottom), outline=255, fill=0) 98 | x += shape_width+padding 99 | # Draw a rectangle. 100 | draw.rectangle((x, top, x+shape_width, bottom), outline=255, fill=0) 101 | x += shape_width+padding 102 | # Draw a triangle. 103 | draw.polygon([(x, bottom), (x+shape_width/2, top), (x+shape_width, bottom)], outline=255, fill=0) 104 | x += shape_width+padding 105 | # Draw an X. 106 | draw.line((x, bottom, x+shape_width, top), fill=255) 107 | draw.line((x, top, x+shape_width, bottom), fill=255) 108 | x += shape_width+padding 109 | 110 | # Load default font. 111 | font = ImageFont.load_default() 112 | 113 | # Alternatively load a TTF font. Make sure the .ttf font file is in the same directory as the python script! 114 | # Some other nice fonts to try: http://www.dafont.com/bitmap.php 115 | #font = ImageFont.truetype('Minecraftia.ttf', 8) 116 | 117 | # Write two lines of text. 118 | draw.text((x, top), 'Hello', font=font, fill=255) 119 | draw.text((x, top+20), 'World!', font=font, fill=255) 120 | 121 | # Display image. 122 | disp.image(image) 123 | disp.display() 124 | -------------------------------------------------------------------------------- /Adafruit_Python_SSD1306/setup.py: -------------------------------------------------------------------------------- 1 | from ez_setup import use_setuptools 2 | use_setuptools() 3 | from setuptools import setup, find_packages 4 | 5 | classifiers = ['Development Status :: 4 - Beta', 6 | 'Operating System :: POSIX :: Linux', 7 | 'License :: OSI Approved :: MIT License', 8 | 'Intended Audience :: Developers', 9 | 'Programming Language :: Python :: 2.7', 10 | 'Programming Language :: Python :: 3', 11 | 'Topic :: Software Development', 12 | 'Topic :: System :: Hardware'] 13 | 14 | setup(name = 'Adafruit_SSD1306', 15 | version = '1.6.0', 16 | author = 'Tony DiCola', 17 | author_email = 'tdicola@adafruit.com', 18 | description = 'Python library to use SSD1306-based 128x64 or 128x32 pixel OLED displays with a Raspberry Pi or Beaglebone Black.', 19 | license = 'MIT', 20 | classifiers = classifiers, 21 | url = 'https://github.com/adafruit/Adafruit_Python_SSD1306/', 22 | dependency_links = ['https://github.com/adafruit/Adafruit_Python_GPIO/tarball/master#egg=Adafruit-GPIO-0.6.5'], 23 | install_requires = ['Adafruit-GPIO>=0.6.5'], 24 | packages = find_packages()) 25 | -------------------------------------------------------------------------------- /MySQLFiles/GroveWeatherPi.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 3.4.11.1deb2+deb7u1 3 | -- http://www.phpmyadmin.net 4 | -- 5 | -- Host: localhost 6 | -- Generation Time: May 10, 2015 at 05:31 PM 7 | -- Server version: 5.5.41 8 | -- PHP Version: 5.4.4-14+deb7u12 9 | 10 | SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 11 | SET time_zone = "+00:00"; 12 | 13 | 14 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 15 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 16 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 17 | /*!40101 SET NAMES utf8 */; 18 | 19 | -- 20 | -- Database: `WeatherPi` 21 | -- 22 | 23 | -- -------------------------------------------------------- 24 | 25 | -- 26 | -- Table structure for table `PowerSystem` 27 | -- 28 | 29 | CREATE TABLE IF NOT EXISTS `PowerSystem` ( 30 | `ID` int(11) NOT NULL AUTO_INCREMENT, 31 | `TimeStamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 32 | `batteryVoltage` float NOT NULL, 33 | `batteryCurrent` float NOT NULL, 34 | `solarVoltage` float NOT NULL, 35 | `solarCurrent` float NOT NULL, 36 | `loadVoltage` float NOT NULL, 37 | `loadCurrent` float NOT NULL, 38 | `batteryPower` float NOT NULL, 39 | `solarPower` float NOT NULL, 40 | `loadPower` float NOT NULL, 41 | `batteryCharge` float NOT NULL, 42 | PRIMARY KEY (`ID`) 43 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6381 ; 44 | 45 | -- -------------------------------------------------------- 46 | 47 | -- 48 | -- Table structure for table `Sunlight` 49 | -- 50 | 51 | CREATE TABLE IF NOT EXISTS `Sunlight` ( 52 | `ID` int(11) NOT NULL AUTO_INCREMENT, 53 | `TimeStamp` datetime NOT NULL, 54 | `Visible` int(11) NOT NULL, 55 | `IR` int(250) NOT NULL, 56 | `UV` int(250) NOT NULL, 57 | `UVIndex` float NOT NULL, 58 | PRIMARY KEY (`ID`) 59 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 60 | 61 | -- -------------------------------------------------------- 62 | -- 63 | -- Table structure for table `systemlog` 64 | -- 65 | 66 | CREATE TABLE IF NOT EXISTS `systemlog` ( 67 | `ID` int(11) NOT NULL AUTO_INCREMENT, 68 | `TimeStamp` datetime NOT NULL, 69 | `Level` int(11) NOT NULL, 70 | `Source` varchar(250) NOT NULL, 71 | `Message` varchar(250) NOT NULL, 72 | PRIMARY KEY (`ID`) 73 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=295 ; 74 | 75 | -- -------------------------------------------------------- 76 | 77 | -- 78 | -- Table structure for table `WeatherData` 79 | -- 80 | 81 | CREATE TABLE IF NOT EXISTS `WeatherData` ( 82 | `ID` int(20) NOT NULL AUTO_INCREMENT, 83 | `TimeStamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 84 | `as3935LightningCount` float NOT NULL, 85 | `as3935LastInterrupt` float NOT NULL, 86 | `as3935LastDistance` float NOT NULL, 87 | `as3935LastStatus` varchar(200) NOT NULL, 88 | `currentWindSpeed` float NOT NULL, 89 | `currentWindGust` float NOT NULL, 90 | `currentWindDirection` float NOT NULL, 91 | `currentWindDirectionVoltage` float NOT NULL, 92 | `totalRain` float NOT NULL, 93 | `bmp180Temperature` int(20) NOT NULL, 94 | `bmp180Pressure` float NOT NULL, 95 | `bmp180Altitude` float NOT NULL, 96 | `bmp180SeaLevel` float NOT NULL, 97 | `outsideTemperature` float NOT NULL, 98 | `outsideHumidity` float NOT NULL, 99 | `insideTemperature` float NOT NULL, 100 | `insideHumidity` float NOT NULL, 101 | PRIMARY KEY (`ID`) 102 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Weather Data' AUTO_INCREMENT=6019 ; 103 | 104 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 105 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 106 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 107 | 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GroveWeatherPi Libraries and Example for Raspberry Pi Solar Powered Weather Station 2 | 3 | Supports SwitchDoc Labs WeatherRack WeatherBoard (WeatherPiArduino V2 and above) 4 | 5 | Version 3.17 6 | 7 | http://www.switchdoc.com/ 8 | 9 | June 7, 2019 - Version 3.17 Improved AM2315 reliablity - fixed 0 CRC error 10 | 11 | March 30, 2019 - Version 3.16 Improved AM2315 reliablity - added support for Grove PowerSave 12 | 13 | February 8, 2019 - Version 3.15 Increase Max Retries on AM2315 to 10 per suggestion 14 | 15 | January 12, 2019 - Version 3.14 Fixed am2315 not assigned error 16 | 17 | January 10, 2019 - Version 3.13 Added "None" detection to AM2315, added Try, Except loop on AM2315 read 18 | 19 | December 19, 2018 - Version 3.12 Improved Blynk reliability 20 | 21 | November 28, 2018 - Version 3.11 Further improved AM2315, fixed startup glitch with English/Metric units, fixed Rain Status 22 | 23 | November 26, 2018 - Version 3.10 Added Blynk App support and changed sampling method to remove I2C errors - fixed AM2315 humidity/temperature mixup 24 | 25 | November 14, 2018 - Version 3.04 Added CRC checking to the AM2315 Python Driver. 26 | 27 | November 14, 2018 - Version 3.03 Added New AM2315 Python Driver. removed tentacle_pi 28 | 29 | October 1, 2018 - Improved README.md install instructions 30 | 31 | June 19, 2018 - Version 3.02 Fixed SI1145 Gain (made for outdoors) Adjusted Lux readings for outdoor sunlight rough calibration 32 | 33 | May 30, 2018 - Version 3.01 Fixed MySQL Garding, bad read issues with SI1145, gave fix for Mising BBIO Library in README.md 34 | 35 | November 18, 2017 - Version 2.99 Adjusted Lightning Detector detection for 0x02 or 0x03 36 | 37 | November 16, 2017 - Version 2.98 Fixed name clash with latest OS version 38 | 39 | October 2, 2017 - Version 2.97 Fixed SI1145 issues with reading 40 | 41 | August 24, 2017 - Fixed AS3935 Missing issue with Interrupt variable 42 | 43 | July 20, 2017 - Fixed Rainfall 2X inaccuracy and 60 minute and midnight issues 44 | 45 | July 17, 2017 - Updated Bounce Times to fix wind speed issues - This probably fixes the Wind Gust problem too. Not conclusive. 46 | 47 | June 19, 2017 - Fixed uninitialized variable errors 48 | 49 | June 17, 2017 - Changed the README.md to require the installation of the software suporting SI1145 detection 50 | 51 | May 5, 2017 - Commented out 48 Reboot add_job (uncomment to add back in), Fixed SI1145 bad installation detection 52 | 53 | May 4, 2017 - Fixed problem with inside temperature being zero when you have an HTU rather than a HDC1080 54 | 55 | March 9, 2017 - Added time based scheduler into the main loop instead of polling (APscheduler). Added support for Grove HDC1000 56 | 57 | October 26, 2016 - Support added for Grove Sunlight/IR/UV SI1145 sensor. Database updated. Run mysql as below 58 | 59 | October 24, 2016 - Improved WXLink Error Checking 60 | 61 | October 3, 2016 - Added CRC Check to WXLink support, changed Barometric report on WU to Sea Level, added Altitude configuration in confif.py 62 | 63 | September 9, 2016 - Added WeatherUnderground Support - see Blog article on www.switchdoc.com for instructions. The summary of the instructions are: 64 | 65 | 1) sign up for a personal weather station on weatherunderground.com 66 | 67 | 2) Get your station name and key and put them in your config.py file, and then setting the WeatherUnderground_Present to True 68 | 69 | 70 | August 30, 2016 - Improved WXLink support reliablity - now detects and adjusts for missing records from WXLink reads 71 | 72 | August 26, 2016 - Added Support for WXLink Wireless Weather Connector 73 | 74 | August 17, 2016 - Added support back in for RasPiConnect 75 | 76 | August 16, 2016 - Support for Weather Board and improved device detection without exceptions 77 | 78 | March 28, 2015 - added subdirectories 79 | 80 | May 9, 2015 - Updated software for WatchDog Timer and Email 81 | 82 | May 10, 2015 - Added mysql table SQL files for database building 83 | 84 | ----------------- 85 | Install this for smbus: 86 | 87 | sudo apt-get install python-smbus 88 | 89 | Install this next: 90 | 91 | 92 | git clone https://github.com/adafruit/Adafruit_Python_PureIO.git
93 | cd Adafruit_Python_PureIO
94 | sudo python setup.py install
95 | 96 | Other installations required for AM2315: 97 | 98 | sudo apt-get install python-pip 99 | 100 | sudo apt-get install libi2c-dev 101 | 102 | 103 | #Installing apscheduler 104 | 105 | sudo pip install --upgrade setuptools pip
106 | 107 | sudo pip install setuptools --upgrade
108 | sudo pip install apscheduler
109 | 110 | 111 | ----------------
112 | Note some configurations of Raspberry Pi software requres the following:
113 | It won't hurt to do this in any case.
114 | ----------------
115 |
116 | sudo apt-get update
117 | sudo apt-get install build-essential python-pip python-dev python-smbus git
118 | git clone https://github.com/adafruit/Adafruit_Python_GPIO.git
119 | cd Adafruit_Python_GPIO
120 | sudo python setup.py install
121 | cd ..
122 | cd SDL_Pi_GroveWeatherPi
123 | cd Adafruit_Python_SSD1306
124 | sudo python setup.py install
125 | 
126 | SwitchDocLabs Documentation for WeatherRack/WeatherPiArduino under products on: store.switchdoc.com 127 | 128 | Read the GroveWeatherPi Instructable on instructables.com for more software installation instructions 129 | 130 | or 131 | 132 | Read the tutorial on GroveWeatherPi on http://www.switchdoc.com/2016/08/tutorial-part-1-building-a-solar-powered-raspberry-pi-weather-station-groveweatherpi/ 133 | for more software installation instructions. 134 | 135 | ----------- 136 | setup your configuration variables in config.py! 137 | ----------- 138 | 139 | -------- 140 | Add SQL instructions 141 | ---------- 142 | 143 | Use phpmyadmin or sql command lines to add the included SQL file to your MySQL databases.
144 | Note: If the database has been updated, run the example below to update your database. The current contents will not be lost. 145 | 146 | 147 | example: sudo mysql -u root -p GroveWeatherPi< GroveWeatherPi.sql 148 | 149 | user: root 150 | 151 | password: password 152 | 153 | Obviously with these credentials, don't connect port 3306 to the Internet. Change them if you aren't sure. 154 | 155 | NOTE: 156 | 157 | If you have a WXLink wireless transmitter installed, the software assumes you have connected your AM2315 outdoor temp/humidity sensor to the WXLink. If you put another AM2315 on your local system, it will use those values instead of the WXLink values 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /RTC_SDL_DS3231/README.md: -------------------------------------------------------------------------------- 1 | 2 | Raspberry Pi Python Library for SwitchDoc Labs DS3231/AT24C32 RTC Module 3 | 4 | SwitchDoc Labs, LLC December 19, 2014 5 | 6 | Clone respository and run testDS3231.py to test 7 | 8 | More Information on www.switchdoc.com 9 | 10 | Runs RTC and EEPROM 11 | 12 | 13 | -------------------------------------------------------------------------------- /RTC_SDL_DS3231/testSDL_DS3231.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Test SDL_DS3231 4 | # John C. Shovic, SwitchDoc Labs 5 | # 08/03/2014 6 | # 7 | # 8 | 9 | # imports 10 | 11 | import sys 12 | import time 13 | import datetime 14 | import random 15 | import SDL_DS3231 16 | 17 | # Main Program 18 | 19 | print "" 20 | print "Test SDL_DS3231 Version 1.0 - SwitchDoc Labs" 21 | print "" 22 | print "" 23 | print "Program Started at:"+ time.strftime("%Y-%m-%d %H:%M:%S") 24 | print "" 25 | 26 | filename = time.strftime("%Y-%m-%d%H:%M:%SRTCTest") + ".txt" 27 | starttime = datetime.datetime.utcnow() 28 | 29 | ds3231 = SDL_DS3231.SDL_DS3231(1, 0x68) 30 | #comment out the next line after the clock has been initialized 31 | ds3231.write_now() 32 | 33 | # Main Loop - sleeps 10 seconds, then reads and prints values of all clocks 34 | # Also reads two bytes of EEPROM and writes the next value to the two bytes 35 | 36 | # do the AT24C32 eeprom 37 | 38 | print "----------------- " 39 | print "----------------- " 40 | print " Test the AT24C32 EEPROM" 41 | print "----------------- " 42 | print "writing first 10 addresses with random data" 43 | for x in range(0,10): 44 | value = random.randint(0,255) 45 | print "address = %i writing value=%i" % (x, value) 46 | ds3231.write_AT24C32_byte(x, value) 47 | print "----------------- " 48 | 49 | print "reading first 10 addresses" 50 | for x in range(0,10): 51 | print "address = %i value = %i" %(x, ds3231.read_AT24C32_byte(x)) 52 | print "----------------- " 53 | print "----------------- " 54 | 55 | 56 | while True: 57 | 58 | 59 | 60 | 61 | # 62 | currenttime = datetime.datetime.utcnow() 63 | 64 | deltatime = currenttime - starttime 65 | 66 | print "" 67 | print "Raspberry Pi=\t" + time.strftime("%Y-%m-%d %H:%M:%S") 68 | 69 | print "DS3231=\t\t%s" % ds3231.read_datetime() 70 | 71 | print "DS3231 Temp=", ds3231.getTemp() 72 | time.sleep(10.0) 73 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.swp 3 | build/ 4 | MANIFEST 5 | dist/ 6 | __pycache__/ 7 | venv/ 8 | RPi_AS3935.egg-info/ 9 | .tox/ 10 | .coverage 11 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 2.7 3 | env: 4 | - TOX_ENV=pep8 5 | - TOX_ENV=py26 6 | - TOX_ENV=py27 7 | - TOX_ENV=py34 8 | - TOX_ENV=flake8 9 | install: 10 | - pip install --upgrade pip setuptools tox virtualenv . 11 | matrix: 12 | allow_failures: 13 | - env: TOX_ENV=py26 14 | - env: TOX_ENV=py34 15 | script: 16 | - "tox -e $TOX_ENV" 17 | notifications: 18 | email: false 19 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/LICENSE: -------------------------------------------------------------------------------- 1 | Licensed under the Apache License, Version 2.0 (the "License"); 2 | you may not use this file except in compliance with the License. 3 | You may obtain a copy of the License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/README.md: -------------------------------------------------------------------------------- 1 | RaspberryPi-AS3935 2 | ================== 3 | 4 | [![Build Status](https://travis-ci.org/pcfens/RaspberryPi-AS3935.png?branch=master)](https://travis-ci.org/pcfens/RaspberryPi-AS3935) 5 | 6 | A python library and demo script for interacting with the 7 | [AMS Franklin Lightning Sensor](http://www.ams.com/eng/Products/RF-Products/Lightning-Sensor/AS3935). 8 | 9 | This script will only work if the correct kernel modules are loaded 10 | on your Pi. Adafruit has a nice [tutorial](http://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c) 11 | set up, though depending on the breakout board that you use, you may 12 | not see anything show up when you run `i2cdetect`. 13 | 14 | ## Installation 15 | 16 | You can install this module by running 17 | ``` 18 | pip install RPi_AS3935 19 | ``` 20 | 21 | or you can clone this repository and run 22 | ``` 23 | python setup.py install 24 | ``` 25 | 26 | ## Breakout Board 27 | 28 | The AS3935 is a small chip, and rather than trying to solder it myself 29 | I purchased a (v2) breakout board from [Embedded Adventures](http://www.embeddedadventures.com/as3935_lightning_sensor_module_mod-1016.html). 30 | 31 | 32 | ## Connecting the AS3935 33 | 34 | In my test setup I connected my breakout board to the Pi as shown 35 | 36 | | AS3935 Pin | Raspberry Pi Pin | 37 | | ---------: | :--------------- | 38 | | 4 (GND) | 25 (Ground) | 39 | | 5 (VDD) | 1 (3v3 Power) | 40 | | 10 (IRQ) | 11 (GPIO 17) | 41 | | 11 (I2CL) | 5 (SCL) | 42 | | 13 (I2CD) | 3 (SDA) | 43 | 44 | ## Known Issues 45 | 46 | ### Addressing 47 | 48 | You may need edit line 12 of demo.py so that the correct address is read. 49 | 50 | | Breakout Board | Default Address | 51 | | :------------- | :-------------- | 52 | | Embedded Adeventures v2 | 0x00 | 53 | | Embedded Adeventures v4 (untested) | 0x03 | 54 | | Tautic Electronics (untested) | 0x00 | 55 | 56 | ### RaspberryPi Model 57 | 58 | If you have one of the newer 512MB Pi boards, then you need to adjust line 12 59 | in the demo script to read 60 | ```python 61 | sensor = RPi_AS3935(address = 0x00, bus = 1) 62 | ``` 63 | 64 | ## Implementations 65 | 66 | * [Push based web interface](https://github.com/pcfens/RPi-AS3935-Web) 67 | 68 | Send a Pull Request if you'd like to get your original implementation listed here. 69 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/RPi_AS3935/__init__.py: -------------------------------------------------------------------------------- 1 | """A module to make communication between the Raspberry Pi and the 2 | AS3935 lightning sensor (over I2C) as easy as possible. It should be 3 | easily adaptable to make work on non-Raspberry Pi things too. 4 | 5 | .. moduleauthor:: Phil Fenstermacher 6 | 7 | """ 8 | 9 | from RPi_AS3935 import RPi_AS3935 10 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/demo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from RPi_AS3935 import RPi_AS3935 3 | 4 | import RPi.GPIO as GPIO 5 | import time 6 | from datetime import datetime 7 | 8 | GPIO.setmode(GPIO.BCM) 9 | 10 | # Rev. 1 Raspberry Pis should leave bus set at 0, while rev. 2 Pis should set 11 | # bus equal to 1. The address should be changed to match the address of the 12 | # sensor. (Common implementations are in README.md) 13 | sensor = RPi_AS3935(address=0x02, bus=1) 14 | 15 | sensor.set_indoors(True) 16 | sensor.set_noise_floor(0) 17 | sensor.calibrate(tun_cap=0x0F) 18 | 19 | 20 | def handle_interrupt(channel): 21 | time.sleep(0.003) 22 | global sensor 23 | reason = sensor.get_interrupt() 24 | if reason == 0x01: 25 | print "Noise level too high - adjusting" 26 | sensor.raise_noise_floor() 27 | elif reason == 0x04: 28 | print "Disturber detected - masking" 29 | sensor.set_mask_disturber(True) 30 | elif reason == 0x08: 31 | now = datetime.now().strftime('%H:%M:%S - %Y/%m/%d') 32 | distance = sensor.get_distance() 33 | print "We sensed lightning!" 34 | print "It was " + str(distance) + "km away. (%s)" % now 35 | print "" 36 | 37 | pin = 16 38 | 39 | #GPIO.setup(pin, GPIO.IN ) 40 | GPIO.setup(pin, GPIO.IN, pull_up_down = GPIO.PUD_UP ) 41 | GPIO.add_event_detect(pin, GPIO.RISING, callback=handle_interrupt) 42 | 43 | print "Waiting for lightning - or at least something that looks like it" 44 | 45 | while True: 46 | time.sleep(1.0) 47 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/requirements.txt: -------------------------------------------------------------------------------- 1 | -e . 2 | 3 | pytest 4 | coverage 5 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/requirements/base.txt: -------------------------------------------------------------------------------- 1 | RPi_AS3935 >= 0.0.8 2 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/requirements/flake8.txt: -------------------------------------------------------------------------------- 1 | -r base.txt 2 | flake8 3 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/requirements/pep8.txt: -------------------------------------------------------------------------------- 1 | -r base.txt 2 | pep8 3 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name='RPi_AS3935', 5 | version='0.0.9', 6 | description='Raspberry Pi <-I2C-> AS3935 lightning sensor communication library', 7 | author='Phil Fenstermacher', 8 | author_email='phillip.fenstermacher@gmail.com', 9 | url='https://github.com/pcfens/RaspberryPi-AS3935', 10 | packages=['RPi_AS3935'], 11 | keywords=['RaspberryPi', 'AS3935', 'lightning', 'weather'], 12 | license='Apache-2.0', 13 | classifiers=[ 14 | 'Development Status :: 4 - Beta', 15 | 'License :: OSI Approved :: Apache Software License', 16 | 'Topic :: Utilities', 17 | ], 18 | ) 19 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/tests/conftest.py: -------------------------------------------------------------------------------- 1 | from RPi_AS3935 import RPi_AS3935 2 | import pytest 3 | 4 | 5 | class RPi_AS3935Proxy(RPi_AS3935): 6 | def __init__(self, address, bus=0): 7 | self.address = address 8 | self.i2cbus = bus 9 | self.registers = [50, 2, 194, 32, 0, 0, 0, 63, 0, 173, 0, 37, 3, 1, 34, 131, 1, 31, 67, 2, 27, 99, 3, 24, 20, 5, 20, 157, 7, 17, 106, 11] 10 | 11 | def set_byte(self, register, value): 12 | self.registers[register] = value 13 | print value 14 | 15 | def read_data(self): 16 | self.registers = self.registers 17 | 18 | 19 | @pytest.fixture(scope='module') 20 | def as3935(): 21 | return RPi_AS3935Proxy(address=0x00, bus=0) 22 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/tests/test_disp_lco.py: -------------------------------------------------------------------------------- 1 | def test_set_disp_lco_true(as3935): 2 | as3935.set_disp_lco(True) 3 | assert (as3935.registers[0x08] & 0x80) == 0x80 4 | 5 | 6 | def test_get_disp_lco_true(as3935): 7 | disp_lco = as3935.get_disp_lco() 8 | assert disp_lco is True 9 | 10 | 11 | def test_set_disp_lco_false(as3935): 12 | as3935.set_disp_lco(False) 13 | assert (as3935.registers[0x08] & 0x80) == 0x00 14 | 15 | 16 | def test_get_disp_lco_false(as3935): 17 | disp_lco = as3935.get_disp_lco() 18 | assert disp_lco is False 19 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/tests/test_disturbers.py: -------------------------------------------------------------------------------- 1 | def test_set_mask_disturber_true(as3935): 2 | as3935.set_mask_disturber(True) 3 | assert (as3935.registers[0x03] & 0x20) == 0x20 4 | 5 | 6 | def test_get_mask_disturber_true(as3935): 7 | mask_disturber = as3935.get_mask_disturber() 8 | assert mask_disturber is True 9 | 10 | 11 | def test_set_mask_disturber_false(as3935): 12 | as3935.set_mask_disturber(False) 13 | assert (as3935.registers[0x03] & 0x20) == 0x00 14 | 15 | 16 | def test_get_mask_disturber_false(as3935): 17 | mask_disturber = as3935.get_mask_disturber() 18 | assert mask_disturber is False 19 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/tests/test_indoors.py: -------------------------------------------------------------------------------- 1 | def test_set_indoors_true(as3935): 2 | as3935.set_indoors(True) 3 | assert (as3935.registers[0x00] & 0x10) == 0x10 4 | 5 | 6 | def test_get_indoors_true(as3935): 7 | indoors = as3935.get_indoors() 8 | assert indoors is True 9 | 10 | 11 | def test_set_indoors_false(as3935): 12 | as3935.set_indoors(False) 13 | assert (as3935.registers[0x00] & 0x10) == 0x00 14 | 15 | 16 | def test_get_indoors_false(as3935): 17 | indoors = as3935.get_indoors() 18 | assert indoors is False 19 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/tests/test_min_strikes.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def test_set_min_strikes_5(as3935): 5 | as3935.set_min_strikes(5) 6 | assert (as3935.registers[0x02] & 0x30) == 0x10 7 | 8 | 9 | def test_get_min_strikes_5(as3935): 10 | min_strikes = as3935.get_min_strikes() 11 | assert min_strikes == 5 12 | 13 | 14 | def test_set_invalid_min_strikes(as3935): 15 | with pytest.raises(Exception): 16 | as3935.set_min_strikes(2) 17 | 18 | 19 | def test_set_min_strikes_9(as3935): 20 | as3935.set_min_strikes(9) 21 | assert (as3935.registers[0x02] & 0x30) == 0x20 22 | 23 | 24 | def test_get_min_strikes_9(as3935): 25 | min_strikes = as3935.get_min_strikes() 26 | assert min_strikes == 9 27 | 28 | 29 | def test_set_min_strikes_16(as3935): 30 | as3935.set_min_strikes(16) 31 | assert (as3935.registers[0x02] & 0x30) == 0x30 32 | 33 | 34 | def test_get_min_strikes_16(as3935): 35 | min_strikes = as3935.get_min_strikes() 36 | assert min_strikes == 16 37 | 38 | 39 | def test_set_min_strikes_1(as3935): 40 | as3935.set_min_strikes(1) 41 | assert (as3935.registers[0x02] & 0x30) == 0x00 42 | 43 | 44 | def test_get_min_strikes_1(as3935): 45 | min_strikes = as3935.get_min_strikes() 46 | assert min_strikes == 1 47 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/tests/test_noise_floor.py: -------------------------------------------------------------------------------- 1 | def test_get_noise_floor(as3935): 2 | noise_floor = as3935.get_noise_floor() 3 | assert noise_floor == 0 4 | 5 | 6 | def test_set_noise_floor(as3935): 7 | as3935.set_noise_floor(2) 8 | assert (as3935.registers[0x01] & 0x70) == 0x20 9 | 10 | 11 | def test_raise_noise_floor(as3935): 12 | as3935.raise_noise_floor() 13 | assert (as3935.registers[0x01] & 0x70) == 0x30 14 | 15 | 16 | def test_lower_noise_floor(as3935): 17 | as3935.lower_noise_floor() 18 | assert (as3935.registers[0x01] & 0x70) == 0x20 19 | -------------------------------------------------------------------------------- /RaspberryPi-AS3935/tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = pep8,flake8,py27 3 | 4 | [flake8] 5 | exclude = *.egg*,.env,.git,.hg,.tox,_*,build*,dist*,venv* 6 | ignore = E261 7 | max-line-length = 150 8 | 9 | [pep8] 10 | count = 1 11 | exclude = *.egg*,.env,.git,.hg,.tox,_*,build*,dist*,venv* 12 | ignore = E261 13 | max-line-length = 150 14 | show-source = 1 15 | statistics = 1 16 | 17 | [testenv] 18 | deps = -rrequirements.txt 19 | commands = python -m coverage run --source RPi_AS3935 -m pytest 20 | python -m coverage report -m 21 | 22 | [testenv:pep8] 23 | basepython = python2.7 24 | deps = -rrequirements/pep8.txt 25 | commands = 26 | pep8 tests/ RPi_AS3935/ 27 | 28 | [testenv:flake8] 29 | basepython = python2.7 30 | deps = -rrequirements/flake8.txt 31 | commands = 32 | flake8 tests/ RPi_AS3935/ 33 | -------------------------------------------------------------------------------- /SDL_Adafruit_ADS1x15/Adafruit_I2C.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import re 3 | import smbus 4 | 5 | # =========================================================================== 6 | # Adafruit_I2C Class 7 | # =========================================================================== 8 | 9 | class Adafruit_I2C(object): 10 | 11 | @staticmethod 12 | def getPiRevision(): 13 | "Gets the version number of the Raspberry Pi board" 14 | # Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History 15 | try: 16 | with open('/proc/cpuinfo', 'r') as infile: 17 | for line in infile: 18 | # Match a line of the form "Revision : 0002" while ignoring extra 19 | # info in front of the revsion (like 1000 when the Pi was over-volted). 20 | match = re.match('Revision\s+:\s+.*(\w{4})$', line) 21 | if match and match.group(1) in ['0000', '0002', '0003']: 22 | # Return revision 1 if revision ends with 0000, 0002 or 0003. 23 | return 1 24 | elif match: 25 | # Assume revision 2 if revision ends with any other 4 chars. 26 | return 2 27 | # Couldn't find the revision, assume revision 0 like older code for compatibility. 28 | return 0 29 | except: 30 | return 0 31 | 32 | @staticmethod 33 | def getPiI2CBusNumber(): 34 | # Gets the I2C bus number /dev/i2c# 35 | return 1 if Adafruit_I2C.getPiRevision() > 1 else 0 36 | 37 | def __init__(self, address, busnum=-1, debug=False): 38 | self.address = address 39 | # By default, the correct I2C bus is auto-detected using /proc/cpuinfo 40 | # Alternatively, you can hard-code the bus version below: 41 | # self.bus = smbus.SMBus(0); # Force I2C0 (early 256MB Pi's) 42 | # self.bus = smbus.SMBus(1); # Force I2C1 (512MB Pi's) 43 | self.bus = smbus.SMBus(busnum if busnum >= 0 else Adafruit_I2C.getPiI2CBusNumber()) 44 | self.debug = debug 45 | 46 | def reverseByteOrder(self, data): 47 | "Reverses the byte order of an int (16-bit) or long (32-bit) value" 48 | # Courtesy Vishal Sapre 49 | byteCount = len(hex(data)[2:].replace('L','')[::2]) 50 | val = 0 51 | for i in range(byteCount): 52 | val = (val << 8) | (data & 0xff) 53 | data >>= 8 54 | return val 55 | 56 | def errMsg(self): 57 | print "Error accessing 0x%02X: Check your I2C address" % self.address 58 | return -1 59 | 60 | def write8(self, reg, value): 61 | "Writes an 8-bit value to the specified register/address" 62 | try: 63 | self.bus.write_byte_data(self.address, reg, value) 64 | if self.debug: 65 | print "I2C: Wrote 0x%02X to register 0x%02X" % (value, reg) 66 | except IOError, err: 67 | return self.errMsg() 68 | 69 | def write16(self, reg, value): 70 | "Writes a 16-bit value to the specified register/address pair" 71 | try: 72 | self.bus.write_word_data(self.address, reg, value) 73 | if self.debug: 74 | print ("I2C: Wrote 0x%02X to register pair 0x%02X,0x%02X" % 75 | (value, reg, reg+1)) 76 | except IOError, err: 77 | return self.errMsg() 78 | 79 | def writeRaw8(self, value): 80 | "Writes an 8-bit value on the bus" 81 | try: 82 | self.bus.write_byte(self.address, value) 83 | if self.debug: 84 | print "I2C: Wrote 0x%02X" % value 85 | except IOError, err: 86 | return self.errMsg() 87 | 88 | def writeList(self, reg, list): 89 | "Writes an array of bytes using I2C format" 90 | try: 91 | if self.debug: 92 | print "I2C: Writing list to register 0x%02X:" % reg 93 | print list 94 | self.bus.write_i2c_block_data(self.address, reg, list) 95 | except IOError, err: 96 | return self.errMsg() 97 | 98 | def readList(self, reg, length): 99 | "Read a list of bytes from the I2C device" 100 | try: 101 | results = self.bus.read_i2c_block_data(self.address, reg, length) 102 | if self.debug: 103 | print ("I2C: Device 0x%02X returned the following from reg 0x%02X" % 104 | (self.address, reg)) 105 | print results 106 | return results 107 | except IOError, err: 108 | return self.errMsg() 109 | 110 | def readU8(self, reg): 111 | "Read an unsigned byte from the I2C device" 112 | try: 113 | result = self.bus.read_byte_data(self.address, reg) 114 | if self.debug: 115 | print ("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" % 116 | (self.address, result & 0xFF, reg)) 117 | return result 118 | except IOError, err: 119 | return self.errMsg() 120 | 121 | def readS8(self, reg): 122 | "Reads a signed byte from the I2C device" 123 | try: 124 | result = self.bus.read_byte_data(self.address, reg) 125 | if result > 127: result -= 256 126 | if self.debug: 127 | print ("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" % 128 | (self.address, result & 0xFF, reg)) 129 | return result 130 | except IOError, err: 131 | return self.errMsg() 132 | 133 | def readU16(self, reg, little_endian=True): 134 | "Reads an unsigned 16-bit value from the I2C device" 135 | try: 136 | result = self.bus.read_word_data(self.address,reg) 137 | # Swap bytes if using big endian because read_word_data assumes little 138 | # endian on ARM (little endian) systems. 139 | if not little_endian: 140 | result = ((result << 8) & 0xFF00) + (result >> 8) 141 | if (self.debug): 142 | print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg) 143 | return result 144 | except IOError, err: 145 | return self.errMsg() 146 | 147 | def readS16(self, reg, little_endian=True): 148 | "Reads a signed 16-bit value from the I2C device" 149 | try: 150 | result = self.readU16(reg,little_endian) 151 | if result > 32767: result -= 65536 152 | return result 153 | except IOError, err: 154 | return self.errMsg() 155 | 156 | if __name__ == '__main__': 157 | try: 158 | bus = Adafruit_I2C(address=0) 159 | print "Default I2C bus is accessible" 160 | except: 161 | print "Error accessing default I2C bus" 162 | -------------------------------------------------------------------------------- /SDL_Adafruit_ADS1x15/ads1x15_ex_comparator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import time, signal, sys 4 | from Adafruit_ADS1x15 import ADS1x15 5 | 6 | def signal_handler(signal, frame): 7 | print 'You pressed Ctrl+C!' 8 | print adc.getLastConversionResults()/1000.0 9 | adc.stopContinuousConversion() 10 | sys.exit(0) 11 | 12 | signal.signal(signal.SIGINT, signal_handler) 13 | # Print 'Press Ctrl+C to exit' 14 | 15 | ADS1015 = 0x00 # 12-bit ADC 16 | ADS1115 = 0x01 # 16-bit ADC 17 | 18 | # Initialise the ADC using the default mode (use default I2C address) 19 | # Set this to ADS1015 or ADS1115 depending on the ADC you are using! 20 | adc = ADS1x15(ic=ADS1115) 21 | 22 | # start comparator on channel 2 with a thresholdHigh=200mV and low=100mV 23 | # in traditional mode, non-latching, +/-1.024V and 250sps 24 | adc.startSingleEndedComparator(2, 200, 100, pga=1024, sps=250, activeLow=True, traditionalMode=True, latching=False, numReadings=1) 25 | 26 | while True: 27 | print adc.getLastConversionResults()/1000.0 28 | time.sleep(0.25) 29 | 30 | #time.sleep(0.1) 31 | -------------------------------------------------------------------------------- /SDL_Adafruit_ADS1x15/ads1x15_ex_differential.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import time, signal, sys 4 | from Adafruit_ADS1x15 import ADS1x15 5 | 6 | def signal_handler(signal, frame): 7 | #print 'You pressed Ctrl+C!' 8 | sys.exit(0) 9 | signal.signal(signal.SIGINT, signal_handler) 10 | #print 'Press Ctrl+C to exit' 11 | 12 | ADS1015 = 0x00 # 12-bit ADC 13 | ADS1115 = 0x01 # 16-bit ADC 14 | 15 | # Initialise the ADC using the default mode (use default I2C address) 16 | # Set this to ADS1015 or ADS1115 depending on the ADC you are using! 17 | adc = ADS1x15(ic=ADS1115) 18 | 19 | # Read channels 2 and 3 in single-ended mode, at +/-4.096V and 250sps 20 | volts2 = adc.readADCSingleEnded(2, 4096, 250)/1000.0 21 | volts3 = adc.readADCSingleEnded(3, 4096, 250)/1000.0 22 | 23 | # Now do a differential reading of channels 2 and 3 24 | voltsdiff = adc.readADCDifferential23(4096, 250)/1000.0 25 | 26 | # Display the two different reading for comparison purposes 27 | print "%.8f %.8f %.8f %.8f" % (volts2, volts3, volts3-volts2, -voltsdiff) 28 | -------------------------------------------------------------------------------- /SDL_Adafruit_ADS1x15/ads1x15_ex_singleended.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import time, signal, sys 4 | from Adafruit_ADS1x15 import ADS1x15 5 | 6 | def signal_handler(signal, frame): 7 | print 'You pressed Ctrl+C!' 8 | sys.exit(0) 9 | signal.signal(signal.SIGINT, signal_handler) 10 | #print 'Press Ctrl+C to exit' 11 | 12 | ADS1015 = 0x00 # 12-bit ADC 13 | ADS1115 = 0x01 # 16-bit ADC 14 | 15 | # Select the gain 16 | # gain = 6144 # +/- 6.144V 17 | gain = 4096 # +/- 4.096V 18 | # gain = 2048 # +/- 2.048V 19 | # gain = 1024 # +/- 1.024V 20 | # gain = 512 # +/- 0.512V 21 | # gain = 256 # +/- 0.256V 22 | 23 | # Select the sample rate 24 | # sps = 8 # 8 samples per second 25 | # sps = 16 # 16 samples per second 26 | # sps = 32 # 32 samples per second 27 | # sps = 64 # 64 samples per second 28 | # sps = 128 # 128 samples per second 29 | sps = 250 # 250 samples per second 30 | # sps = 475 # 475 samples per second 31 | # sps = 860 # 860 samples per second 32 | 33 | # Initialise the ADC using the default mode (use default I2C address) 34 | # Set this to ADS1015 or ADS1115 depending on the ADC you are using! 35 | adc = ADS1x15(ic=ADS1115) 36 | while (1): 37 | 38 | # Read channel 1 in single-ended mode using the settings above 39 | 40 | volts = adc.readADCSingleEnded(1, gain, sps) / 1000 41 | 42 | # To read channel 3 in single-ended mode, +/- 1.024V, 860 sps use: 43 | # volts = adc.readADCSingleEnded(3, 1024, 860) 44 | 45 | print "%.6f" % (volts) 46 | time.sleep(0.5) 47 | -------------------------------------------------------------------------------- /SDL_Pi_AM2315/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | tx* 3 | .*.swp 4 | *.xml 5 | *.temp 6 | *.test 7 | nohup.out 8 | .*DS_Store 9 | conflocal.py 10 | -------------------------------------------------------------------------------- /SDL_Pi_AM2315/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Robert Wolterman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SDL_Pi_AM2315/README.md: -------------------------------------------------------------------------------- 1 | # 2 | # SDL_Pi_AM2315 3 | # 4 | # AM2315 Pure Python Library 5 | # SwitchDoc Labs November 2019 6 | # 7 | # 8 | 9 | Version 1.1: November 14, 2019 - Added CRC Check. Now returns -1 in CRC on CRC Fail 10 | 11 | 12 | #Introduction 13 | This is a pure python AM2315 library to replace the tentacle_pi C based library 14 | 15 | For the SwitchDoc Labs AM2315
16 | https://shop.switchdoc.com/products/grove-am2315-encased-i2c-temperature-humidity-sensor-for-raspberry-pi-arduino 17 | 18 | #Installation 19 | 20 | Requires installation of Adafruit_Python_GPIO 21 | 22 | ``` 23 | sudo apt-get update 24 | sudo apt-get install build-essential python-pip python-dev python-smbus git 25 | git clone https://github.com/adafruit/Adafruit_Python_GPIO.git 26 | cd Adafruit_Python_GPIO 27 | sudo python setup.py install 28 | ``` 29 | 30 | 31 | Place files in program directory 32 | 33 | # testing 34 | 35 | ``` 36 | import AM2315 37 | sens = AM2315.AM2315() 38 | print sens.read_temperature() 39 | print sens.read_humidity() 40 | print sens.read_humidity_temperature() 41 | print sens.read_humidity_temperature_crc() 42 | ``` 43 | -------------------------------------------------------------------------------- /SDL_Pi_AM2315/testAM2315.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import AM2315 4 | import time 5 | import traceback 6 | 7 | 8 | 9 | thsen = AM2315.AM2315(powerpin=6) 10 | 11 | 12 | while (1): 13 | ''' 14 | try: 15 | outsideHumidity, outsideTemperature, crc_check =thsen.fast_read_humidity_temperature_crc() 16 | print "FROT=", outsideTemperature 17 | print "FROH=", outsideHumidity 18 | print "FROCRC=", crc_check 19 | except: 20 | traceback.print_exc() 21 | print "bad AM2315 read" 22 | ''' 23 | #print "T ", thsen.read_temperature() 24 | #print "H ", thsen.read_humidity() 25 | #print "H,T ", thsen.read_humidity_temperature() 26 | #print "H,T,C ", thsen.read_humidity_temperature_crc() 27 | h,t,c = thsen.read_humidity_temperature_crc() 28 | print "CRC=0x%02x" % c 29 | 30 | 31 | print "AM2315 Stats: (g,br,bc,rt,pc)", thsen.read_status_info() 32 | 33 | time.sleep(2.0) 34 | -------------------------------------------------------------------------------- /SDL_Pi_FRAM/README.md: -------------------------------------------------------------------------------- 1 | # 2 | # Raspberry Pi I2C FRAM Reading Library 3 | # SwitchDoc Labs 4 | # February 16, 2015 5 | # 6 | # SwitchDoc Labs www.switchdoc.com 7 | # Designed for WeatherPiArduino 8 | # 9 | 10 | 11 | -------------------------------------------------------------------------------- /SDL_Pi_FRAM/SDL_Pi_FRAM.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # SDL_Pi_FRAM.py Python Driver Code 4 | # SwitchDoc Labs 02/16/2014 5 | # V 1.2 6 | 7 | 8 | from datetime import datetime 9 | 10 | import time 11 | import smbus 12 | 13 | 14 | 15 | class SDL_Pi_FRAM(): 16 | 17 | 18 | ########################### 19 | # SDL_Pi_FRAM Code 20 | ########################### 21 | def __init__(self, twi=1, addr=0x50): 22 | self._bus = smbus.SMBus(twi) 23 | self._addr = addr 24 | 25 | 26 | 27 | def write8(self, address, data): 28 | #print "addr =0x%x address = 0x%x data = 0x%x " % (self._addr, address, data) 29 | self._bus.write_i2c_block_data(self._addr,address>>8,[address%256, data]) 30 | 31 | 32 | 33 | def read8(self, address): 34 | 35 | self._bus.write_i2c_block_data(self._addr,address>>8,[address%256]) 36 | returndata = self._bus.read_byte(self._addr) # this will read at the current address pointer, which we on the previous line 37 | #print "addr = 0x%x address = 0x%x %i returndata = 0x%x " % (self._addr, address, address, returndata) 38 | return returndata 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /SDL_Pi_FRAM/testSDL_Pi_FRAM.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Test SDL_Pi_FRAM 4 | # SwitchDoc Labs 5 | # For WeatherPiArduino 6 | # February 16, 2015 7 | # 8 | # 9 | 10 | # imports 11 | 12 | import sys 13 | import time 14 | import random 15 | import SDL_Pi_FRAM 16 | 17 | # Main Program 18 | 19 | print "" 20 | print "Test SDL_Pi_FRAM Version 1.0 - SwitchDoc Labs" 21 | print "" 22 | print "" 23 | print "Program Started at:"+ time.strftime("%Y-%m-%d %H:%M:%S") 24 | print "" 25 | 26 | fram = SDL_Pi_FRAM.SDL_Pi_FRAM(addr = 0x50) 27 | 28 | while True: 29 | print "----------------- " 30 | print "----------------- " 31 | print " Reading and Writing to FRAM " 32 | print "----------------- " 33 | print "writing first 10 addresses with random data" 34 | for x in range(0,10): 35 | value = random.randint(0,255) 36 | print "address = %i writing value=%i" % (x, value) 37 | fram.write8(x, value) 38 | print "----------------- " 39 | 40 | print "reading first 10 addresses" 41 | for x in range(0,10): 42 | print "address = %i value = %i" %(x, fram.read8(x)) 43 | print "----------------- " 44 | print "----------------- " 45 | 46 | time.sleep(10.0) 47 | 48 | 49 | -------------------------------------------------------------------------------- /SDL_Pi_HDC1000/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | tx* 3 | .*.swp 4 | *.xml 5 | *.temp 6 | *.test 7 | nohup.out 8 | .*DS_Store 9 | conflocal.py 10 | -------------------------------------------------------------------------------- /SDL_Pi_HDC1000/README.md: -------------------------------------------------------------------------------- 1 | Pure Python Raspberry Pi Driver for the TI HDC1000 Temperature and Humidity Sensor 2 |
3 | SDL_Pi_HDC1000
4 | Designed for the SwitchDoc Labs HDC1000 Breakout Board 5 |
6 | store.switchdoc.com 7 | 8 | March 9, 2017: Added Serial Number, Manufacturer ID and Device ID 9 | 10 | Initial Release: January 2017, Version 1.0
11 | 12 | HDC1000 is on default I2C address value of 0x40 13 | 14 | Default resolution is 14 bit tempeature and 14 bit humidity
15 | Heater is default off 16 | 17 | To test: 18 | 19 | 1) Add your HDC1000 to your I2C bus 20 | 21 | 2) Install the archive 22 | 23 | 3) sudo python testHDC1000.py 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SDL_Pi_HDC1000/SDL_Pi_HDC1000.py: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # SDL_Pi_HDC1000 4 | # Raspberry Pi Driver for the SwitchDoc Labs HDC1000 Breakout Board 5 | # 6 | # SwitchDoc Labs 7 | # January 2017 8 | # 9 | # Version 1.1 10 | 11 | #constants 12 | 13 | # I2C Address 14 | HDC1000_ADDRESS = (0x40) # 1000000 15 | # Registers 16 | HDC1000_TEMPERATURE_REGISTER = (0x00) 17 | HDC1000_HUMIDITY_REGISTER = (0x01) 18 | HDC1000_CONFIGURATION_REGISTER = (0x02) 19 | HDC1000_MANUFACTURERID_REGISTER = (0xFE) 20 | HDC1000_DEVICEID_REGISTER = (0xFF) 21 | HDC1000_SERIALIDHIGH_REGISTER = (0xFB) 22 | HDC1000_SERIALIDMID_REGISTER = (0xFC) 23 | HDC1000_SERIALIDBOTTOM_REGISTER = (0xFD) 24 | 25 | #Configuration Register Bits 26 | 27 | HDC1000_CONFIG_RESET_BIT = (0x8000) 28 | HDC1000_CONFIG_HEATER_ENABLE = (0x2000) 29 | HDC1000_CONFIG_ACQUISITION_MODE = (0x1000) 30 | HDC1000_CONFIG_BATTERY_STATUS = (0x0800) 31 | HDC1000_CONFIG_TEMPERATURE_RESOLUTION = (0x0400) 32 | HDC1000_CONFIG_HUMIDITY_RESOLUTION_HBIT = (0x0200) 33 | HDC1000_CONFIG_HUMIDITY_RESOLUTION_LBIT = (0x0100) 34 | 35 | HDC1000_CONFIG_TEMPERATURE_RESOLUTION_14BIT = (0x0000) 36 | HDC1000_CONFIG_TEMPERATURE_RESOLUTION_11BIT = (0x0400) 37 | 38 | HDC1000_CONFIG_HUMIDITY_RESOLUTION_14BIT = (0x0000) 39 | HDC1000_CONFIG_HUMIDITY_RESOLUTION_11BIT = (0x0100) 40 | HDC1000_CONFIG_HUMIDITY_RESOLUTION_8BIT = (0x0200) 41 | 42 | import smbus 43 | import time 44 | 45 | 46 | class SDL_Pi_HDC1000: 47 | def __init__(self, twi=1, addr=HDC1000_ADDRESS ): 48 | self._bus = smbus.SMBus(twi) 49 | self._addr = addr 50 | # 0x10(48) Temperature, Humidity enabled, Resolultion = 14-bits, Heater off 51 | config = HDC1000_CONFIG_ACQUISITION_MODE 52 | self._bus.write_byte_data(HDC1000_ADDRESS,HDC1000_CONFIGURATION_REGISTER, config>>8) 53 | 54 | 55 | # public functions 56 | 57 | def readTemperature(self): 58 | 59 | # Send temp measurement command, 0x00(00) 60 | 61 | self._bus.write_byte(HDC1000_ADDRESS, HDC1000_TEMPERATURE_REGISTER ) 62 | time.sleep(0.020) 63 | 64 | 65 | # Read data back, 2 bytes 66 | 67 | # temp MSB, temp LSB 68 | data0 = self._bus.read_byte(HDC1000_ADDRESS) 69 | data1 = self._bus.read_byte(HDC1000_ADDRESS) 70 | # Convert the data 71 | temp = (data0 * 256) + data1 72 | cTemp = (temp / 65536.0) * 165.0 - 40 73 | return cTemp 74 | 75 | 76 | def readHumidity(self): 77 | # Send humidity measurement command, 0x01(01) 78 | 79 | self._bus.write_byte(HDC1000_ADDRESS, HDC1000_HUMIDITY_REGISTER) 80 | 81 | time.sleep(0.020) 82 | 83 | 84 | # Read data back, 2 bytes 85 | 86 | # humidity MSB, humidity LSB 87 | data0 = self._bus.read_byte(HDC1000_ADDRESS) 88 | data1 = self._bus.read_byte(HDC1000_ADDRESS) 89 | # Convert the data 90 | humidity = (data0 * 256) + data1 91 | humidity = (humidity / 65536.0) * 100.0 92 | return humidity 93 | 94 | def readConfigRegister(self): 95 | # Read config register 96 | 97 | self._bus.write_byte(HDC1000_ADDRESS, HDC1000_CONFIGURATION_REGISTER) 98 | 99 | # config register 100 | data0 = self._bus.read_byte(HDC1000_ADDRESS) 101 | data1 = self._bus.read_byte(HDC1000_ADDRESS) 102 | 103 | #print "register=%d %X"% (data0, data0) 104 | return data0 105 | 106 | def turnHeaterOn(self): 107 | # Read config register 108 | config = self.readConfigRegister() 109 | config = config<<8 | HDC1000_CONFIG_HEATER_ENABLE 110 | self._bus.write_byte_data(HDC1000_ADDRESS,HDC1000_CONFIGURATION_REGISTER,config>>8) 111 | 112 | return 113 | 114 | def turnHeaterOff(self): 115 | # Read config register 116 | config = self.readConfigRegister() 117 | config = config<<8 & ~HDC1000_CONFIG_HEATER_ENABLE 118 | self._bus.write_byte_data(HDC1000_ADDRESS,HDC1000_CONFIGURATION_REGISTER,config>>8) 119 | 120 | return 121 | 122 | def setHumidityResolution(self,resolution): 123 | # Read config register 124 | config = self.readConfigRegister() 125 | config = (config<<8 & ~0x0300) | resolution 126 | self._bus.write_byte_data(HDC1000_ADDRESS,HDC1000_CONFIGURATION_REGISTER,config>>8) 127 | return 128 | 129 | def setTemperatureResolution(self,resolution): 130 | # Read config register 131 | config = self.readConfigRegister() 132 | config = (config<<8 & ~0x0400) | resolution 133 | self._bus.write_byte_data(HDC1000_ADDRESS,HDC1000_CONFIGURATION_REGISTER,config>>8) 134 | return 135 | 136 | 137 | def readBatteryStatus(self): 138 | 139 | # Read config register 140 | config = self.readConfigRegister() 141 | config = config<<8 & ~ HDC1000_CONFIG_HEATER_ENABLE 142 | 143 | if (config == 0): 144 | return True 145 | else: 146 | return False 147 | 148 | return 0 149 | 150 | def readManufacturerID(self): 151 | 152 | data = self._bus.read_i2c_block_data (HDC1000_ADDRESS, HDC1000_MANUFACTURERID_REGISTER , 2) 153 | return data[0] * 256 + data[1] 154 | 155 | def readDeviceID(self): 156 | 157 | data = self._bus.read_i2c_block_data (HDC1000_ADDRESS, HDC1000_DEVICEID_REGISTER , 2) 158 | return data[0] * 256 + data[1] 159 | 160 | def readSerialNumber(self): 161 | 162 | serialNumber = 0 163 | 164 | data = self._bus.read_i2c_block_data (HDC1000_ADDRESS, HDC1000_SERIALIDHIGH_REGISTER , 2) 165 | serialNumber = data[0]*256+ data[1] 166 | 167 | data = self._bus.read_i2c_block_data (HDC1000_ADDRESS, HDC1000_SERIALIDMID_REGISTER , 2) 168 | serialNumber = serialNumber*256 + data[0]*256 + data[1] 169 | 170 | data = self._bus.read_i2c_block_data (HDC1000_ADDRESS, HDC1000_SERIALIDBOTTOM_REGISTER , 2) 171 | serialNumber = serialNumber*256 + data[0]*256 + data[1] 172 | 173 | return serialNumber 174 | 175 | 176 | -------------------------------------------------------------------------------- /SDL_Pi_HDC1000/testHDC1000.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Test SDL_Pi_HDC1000 4 | # 5 | # January 2017 6 | # 7 | 8 | #imports 9 | 10 | import sys 11 | import time 12 | import datetime 13 | import SDL_Pi_HDC1000 14 | 15 | 16 | 17 | # Main Program 18 | 19 | print "" 20 | print "Test SDL_Pi_HDC1000 Version 1.0 - SwitchDoc Labs" 21 | print "" 22 | print "Sample uses 0x40 and SwitchDoc HDC1000 Breakout board " 23 | print "Program Started at:"+ time.strftime("%Y-%m-%d %H:%M:%S") 24 | print "" 25 | 26 | hdc1000 = SDL_Pi_HDC1000.SDL_Pi_HDC1000() 27 | 28 | print "------------" 29 | print "Manfacturer ID=0x%X"% hdc1000.readManufacturerID() 30 | print "Device ID=0x%X"% hdc1000.readDeviceID() 31 | print "Serial Number ID=0x%X"% hdc1000.readSerialNumber() 32 | while True: 33 | 34 | print "-----------------" 35 | print "Temperature = %3.1f C" % hdc1000.readTemperature() 36 | print "Humidity = %3.1f %%" % hdc1000.readHumidity() 37 | 38 | # read configuration register 39 | print "configure register = 0x%X" % hdc1000.readConfigRegister() 40 | # turn heater on 41 | print "turning Heater On" 42 | hdc1000.turnHeaterOn() 43 | # read configuration register 44 | print "configure register = 0x%X" % hdc1000.readConfigRegister() 45 | # turn heater off 46 | print "turning Heater Off" 47 | hdc1000.turnHeaterOff() 48 | # read configuration register 49 | print "configure register = 0x%X" % hdc1000.readConfigRegister() 50 | 51 | # change temperature resolution 52 | print "change temperature resolution" 53 | hdc1000.setTemperatureResolution(SDL_Pi_HDC1000.HDC1000_CONFIG_TEMPERATURE_RESOLUTION_11BIT) 54 | # read configuration register 55 | print "configure register = 0x%X" % hdc1000.readConfigRegister() 56 | # change temperature resolution 57 | print "change temperature resolution" 58 | hdc1000.setTemperatureResolution(SDL_Pi_HDC1000.HDC1000_CONFIG_TEMPERATURE_RESOLUTION_14BIT) 59 | # read configuration register 60 | print "configure register = 0x%X" % hdc1000.readConfigRegister() 61 | 62 | # change humdity resolution 63 | print "change humidity resolution" 64 | hdc1000.setHumidityResolution(SDL_Pi_HDC1000.HDC1000_CONFIG_HUMIDITY_RESOLUTION_8BIT) 65 | # read configuration register 66 | print "configure register = 0x%X" % hdc1000.readConfigRegister() 67 | # change humdity resolution 68 | print "change humidity resolution" 69 | hdc1000.setHumidityResolution(SDL_Pi_HDC1000.HDC1000_CONFIG_HUMIDITY_RESOLUTION_14BIT) 70 | # read configuration register 71 | print "configure register = 0x%X" % hdc1000.readConfigRegister() 72 | 73 | time.sleep(3.0) 74 | -------------------------------------------------------------------------------- /SDL_Pi_INA3221/.gitignore: -------------------------------------------------------------------------------- 1 | .*DS_Store 2 | *.pyc 3 | tx* 4 | .*.swp 5 | *.xml 6 | *.temp 7 | *.test 8 | nohup.out 9 | -------------------------------------------------------------------------------- /SDL_Pi_INA3221/README.md: -------------------------------------------------------------------------------- 1 | 2 | Raspberry Pi Python Library for SwitchDoc Labs INA3221 Breakout Board and SunAirPlus 3 | 4 | SwitchDoc Labs, LLC March 4, 2015 5 | 6 | Run testINA3221.py to test all three channels 7 | 8 | More Information on www.switchdoc.com 9 | 10 | 11 | -------------------------------------------------------------------------------- /SDL_Pi_INA3221/testSDL_Pi_INA3221.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Test SDL_Pi_INA3221 4 | # John C. Shovic, SwitchDoc Labs 5 | # 03/05/2015 6 | # 7 | # 8 | 9 | # imports 10 | 11 | import sys 12 | import time 13 | import datetime 14 | import random 15 | import SDL_Pi_INA3221 16 | 17 | # Main Program 18 | 19 | print "" 20 | print "Test SDL_Pi_INA3221 Version 1.0 - SwitchDoc Labs" 21 | print "" 22 | print "Sample uses 0x40 and SunAirPlus board INA3221" 23 | print " Will work with the INA3221 SwitchDoc Labs Breakout Board" 24 | print "Program Started at:"+ time.strftime("%Y-%m-%d %H:%M:%S") 25 | print "" 26 | 27 | filename = time.strftime("%Y-%m-%d%H:%M:%SRTCTest") + ".txt" 28 | starttime = datetime.datetime.utcnow() 29 | 30 | ina3221 = SDL_Pi_INA3221.SDL_Pi_INA3221(addr=0x40) 31 | 32 | # the three channels of the INA3221 named for SunAirPlus Solar Power Controller channels (www.switchdoc.com) 33 | LIPO_BATTERY_CHANNEL = 1 34 | SOLAR_CELL_CHANNEL = 2 35 | OUTPUT_CHANNEL = 3 36 | 37 | 38 | while True: 39 | 40 | print "------------------------------" 41 | shuntvoltage1 = 0 42 | busvoltage1 = 0 43 | current_mA1 = 0 44 | loadvoltage1 = 0 45 | 46 | 47 | busvoltage1 = ina3221.getBusVoltage_V(LIPO_BATTERY_CHANNEL) 48 | shuntvoltage1 = ina3221.getShuntVoltage_mV(LIPO_BATTERY_CHANNEL) 49 | # minus is to get the "sense" right. - means the battery is charging, + that it is discharging 50 | current_mA1 = ina3221.getCurrent_mA(LIPO_BATTERY_CHANNEL) 51 | 52 | loadvoltage1 = busvoltage1 + (shuntvoltage1 / 1000) 53 | 54 | print "LIPO_Battery Bus Voltage: %3.2f V " % busvoltage1 55 | print "LIPO_Battery Shunt Voltage: %3.2f mV " % shuntvoltage1 56 | print "LIPO_Battery Load Voltage: %3.2f V" % loadvoltage1 57 | print "LIPO_Battery Current 1: %3.2f mA" % current_mA1 58 | print 59 | 60 | shuntvoltage2 = 0 61 | busvoltage2 = 0 62 | current_mA2 = 0 63 | loadvoltage2 = 0 64 | 65 | busvoltage2 = ina3221.getBusVoltage_V(SOLAR_CELL_CHANNEL) 66 | shuntvoltage2 = ina3221.getShuntVoltage_mV(SOLAR_CELL_CHANNEL) 67 | current_mA2 = -ina3221.getCurrent_mA(SOLAR_CELL_CHANNEL) 68 | loadvoltage2 = busvoltage2 + (shuntvoltage2 / 1000) 69 | 70 | print "Solar Cell Bus Voltage 2: %3.2f V " % busvoltage2 71 | print "Solar Cell Shunt Voltage 2: %3.2f mV " % shuntvoltage2 72 | print "Solar Cell Load Voltage 2: %3.2f V" % loadvoltage2 73 | print "Solar Cell Current 2: %3.2f mA" % current_mA2 74 | print 75 | 76 | shuntvoltage3 = 0 77 | busvoltage3 = 0 78 | current_mA3 = 0 79 | loadvoltage3 = 0 80 | 81 | busvoltage3 = ina3221.getBusVoltage_V(OUTPUT_CHANNEL) 82 | shuntvoltage3 = ina3221.getShuntVoltage_mV(OUTPUT_CHANNEL) 83 | current_mA3 = ina3221.getCurrent_mA(OUTPUT_CHANNEL) 84 | loadvoltage3 = busvoltage3 + (shuntvoltage3 / 1000) 85 | 86 | print "Output Bus Voltage 3: %3.2f V " % busvoltage3 87 | print "Output Shunt Voltage 3: %3.2f mV " % shuntvoltage3 88 | print "Output Load Voltage 3: %3.2f V" % loadvoltage3 89 | print "Output Current 3: %3.2f mA" % current_mA3 90 | print 91 | 92 | 93 | # 94 | time.sleep(2.0) 95 | -------------------------------------------------------------------------------- /SDL_Pi_SI1145/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | tx* 3 | .*.swp 4 | *.xml 5 | *.temp 6 | *.test 7 | nohup.out 8 | .*DS_Store 9 | conflocal.py 10 | -------------------------------------------------------------------------------- /SDL_Pi_SI1145/README.md: -------------------------------------------------------------------------------- 1 | SwitchDoc Labs October, 2017 2 | 3 | Restructured for software distribution
4 | Library functions added for reading VIS/IR in Lux with Dark Offset applied
5 | Gain and Range changed for showing indoor ranges
6 | 7 | 8 | -------------------------------------------------------------------------------- /SDL_Pi_SI1145/SI1145Lux.py: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # SI1145 Lux Conversion Routines 4 | # SwitchDocLabs 5 | # Thanks to primexandy for C routines 6 | # December 2016 7 | # 8 | # Added Dark Offsets for IR/Vis 9 | # 10 | # 11 | DARKOFFSETVIS = 259 12 | DARKOFFSETIR = 253 13 | 14 | 15 | 16 | def SI1145_IR_to_Lux(ir): 17 | # irlux = ir * 14.5 / 2.44 for range = high and gain = 1 18 | # apply dark offset 19 | ir = ir - DARKOFFSETIR 20 | if ir < 0: 21 | ir = 0 22 | 23 | lux = 2.44 24 | irlux = 0 25 | multiplier = 0 26 | range = 0 27 | sensitivity = 0 28 | gain = 1 29 | # Get gain multipler 30 | # These are set to defaults in the Adafruit driver - need to change if you change them in the SI1145 driver 31 | ''' 32 | range = SI1145_Read_Param(fd, (unsigned char)ALS_IR_ADC_MISC) 33 | if ((range & 32) == 32): 34 | gain = 14.5 35 | ''' 36 | #gain = 14.5 37 | # Get sensitivity 38 | # These are set to defaults in the Adafruit driver - need to change if you change them in the SI1145 driver 39 | ''' 40 | sensitivity = SI1145_Read_Param(fd, (unsigned char)ALS_IR_ADC_GAIN) 41 | if ((sensitivity & 7) == 0): 42 | multiplier = 1 43 | if ((sensitivity & 7) == 1): 44 | multiplier = 2 45 | if ((sensitivity & 7) == 2): 46 | multiplier = 4 47 | if ((sensitivity & 7) == 3): 48 | multiplier = 8 49 | if ((sensitivity & 7) == 4): 50 | multiplier = 16 51 | if ((sensitivity & 7) == 5): 52 | multiplier = 32 53 | if ((sensitivity & 7) == 6): 54 | multiplier = 64 55 | if ((sensitivity & 7) == 7): 56 | multiplier = 128 57 | ''' 58 | multiplier = 1 59 | #calibration factor to sunlight applied 60 | irlux = ir * (gain / (lux * multiplier)) * 50 61 | return irlux 62 | 63 | def SI1145_VIS_to_Lux(vis): 64 | # vislux = vis * 14.5 / 2.44 for range = high and gain = 1 65 | # apply dark offset 66 | vis = vis - DARKOFFSETVIS 67 | if vis < 0: 68 | vis = 0 69 | 70 | lux = 2.44 71 | vislux = 0 72 | multiplier = 0 73 | range = 0 74 | sensitivity = 0 75 | gain = 1 76 | # Get gain multipler 77 | # These are set to defaults in the Adafruit driver - need to change if you change them in the SI1145 driver 78 | ''' 79 | range = SI1145_Read_Param(fd, (unsigned char)ALS_VIS_ADC_MISC) 80 | if ((range & 32) == 32): 81 | gain = 14.5 82 | ''' 83 | #gain = 14.5 84 | # Get sensitivity 85 | # These are set to defaults in the Adafruit driver - need to change if you change them in the SI1145 driver 86 | ''' 87 | sensitivity = SI1145_Read_Param(fd, (unsigned char)ALS_VIS_ADC_GAIN) 88 | if ((sensitivity & 7) == 0): 89 | multiplier = 1 90 | if ((sensitivity & 7) == 1): 91 | multiplier = 2 92 | if ((sensitivity & 7) == 2): 93 | multiplier = 4 94 | if ((sensitivity & 7) == 3): 95 | multiplier = 8 96 | if ((sensitivity & 7) == 4): 97 | multiplier = 16 98 | if ((sensitivity & 7) == 5): 99 | multiplier = 32 100 | if ((sensitivity & 7) == 6): 101 | multiplier = 64 102 | if ((sensitivity & 7) == 7): 103 | multiplier = 128 104 | ''' 105 | multiplier = 1 106 | # calibration to bright sunlight added 107 | vislux = vis * (gain / (lux * multiplier)) * 100 108 | return vislux 109 | 110 | 111 | -------------------------------------------------------------------------------- /SDL_Pi_SI1145/simpletest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Author: Joe Gutting 4 | # With use of Adafruit SI1145 library for Arduino, Adafruit_GPIO.I2C & BMP Library by Tony DiCola 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | # Can enable debug output by uncommenting: 25 | #import logging 26 | #logging.basicConfig(level=logging.DEBUG) 27 | 28 | import time 29 | import SDL_Pi_SI1145 30 | import SI1145Lux 31 | 32 | # Default constructor will pick a default I2C bus. 33 | # 34 | # For the Raspberry Pi this means you should hook up to the only exposed I2C bus 35 | # from the main GPIO header and the library will figure out the bus number based 36 | # on the Pi's revision. 37 | # 38 | # For the Beaglebone Black the library will assume bus 1 by default, which is 39 | # exposed with SCL = P9_19 and SDA = P9_20. 40 | 41 | sensor = SDL_Pi_SI1145.SDL_Pi_SI1145() 42 | 43 | print 'Press Cntrl + Z to cancel' 44 | 45 | while True: 46 | vis = sensor.readVisible() 47 | IR = sensor.readIR() 48 | UV = sensor.readUV() 49 | IR_Lux = SI1145Lux.SI1145_IR_to_Lux(IR) 50 | vis_Lux = SI1145Lux.SI1145_VIS_to_Lux(vis) 51 | uvIndex = UV / 100.0 52 | print '--------------------' 53 | print 'Vis: ' + str(vis) 54 | print 'IR: ' + str(IR) 55 | print 'UV: ' + str(UV) 56 | print '--------------------' 57 | print 'Vis Lux: ' + str(vis_Lux) 58 | print 'IR Lux: ' + str(IR_Lux) 59 | print 'UV Index: ' + str(uvIndex) 60 | print '--------------------' 61 | time.sleep(5) 62 | 63 | -------------------------------------------------------------------------------- /SDL_Pi_SSD1306/README.md: -------------------------------------------------------------------------------- 1 | Modifications by SwitchDoc Labs to support the Grove OLED 128x64 Display from SwitchDoc Labs March 2016 2 | 3 | 4 | Before using the library you will need to make sure you have a few dependencies installed. Connect to your device using SSH and follow the steps below. 5 | 6 | If you're using a Raspberry Pi, install the RPi.GPIO library by executing: 7 | sudo apt-get update 8 | sudo apt-get install build-essential python-dev python-pip 9 | sudo pip install RPi.GPIO 10 | 11 | 12 | Finally, on the Raspberry Pi install the Python Imaging Library and smbus library by executing: 13 | 14 | sudo apt-get install python-imaging python-smbus 15 | 16 | Now to download and install the SSD1306 python library code and examples, execute the following commands: 17 | 18 | sudo apt-get install git 19 | git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git 20 | cd Adafruit_Python_SSD1306 21 | sudo python setup.py install 22 | 23 | ------------------------ 24 | Running test programs 25 | ------------------------ 26 | 27 | The Adafruit test programs have been slightly modified to run the SwitchDoc Labs OLED display. The I2C address has changed to 0x3C. 28 | 29 | To run: 30 | 31 | sudo python SDL_image.py 32 | 33 | sudo python SDL_animate.py 34 | 35 | sudo python SDL_shapes.py 36 | --------------------------------- 37 | 38 | 39 | 40 | 41 | Adafruit Python SSD1306 42 | ======================= 43 | 44 | Python library to use SSD1306-based 128x64 or 128x32 pixel OLED displays with a Raspberry Pi or Beaglebone Black. 45 | 46 | Designed specifically to work with the Adafruit SSD1306-based OLED displays ----> https://www.adafruit.com/categories/98 47 | 48 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 49 | 50 | Written by Tony DiCola for Adafruit Industries. 51 | MIT license, all text above must be included in any redistribution 52 | -------------------------------------------------------------------------------- /SDL_Pi_SSD1306/SDL_animate.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import math 22 | import time 23 | 24 | import Adafruit_GPIO.SPI as SPI 25 | import Adafruit_SSD1306 26 | 27 | import Image 28 | import ImageFont 29 | import ImageDraw 30 | 31 | 32 | # Raspberry Pi pin configuration: 33 | RST = 24 34 | # Note the following are only used with SPI: 35 | DC = 23 36 | SPI_PORT = 0 37 | SPI_DEVICE = 0 38 | 39 | # Beaglebone Black pin configuration: 40 | # RST = 'P9_12' 41 | # Note the following are only used with SPI: 42 | # DC = 'P9_15' 43 | # SPI_PORT = 1 44 | # SPI_DEVICE = 0 45 | 46 | # 128x32 display with hardware I2C: 47 | disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) 48 | 49 | # 128x64 display with hardware I2C: 50 | #disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) 51 | 52 | 53 | # Note you can change the I2C address by passing an i2c_address parameter like: 54 | disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, i2c_address=0x3C) 55 | 56 | # 128x32 display with hardware SPI: 57 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 58 | 59 | # 128x64 display with hardware SPI: 60 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 61 | 62 | # Initialize library. 63 | disp.begin() 64 | 65 | # Get display width and height. 66 | width = disp.width 67 | height = disp.height 68 | 69 | # Clear display. 70 | disp.clear() 71 | disp.display() 72 | 73 | # Create image buffer. 74 | # Make sure to create image with mode '1' for 1-bit color. 75 | image = Image.new('1', (width, height)) 76 | 77 | # Load default font. 78 | font = ImageFont.load_default() 79 | 80 | # Alternatively load a TTF font. Make sure the .ttf font file is in the same directory as this python script! 81 | # Some nice fonts to try: http://www.dafont.com/bitmap.php 82 | # font = ImageFont.truetype('Minecraftia.ttf', 8) 83 | 84 | # Create drawing object. 85 | draw = ImageDraw.Draw(image) 86 | 87 | # Define text and get total width. 88 | text = 'SSD1306 ORGANIC LED DISPLAY. THIS IS AN OLD SCHOOL DEMO SCROLLER!! GREETZ TO: LADYADA & THE ADAFRUIT CREW, TRIXTER, FUTURE CREW, AND FARBRAUSCH' 89 | maxwidth, unused = draw.textsize(text, font=font) 90 | 91 | # Set animation and sine wave parameters. 92 | amplitude = height/4 93 | offset = height/2 - 4 94 | velocity = -2 95 | startpos = width 96 | 97 | # Animate text moving in sine wave. 98 | print 'Press Ctrl-C to quit.' 99 | pos = startpos 100 | while True: 101 | # Clear image buffer by drawing a black filled box. 102 | draw.rectangle((0,0,width,height), outline=0, fill=0) 103 | # Enumerate characters and draw them offset vertically based on a sine wave. 104 | x = pos 105 | for i, c in enumerate(text): 106 | # Stop drawing if off the right side of screen. 107 | if x > width: 108 | break 109 | # Calculate width but skip drawing if off the left side of screen. 110 | if x < -10: 111 | char_width, char_height = draw.textsize(c, font=font) 112 | x += char_width 113 | continue 114 | # Calculate offset from sine wave. 115 | y = offset+math.floor(amplitude*math.sin(x/float(width)*2.0*math.pi)) 116 | # Draw text. 117 | draw.text((x, y), c, font=font, fill=255) 118 | # Increment x position based on chacacter width. 119 | char_width, char_height = draw.textsize(c, font=font) 120 | x += char_width 121 | # Draw the image buffer. 122 | disp.image(image) 123 | disp.display() 124 | # Move position for next frame. 125 | pos += velocity 126 | # Start over if text has scrolled completely off left side of screen. 127 | if pos < -maxwidth: 128 | pos = startpos 129 | # Pause briefly before drawing next frame. 130 | time.sleep(0.1) 131 | -------------------------------------------------------------------------------- /SDL_Pi_SSD1306/SDL_image.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import time 22 | 23 | import Adafruit_GPIO.SPI as SPI 24 | import Adafruit_SSD1306 25 | 26 | import Image 27 | 28 | 29 | # Raspberry Pi pin configuration: 30 | RST = 24 31 | # Note the following are only used with SPI: 32 | DC = 23 33 | SPI_PORT = 0 34 | SPI_DEVICE = 0 35 | 36 | # Beaglebone Black pin configuration: 37 | # RST = 'P9_12' 38 | # Note the following are only used with SPI: 39 | # DC = 'P9_15' 40 | # SPI_PORT = 1 41 | # SPI_DEVICE = 0 42 | 43 | # 128x32 display with hardware I2C: 44 | #disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) 45 | 46 | # 128x64 display with hardware I2C: 47 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) 48 | 49 | # 128x32 display with hardware SPI: 50 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 51 | 52 | # 128x64 display with hardware SPI: 53 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 54 | 55 | # Note you can change the I2C address by passing an i2c_address parameter like: 56 | disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, i2c_address=0x3C) 57 | # Initialize library. 58 | disp.begin() 59 | 60 | # Clear display. 61 | disp.clear() 62 | disp.display() 63 | 64 | # Load image based on OLED display height. Note that image is converted to 1 bit color. 65 | if disp.height == 64: 66 | image = Image.open('happycat_oled_64.ppm').convert('1') 67 | else: 68 | image = Image.open('happycat_oled_32.ppm').convert('1') 69 | 70 | # Alternatively load a different format image, resize it, and convert to 1 bit color. 71 | #image = Image.open('happycat.png').resize((disp.width, disp.height), Image.ANTIALIAS).convert('1') 72 | 73 | # Display image. 74 | disp.image(image) 75 | disp.display() 76 | -------------------------------------------------------------------------------- /SDL_Pi_SSD1306/SDL_shapes.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | import time 22 | 23 | import Adafruit_GPIO.SPI as SPI 24 | import Adafruit_SSD1306 25 | 26 | import Image 27 | import ImageDraw 28 | import ImageFont 29 | 30 | 31 | # Raspberry Pi pin configuration: 32 | RST = 24 33 | # Note the following are only used with SPI: 34 | DC = 23 35 | SPI_PORT = 0 36 | SPI_DEVICE = 0 37 | 38 | # Beaglebone Black pin configuration: 39 | # RST = 'P9_12' 40 | # Note the following are only used with SPI: 41 | # DC = 'P9_15' 42 | # SPI_PORT = 1 43 | # SPI_DEVICE = 0 44 | 45 | # 128x32 display with hardware I2C: 46 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) 47 | 48 | # 128x64 display with hardware I2C: 49 | #disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) 50 | 51 | # Note you can change the I2C address by passing an i2c_address parameter like: 52 | disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, i2c_address=0x3C) 53 | 54 | # Alternatively you can specify an explicit I2C bus number, for example 55 | # with the 128x32 display you would use: 56 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, i2c_bus=2) 57 | 58 | # 128x32 display with hardware SPI: 59 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 60 | 61 | # 128x64 display with hardware SPI: 62 | # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) 63 | 64 | # Alternatively you can specify a software SPI implementation by providing 65 | # digital GPIO pin numbers for all the required display pins. For example 66 | # on a Raspberry Pi with the 128x32 display you might use: 67 | # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, sclk=18, din=25, cs=22) 68 | 69 | # Initialize library. 70 | disp.begin() 71 | 72 | # Clear display. 73 | disp.clear() 74 | disp.display() 75 | 76 | # Create blank image for drawing. 77 | # Make sure to create image with mode '1' for 1-bit color. 78 | width = disp.width 79 | height = disp.height 80 | image = Image.new('1', (width, height)) 81 | 82 | # Get drawing object to draw on image. 83 | draw = ImageDraw.Draw(image) 84 | 85 | # Draw a black filled box to clear the image. 86 | draw.rectangle((0,0,width,height), outline=0, fill=0) 87 | 88 | # Draw some shapes. 89 | # First define some constants to allow easy resizing of shapes. 90 | padding = 2 91 | shape_width = 20 92 | top = padding 93 | bottom = height-padding 94 | # Move left to right keeping track of the current x position for drawing shapes. 95 | x = padding 96 | # Draw an ellipse. 97 | draw.ellipse((x, top , x+shape_width, bottom), outline=255, fill=0) 98 | x += shape_width+padding 99 | # Draw a rectangle. 100 | draw.rectangle((x, top, x+shape_width, bottom), outline=255, fill=0) 101 | x += shape_width+padding 102 | # Draw a triangle. 103 | draw.polygon([(x, bottom), (x+shape_width/2, top), (x+shape_width, bottom)], outline=255, fill=0) 104 | x += shape_width+padding 105 | # Draw an X. 106 | draw.line((x, bottom, x+shape_width, top), fill=255) 107 | draw.line((x, top, x+shape_width, bottom), fill=255) 108 | x += shape_width+padding 109 | 110 | # Load default font. 111 | font = ImageFont.load_default() 112 | 113 | # Alternatively load a TTF font. Make sure the .ttf font file is in the same directory as the python script! 114 | # Some other nice fonts to try: http://www.dafont.com/bitmap.php 115 | #font = ImageFont.truetype('Minecraftia.ttf', 8) 116 | 117 | # Write two lines of text. 118 | draw.text((x, top), 'Hello', font=font, fill=255) 119 | draw.text((x, top+20), 'World!', font=font, fill=255) 120 | 121 | # Display image. 122 | disp.image(image) 123 | disp.display() 124 | -------------------------------------------------------------------------------- /SDL_Pi_SSD1306/happycat_oled_32.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/SDL_Pi_SSD1306/happycat_oled_32.ppm -------------------------------------------------------------------------------- /SDL_Pi_SSD1306/happycat_oled_64.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/SDL_Pi_SSD1306/happycat_oled_64.ppm -------------------------------------------------------------------------------- /SDL_Pi_TCA9545/.gitignore: -------------------------------------------------------------------------------- 1 | .*DS_Store 2 | *.pyc 3 | tx* 4 | .*.swp 5 | *.xml 6 | *.temp 7 | *.test 8 | nohup.out 9 | -------------------------------------------------------------------------------- /SDL_Pi_TCA9545/README.md: -------------------------------------------------------------------------------- 1 | 2 | Raspberry Pi Python Library for SwitchDoc Labs I2C Mux (TCA9545A) Breakout Board 3 | 4 | SwitchDoc Labs, LLC April 2, 2015 5 | 6 | Run testSDL_Pi_TCA9545.py to test all three channels 7 | 8 | More Information on www.switchdoc.com 9 | 10 | January 17, 2016: Verified to work with new I2CMux Grove board from SwitchDoc Labs 11 | 12 | April 10, 2015: Removed debug statement in read_control_register 13 | 14 | -------------------------------------------------------------------------------- /SDL_Pi_TCA9545/SDL_Pi_TCA9545.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # SDL_Pi_TCA9545.py Python Driver Code 4 | # SwitchDoc Labs April 1, 2015 5 | # V 1.2 6 | 7 | 8 | #encoding: utf-8 9 | 10 | from datetime import datetime 11 | 12 | import smbus 13 | 14 | # constants 15 | 16 | #/*========================================================================= 17 | # I2C ADDRESS/BITS 18 | # -----------------------------------------------------------------------*/ 19 | TCA9545_ADDRESS = (0x73) # 1110011 (A0+A1=VDD) 20 | #/*=========================================================================*/ 21 | 22 | #/*========================================================================= 23 | # CONFIG REGISTER (R/W) 24 | # -----------------------------------------------------------------------*/ 25 | TCA9545_REG_CONFIG = (0x00) 26 | # /*---------------------------------------------------------------------*/ 27 | 28 | TCA9545_CONFIG_BUS0 = (0x01) # 1 = enable, 0 = disable 29 | TCA9545_CONFIG_BUS1 = (0x02) # 1 = enable, 0 = disable 30 | TCA9545_CONFIG_BUS2 = (0x04) # 1 = enable, 0 = disable 31 | TCA9545_CONFIG_BUS3 = (0x08) # 1 = enable, 0 = disable 32 | 33 | #/*=========================================================================*/ 34 | 35 | 36 | class SDL_Pi_TCA9545(): 37 | 38 | 39 | 40 | ########################### 41 | # TCA9545 Code 42 | ########################### 43 | def __init__(self, twi=1, addr=TCA9545_ADDRESS, bus_enable = TCA9545_CONFIG_BUS0 ): 44 | self._bus = smbus.SMBus(twi) 45 | self._addr = addr 46 | config = bus_enable 47 | self._write(TCA9545_REG_CONFIG, config) 48 | 49 | 50 | def _write(self, register, data): 51 | #print "addr =0x%x register = 0x%x data = 0x%x " % (self._addr, register, data) 52 | self._bus.write_byte_data(self._addr, register, data) 53 | 54 | 55 | def _read(self ): 56 | 57 | returndata = self._bus.read_byte(self._addr) 58 | #print "addr = 0x%x returndata = 0x%x " % (self._addr, returndata) 59 | return returndata 60 | 61 | 62 | 63 | # public functions 64 | 65 | def read_control_register(self): 66 | # Reads Control Register 67 | 68 | value = self._read() 69 | return value 70 | 71 | def write_control_register(self, config): 72 | # Writes Control Register 73 | 74 | self._write(TCA9545_REG_CONFIG, config) 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /SDL_Pi_TCA9545/testSDL_Pi_TCA9545.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Test SDL_Pi_INA3221 4 | # John C. Shovic, SwitchDoc Labs 5 | # 03/05/2015 6 | # 7 | # 8 | 9 | # imports 10 | 11 | import sys 12 | import time 13 | import datetime 14 | import random 15 | import SDL_Pi_TCA9545 16 | import subprocess 17 | 18 | 19 | 20 | #/*========================================================================= 21 | # I2C ADDRESS/BITS 22 | # -----------------------------------------------------------------------*/ 23 | TCA9545_ADDRESS = (0x73) # 1110011 (A0+A1=VDD) 24 | #/*=========================================================================*/ 25 | 26 | #/*========================================================================= 27 | # CONFIG REGISTER (R/W) 28 | # -----------------------------------------------------------------------*/ 29 | TCA9545_REG_CONFIG = (0x00) 30 | # /*---------------------------------------------------------------------*/ 31 | 32 | TCA9545_CONFIG_BUS0 = (0x01) # 1 = enable, 0 = disable 33 | TCA9545_CONFIG_BUS1 = (0x02) # 1 = enable, 0 = disable 34 | TCA9545_CONFIG_BUS2 = (0x04) # 1 = enable, 0 = disable 35 | TCA9545_CONFIG_BUS3 = (0x08) # 1 = enable, 0 = disable 36 | 37 | #/*=========================================================================*/ 38 | 39 | # Main Program 40 | 41 | print "" 42 | print "Test SDL_Pi_TCA9545 Version 1.0 - SwitchDoc Labs" 43 | print "" 44 | print "Sample uses 0x73" 45 | print "Program Started at:"+ time.strftime("%Y-%m-%d %H:%M:%S") 46 | print "" 47 | 48 | filename = time.strftime("%Y-%m-%d%H:%M:%SRTCTest") + ".txt" 49 | starttime = datetime.datetime.utcnow() 50 | 51 | tca9545 = SDL_Pi_TCA9545.SDL_Pi_TCA9545(addr=TCA9545_ADDRESS, bus_enable = TCA9545_CONFIG_BUS0) 52 | 53 | # rotates through all 4 I2C buses and prints out what is available on each 54 | 55 | while True: 56 | print "-----------BUS 0-------------------" 57 | 58 | tca9545.write_control_register(TCA9545_CONFIG_BUS0) 59 | # read the control register back 60 | control_register = tca9545.read_control_register() 61 | print "tca9545 control register B3-B0 = 0x%x"% (control_register & 0x0f ) 62 | print "ignore Interrupts if INT3' - INT0' not connected" 63 | print "tca9545 control register Interrupts = 0x%x"% ((control_register & 0xf0) >> 4) 64 | 65 | i2ccommand = "sudo i2cdetect -y 1" 66 | output = subprocess.check_output (i2ccommand,shell=True, stderr=subprocess.STDOUT ) 67 | print output 68 | 69 | print "-----------------------------------" 70 | print 71 | time.sleep(5.0) 72 | 73 | print "-----------BUS 1-------------------" 74 | 75 | tca9545.write_control_register(TCA9545_CONFIG_BUS1) 76 | # read the control register back 77 | control_register = tca9545.read_control_register() 78 | print "tca9545 control register B3-B0 = 0x%x"% (control_register & 0x0f ) 79 | print "ignore Interrupts if INT3' - INT0' not connected" 80 | print "tca9545 control register Interrupts = 0x%x"% ((control_register & 0xf0) >> 4) 81 | 82 | i2ccommand = "sudo i2cdetect -y 1" 83 | output = subprocess.check_output (i2ccommand,shell=True, stderr=subprocess.STDOUT ) 84 | print output 85 | 86 | print "-----------------------------------" 87 | print 88 | time.sleep(5.0) 89 | 90 | print "-----------BUS 2-------------------" 91 | 92 | tca9545.write_control_register(TCA9545_CONFIG_BUS2) 93 | # read the control register back 94 | control_register = tca9545.read_control_register() 95 | print "tca9545 control register B3-B0 = 0x%x"% (control_register & 0x0f ) 96 | print "ignore Interrupts if INT3' - INT0' not connected" 97 | print "tca9545 control register Interrupts = 0x%x"% ((control_register & 0xf0) >> 4) 98 | 99 | i2ccommand = "sudo i2cdetect -y 1" 100 | output = subprocess.check_output (i2ccommand,shell=True, stderr=subprocess.STDOUT ) 101 | print output 102 | 103 | print "-----------------------------------" 104 | print 105 | time.sleep(5.0) 106 | 107 | print "-----------BUS 3-------------------" 108 | 109 | tca9545.write_control_register(TCA9545_CONFIG_BUS3) 110 | # read the control register back 111 | control_register = tca9545.read_control_register() 112 | print "tca9545 control register B3-B0 = 0x%x"% (control_register & 0x0f ) 113 | print "ignore Interrupts if INT3' - INT0' not connected" 114 | print "tca9545 control register Interrupts = 0x%x"% ((control_register & 0xf0) >> 4) 115 | 116 | i2ccommand = "sudo i2cdetect -y 1" 117 | output = subprocess.check_output (i2ccommand,shell=True, stderr=subprocess.STDOUT ) 118 | print output 119 | 120 | print "-----------------------------------" 121 | print 122 | time.sleep(5.0) 123 | 124 | -------------------------------------------------------------------------------- /SDL_Pi_WeatherRack/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | tx* 3 | .*.swp 4 | *.xml 5 | *.temp 6 | *.test 7 | nohup.out 8 | .*DS_Store 9 | -------------------------------------------------------------------------------- /SDL_Pi_WeatherRack/NoWPAConfig.py: -------------------------------------------------------------------------------- 1 | # device present global variables 2 | 3 | AS3935_Present = False 4 | DS3231_Present = False 5 | BMP280_Present = False 6 | FRAM_Present = False 7 | HTU21DF_Present = False 8 | AM2315_Present = False 9 | ADS1015_Present = False 10 | ADS1115_Present = False 11 | -------------------------------------------------------------------------------- /SDL_Pi_WeatherRack/README.md: -------------------------------------------------------------------------------- 1 | SDL_Pi_WeatherRack - Python Class Library for: 2 | 3 | SwitchDoc Labs WeatherRack
4 | Argent Data Systems
5 | SparkFun Weather Station
6 | 7 | Created by SwitchDoc Labs February 13, 2015. Released into the public domain. 8 | 9 | www.switchdoc.com 10 | 11 | Version 1.0 - February 13, 2015
12 | Version 1.1 - February 20, 2015 - Added 3.3V Constants
13 | Version 1.2 - March 30, 2015 - Fixed Wind Gust Measurement
14 | Version 1.3 - July 25, 2015 - Removed 300ms debounce error
15 | Version 1.4 - August 13, 2015 - Removed divide by 2 in rain measurements (see 1.3)
16 | Version 1.5 - November 29, 2015 - change ADS1015 address to the default 0x48 (which is the default on WeatherPiArduino)
17 | Version 2.0 - Modifications for WeatherPiArduino Version 2
18 | Version 2.1 - July 17, 2017 - Modified Hardware Bounce times
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SDL_Pi_WeatherRack/SDL_Pi_WeatherRackTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # SDL_Pi_WeatherRack Example Test File 4 | # Version 1.0 February 12, 2015 5 | # 6 | # SwitchDoc Labs 7 | # www.switchdoc.com 8 | # 9 | # 10 | 11 | 12 | #imports 13 | 14 | import time 15 | import sys 16 | 17 | sys.path.append('../Adafruit_ADS1x15') 18 | sys.path.append('../') 19 | 20 | import config 21 | 22 | import SDL_Pi_WeatherRack as SDL_Pi_WeatherRack 23 | 24 | # 25 | # GPIO Numbering Mode GPIO.BCM 26 | # 27 | 28 | anenometerPin = 26 29 | rainPin = 21 30 | #anenometerPin = 6 31 | #rainPin = 12 32 | 33 | # constants 34 | 35 | SDL_MODE_INTERNAL_AD = 0 36 | SDL_MODE_I2C_ADS1015 = 1 37 | 38 | #sample mode means return immediately. THe wind speed is averaged at sampleTime or when you ask, whichever is longer 39 | SDL_MODE_SAMPLE = 0 40 | #Delay mode means to wait for sampleTime and the average after that time. 41 | SDL_MODE_DELAY = 1 42 | 43 | weatherStation = SDL_Pi_WeatherRack.SDL_Pi_WeatherRack(anenometerPin, rainPin, 0,0, SDL_MODE_I2C_ADS1015) 44 | 45 | weatherStation.setWindMode(SDL_MODE_SAMPLE, 5.0) 46 | #weatherStation.setWindMode(SDL_MODE_DELAY, 5.0) 47 | 48 | maxEverWind = 0.0 49 | maxEverGust = 0.0 50 | totalRain = 0 51 | while True: 52 | 53 | 54 | print "---------------------------------------- " 55 | print "----------------- " 56 | print " SDL_Pi_WeatherRack Library" 57 | print " WeatherRack Weather Sensors" 58 | print "----------------- " 59 | # 60 | 61 | currentWindSpeed = weatherStation.current_wind_speed()/1.609 62 | currentWindGust = weatherStation.get_wind_gust()/1.609 63 | totalRain = totalRain + (weatherStation.get_current_rain_total()/25.4) 64 | print("Rain Total=\t%0.2f in")%(totalRain) 65 | print("Wind Speed=\t%0.2f MPH")%(currentWindSpeed) 66 | if currentWindSpeed > maxEverWind: 67 | maxEverWind = currentWindSpeed 68 | 69 | if currentWindGust > maxEverGust: 70 | maxEverGust = currentWindGust 71 | 72 | print("max Ever Wind Speed=\t%0.2f MPH")%(maxEverWind) 73 | print("MPH wind_gust=\t%0.2f MPH")%(currentWindGust) 74 | print("max Ever Gust wind_gust=\t%0.2f MPH")%(maxEverGust) 75 | print "Wind Direction=\t\t\t %0.2f Degrees" % weatherStation.current_wind_direction() 76 | 77 | print "Wind Direction Voltage=\t\t %0.3f V" % weatherStation.current_wind_direction_voltage() 78 | 79 | print "----------------- " 80 | print "----------------- " 81 | 82 | time.sleep(5.0) 83 | -------------------------------------------------------------------------------- /Scroll_SSD1306.py: -------------------------------------------------------------------------------- 1 | # 2 | # Libraries to use the SDL_1306 as a scrollable device for WPA V3 3 | # 4 | 5 | import time 6 | 7 | import Adafruit_GPIO.SPI as SPI 8 | import Adafruit_SSD1306 9 | 10 | from PIL import Image 11 | from PIL import ImageDraw 12 | from PIL import ImageFont 13 | 14 | OLEDLines = ["","","","","",""] 15 | width = 128 16 | height = 64 17 | top = 0 18 | lineheight = 10 19 | currentLine = 0 20 | offset = 0 21 | 22 | image = Image.new('1', (width, height)) 23 | 24 | 25 | draw = ImageDraw.Draw(image) 26 | # Load default font. 27 | 28 | font = ImageFont.load_default() 29 | 30 | 31 | def addLineOLED(display, text): 32 | 33 | 34 | global currentLine, offset, OLEDLines 35 | # Write line of text. 36 | 37 | # Draw a black filled box to clear the line. 38 | draw.rectangle((0,lineheight*currentLine, 127, lineheight*(currentLine+1)-1), outline=0, fill=0) 39 | draw.text((0, lineheight*currentLine), text, font=font, fill=255) 40 | OLEDLines[currentLine] = text 41 | 42 | if (currentLine == 5): 43 | for i in range(0,5): 44 | j = 5 - i -1 45 | draw.rectangle((0,lineheight*(j), 127, lineheight*(j+1)-1), outline=0, fill=0) 46 | draw.text((0, lineheight*(j)), OLEDLines[j], font=font, fill=255) 47 | 48 | 49 | if (currentLine < 5): 50 | currentLine = currentLine + 1 51 | else: 52 | currentLine = 5 53 | # rewrite lines 54 | for i in range(0,5): 55 | OLEDLines[i] = OLEDLines[i+1] 56 | ''' 57 | for i in range(0,1): 58 | offset = (offset + 1) % 64 59 | display.command(0x40 | offset) 60 | time.sleep(0.01) 61 | 62 | ''' 63 | 64 | display.image(image) 65 | display.display() 66 | 67 | 68 | def addNumberedLineOLED(display, linenumber, text): 69 | 70 | # write one line of text at linenumber 71 | 72 | draw.rectangle((0,lineheight*currentLine, 127, lineheight*(currentLine+1)-1), outline=0, fill=0) 73 | draw.text((0, linenumber*lineheight), text, font=font, fill=255) 74 | 75 | display.image(image) 76 | display.display() 77 | 78 | -------------------------------------------------------------------------------- /WeatherPiSQL/WeatherPiStructure.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS GroveWeatherPi; 2 | USE GroveWeatherPi; 3 | -- phpMyAdmin SQL Dump 4 | -- version 3.4.11.1deb2+deb7u1 5 | -- http://www.phpmyadmin.net 6 | -- 7 | -- Host: localhost 8 | -- Generation Time: Jul 23, 2015 at 12:27 AM 9 | -- Server version: 5.5.44 10 | -- PHP Version: 5.4.41-0+deb7u1 11 | 12 | SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 13 | SET time_zone = "+00:00"; 14 | 15 | 16 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 17 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 18 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 19 | /*!40101 SET NAMES utf8 */; 20 | 21 | -- 22 | -- Database: `GroveWeatherPi` 23 | -- 24 | 25 | -- -------------------------------------------------------- 26 | 27 | -- 28 | -- Table structure for table `PowerSystem` 29 | -- 30 | 31 | DROP TABLE IF EXISTS `PowerSystem`; 32 | CREATE TABLE IF NOT EXISTS `PowerSystem` ( 33 | `ID` int(11) NOT NULL AUTO_INCREMENT, 34 | `TimeStamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 35 | `batteryVoltage` float NOT NULL, 36 | `batteryCurrent` float NOT NULL, 37 | `solarVoltage` float NOT NULL, 38 | `solarCurrent` float NOT NULL, 39 | `loadVoltage` float NOT NULL, 40 | `loadCurrent` float NOT NULL, 41 | `batteryPower` float NOT NULL, 42 | `solarPower` float NOT NULL, 43 | `loadPower` float NOT NULL, 44 | `batteryCharge` float NOT NULL, 45 | PRIMARY KEY (`ID`) 46 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=16170 ; 47 | 48 | -- -------------------------------------------------------- 49 | 50 | -- 51 | -- Table structure for table `systemlog` 52 | -- 53 | 54 | DROP TABLE IF EXISTS `systemlog`; 55 | CREATE TABLE IF NOT EXISTS `systemlog` ( 56 | `ID` int(11) NOT NULL AUTO_INCREMENT, 57 | `TimeStamp` datetime NOT NULL, 58 | `Level` int(11) NOT NULL, 59 | `Source` varchar(250) NOT NULL, 60 | `Message` varchar(250) NOT NULL, 61 | PRIMARY KEY (`ID`) 62 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1527 ; 63 | 64 | -- -------------------------------------------------------- 65 | 66 | -- 67 | -- Table structure for table `WeatherData` 68 | -- 69 | 70 | DROP TABLE IF EXISTS `WeatherData`; 71 | CREATE TABLE IF NOT EXISTS `WeatherData` ( 72 | `ID` int(20) NOT NULL AUTO_INCREMENT, 73 | `TimeStamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 74 | `as3935LightningCount` float NOT NULL, 75 | `as3935LastInterrupt` float NOT NULL, 76 | `as3935LastDistance` float NOT NULL, 77 | `as3935LastStatus` varchar(200) NOT NULL, 78 | `currentWindSpeed` float NOT NULL, 79 | `currentWindGust` float NOT NULL, 80 | `currentWindDirection` float NOT NULL, 81 | `currentWindDirectionVoltage` float NOT NULL, 82 | `totalRain` float NOT NULL, 83 | `bmp180Temperature` int(20) NOT NULL, 84 | `bmp180Pressure` float NOT NULL, 85 | `bmp180Altitude` float NOT NULL, 86 | `bmp180SeaLevel` float NOT NULL, 87 | `outsideTemperature` float NOT NULL, 88 | `outsideHumidity` float NOT NULL, 89 | `insideTemperature` float NOT NULL, 90 | `insideHumidity` float NOT NULL, 91 | PRIMARY KEY (`ID`) 92 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Weather Data' AUTO_INCREMENT=15808 ; 93 | 94 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 95 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 96 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 97 | -------------------------------------------------------------------------------- /WeatherUnderground.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # Send GroveWeatherPi Information to the WeatherUnderground 4 | # 5 | # SwitchDoc Labs September, 2016 6 | # modifications November 2016 - Luksmann - changed to request library to improve reliablity 7 | # 8 | import sys 9 | import requests 10 | # import httplib 11 | 12 | # Check for user imports 13 | try: 14 | import conflocal as config 15 | except ImportError: 16 | import config 17 | 18 | def sendWeatherUndergroundData( as3935LightningCount, as3935, as3935LastInterrupt, as3935LastDistance, as3935LastStatus, currentWindSpeed, currentWindGust, totalRain, bmp180Temperature, bmp180Pressure, bmp180Altitude, bmp180SeaLevel, outsideTemperature, outsideHumidity, crc_check, currentWindDirection, currentWindDirectionVoltage, HTUtemperature, HTUhumidity, rain60Minutes): 19 | 20 | # https://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?ID=KCASANFR5&PASSWORD=XXXXXX&dateutc=2000-01-01+10%3A32%3A35&winddir=230&windspeedmph=12&windgustmph=12&tempf=70&rainin=0&baromin=29.1&dewptf=68.2&humidity=90&weather=&clouds=&softwaretype=vws%20versionxx&action=updateraw 21 | 22 | # build the URL 23 | myURL = "ID="+config.WeatherUnderground_StationID 24 | myURL += "&PASSWORD="+config.WeatherUnderground_StationKey 25 | myURL += "&dateutc=now" 26 | 27 | # now weather station variables 28 | 29 | myURL += "&winddir=%i" % currentWindDirection 30 | print "cws=|",currentWindSpeed 31 | 32 | myURL += "&windspeedmph=%0.2f" % (currentWindSpeed/1.6) 33 | myURL += "&windgustmph=%0.2f" % (currentWindGust/1.6) 34 | 35 | myURL += "&humidity=%i" % outsideHumidity 36 | myURL += "&tempf=%0.2f" % ((outsideTemperature*9.0/5.0)+32.0) 37 | 38 | dewpoint = outsideTemperature - ((100.0 - outsideHumidity) / 5.0); 39 | dewpointf = ((dewpoint*9.0/5.0)+32.0) 40 | myURL += "&dewptf=%0.2f" % dewpointf 41 | 42 | myURL += "&rainin=%0.2f" % ((rain60Minutes)/25.4) 43 | myURL += "&dailyrainin=%0.2f" % ((totalRain)/25.4) 44 | myURL += "&baromin=%0.2f" % ((bmp180SeaLevel) * 0.2953) 45 | 46 | myURL += "&indoortempf=%0.2f" % ((HTUtemperature*9.0/5.0)+32.0) 47 | myURL += "&indoorhumidity%0.2f=" % HTUhumidity 48 | 49 | myURL += "&software=GroveWeatherPi" 50 | 51 | 52 | 53 | print "myURL=", myURL 54 | #send it 55 | r = requests.get("https://weatherstation.wunderground.com/weatherstation/updateweatherstation.php", params=myURL) 56 | 57 | print(r.url) 58 | print(r.text) 59 | print "GET sent" 60 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # 4 | # configuration file - contains customization for exact system 5 | # JCS 11/8/2013 6 | # 7 | 8 | # it is a good idea to copy this file into a file called "conflocal.py" and edit that instead of this one. This file is wiped out if you update GroveWeatherPi. 9 | 10 | 11 | 12 | mailUser = "yourusename" 13 | mailPassword = "yourmailpassword" 14 | 15 | notifyAddress ="you@example.com" 16 | 17 | fromAddress = "yourfromaddress@example.com" 18 | 19 | textnotifyAddress = "yourphonenumber@yourprovider" 20 | 21 | #MySQL Logging and Password Information 22 | 23 | enable_MySQL_Logging = False 24 | MySQL_Password = "password" 25 | 26 | # modify this IP to enable WLAN operating detection - search for WLAN_check in GroveWeatherPi.py 27 | enable_WLAN_Detection = True 28 | PingableRouterAddress = "192.168.1.1" 29 | 30 | # WeatherUnderground Station 31 | 32 | WeatherUnderground_Present = False 33 | WeatherUnderground_StationID = "KWXXXXX" 34 | WeatherUnderground_StationKey = "YYYYYYY" 35 | 36 | ############ 37 | # Blynk configuration 38 | ############ 39 | 40 | USEBLYNK = False 41 | BLYNK_AUTH = 'xxxxx' 42 | BLYNK_URL = 'http://blynk-cloud.com/' 43 | 44 | 45 | 46 | # for barometeric pressure - needed to calculate sealevel equivalent - set your weatherstation elevation here 47 | 48 | BMP280_Altitude_Meters = 648.0 49 | 50 | # device present global variables 51 | 52 | Lightning_Mode = False 53 | SolarPower_Mode = False 54 | 55 | TCA9545_I2CMux_Present = False 56 | SunAirPlus_Present = False 57 | AS3935_Present = False 58 | DS3231_Present = False 59 | BMP280_Present = False 60 | FRAM_Present = False 61 | HTU21DF_Present = False 62 | HDC1080_Present = False 63 | AM2315_Present = False 64 | ADS1015_Present = False 65 | ADS1115_Present = False 66 | OLED_Present = False 67 | OLED_Originally_Present = False 68 | WXLink_Present = False 69 | Sunlight_Preset = False 70 | 71 | # set Sunlight High Gain (indoors - 1) or Low Gain (outdoors - 0) 72 | Sunlight_Gain = 0 73 | 74 | 75 | # if the WXLink has stopped transmitting, == False 76 | WXLink_Data_Fresh = False 77 | WXLInk_LastMessageID = 0 78 | -------------------------------------------------------------------------------- /crcpython2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf8 -*- 2 | 3 | # 4 | # CRC CCITT 5 | # 6 | # comes in 3 flavors 7 | # (XModem) starting value: 0x0000 8 | # starting value: 0xffff 9 | # starting value: 0x1d0f 10 | # 11 | 12 | 13 | from ctypes import c_ushort 14 | 15 | 16 | class CRCCCITT(object): 17 | crc_ccitt_table = [] 18 | 19 | # The CRC's are computed using polynomials. 20 | # Here is the most used coefficient for CRC CCITT 21 | crc_ccitt_constant = 0x1021 22 | 23 | def __init__(self, version='XModem'): 24 | try: 25 | dict_versions = {'XModem': 0x0000, 'FFFF': 0xffff, '1D0F': 0x1d0f} 26 | if version not in dict_versions.keys(): 27 | raise Exception("Your version parameter should be one of \ 28 | the {} options".format("|".join(dict_versions.keys()))) 29 | 30 | self.starting_value = dict_versions[version] 31 | 32 | # initialize the precalculated tables 33 | if not len(self.crc_ccitt_table): 34 | self.init_crc_table() 35 | except Exception as e: 36 | print("EXCEPTION(__init__): {}".format(e)) 37 | 38 | def calculate(self, input_data=None): 39 | try: 40 | is_string = isinstance(input_data, str) 41 | is_bytes = isinstance(input_data, (bytes, bytearray)) 42 | 43 | if not is_string and not is_bytes: 44 | raise Exception("Please provide a string or a byte sequence \ 45 | as argument for calculation.") 46 | 47 | crc_value = self.starting_value 48 | 49 | for c in input_data: 50 | d = ord(c) if is_string else c 51 | tmp = ((crc_value >> 8) & 0xff) ^ d 52 | crc_value = ((crc_value << 8) & 0xff00) ^ self.crc_ccitt_table[tmp] 53 | 54 | return crc_value 55 | except Exception as e: 56 | print("EXCEPTION(calculate): {}".format(e)) 57 | 58 | def init_crc_table(self): 59 | """The algorithm uses tables with precalculated values""" 60 | for i in range(0, 256): 61 | crc = 0 62 | c = i << 8 63 | 64 | for j in range(0, 8): 65 | if (crc ^ c) & 0x8000: 66 | crc = c_ushort(crc << 1).value ^ self.crc_ccitt_constant 67 | else: 68 | crc = c_ushort(crc << 1).value 69 | 70 | c = c_ushort(c << 1).value # equivalent of c = c << 1 71 | 72 | self.crc_ccitt_table.append(crc) 73 | -------------------------------------------------------------------------------- /doAllGraphs.py: -------------------------------------------------------------------------------- 1 | # 2 | # calculate all graphs 3 | # 4 | # SwitchDoc Labs March 30, 2015 5 | 6 | import sys 7 | sys.path.append('/home/pi/SDL_Pi_GroveWeatherPi/graphs') 8 | 9 | # Check for user imports 10 | try: 11 | import conflocal as config 12 | except ImportError: 13 | import config 14 | 15 | 16 | import TemperatureHumidityGraph 17 | import PowerCurrentGraph 18 | import PowerVoltageGraph 19 | import BarometerLightningGraph 20 | 21 | def doAllGraphs(): 22 | 23 | if (config.enable_MySQL_Logging == True): 24 | 25 | BarometerLightningGraph.BarometerLightningGraph('test', 10, 0) 26 | TemperatureHumidityGraph.TemperatureHumidityGraph('test', 10, 0) 27 | PowerCurrentGraph.PowerCurrentGraph('test', 10, 0) 28 | PowerVoltageGraph.PowerVoltageGraph('test', 10, 0) 29 | 30 | -------------------------------------------------------------------------------- /graphs/BarometerLightningGraph.py: -------------------------------------------------------------------------------- 1 | # BarometerLightningGraph 2 | # filename: BarometerLightningGraph.py 3 | # Version 1.1 03/30/15 4 | # 5 | # contains graphing code 6 | # 7 | # 8 | 9 | import sys 10 | import time 11 | import RPi.GPIO as GPIO 12 | 13 | import gc 14 | import datetime 15 | 16 | import matplotlib 17 | # Force matplotlib to not use any Xwindows backend. 18 | matplotlib.use('Agg') 19 | 20 | from matplotlib import pyplot 21 | from matplotlib import dates 22 | 23 | import pylab 24 | 25 | import MySQLdb as mdb 26 | 27 | # Check for user imports 28 | try: 29 | import conflocal as config 30 | except ImportError: 31 | import config 32 | 33 | 34 | def BarometerLightningGraph(source,days,delay): 35 | 36 | 37 | 38 | print("BarometerLightningGraph source:%s days:%s" % (source,days)) 39 | print("sleeping seconds:", delay) 40 | time.sleep(delay) 41 | print("BarometerLightningGraph running now") 42 | 43 | # blink GPIO LED when it's run 44 | GPIO.setup(18, GPIO.OUT) 45 | GPIO.output(18, True) 46 | time.sleep(0.2) 47 | GPIO.output(18, False) 48 | 49 | 50 | # now we have get the data, stuff it in the graph 51 | 52 | try: 53 | print("trying database") 54 | db = mdb.connect('localhost', 'root', config.MySQL_Password, 'GroveWeatherPi'); 55 | 56 | cursor = db.cursor() 57 | 58 | query = "SELECT TimeStamp, bmp180SeaLevel, as3935LastInterrupt, as3935LastDistance FROM WeatherData where now() - interval %i hour < TimeStamp" % (days*24) 59 | print "query=", query 60 | cursor.execute(query) 61 | result = cursor.fetchall() 62 | 63 | t = [] 64 | s = [] 65 | u = [] 66 | v = [] 67 | 68 | for record in result: 69 | t.append(record[0]) 70 | s.append(record[1]) 71 | u.append(record[2]) 72 | v.append(record[3]) 73 | 74 | 75 | fig = pyplot.figure() 76 | 77 | print ("count of t=",len(t)) 78 | if (len(t) == 0): 79 | return 80 | #dts = map(datetime.datetime.fromtimestamp, s) 81 | #fds = dates.date2num(t) # converted 82 | # matplotlib date format object 83 | hfmt = dates.DateFormatter('%m/%d-%H') 84 | 85 | 86 | ax = fig.add_subplot(111) 87 | for i in range(len(s)): 88 | s[i] = s[i] * 10 89 | 90 | #ax.vlines(fds, -200.0, 1000.0,colors='w') 91 | ax.xaxis.set_major_locator(dates.HourLocator(interval=6)) 92 | ax.xaxis.set_major_formatter(hfmt) 93 | pylab.xticks(rotation='vertical') 94 | 95 | pyplot.subplots_adjust(bottom=.3) 96 | pylab.plot(t, s, color='b',label="Barometric Pressure (mb) ",linestyle="-",marker=".") 97 | pylab.xlabel("Hours") 98 | pylab.ylabel("millibars") 99 | pylab.legend(loc='upper left') 100 | pylab.axis([min(t), max(t), 900, 1100]) 101 | ax2 = pylab.twinx() 102 | pylab.ylabel("Last Interrupt / Distance ") 103 | 104 | # scale array 105 | 106 | for i in range(len(v)): 107 | v[i] = v[i] * 10 108 | for i in range(len(u)): 109 | u[i] = u[i] * 10 110 | 111 | 112 | pylab.plot(t, u, color='y',label="as3935 Last Interrupt",linestyle="-",marker=".") 113 | pylab.plot(t, v, color='r',label="as3935 Last Distance",linestyle="-",marker=".") 114 | pylab.axis([min(t), max(t), 0, max(u)]) 115 | pylab.legend(loc='lower left') 116 | pylab.figtext(.5, .05, ("Barometer and Lightning Statistics Last %i Days" % days),fontsize=18,ha='center') 117 | 118 | #pylab.grid(True) 119 | 120 | pyplot.setp( ax.xaxis.get_majorticklabels(), rotation=70) 121 | ax.xaxis.set_major_formatter(dates.DateFormatter('%m/%d-%H')) 122 | pyplot.show() 123 | try: 124 | pyplot.savefig("/home/pi/RasPiConnectServer/static/BarometerLightningGraph.png") 125 | except: 126 | pyplot.savefig("/home/pi/SDL_Pi_GroveWeatherPi/static/BarometerLightningGraph.png") 127 | 128 | 129 | except mdb.Error, e: 130 | 131 | print "Error %d: %s" % (e.args[0],e.args[1]) 132 | 133 | finally: 134 | 135 | cursor.close() 136 | db.close() 137 | 138 | del cursor 139 | del db 140 | 141 | fig.clf() 142 | pyplot.close() 143 | pylab.close() 144 | del t, s, u, v 145 | gc.collect() 146 | print("BarometerLightningGraph finished now") 147 | -------------------------------------------------------------------------------- /graphs/PowerCurrentGraph.py: -------------------------------------------------------------------------------- 1 | # PowerCurrentGraph 2 | # filename: PowerCurrentGraph.py 3 | # Version 1.3 09/12/13 4 | # Version 1.4 03/30/15 5 | # 6 | # contains event routines for data collection 7 | # 8 | # 9 | 10 | import sys 11 | import time 12 | import RPi.GPIO as GPIO 13 | 14 | import gc 15 | import datetime 16 | 17 | import matplotlib 18 | # Force matplotlib to not use any Xwindows backend. 19 | matplotlib.use('Agg') 20 | 21 | from matplotlib import pyplot 22 | from matplotlib import dates 23 | 24 | import pylab 25 | 26 | import MySQLdb as mdb 27 | 28 | # Check for user imports 29 | try: 30 | import conflocal as config 31 | except ImportError: 32 | import config 33 | 34 | def PowerCurrentGraph(source,days,delay): 35 | 36 | 37 | 38 | print("PowerCurrentGraph source:%s days:%s delay:%i" % (source,days,delay)) 39 | print("sleeping :",delay) 40 | time.sleep(delay) 41 | print("PowerCurrentGraph running now") 42 | 43 | # blink GPIO LED when it's run 44 | GPIO.setup(18, GPIO.OUT) 45 | GPIO.output(18, True) 46 | time.sleep(0.2) 47 | GPIO.output(18, False) 48 | 49 | # now we have get the data, stuff it in the graph 50 | 51 | try: 52 | print("trying database") 53 | db = mdb.connect('localhost', 'root', config.MySQL_Password, 'GroveWeatherPi'); 54 | 55 | cursor = db.cursor() 56 | 57 | query = "SELECT TimeStamp, solarCurrent, batteryCurrent, loadCurrent FROM PowerSystem where now() - interval %i hour < TimeStamp" % (days*24) 58 | cursor.execute(query) 59 | result = cursor.fetchall() 60 | 61 | t = [] 62 | s = [] 63 | u = [] 64 | v = [] 65 | #x = [] 66 | 67 | for record in result: 68 | t.append(record[0]) 69 | s.append(record[1]) 70 | u.append(record[2]) 71 | v.append(record[3]) 72 | #x.append(record[4]) 73 | fig = pyplot.figure() 74 | 75 | 76 | print ("count of t=",len(t)) 77 | #print (t) 78 | if (len(t) == 0): 79 | return 80 | #dts = map(datetime.datetime.fromtimestamp, t) 81 | #print dts 82 | #fds = dates.date2num(t) # converted 83 | # matplotlib date format object 84 | hfmt = dates.DateFormatter('%m/%d-%H') 85 | 86 | fig.set_facecolor('white') 87 | ax = fig.add_subplot(111,axisbg = 'white') 88 | #ax.vlines(fds, -200.0, 1000.0,colors='w') 89 | 90 | ax.xaxis.set_major_locator(dates.HourLocator(interval=6)) 91 | ax.xaxis.set_major_formatter(hfmt) 92 | ax.set_ylim(bottom = -200.0) 93 | pyplot.xticks(rotation='vertical') 94 | pyplot.subplots_adjust(bottom=.3) 95 | pylab.plot(t, s, color='b',label="Solar",linestyle="-",marker=".") 96 | pylab.plot(t, u, color='r',label="Battery",linestyle="-",marker=".") 97 | pylab.plot(t, v, color='g',label="Load",linestyle="-",marker=".") 98 | #pylab.plot(t, x, color='m',label="Power Eff",linestyle="-",marker=".") 99 | pylab.xlabel("Hours") 100 | pylab.ylabel("Current ma") 101 | pylab.legend(loc='upper left') 102 | 103 | if (max(u) > max(s)): 104 | myMax = max(u)+ 100.0 105 | else: 106 | myMax = max(s) 107 | pylab.axis([min(t), max(t), min(u), myMax]) 108 | pylab.figtext(.5, .05, ("GroveWeatherPi Power Current Last %i Days" % days),fontsize=18,ha='center') 109 | pyplot.setp( ax.xaxis.get_majorticklabels(), rotation=70) 110 | 111 | pylab.grid(True) 112 | 113 | pyplot.show() 114 | try: 115 | pyplot.savefig("/home/pi/RasPiConnectServer/static/PowerCurrentGraph.png",facecolor=fig.get_facecolor()) 116 | except: 117 | pyplot.savefig("/home/pi/SDL_Pi_GroveWeatherPi/static/PowerCurrentGraph.png",facecolor=fig.get_facecolor()) 118 | 119 | 120 | except mdb.Error, e: 121 | 122 | print "Error %d: %s" % (e.args[0],e.args[1]) 123 | 124 | finally: 125 | 126 | cursor.close() 127 | db.close() 128 | 129 | del cursor 130 | del db 131 | 132 | fig.clf() 133 | pyplot.close() 134 | pylab.close() 135 | del t, s, u, v 136 | gc.collect() 137 | print("PowerCurrentGrapGraph finished now") 138 | -------------------------------------------------------------------------------- /graphs/PowerVoltageGraph.py: -------------------------------------------------------------------------------- 1 | # PowerVoltageGraph 2 | # filename: VoltageGraph.py 3 | # Version 1.3 09/12/13 4 | # Version 1.4 03/30/15 5 | # 6 | # contains event routines for data collection 7 | # 8 | # 9 | 10 | import sys 11 | import time 12 | import RPi.GPIO as GPIO 13 | 14 | import gc 15 | import datetime 16 | 17 | import matplotlib 18 | # Force matplotlib to not use any Xwindows backend. 19 | matplotlib.use('Agg') 20 | 21 | from matplotlib import pyplot 22 | from matplotlib import dates 23 | 24 | import pylab 25 | 26 | import MySQLdb as mdb 27 | 28 | # Check for user imports 29 | try: 30 | import conflocal as config 31 | except ImportError: 32 | import config 33 | 34 | def PowerVoltageGraph(source,days,delay): 35 | 36 | 37 | 38 | print("PowerVoltageGraph source:%s days:%s delay:%i" % (source,days,delay)) 39 | print("sleeping :",delay) 40 | time.sleep(delay) 41 | print("PowerVoltageGraph running now") 42 | 43 | # blink GPIO LED when it's run 44 | GPIO.setup(18, GPIO.OUT) 45 | GPIO.output(18, True) 46 | time.sleep(0.2) 47 | GPIO.output(18, False) 48 | 49 | # now we have get the data, stuff it in the graph 50 | 51 | try: 52 | print("trying database") 53 | db = mdb.connect('localhost', 'root', config.MySQL_Password, 'GroveWeatherPi'); 54 | 55 | cursor = db.cursor() 56 | 57 | query = "SELECT TimeStamp, solarVoltage, batteryVoltage, loadVoltage FROM PowerSystem where now() - interval %i hour < TimeStamp" % (days*24) 58 | cursor.execute(query) 59 | result = cursor.fetchall() 60 | 61 | t = [] 62 | s = [] 63 | u = [] 64 | v = [] 65 | #x = [] 66 | 67 | for record in result: 68 | t.append(record[0]) 69 | s.append(record[1]) 70 | u.append(record[2]) 71 | v.append(record[3]) 72 | #x.append(record[4]) 73 | fig = pyplot.figure() 74 | 75 | print ("count of t=",len(t)) 76 | #print (t) 77 | if (len(t) == 0): 78 | return 79 | #dts = map(datetime.datetime.fromtimestamp, t) 80 | #print dts 81 | #fds = dates.date2num(t) # converted 82 | # matplotlib date format object 83 | hfmt = dates.DateFormatter('%m/%d-%H') 84 | 85 | fig = pyplot.figure() 86 | fig.set_facecolor('white') 87 | ax = fig.add_subplot(111,axisbg = 'white') 88 | #ax.vlines(fds, -200.0, 1000.0,colors='w') 89 | 90 | ax.xaxis.set_major_locator(dates.HourLocator(interval=6)) 91 | ax.xaxis.set_major_formatter(hfmt) 92 | ax.set_ylim(bottom = -200.0) 93 | pyplot.xticks(rotation='vertical') 94 | pyplot.subplots_adjust(bottom=.3) 95 | pylab.plot(t, s, color='b',label="Solar",linestyle="-",marker=".") 96 | pylab.plot(t, u, color='r',label="Battery",linestyle="-",marker=".") 97 | pylab.plot(t, v, color='g',label="Load",linestyle="-",marker=".") 98 | #pylab.plot(t, x, color='m',label="Power Eff",linestyle="-",marker=".") 99 | pylab.xlabel("Hours") 100 | pylab.ylabel("Voltage V") 101 | pylab.legend(loc='upper left') 102 | 103 | if (max(u) > max(s)): 104 | myMax = max(u)+ 100.0 105 | else: 106 | myMax = max(s) 107 | pylab.axis([min(t), max(t), min(u), myMax]) 108 | pylab.figtext(.5, .05, ("GroveWeatherPi Power Voltage Last %i Days" % days),fontsize=18,ha='center') 109 | pyplot.setp( ax.xaxis.get_majorticklabels(), rotation=70) 110 | 111 | pylab.grid(True) 112 | 113 | pyplot.show() 114 | try: 115 | pyplot.savefig("/home/pi/RasPiConnectServer/static/PowerVoltageGraph.png",facecolor=fig.get_facecolor()) 116 | except: 117 | pyplot.savefig("/home/pi/SDL_Pi_GroveWeatherPi/static/PowerVoltageGraph.png",facecolor=fig.get_facecolor()) 118 | 119 | 120 | except mdb.Error, e: 121 | 122 | print "Error %d: %s" % (e.args[0],e.args[1]) 123 | 124 | finally: 125 | 126 | cursor.close() 127 | db.close() 128 | 129 | del cursor 130 | del db 131 | 132 | fig.clf() 133 | pyplot.close() 134 | pylab.close() 135 | del t, s, u, v 136 | gc.collect() 137 | print("PowerVoltageGraph finished now") 138 | -------------------------------------------------------------------------------- /graphs/TemperatureHumidityGraph.py: -------------------------------------------------------------------------------- 1 | # TemperatureHumidityGraph 2 | # filename:TemperatureHumidityGraph.py 3 | # Version 1.1 03/30/15 4 | # 5 | # contains event routines for data collection 6 | # 7 | # 8 | 9 | import sys 10 | import time 11 | import RPi.GPIO as GPIO 12 | 13 | import gc 14 | import datetime 15 | 16 | import matplotlib 17 | # Force matplotlib to not use any Xwindows backend. 18 | matplotlib.use('Agg') 19 | 20 | from matplotlib import pyplot 21 | from matplotlib import dates 22 | 23 | import pylab 24 | 25 | import MySQLdb as mdb 26 | 27 | # Check for user imports 28 | try: 29 | import conflocal as config 30 | except ImportError: 31 | import config 32 | 33 | 34 | 35 | def TemperatureHumidityGraph(source,days,delay): 36 | 37 | 38 | 39 | print("TemperatureHumidityGraph source:%s days:%s" % (source,days)) 40 | print("sleeping seconds:", delay) 41 | time.sleep(delay) 42 | print("TemperatureHumidityGraph running now") 43 | 44 | 45 | # blink GPIO LED when it's run 46 | GPIO.setup(18, GPIO.OUT) 47 | GPIO.output(18, True) 48 | time.sleep(0.2) 49 | GPIO.output(18, False) 50 | 51 | # now we have get the data, stuff it in the graph 52 | 53 | try: 54 | print("trying database") 55 | db = mdb.connect('localhost', 'root', config.MySQL_Password, 'GroveWeatherPi'); 56 | 57 | cursor = db.cursor() 58 | 59 | query = "SELECT TimeStamp, bmp180Temperature, outsideTemperature, outsideHumidity, insideHumidity FROM WeatherData where now() - interval %i hour < TimeStamp" % (days*24) 60 | 61 | print "query=", query 62 | cursor.execute(query) 63 | result = cursor.fetchall() 64 | 65 | t = [] 66 | u = [] 67 | v = [] 68 | x = [] 69 | z = [] 70 | 71 | fig = pyplot.figure() 72 | 73 | 74 | 75 | for record in result: 76 | t.append(record[0]) 77 | u.append(record[1]) 78 | v.append(record[2]) 79 | x.append(record[3]) 80 | z.append(record[4]) 81 | 82 | print ("count of t=",len(t)) 83 | if (len(t) == 0): 84 | return 85 | 86 | #dts = map(datetime.datetime.fromtimestamp, s) 87 | #fds = dates.date2num(dts) # converted 88 | # matplotlib date format object 89 | hfmt = dates.DateFormatter('%m/%d-%H') 90 | 91 | 92 | ax = fig.add_subplot(111) 93 | ax.xaxis.set_major_locator(dates.HourLocator(interval=6)) 94 | ax.xaxis.set_major_formatter(hfmt) 95 | pylab.xticks(rotation='vertical') 96 | 97 | pyplot.subplots_adjust(bottom=.3) 98 | pylab.plot(t, v, color='g',label="Outside Temp (C)",linestyle="-",marker=".") 99 | pylab.plot(t, u, color='r',label="Inside Temp (C)",linestyle="-",marker=".") 100 | pylab.xlabel("Hours") 101 | pylab.ylabel("degrees C") 102 | pylab.legend(loc='upper left') 103 | pylab.axis([min(t), max(t), 0, 40]) 104 | ax2 = pylab.twinx() 105 | pylab.ylabel("% ") 106 | pylab.plot(t, x, color='y',label="Outside Hum %",linestyle="-",marker=".") 107 | pylab.plot(t, z, color='b',label="Inside Hum %",linestyle="-",marker=".") 108 | pylab.axis([min(t), max(t), 0, 100]) 109 | pylab.legend(loc='lower left') 110 | pylab.figtext(.5, .05, ("Environmental Statistics Last %i Days" % days),fontsize=18,ha='center') 111 | 112 | #pylab.grid(True) 113 | 114 | pyplot.setp( ax.xaxis.get_majorticklabels(), rotation=70) 115 | ax.xaxis.set_major_formatter(dates.DateFormatter('%m/%d-%H')) 116 | pyplot.show() 117 | try: 118 | pyplot.savefig("/home/pi/RasPiConnectServer/static/TemperatureHumidityGraph.png") 119 | except: 120 | pyplot.savefig("/home/pi/SDL_Pi_GroveWeatherPi/static/TemperatureHumidityGraph.png") 121 | 122 | 123 | except mdb.Error, e: 124 | 125 | print "Error %d: %s" % (e.args[0],e.args[1]) 126 | 127 | finally: 128 | 129 | cursor.close() 130 | db.close() 131 | 132 | del cursor 133 | del db 134 | 135 | fig.clf() 136 | pyplot.close() 137 | pylab.close() 138 | del t, u, v, x 139 | gc.collect() 140 | print("TemperatureHumidityGraph finished now") 141 | -------------------------------------------------------------------------------- /graphs/testTemp.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # calculate all graphs 4 | # 5 | # SwitchDoc Labs March 30, 2015 6 | 7 | import sys 8 | import RPi.GPIO as GPIO 9 | 10 | 11 | 12 | GPIO.setmode(GPIO.BCM) 13 | 14 | 15 | import TemperatureHumidityGraph 16 | 17 | 18 | TemperatureHumidityGraph.TemperatureHumidityGraph('test', 10, 0) 19 | 20 | -------------------------------------------------------------------------------- /htu21dflib/.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Libraries 8 | *.lib 9 | *.a 10 | 11 | # Shared objects (inc. Windows DLLs) 12 | *.dll 13 | *.so 14 | *.so.* 15 | *.dylib 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.i*86 22 | *.x86_64 23 | *.hex 24 | 25 | *~ 26 | *.swp 27 | tags 28 | -------------------------------------------------------------------------------- /htu21dflib/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 bbx10node@gmail.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /htu21dflib/README.md: -------------------------------------------------------------------------------- 1 | htu21dflib 2 | ========== 3 | 4 | htu21df temperature and humidity sensor support for Raspberry Pi. 5 | 6 | Adafruit HTU21D-F breakout board details. 7 | 8 | http://www.adafruit.com/products/1899 9 | 10 | Adafruit guide to configuring the Pi for i2c. 11 | 12 | https://learn.adafruit.com/using-the-bmp085-with-raspberry-pi/configuring-the-pi-for-i2c 13 | 14 | ## Build it 15 | 16 | ./build.sh 17 | 18 | ## Run test program 19 | 20 | ./htu21dflib 21 | 22 | Sample output 23 | 24 | ``` 25 | 29.1 52.3 26 | 29.1 52.3 27 | 29.1 52.3 28 | 29.1 52.3 29 | ``` 30 | 31 | ## Dweet your data 32 | 33 | ./dweetio 34 | 35 | Login into http://freeboard.io to access your dweet data. Create a real-time 36 | instrumentation panel with temperature and humidity guages without programming. 37 | 38 | -------------------------------------------------------------------------------- /htu21dflib/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Build the code with a standalone test program. 3 | # htu21dflib -- A small test program using the library. Use it verify 4 | # the code and sensor are working. 5 | # htu21dflib.o -- The library code which can be linked into a larger program. 6 | # dweetio -- Demo program that dweets the data to http://dweet.io. 7 | # Create a real-time instrumentation panel with this data 8 | # by connecting to http://freeboard.io 9 | # 10 | gcc -O2 -Wall -o htu21dflib -DHTU21DFTEST htu21dflib.c 11 | gcc -O2 -Wall -c htu21dflib.c 12 | gcc -O2 -Wall htu21dflib.o -o dweetio dweetio.c 13 | gcc -O2 -Wall htu21dflib.o -o mqtt mqtt.c 14 | -------------------------------------------------------------------------------- /htu21dflib/dweetio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/htu21dflib/dweetio -------------------------------------------------------------------------------- /htu21dflib/dweetio.c: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 bbx10node@gmail.com 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "htu21dflib.h" 31 | 32 | static const char I2CDEV[] = "/dev/i2c-1"; // raspberry pi 33 | static const uint8_t I2CADDR = 0x40; // htu21df i2c address 34 | 35 | // dweet thing_name. Be sure to make up your own thing name! If you do not, 36 | // your data will be mixed with everyone else's data using the same thing 37 | // name. 38 | static const char THING_NAME[] = "flippant-boot"; 39 | 40 | int main(int argc, char *argv[]) 41 | { 42 | int rc; // return code 43 | int i2cfd; // i2c file descriptor 44 | float temperature, humidity; 45 | char curlstr[256]; 46 | 47 | i2cfd = i2c_open(I2CDEV); 48 | if (i2cfd < 0) { 49 | printf("i2c_open failed %d\n", i2cfd); 50 | return -1; 51 | } 52 | 53 | rc = htu21df_init(i2cfd, I2CADDR); 54 | if (rc < 0) { 55 | printf("i2c_init failed %d\n", rc); 56 | return -2; 57 | } 58 | 59 | while (1) { 60 | rc = htu21df_read_temperature(i2cfd, &temperature); 61 | if (rc < 0) { 62 | printf("i2c_read_temperature failed %d\n", rc); 63 | return -3; 64 | } 65 | 66 | rc = htu21df_read_humidity(i2cfd, &humidity); 67 | if (rc < 0) { 68 | printf("i2c_read_humidity failed %d\n", rc); 69 | return -4; 70 | } 71 | // Format the command to dweet the data 72 | rc = snprintf(curlstr, sizeof(curlstr), 73 | "curl \"https://dweet.io/dweet/for/%s?temperature=%.1f&humidity=%.1f\"", 74 | THING_NAME, temperature, humidity); 75 | if (rc < 0) { 76 | printf("snprintf failed %d\n", rc); 77 | } 78 | // Run the command to dweet the data 79 | rc = system(curlstr); 80 | if (rc != 0) { 81 | printf("system failed %d\n", rc); 82 | } 83 | // Wait 10 seconds 84 | sleep(10); 85 | } 86 | 87 | rc = i2c_close(i2cfd); 88 | if (rc < 0) { 89 | printf("i2c_close failed %d\n", rc); 90 | return -5; 91 | } 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /htu21dflib/htu21dflib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/htu21dflib/htu21dflib -------------------------------------------------------------------------------- /htu21dflib/htu21dflib.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 bbx10 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | int i2c_open(const char *i2cdevname); 26 | 27 | int i2c_close(int i2cfd); 28 | 29 | int htu21df_init(int i2cfd, uint8_t i2caddr); 30 | 31 | int htu21df_read_temperature(int i2cfd, float *temperature); 32 | 33 | int htu21df_read_humidity(int i2cfd, float *humidity); 34 | -------------------------------------------------------------------------------- /htu21dflib/mqtt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/htu21dflib/mqtt -------------------------------------------------------------------------------- /htu21dflib/mqtt.c: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 bbx10node@gmail.com 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "htu21dflib.h" 31 | 32 | static const char I2CDEV[] = "/dev/i2c-1"; // raspberry pi 33 | static const uint8_t I2CADDR = 0x40; // htu21df i2c address 34 | 35 | static const char MQTT_HOST[] = "bbone"; // mqtt host 36 | static const char MQTT_TOPIC_TEMPERATURE[] = "temperature/mbed"; // mqtt temp topic 37 | static const char MQTT_TOPIC_HUMIDITY[] = "humidity/mbed"; // mqtt humi topic 38 | 39 | int main(int argc, char *argv[]) 40 | { 41 | int rc; // return code 42 | int i2cfd; // i2c file descriptor 43 | float temperature, humidity; 44 | char mqttstr[256]; 45 | 46 | i2cfd = i2c_open(I2CDEV); 47 | if (i2cfd < 0) { 48 | printf("i2c_open failed %d\n", i2cfd); 49 | return -1; 50 | } 51 | 52 | rc = htu21df_init(i2cfd, I2CADDR); 53 | if (rc < 0) { 54 | printf("i2c_init failed %d\n", rc); 55 | return -2; 56 | } 57 | 58 | while (1) { 59 | rc = htu21df_read_temperature(i2cfd, &temperature); 60 | if (rc < 0) { 61 | printf("i2c_read_temperature failed %d\n", rc); 62 | return -3; 63 | } 64 | 65 | rc = htu21df_read_humidity(i2cfd, &humidity); 66 | if (rc < 0) { 67 | printf("i2c_read_humidity failed %d\n", rc); 68 | return -4; 69 | } 70 | // Format the command to mqtt the temperature 71 | rc = snprintf(mqttstr, sizeof(mqttstr), 72 | "mosquitto_pub -h %s -t %s -m %0.1f", 73 | MQTT_HOST, MQTT_TOPIC_TEMPERATURE, temperature); 74 | if (rc < 0) { 75 | printf("snprintf failed %d\n", rc); 76 | } 77 | // Run the command to dweet the data 78 | rc = system(mqttstr); 79 | if (rc != 0) { 80 | printf("system failed %d\n", rc); 81 | } 82 | // Format the command to mqtt the humidity 83 | rc = snprintf(mqttstr, sizeof(mqttstr), 84 | "mosquitto_pub -h %s -t %s -m %0.1f", 85 | MQTT_HOST, MQTT_TOPIC_HUMIDITY, humidity); 86 | if (rc < 0) { 87 | printf("snprintf failed %d\n", rc); 88 | } 89 | // Run the command to dweet the data 90 | rc = system(mqttstr); 91 | if (rc != 0) { 92 | printf("system failed %d\n", rc); 93 | } 94 | // Wait 10 seconds 95 | sleep(10); 96 | } 97 | 98 | rc = i2c_close(i2cfd); 99 | if (rc < 0) { 100 | printf("i2c_close failed %d\n", rc); 101 | return -5; 102 | } 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /pclogging.py: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # logging system from Project Curacao 4 | # filename: pclogger.py 5 | # Version 1.0 10/04/13 6 | # 7 | # contains logging data 8 | # 9 | 10 | 11 | CRITICAL=50 12 | ERROR=40 13 | WARNING=30 14 | INFO=20 15 | DEBUG=10 16 | NOTSET=0 17 | 18 | 19 | import sys 20 | import time 21 | # Check for user imports 22 | try: 23 | import conflocal as config 24 | except ImportError: 25 | import config 26 | 27 | if (config.enable_MySQL_Logging == True): 28 | import MySQLdb as mdb 29 | 30 | 31 | def log(level, source, message): 32 | 33 | 34 | if (config.enable_MySQL_Logging == True): 35 | LOWESTDEBUG = 0 36 | # open mysql database 37 | 38 | # write log 39 | 40 | 41 | # commit 42 | 43 | 44 | # close 45 | 46 | if (level >= LOWESTDEBUG): 47 | try: 48 | 49 | #print("trying database") 50 | con = mdb.connect('localhost', 'root', config.MySQL_Password, 'GroveWeatherPi'); 51 | 52 | cur = con.cursor() 53 | #print "before query" 54 | 55 | query = "INSERT INTO systemlog(TimeStamp, Level, Source, Message) VALUES(UTC_TIMESTAMP(), %i, '%s', '%s')" % (level, source, message) 56 | #print("query=%s" % query) 57 | 58 | cur.execute(query) 59 | 60 | con.commit() 61 | 62 | 63 | except mdb.Error, e: 64 | 65 | print "Error %d: %s" % (e.args[0],e.args[1]) 66 | con.rollback() 67 | #sys.exit(1) 68 | 69 | finally: 70 | cur.close() 71 | con.close() 72 | 73 | del cur 74 | del con 75 | 76 | -------------------------------------------------------------------------------- /sendemail.py: -------------------------------------------------------------------------------- 1 | def sendEmail(source, message, subject, toaddress, fromaddress, filename): 2 | 3 | # if conflocal.py is not found, import default config.py 4 | 5 | # Check for user imports 6 | try: 7 | import conflocal as config 8 | except ImportError: 9 | import config 10 | 11 | # Import smtplib for the actual sending function 12 | import smtplib 13 | 14 | # Here are the email package modules we'll need 15 | from email.mime.image import MIMEImage 16 | from email.mime.multipart import MIMEMultipart 17 | from email.mime.text import MIMEText 18 | 19 | COMMASPACE = ', ' 20 | 21 | # Create the container (outer) email message. 22 | msg = MIMEMultipart() 23 | msg['Subject'] = subject 24 | # me == the sender's email address 25 | # family = the list of all recipients' email addresses 26 | msg['From'] = fromaddress 27 | msg['To'] = toaddress 28 | #msg.attach(message) 29 | 30 | mainbody = MIMEText(message, 'plain') 31 | msg.attach(mainbody) 32 | 33 | # Assume we know that the image files are all in PNG format 34 | # Open the files in binary mode. Let the MIMEImage class automatically 35 | # guess the specific image type. 36 | if (filename != ""): 37 | fp = open(filename, 'rb') 38 | img = MIMEImage(fp.read()) 39 | fp.close() 40 | msg.attach(img) 41 | 42 | # Send the email via our own SMTP server. 43 | 44 | try: 45 | # open up a line with the server 46 | s = smtplib.SMTP("smtp.gmail.com", 587) 47 | s.ehlo() 48 | s.starttls() 49 | s.ehlo() 50 | 51 | # login, send email, logout 52 | s.login(config.mailUser, config.mailPassword) 53 | s.sendmail(config.mailUser, toaddress, msg.as_string()) 54 | #s.close() 55 | 56 | 57 | s.quit() 58 | 59 | except: 60 | 61 | print("sendmail exception raised") 62 | return 0 63 | 64 | 65 | -------------------------------------------------------------------------------- /startserver.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | cd /home/pi/SDL_Pi_GroveWeatherPi 4 | sudo python GroveWeatherPi.py 5 | -------------------------------------------------------------------------------- /state.py: -------------------------------------------------------------------------------- 1 | # 2 | # Contains updated State Variables for Blynk and Sections 3 | # 4 | # 5 | 6 | # Weather Variables 7 | 8 | currentOutsideTemperature = 2.0 9 | currentOutsideHumidity = 2 10 | 11 | currentInsideTemperature = 1.0 12 | currentInsideHumidity = 4 13 | 14 | currentRain60Minutes = 0.1 15 | 16 | currentSunlightVisible = 1 17 | currentSunlightIR = 2 18 | currentSunlightUV = 3 19 | currentSunlightUVIndex = 4 20 | 21 | ScurrentWindSpeed = 6 22 | ScurrentWindGust = 7 23 | ScurrentWindDirection = 7.5 24 | currentTotalRain = 8 25 | 26 | currentBarometricPressure = 9 27 | currentAltitude = 10 28 | currentSeaLevel = 10 29 | barometricTrend = True 30 | pastBarometricReading = 9 31 | 32 | AirQuality_Sensor_Value = 101 33 | 34 | 35 | 36 | 37 | # Lightning Values 38 | 39 | currentAs3935Interrupt = 11 40 | 41 | currentAs3935LastInterrupt = 12 42 | currentAs3935LastDistance = 13 43 | currentAs3935LastStatus = 14 44 | 45 | currentAs3935LastLightningTimeStamp = 0 46 | 47 | # Button Variables 48 | 49 | runRainbow = False 50 | flashStrip = False 51 | runOLED = True 52 | 53 | 54 | 55 | # status Values 56 | 57 | Last_Event = "My Last Event" 58 | EnglishMetric = 0 59 | 60 | 61 | # Solar Values 62 | 63 | 64 | batteryVoltage = 0 65 | batteryCurrent = 0 66 | solarVoltage = 0 67 | solarCurrent = 0 68 | loadVoltage = 0 69 | loadCurrent = 0 70 | batteryPower = 0 71 | solarPower = 0 72 | loadPower = 0 73 | batteryCharge = 0 74 | 75 | # WXLink Values 76 | WXbatteryVoltage = 0 77 | WXbatteryCurrent = 0 78 | WXsolarVoltage = 0 79 | WXsolarCurrent = 0 80 | WXloadVoltage = 0 81 | WXloadCurrent = 0 82 | WXbatteryPower = 0 83 | WXsolarPower = 0 84 | WXloadPower = 0 85 | WXbatteryCharge = 0 86 | 87 | 88 | 89 | 90 | def printState(): 91 | 92 | print "-------------" 93 | print "Current State" 94 | print "-------------" 95 | print"currentOutsideTemperature = ",currentOutsideTemperature 96 | print"currentOutsideHumidity = ", currentOutsideHumidity 97 | 98 | print"currentInsideTemperature = ",currentInsideTemperature 99 | print"currentInsideHumidity = ", currentInsideHumidity 100 | 101 | print"currentRain60Minutes = ", currentRain60Minutes 102 | 103 | print"currentSunlightVisible = ", currentSunlightVisible 104 | print"currentSunlightIR = ", currentSunlightIR 105 | print"currentSunlightUV = ", currentSunlightUV 106 | print"currentSunlightUVIndex = ", currentSunlightUVIndex 107 | 108 | print"ScurrentWindSpeed = ", ScurrentWindSpeed 109 | print"ScurrentWindGust = ", ScurrentWindGust 110 | print"ScurrentWindDirection = ", ScurrentWindDirection 111 | print"currentTotalRain = ", currentTotalRain 112 | 113 | print "currentBarometricPressure = ", currentBarometricPressure 114 | print "currentAltitude = ", currentAltitude 115 | print "currentSeaLevel = ", currentSeaLevel 116 | print "barometricTrend =",barometricTrend 117 | print "pastBarometricReading = ", pastBarometricReading 118 | 119 | print "AirQuality_Sensor_Value = ", AirQuality_Sensor_Value 120 | 121 | print "-------------" 122 | 123 | 124 | print "currentAs3935Interrupt = ", currentAs3935Interrupt 125 | 126 | print "currentAs3935LastInterrupt = ", currentAs3935LastInterrupt 127 | print "currentAs3935LastDistance = ", currentAs3935LastDistance 128 | print "currentAs3935LastStatus = ", currentAs3935LastStatus 129 | 130 | print "currentAs3935LastLightningTimeStamp = ", currentAs3935LastLightningTimeStamp 131 | 132 | 133 | 134 | print "-------------" 135 | 136 | 137 | print "runRainbow = ", runRainbow 138 | print "flashStrip = ", flashStrip 139 | print "runOLED =", runOLED 140 | print "-------------" 141 | 142 | 143 | 144 | print "Last_Event = ", Last_Event 145 | print "EnglishMetric = ", EnglishMetric 146 | 147 | 148 | print "-------------" 149 | 150 | print "batteryVoltage", batteryVoltage 151 | print "batteryCurrent", batteryCurrent 152 | print "solarVoltage", solarVoltage 153 | print "solarCurrent", solarCurrent 154 | print "loadVoltage", loadVoltage 155 | print "loadCurrent", loadCurrent 156 | print "batteryPower", batteryPower 157 | print "solarPower", solarPower 158 | print "loadPower", loadPower 159 | print "batteryCharge", batteryCharge 160 | 161 | print "-------------" 162 | 163 | print "-------------" 164 | 165 | print "WXbatteryVoltage", WXbatteryVoltage 166 | print "WXbatteryCurrent", WXbatteryCurrent 167 | print "WXsolarVoltage", WXsolarVoltage 168 | print "WXsolarCurrent", WXsolarCurrent 169 | print "WXloadVoltage", WXloadVoltage 170 | print "WXloadCurrent", WXloadCurrent 171 | print "WXbatteryPower", WXbatteryPower 172 | print "WXsolarPower", WXsolarPower 173 | print "WXloadPower", WXloadPower 174 | print "WXbatteryCharge", WXbatteryCharge 175 | 176 | print "-------------" 177 | 178 | 179 | -------------------------------------------------------------------------------- /state/SunAirPlusStats.txt: -------------------------------------------------------------------------------- 1 | 3.56472 2 | 447.2 3 | 2.944 4 | -0.0 5 | 4.928 6 | 259.6 7 | 1.594142784 8 | -0.0 9 | 1.2793088 10 | 23.8514243314 11 | -------------------------------------------------------------------------------- /state/WeatherCommand.txt: -------------------------------------------------------------------------------- 1 | DONE -------------------------------------------------------------------------------- /state/WeatherStats.txt: -------------------------------------------------------------------------------- 1 | 0.0 2 | 0 3 | 0 4 | 0 5 | 6 | 0.0 7 | 0.000349245965562 8 | 0.0 9 | 26.41 10 | 93.81 11 | 645.332015672 12 | 93.822 13 | 23.1000003815 14 | 26.2000007629 15 | 270.0 16 | 4.4454375 17 | 25.3 18 | 23.7 19 | -------------------------------------------------------------------------------- /static/BarometerLightningGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/static/BarometerLightningGraph.png -------------------------------------------------------------------------------- /static/PowerCurrentGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/static/PowerCurrentGraph.png -------------------------------------------------------------------------------- /static/PowerVoltageGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/static/PowerVoltageGraph.png -------------------------------------------------------------------------------- /static/TemperatureHumidityGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/switchdoclabs/SDL_Pi_GroveWeatherPi/9d6408ecfa3629a161d70ad42c6e8920302f8d60/static/TemperatureHumidityGraph.png -------------------------------------------------------------------------------- /testAM2315.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sys 3 | sys.path.append('./SDL_Pi_TCA9545') 4 | 5 | import SDL_Pi_TCA9545 6 | 7 | 8 | 9 | 10 | ################ 11 | # TCA9545 I2C Mux 12 | 13 | #/*========================================================================= 14 | # I2C ADDRESS/BITS 15 | # -----------------------------------------------------------------------*/ 16 | TCA9545_ADDRESS = (0x73) # 1110011 (A0+A1=VDD) 17 | #/*=========================================================================*/ 18 | 19 | #/*========================================================================= 20 | # CONFIG REGISTER (R/W) 21 | # -----------------------------------------------------------------------*/ 22 | TCA9545_REG_CONFIG = (0x00) 23 | # /*---------------------------------------------------------------------*/ 24 | 25 | TCA9545_CONFIG_BUS0 = (0x01) # 1 = enable, 0 = disable 26 | TCA9545_CONFIG_BUS1 = (0x02) # 1 = enable, 0 = disable 27 | TCA9545_CONFIG_BUS2 = (0x04) # 1 = enable, 0 = disable 28 | TCA9545_CONFIG_BUS3 = (0x08) # 1 = enable, 0 = disable 29 | 30 | #/*=========================================================================*/ 31 | 32 | # I2C Mux TCA9545 Detection 33 | try: 34 | tca9545 = SDL_Pi_TCA9545.SDL_Pi_TCA9545(addr=TCA9545_ADDRESS, bus_enable = TCA9545_CONFIG_BUS0) 35 | 36 | 37 | # turn I2CBus 0 on 38 | tca9545.write_control_register(TCA9545_CONFIG_BUS0) 39 | TCA9545_I2CMux_Present = True 40 | except: 41 | print ">>>>>>>>>>>>>>>>>>><<<<<<<<<<<" 42 | print "TCA9545 I2C Mux Not Present" 43 | print ">>>>>>>>>>>>>>>>>>><<<<<<<<<<<" 44 | sys.path.append('./SDL_Pi_AM2315') 45 | 46 | import AM2315 47 | 48 | am2315 = AM2315.AM2315() 49 | 50 | for x in range(0,10): 51 | outsideHumidity, outsideTemperature, crc_check = am2315.read_humidity_temperature_crc() 52 | print "temperature: %0.1f" % outsideTemperature 53 | print "humidity: %0.1f" % outsideHumidity 54 | print "crc: %s" % crc_check 55 | print 56 | time.sleep(2.0) 57 | -------------------------------------------------------------------------------- /testAS3935.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | sys.path.append('./SDL_Pi_TCA9545') 5 | sys.path.append('./RaspberryPi-AS3935/RPi_AS3935') 6 | 7 | 8 | import SDL_Pi_TCA9545 9 | 10 | 11 | 12 | 13 | ################ 14 | # TCA9545 I2C Mux 15 | 16 | #/*========================================================================= 17 | # I2C ADDRESS/BITS 18 | # -----------------------------------------------------------------------*/ 19 | TCA9545_ADDRESS = (0x73) # 1110011 (A0+A1=VDD) 20 | #/*=========================================================================*/ 21 | 22 | #/*========================================================================= 23 | # CONFIG REGISTER (R/W) 24 | # -----------------------------------------------------------------------*/ 25 | TCA9545_REG_CONFIG = (0x00) 26 | # /*---------------------------------------------------------------------*/ 27 | 28 | TCA9545_CONFIG_BUS0 = (0x01) # 1 = enable, 0 = disable 29 | TCA9545_CONFIG_BUS1 = (0x02) # 1 = enable, 0 = disable 30 | TCA9545_CONFIG_BUS2 = (0x04) # 1 = enable, 0 = disable 31 | TCA9545_CONFIG_BUS3 = (0x08) # 1 = enable, 0 = disable 32 | 33 | #/*=========================================================================*/ 34 | 35 | # I2C Mux TCA9545 Detection 36 | try: 37 | tca9545 = SDL_Pi_TCA9545.SDL_Pi_TCA9545(addr=TCA9545_ADDRESS, bus_enable = TCA9545_CONFIG_BUS0) 38 | 39 | 40 | # turn I2CBus 1 on 41 | tca9545.write_control_register(TCA9545_CONFIG_BUS1) 42 | TCA9545_I2CMux_Present = True 43 | except: 44 | print ">>>>>>>>>>>>>>>>>>><<<<<<<<<<<" 45 | print "TCA9545 I2C Mux Not Present" 46 | print ">>>>>>>>>>>>>>>>>>><<<<<<<<<<<" 47 | TCA9545_I2CMux_Present = False 48 | 49 | from RPi_AS3935 import RPi_AS3935 50 | 51 | import RPi.GPIO as GPIO 52 | import time 53 | from datetime import datetime 54 | 55 | GPIO.setmode(GPIO.BCM) 56 | 57 | # Rev. 1 Raspberry Pis should leave bus set at 0, while rev. 2 Pis should set 58 | # bus equal to 1. The address should be changed to match the address of the 59 | # sensor. (Common implementations are in README.md) 60 | sensor = RPi_AS3935(address=0x02, bus=1) 61 | 62 | sensor.set_indoors(True) 63 | sensor.set_noise_floor(0) 64 | sensor.calibrate(tun_cap=0x0F) 65 | 66 | 67 | def handle_interrupt(channel): 68 | time.sleep(0.003) 69 | global sensor 70 | reason = sensor.get_interrupt() 71 | if reason == 0x01: 72 | print "Noise level too high - adjusting" 73 | sensor.raise_noise_floor() 74 | elif reason == 0x04: 75 | print "Disturber detected - masking" 76 | sensor.set_mask_disturber(True) 77 | elif reason == 0x08: 78 | now = datetime.now().strftime('%H:%M:%S - %Y/%m/%d') 79 | distance = sensor.get_distance() 80 | print "We sensed lightning!" 81 | print "It was " + str(distance) + "km away. (%s)" % now 82 | print "" 83 | 84 | pin = 16 85 | 86 | #GPIO.setup(pin, GPIO.IN ) 87 | GPIO.setup(pin, GPIO.IN, pull_up_down = GPIO.PUD_UP ) 88 | GPIO.add_event_detect(pin, GPIO.RISING, callback=handle_interrupt) 89 | 90 | print "Waiting for lightning - or at least something that looks like it" 91 | 92 | while True: 93 | time.sleep(1.0) 94 | -------------------------------------------------------------------------------- /testBlynk.py: -------------------------------------------------------------------------------- 1 | import time 2 | import requests 3 | import json 4 | import updateBlynk 5 | 6 | 7 | print updateBlynk.blynkSGSAppOnline() 8 | 9 | print updateBlynk.blynkInit() 10 | 11 | print updateBlynk.blynkStatusUpdate() 12 | 13 | -------------------------------------------------------------------------------- /testSI1145.py: -------------------------------------------------------------------------------- 1 | 2 | #!/usr/bin/python 3 | 4 | # Author: Joe Gutting 5 | # With use of Adafruit SI1145 library for Arduino, Adafruit_GPIO.I2C & BMP Library by Tony DiCola 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | 25 | # Can enable debug output by uncommenting: 26 | #import logging 27 | #logging.basicConfig(level=logging.DEBUG) 28 | import sys 29 | 30 | sys.path.append('./SDL_Pi_TCA9545') 31 | sys.path.append('./SDL_Pi_SI1145') 32 | 33 | import time 34 | import SDL_Pi_SI1145 35 | import SI1145Lux 36 | 37 | 38 | import SDL_Pi_TCA9545 39 | 40 | 41 | 42 | 43 | ################ 44 | # TCA9545 I2C Mux 45 | 46 | #/*========================================================================= 47 | # I2C ADDRESS/BITS 48 | # -----------------------------------------------------------------------*/ 49 | TCA9545_ADDRESS = (0x73) # 1110011 (A0+A1=VDD) 50 | #/*=========================================================================*/ 51 | 52 | #/*========================================================================= 53 | # CONFIG REGISTER (R/W) 54 | # -----------------------------------------------------------------------*/ 55 | TCA9545_REG_CONFIG = (0x00) 56 | # /*---------------------------------------------------------------------*/ 57 | 58 | TCA9545_CONFIG_BUS0 = (0x01) # 1 = enable, 0 = disable 59 | TCA9545_CONFIG_BUS1 = (0x02) # 1 = enable, 0 = disable 60 | TCA9545_CONFIG_BUS2 = (0x04) # 1 = enable, 0 = disable 61 | TCA9545_CONFIG_BUS3 = (0x08) # 1 = enable, 0 = disable 62 | 63 | #/*=========================================================================*/ 64 | 65 | # I2C Mux TCA9545 Detection 66 | try: 67 | tca9545 = SDL_Pi_TCA9545.SDL_Pi_TCA9545(addr=TCA9545_ADDRESS, bus_enable = TCA9545_CONFIG_BUS0) 68 | 69 | 70 | # turn I2CBus 1 on 71 | tca9545.write_control_register(TCA9545_CONFIG_BUS3) 72 | TCA9545_I2CMux_Present = True 73 | except: 74 | print ">>>>>>>>>>>>>>>>>>><<<<<<<<<<<" 75 | print "TCA9545 I2C Mux Not Present" 76 | print ">>>>>>>>>>>>>>>>>>><<<<<<<<<<<" 77 | 78 | 79 | 80 | # Default constructor will pick a default I2C bus. 81 | # 82 | # For the Raspberry Pi this means you should hook up to the only exposed I2C bus 83 | # from the main GPIO header and the library will figure out the bus number based 84 | # on the Pi's revision. 85 | # 86 | # For the Beaglebone Black the library will assume bus 1 by default, which is 87 | # exposed with SCL = P9_19 and SDA = P9_20. 88 | indoor =0 89 | sensor = SDL_Pi_SI1145.SDL_Pi_SI1145(indoor=indoor) 90 | 91 | time.sleep(1.0) 92 | 93 | 94 | 95 | print 'Press Cntrl + Z to cancel' 96 | 97 | while True: 98 | vis = sensor.readVisible() 99 | IR = sensor.readIR() 100 | UV = sensor.readUV() 101 | IR_Lux = SI1145Lux.SI1145_IR_to_Lux(IR) 102 | vis_Lux = SI1145Lux.SI1145_VIS_to_Lux(vis) 103 | uvIndex = UV / 100.0 104 | print '--------------------' 105 | print '--------------------' 106 | print 'indoor=', indoor 107 | print '--------------------' 108 | print 'Vis: ' + str(vis) 109 | print 'IR: ' + str(IR) 110 | print 'UV: ' + str(UV) 111 | print '--------------------' 112 | print 'Vis Lux: ' + str(vis_Lux) 113 | print 'IR Lux: ' + str(IR_Lux) 114 | print 'UV Index: ' + str(uvIndex) 115 | print '--------------------' 116 | print '--------------------' 117 | time.sleep(5) 118 | 119 | -------------------------------------------------------------------------------- /util.py: -------------------------------------------------------------------------------- 1 | 2 | #utility programs 3 | import state 4 | import updateBlynk 5 | import RPi.GPIO as GPIO 6 | 7 | # Check for user imports 8 | try: 9 | import conflocal as config 10 | except ImportError: 11 | import config 12 | 13 | GPIO.setmode(GPIO.BCM) 14 | 15 | ############### 16 | # Turn OLED On and Off 17 | ############### 18 | 19 | GROVEPOWERSAVEPIN = 12 20 | 21 | def turnOLEDOn(): 22 | GPIO.setup(GROVEPOWERSAVEPIN, GPIO.OUT) 23 | GPIO.output(GROVEPOWERSAVEPIN, True) 24 | if (config.USEBLYNK): 25 | updateBlynk.blynkStatusTerminalUpdate("OLED Turned On") 26 | def turnOLEDOff(): 27 | GPIO.setup(GROVEPOWERSAVEPIN, GPIO.OUT) 28 | GPIO.output(GROVEPOWERSAVEPIN, False) 29 | if (config.USEBLYNK): 30 | updateBlynk.blynkStatusTerminalUpdate("OLED Turned Off") 31 | 32 | 33 | ################ 34 | # Unit Conversion 35 | ################ 36 | # 37 | 38 | def returnTemperatureCF(temperature): 39 | if (state.EnglishMetric == True): 40 | # return Metric 41 | return temperature 42 | else: 43 | return (9.0/5.0)*temperature + 32.0 44 | 45 | def returnTemperatureCFUnit(): 46 | if (state.EnglishMetric == True): 47 | # return Metric 48 | return "C" 49 | else: 50 | return "F" 51 | 52 | def returnWindSpeedUnit(): 53 | if (state.EnglishMetric == True): 54 | # return Metric 55 | return "KPH" 56 | else: 57 | return "MPH" 58 | 59 | def returnWindSpeed(wind): 60 | if (state.EnglishMetric == True): 61 | # return Metric 62 | return wind 63 | else: 64 | return wind/1.6 65 | 66 | 67 | def returnWindDirection(windDirection): 68 | 69 | if (windDirection > 315.0+1.0): 70 | return "NNW" 71 | if (windDirection > 292.5+1.0): 72 | return "NW" 73 | if (windDirection > 270.0+1.0): 74 | return "WNW" 75 | if (windDirection > 247.5+1.0): 76 | return "W" 77 | if (windDirection > 225.0+1.0): 78 | return "WSW" 79 | if (windDirection > 202.5+1.0): 80 | return "SW" 81 | if (windDirection > 180.0+1.0): 82 | return "SSW" 83 | if (windDirection > 157.5+1.0): 84 | return "S" 85 | if (windDirection > 135.0+1.0): 86 | return "SSE" 87 | if (windDirection > 112.5+1.0): 88 | return "SE" 89 | if (windDirection > 90.0+1.0): 90 | return "ESE" 91 | if (windDirection > 67.5+1.0): 92 | return "E" 93 | if (windDirection > 45.0+1.0): 94 | return "ENE" 95 | if (windDirection > 22.5+1.0): 96 | return "NE" 97 | if (windDirection > 0.0+1.0): 98 | return "NNE" 99 | return "N" 100 | --------------------------------------------------------------------------------