Topher Webb – LTUAE

SWITCHDOC LABS vs WEEWX

On the 13th October, 2016 I made my first purchase from SwitchDoc Labs.
SwitchDoc Labs, LLC is a software and hardware engineering company producing specialized products and designs for the small computer industry maker movement (Raspberry Pi, Arduinos and others)

Over the last few years SDL has posted various projects on Kickstarter for some great little toys. What sparked my interest was their weather gear.

I will post more on 2016-2018 in this section, but for now, I am skipping to 2019.

In February, after buying the el-cheapo chinese rip off of a better solar powered weather station ( see Weather2880.com ) the interest in the SDL weather gear was sparked again, and everything was plugged in again.

Wiring List for Raspberry Pi GroveWeatherPi System
FromToDescription
Pi2Grover / D13/D16MOD-1016G / Grove IRQ50cm Grove Cable
Pi2Grover / D21/D26Weather Board / Grove D Rain BucketGrove Cable
Pi2Grover / D26Weather Board / Grove D AnemometerGrove Cable
Pi2Grover / Grove I2C4 Chan I2C Mux / Grove J1 – Computer I2CGrove Cable
4 Chan I2C Mux / Grove J2 / Bus04 Slot I2C Expander / Any SlotGrove Cable
4 Chan I2C Mux / Grove J3 / Bus1MOD-1016 / Grove I2C50cm Grove Cable
4 Chan I2C Mux / Pin Header JP7-14 Chan I2C Mux / Pin Header JP6-1Set Power of I2C Bus to VDD
4 Chan I2C Mux / Pin Header JP7-24 Chan I2C Mux / Pin Header JP6-2Set Power of I2C Bus to VDD
4 Chan I2C Mux / Pin Header JP7-34 Chan I2C Mux / Pin Header JP6-3Set Power of I2C Bus to VDD
4 Chan I2C Mux / Pin Header JP7-44 Chan I2C Mux / Pin Header JP6-4Set Power of I2C Bus to VDD
4 Slot I2C Expander / Any SlotOLED Display / Grove I2CGrove Cable
4 Slot I2C Expander / Any SlotGrove 4Ch/16Bit ADC / Grove I2CGrove Cable
4 Slot I2C Expander / Any SlotWeather Board / Grove I2CGrove Cable
Grove 4Ch/16Bit ADC / Grove A1Weather Board / Grove A Wind VaneGrove Cable
Weather Board / Grove I2CGrove AM2315 Temperature / Humidity SensorGrove Cable
(Optional) HTU21D-F Inside Temperature / Humidity SensorWeather Board / JP14 Plug inPlug in Board
Weather Board RJ11 – Rain BucketWeatherRack Rain Bucket PlugRJ11 Cable
Weather Board RJ11 – Anemometer / Wind VaneWeatherRack Anemometer / Wind Vane PlugRJ11 Cable

Note:   You will use the Female Pin Header to Grove Connector cable provided with your SunAirPlus board in this section.

Wiring List for Solar Power Subsystem for the Raspberry Pi GroveWeatherPi System
FromToDescription
Raspberry Pi Power Micro USBUSB PowerControl USB OutUses USB cable – A/MicroB
USB PowerControl USB InSunAirPlus 5V USB Power Out
USB PowerControl LIPOBATINSunAirPlus JP4 Battery OutFemale to Female Header Jumper Wire
SunAirPlus – From Computer / SCLYellow Female Header Pin on Grove ConnectorSCL
SunAirPlus – From Computer / SCLWhite Female Header Pin on Grove ConnectorSDA
SunAirPlus – From Computer / SCLRed Female Header Pin on Grove ConnectorVDD
SunAirPlus – From Computer / SCLBlack Female Header Pin on Grove ConnectorGND
Grove Connector (Previous 4 Items)4 Chan I2C Mux / Grove J4 – Bus 2Female Pin Header to Grove Connector
SunAIrPlus Battery Female PlugLiPo Battery JST-2 Plug
SunAIrPlus Solar Panel Female PlugSolar Panel JST-2 Plug – Note:  If you have two solar panels, you will need to solder + to + and – to – on the back of the solar panels.   A VoltaicSystems Solar Panel will require an adaptor plug

Parts list for my current setup is:

  • Pi2Grover (sits on top of the PI for I2C/Digital/Analogue signals)
  • Weather Board – Wind and Rain sensor plugs into it (soldered a HTU221D-F inside temp/hum sensor onto the board also)
  • Grove AM2315 outside temp/hum sensor
  • Grove I2C 4Ch/16Bit Analogue Digital converter
  • Grove I2C 4 Channel Multipier
  • Grove Lightning Detector – Thunder Board
  • DS3231 Real time clock
  • Air Quality Sensor v1.3
  • Light sensor (Lux / UV)

In a previous version I had the weather station working wirelessly via LoRa modules, however they died (not sure what happened) and have been shipped back to SDL and awaiting replacements.

To set up my current system I formatted a 16G SD CARD and copied N00BS to it via windows. N00BS lite allows you to install Raspbian via LAN and run on a 30Mb base lot of bootable files.

After Raspbian was downloaded (approx 1Gb) I used Raspi-Config to set the time zone, turn on i2c, turn on ssh and then did an update.

After the update you should be able to use SSH to log into the Pi and then do everything else via windows.

SUDO APT-GET UPDATE -Y && SUDO APT-GET UPGRADE


wget -qO – http://weewx.com/keys.html | sudo apt-key add –

wget -qO – http://weewx.com/apt/weewx.list | sudo tee /etc/apt/sources.list.d/weewx.list

Run these 1 line at a time to tell APT where to find WeeWx files


sudo apt-get update -y && sudo apt-get install weewx

Install WeeWx

Once WeeWx is installed, you will need some modules. Add the below ones as standard. Some may be needed, some are only additional. If WeeWx wants to do a setup, have your Station Name, Lat Lon, Height above sea level all handy. It will ask you for a station type, select SIMULATOR.

# for systems that do not have python 2 installed (for example, ubuntu 18.04 and later):

sudo apt-get install python

# for all systems, you may have to install the python imaging library. try this first:

sudo apt-get install python-pil

# if that doesn’t work, try this:

sudo apt-get install python-imaging

# other required packages:

sudo apt-get install python-configobj && sudo apt-get install python-cheetah

# required if using MySQL:

sudo apt-get install mysql-client && sudo apt-get install python-mysqldb

# required if using FTP on Raspbian systems:

sudo apt-get install ftp

# optional for extended almanac information:

sudo apt-get install python-dev sudo apt-get install python-pip sudo pip install pyephem

sudo pip install tentacle_pi

sudo apt-get install libi2c-dev

Once you have done that. Navigate to the main folder

CD

Then go to the following folder to create a Python file

cd /usr/share/weewx/user

sudo nano GrovePi.py

There wont be a file called GrovePI.py yet so it will be blank.

COPY AND PASTE THE FOLLOWING CODE (https://pastebin.com/YtdYfLZJ) whos author is luksmann (I have edited a few lines to suit MY install of WeeWx)

#
#
GroveWeatherPi Solar Powered Weather Station
Version 2.3 October 3, 2016
#
SwitchDoc Labs
www.switchdoc.com
#
extended by luksmann@gmail.com – no warranties.
imports
import sys
import time
from datetime import datetime
import random
import re
import math
import os

sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Adafruit_ADS1x15’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_SSD1306’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/Adafruit_Python_SSD1306’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/RTC_SDL_DS3231’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/Adafruit_Python_BMP’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/Adafruit_Python_GPIO’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_WeatherRack’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_FRAM’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/RaspberryPi-AS3935/RPi_AS3935’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_INA3221’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_TCA9545’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/graphs’)
sys.path.append(‘/usr/share/weewx’)
import subprocess
import RPi.GPIO as GPIO
import smbus
import struct
Check for user imports
try:
import conflocal as config
except ImportError:
import config
if (config.enable_MySQL_Logging == True):
import MySQLdb as mdb
import weewx.drivers
DRIVER_NAME = ‘GrovePi’
#
Device Present State Variables
#

config.TCA9545_I2CMux_Present = True
config.SunAirPlus_Present = True
config.AS3935_Present = False
config.DS3231_Present = True
config.BMP280_Present = False
config.FRAM_Present = False
config.HTU21DF_Present = True
config.AM2315_Present = True
config.ADS1015_Present = False
config.ADS1115_Present = True
config.OLED_Present = False
config.WXLink_Present = False


import SDL_Pi_INA3221
import SDL_DS3231
import Adafruit_BMP.BMP280 as BMP280
import SDL_Pi_WeatherRack as SDL_Pi_WeatherRack
import SDL_Pi_FRAM
from RPi_AS3935 import RPi_AS3935
import SDL_Pi_TCA9545
import Adafruit_SSD1306
import Scroll_SSD1306
def loader(config_dict, engine):
return GrovePiDriver(**config_dict[DRIVER_NAME])
def returnStatusLine(device, state):
returnString = device if (state == True): returnString = returnString + ": \t\tPresent" else: returnString = returnString + ": \t\tNot Present" return returnString
#
TCA9545 I2C Mux
/*=========================================================================
I2C ADDRESS/BITS
———————————————————————–*/
TCA9545_ADDRESS = (0x73) # 1110011 (A0+A1=VDD)
/=========================================================================/
/*=========================================================================
CONFIG REGISTER (R/W)
———————————————————————–*/
TCA9545_REG_CONFIG = (0x00)
/———————————————————————/
TCA9545_CONFIG_BUS0 = (0x01) # 1 = enable, 0 = disable
TCA9545_CONFIG_BUS1 = (0x02) # 1 = enable, 0 = disable
TCA9545_CONFIG_BUS2 = (0x04) # 1 = enable, 0 = disable
TCA9545_CONFIG_BUS3 = (0x08) # 1 = enable, 0 = disable
/=========================================================================/
I2C Mux TCA9545 Detection
try:
tca9545 = SDL_Pi_TCA9545.SDL_Pi_TCA9545(addr=TCA9545_ADDRESS, bus_enable = TCA9545_CONFIG_BUS0)
# turn I2CBus 1 on tca9545.write_control_register(TCA9545_CONFIG_BUS2) config.TCA9545_I2CMux_Present = True
except:
print “>>>>>>>>>>>>>>>>>>><<<<<<<<<<<” print “TCA9545 I2C Mux Not Present” print “>>>>>>>>>>>>>>>>>>><<<<<<<<<<<“
config.TCA9545_I2CMux_Present = False
#
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
HTU21DF Detection
try:
HTU21DFOut = subprocess.check_output([“htu21dflib/htu21dflib”,”-l”])
config.HTU21DF_Present = True
except:
config.HTU21DF_Present = False
#
WeatherRack Weather Sensors
#
GPIO Numbering Mode GPIO.BCM
#
anemometerPin = 26
rainPin = 21
constants
SDL_MODE_INTERNAL_AD = 0
SDL_MODE_I2C_ADS1015 = 1 # internally, the library checks for ADS1115 or ADS1015 if found
sample mode means return immediately. THe wind speed is averaged at sampleTime or when you ask, whichever is longer
SDL_MODE_SAMPLE = 0
Delay mode means to wait for sampleTime and the average after that time.
SDL_MODE_DELAY = 1
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
weatherStation = SDL_Pi_WeatherRack.SDL_Pi_WeatherRack(anemometerPin, rainPin, 0,0, SDL_MODE_I2C_ADS1015)
weatherStation.setWindMode(SDL_MODE_SAMPLE, 5.0)
weatherStation.setWindMode(SDL_MODE_DELAY, 5.0)
#
DS3231/AT24C32 Setup
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
filename = time.strftime(“%Y-%m-%d%H:%M:%SRTCTest”) + “.txt”
starttime = datetime.utcnow()
ds3231 = SDL_DS3231.SDL_DS3231(1, 0x68)
try:
ds3231.write_now()
ds3231.read_datetime()
#print "DS3231=\t\t%s" % ds3231.read_datetime()
config.DS3231_Present = True
#print "----------------- " #print "----------------- " #print " AT24C32 EEPROM" #print "----------------- " #print "writing first 4 addresses with random data"
for x in range(0,4):
value = random.randint(0,255)
#print "address = %i writing value=%i" % (x, value)
ds3231.write_AT24C32_byte(x, value)
#print "----------------- " #print "reading first 4 addresses" #for x in range(0,4): # print "address = %i value = %i" %(x, ds3231.read_AT24C32_byte(x)) #print "----------------- "
except IOError as e:
#print "I/O error({0}): {1}".format(e.errno, e.strerror)
config.DS3231_Present = False
#
BMP280 Setup
try:
bmp280 = BMP280.BMP280()
config.BMP280_Present = True
except IOError as e:
# print "I/O error({0}): {1}".format(e.errno, e.strerror) config.BMP280_Present = False
#
Setup AM2315
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
#
Detect AM2315
try:
from tentacle_pi.AM2315 import AM2315
try:
am2315 = AM2315(0x5c,”/dev/i2c-1″)
outsideTemperature, outsideHumidity, crc_check = am2315.sense()
#print “outsideTemperature: %0.1f C” % outsideTemperature
#print “outsideHumidity: %0.1f %%” % outsideHumidity
#print “crc: %i” % crc_check
config.AM2315_Present = True
if (crc_check == -1):
config.AM2315_Present = False
except: config.AM2315_Present = False
except:
config.AM2315_Present = False
print “——> See Readme to install tentacle_pi”
#
Set up FRAM
Set up FRAM
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
fram = SDL_Pi_FRAM.SDL_Pi_FRAM(addr = 0x50)
FRAM Detection
try:
fram.read8(0)
config.FRAM_Present = True
except:
config.FRAM_Present = False
fram = SDL_Pi_FRAM.SDL_Pi_FRAM(addr = 0x50)
Main Loop – sleeps 10 seconds
command from RasPiConnect Execution Code
def hardware_name(self):
return DRIVER_NAME
def loader(config_dict, engine):
return GrovePiDriver(**config_dict[DRIVER_NAME])
class GrovePiDriver(weewx.drivers.AbstractDevice):
def init(self, **stn_dict):
self.poll_interval = float(stn_dict.get(‘poll_interval’, 30)) # seconds
self.air_temperature = 0
self.air_sensor = 1
grovepi.pinMode(self.air_sensor, ‘INPUT’)
def genLoopPackets(self): while True: sampleAndDisplay() packet = { 'usUnits': weewx.METRIC, 'outTemp' : outsideTemperature, 'dateTime': int(time.time() + 0.5),
‘inTemp’ : inTemp,
'barometer' : bmp180Pressure, 'pressure' : bmp180Altitude, 'windSpeed' : currentWindSpeed, 'windDir' : currentWindDirection, 'windGust' : currentWindGust, 'outHumidity': outsideHumidity, 'rain' : totalRain, } print packet yield packet time.sleep(15)
def sampleAndDisplay():
global currentWindSpeed, currentWindGust, currentWindDirection global bmp180Temperature, bmp180Pressure, bmp180Altitude, bmp180SeaLevel global outsideTemperature, outsideHumidity, crc_check global currentWindDirectionVoltage global HTUtemperature, HTUhumidity global totalRain
global inTemp
global block1, block2 # turn I2CBus 0 on if (config.TCA9545_I2CMux_Present): tca9545.write_control_register(TCA9545_CONFIG_BUS0)
print “—————– “
print " Local WeatherRack Weather Sensors Sampling" print "----------------- " # currentWindSpeed = weatherStation.current_wind_speed() currentWindGust = weatherStation.get_wind_gust() totalRain = weatherStation.get_current_rain_total() currentWindDirection = weatherStation.current_wind_direction() print("Rain Total=\t%0.2f in")%(totalRain/25.4) print("Wind Speed=\t%0.2f MPH")%(currentWindSpeed/1.6) print("MPH wind_gust=\t%0.2f MPH")%(currentWindGust/1.6) if (config.ADS1015_Present or config.ADS1115_Present): print "Wind Direction=\t\t\t %0.2f Degrees" % weatherStation.current_wind_direction() print "Wind Direction Voltage=\t\t %0.3f V" % weatherStation.current_wind_direction_voltage() else: print "No Wind Direction Available - No ADS1015 or ADS1115 Present" print "----------------- " print "----------------- "
if (config.DS3231_Present == True):
print ” DS3231 Real Time Clock”
else:
print ” DS3231 Real Time Clock Not Present”
print “—————– “
#
if (config.DS3231_Present == True):
currenttime = datetime.utcnow()
deltatime = currenttime – starttime
print “Raspberry Pi=\t” + time.strftime(“%Y-%m-%d %H:%M:%S”)
print “DS3231=\t\t%s” % ds3231.read_datetime()
print “DS3231 Temperature= \t%0.2f C” % ds3231.getTemp()
inTemp = ds3231.getTemp()
print “—————– “
print “SecondCount=”, secondCount
print “—————– “
print “—————– “
print "----------------- " if (config.BMP280_Present == True): print " BMP280 Barometer" else: print " BMP280 Barometer Not Present" print "----------------- " if (config.BMP280_Present): print 'Temperature = \t{0:0.2f} C'.format(bmp280.read_temperature()) print 'Pressure = \t{0:0.2f} KPa'.format(bmp280.read_pressure()/1000) print 'Altitude = \t{0:0.2f} m'.format(bmp280.read_altitude()) print 'Sealevel Pressure = \t{0:0.2f} KPa'.format(bmp280.read_sealevel_pressure(config.BMP280_Altitude_Meters)/1000) print "----------------- " bmp180Pressure = bmp280.read_pressure()/100 bmp180Altitude = bmp280.read_sealevel_pressure(config.BMP280_Altitude_Meters)/100 print "----------------- " if (config.HTU21DF_Present == True): print " HTU21DF Temp/Hum" else: print " HTU21DF Temp/Hum Not Present" print "----------------- " # We use a C library for this device as it just doesn't play well with Python and smbus/I2C libraries if (config.HTU21DF_Present): HTU21DFOut = subprocess.check_output(["htu21dflib/htu21dflib","-l"]) splitstring = HTU21DFOut.split() HTUtemperature = float(splitstring[0]) HTUhumidity = float(splitstring[1]) print "Temperature = \t%0.2f C" % HTUtemperature print "Humidity = \t%0.2f %%" % HTUhumidity else: HTUtemperature = 0.0 HTUhumidity = 0.0 print "----------------- " print "----------------- " # turn I2CBus 0 on if (config.TCA9545_I2CMux_Present): tca9545.write_control_register(TCA9545_CONFIG_BUS0) print "----------------- " if (config.AM2315_Present == True): print " AM2315 Temperature/Humidity Sensor" else: print " AM2315 Temperature/Humidity Sensor Not Present" print "----------------- " if (config.AM2315_Present): outsideTemperature, outsideHumidity, crc_check = am2315.sense() print "outsideTemperature: %0.1f C" % outsideTemperature print "outsideHumidity: %0.1f %%" % outsideHumidity print "crc: %s" % crc_check print "----------------- " print "------------------------------"
if name == “main“:
import weeutil.weeutil
driver = GrovePiDriver()
for packet in driver.genLoopPackets():
print weeutil.weeutil.timestamp_to_string(packet[‘dateTime’]), packet#
#
GroveWeatherPi Solar Powered Weather Station
Version 2.3 October 3, 2016
#
SwitchDoc Labs
www.switchdoc.com
#
extended by luksmann@gmail.com – no warranties.
imports
import sys
import time
from datetime import datetime
import random
import re
import math
import os
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Adafruit_ADS1x15’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_SSD1306’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/Adafruit_Python_SSD1306’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/RTC_SDL_DS3231’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/Adafruit_Python_BMP’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/Adafruit_Python_GPIO’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_WeatherRack’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_FRAM’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/RaspberryPi-AS3935/RPi_AS3935’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_INA3221’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/SDL_Pi_TCA9545’)
sys.path.append(‘/home/pi/SDL_Pi_GroveWeatherPi/graphs’)
sys.path.append(‘/usr/share/weewx’)
import subprocess
import RPi.GPIO as GPIO
import smbus
import struct
Check for user imports
try:
import conflocal as config
except ImportError:
import config
if (config.enable_MySQL_Logging == True):
import MySQLdb as mdb
import weewx.drivers
DRIVER_NAME = ‘GrovePi’
#
Device Present State Variables
#
config.TCA9545_I2CMux_Present = False
config.SunAirPlus_Present = False
config.AS3935_Present = False
config.DS3231_Present = False
config.BMP280_Present = False
config.FRAM_Present = False
config.HTU21DF_Present = False
config.AM2315_Present = False
config.ADS1015_Present = False
config.ADS1115_Present = False
config.OLED_Present = False
config.WXLink_Present = False
import SDL_Pi_INA3221
import SDL_DS3231
import Adafruit_BMP.BMP280 as BMP280
import SDL_Pi_WeatherRack as SDL_Pi_WeatherRack
import SDL_Pi_FRAM
from RPi_AS3935 import RPi_AS3935
import SDL_Pi_TCA9545
import Adafruit_SSD1306
import Scroll_SSD1306
def loader(config_dict, engine):
return GrovePiDriver(**config_dict[DRIVER_NAME])
def returnStatusLine(device, state):
returnString = device if (state == True): returnString = returnString + ": \t\tPresent" else: returnString = returnString + ": \t\tNot Present" return returnString
#
TCA9545 I2C Mux
/*=========================================================================
I2C ADDRESS/BITS
———————————————————————–*/
TCA9545_ADDRESS = (0x73) # 1110011 (A0+A1=VDD)
/=========================================================================/
/*=========================================================================
CONFIG REGISTER (R/W)
———————————————————————–*/
TCA9545_REG_CONFIG = (0x00)
/———————————————————————/
TCA9545_CONFIG_BUS0 = (0x01) # 1 = enable, 0 = disable
TCA9545_CONFIG_BUS1 = (0x02) # 1 = enable, 0 = disable
TCA9545_CONFIG_BUS2 = (0x04) # 1 = enable, 0 = disable
TCA9545_CONFIG_BUS3 = (0x08) # 1 = enable, 0 = disable
/=========================================================================/
I2C Mux TCA9545 Detection
try:
tca9545 = SDL_Pi_TCA9545.SDL_Pi_TCA9545(addr=TCA9545_ADDRESS, bus_enable = TCA9545_CONFIG_BUS0)
# turn I2CBus 1 on tca9545.write_control_register(TCA9545_CONFIG_BUS2) config.TCA9545_I2CMux_Present = True
except:
print “>>>>>>>>>>>>>>>>>>><<<<<<<<<<<” print “TCA9545 I2C Mux Not Present” print “>>>>>>>>>>>>>>>>>>><<<<<<<<<<<“
config.TCA9545_I2CMux_Present = False
#
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
HTU21DF Detection
try:
HTU21DFOut = subprocess.check_output([“htu21dflib/htu21dflib”,”-l”])
config.HTU21DF_Present = True
except:
config.HTU21DF_Present = False
#
WeatherRack Weather Sensors
#
GPIO Numbering Mode GPIO.BCM
#
anemometerPin = 26
rainPin = 21
constants
SDL_MODE_INTERNAL_AD = 0
SDL_MODE_I2C_ADS1015 = 1 # internally, the library checks for ADS1115 or ADS1015 if found
sample mode means return immediately. THe wind speed is averaged at sampleTime or when you ask, whichever is longer
SDL_MODE_SAMPLE = 0
Delay mode means to wait for sampleTime and the average after that time.
SDL_MODE_DELAY = 1
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
weatherStation = SDL_Pi_WeatherRack.SDL_Pi_WeatherRack(anemometerPin, rainPin, 0,0, SDL_MODE_I2C_ADS1015)
weatherStation.setWindMode(SDL_MODE_SAMPLE, 5.0)
weatherStation.setWindMode(SDL_MODE_DELAY, 5.0)
#
DS3231/AT24C32 Setup
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
filename = time.strftime(“%Y-%m-%d%H:%M:%SRTCTest”) + “.txt”
starttime = datetime.utcnow()
ds3231 = SDL_DS3231.SDL_DS3231(1, 0x68)
try:
ds3231.write_now()
ds3231.read_datetime()
#print "DS3231=\t\t%s" % ds3231.read_datetime()
config.DS3231_Present = True
#print "----------------- " #print "----------------- " #print " AT24C32 EEPROM" #print "----------------- " #print "writing first 4 addresses with random data"
for x in range(0,4):
value = random.randint(0,255)
#print "address = %i writing value=%i" % (x, value)
ds3231.write_AT24C32_byte(x, value)
#print "----------------- " #print "reading first 4 addresses" #for x in range(0,4): # print "address = %i value = %i" %(x, ds3231.read_AT24C32_byte(x)) #print "----------------- "
except IOError as e:
#print "I/O error({0}): {1}".format(e.errno, e.strerror)
config.DS3231_Present = False
#
BMP280 Setup
try:
bmp280 = BMP280.BMP280()
config.BMP280_Present = True
except IOError as e:
# print "I/O error({0}): {1}".format(e.errno, e.strerror) config.BMP280_Present = False
#
Setup AM2315
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
#
Detect AM2315
try:
from tentacle_pi.AM2315 import AM2315
try:
am2315 = AM2315(0x5c,”/dev/i2c-1″)
outsideTemperature, outsideHumidity, crc_check = am2315.sense()
#print “outsideTemperature: %0.1f C” % outsideTemperature
#print “outsideHumidity: %0.1f %%” % outsideHumidity
#print “crc: %i” % crc_check
config.AM2315_Present = True
if (crc_check == -1):
config.AM2315_Present = False
except: config.AM2315_Present = False
except:
config.AM2315_Present = False
print “——> See Readme to install tentacle_pi”
#
Set up FRAM
Set up FRAM
turn I2CBus 0 on
if (config.TCA9545_I2CMux_Present):
tca9545.write_control_register(TCA9545_CONFIG_BUS0)
fram = SDL_Pi_FRAM.SDL_Pi_FRAM(addr = 0x50)
FRAM Detection
try:
fram.read8(0)
config.FRAM_Present = True
except:
config.FRAM_Present = False
fram = SDL_Pi_FRAM.SDL_Pi_FRAM(addr = 0x50)
Main Loop – sleeps 10 seconds
command from RasPiConnect Execution Code
def hardware_name(self):
return DRIVER_NAME
def loader(config_dict, engine):
return GrovePiDriver(**config_dict[DRIVER_NAME])
class GrovePiDriver(weewx.drivers.AbstractDevice):
def init(self, **stn_dict):
self.poll_interval = float(stn_dict.get(‘poll_interval’, 30)) # seconds
self.air_temperature = 0
self.air_sensor = 1
grovepi.pinMode(self.air_sensor, ‘INPUT’)
def genLoopPackets(self): while True: sampleAndDisplay() packet = { 'usUnits': weewx.METRIC, 'outTemp' : outsideTemperature, 'dateTime': int(time.time() + 0.5),
‘inTemp’ : inTemp,
'barometer' : bmp180Pressure, 'pressure' : bmp180Altitude, 'windSpeed' : currentWindSpeed, 'windDir' : currentWindDirection, 'windGust' : currentWindGust, 'outHumidity': outsideHumidity, 'rain' : totalRain, } print packet yield packet time.sleep(15)
def sampleAndDisplay():
global currentWindSpeed, currentWindGust, currentWindDirection global bmp180Temperature, bmp180Pressure, bmp180Altitude, bmp180SeaLevel global outsideTemperature, outsideHumidity, crc_check global currentWindDirectionVoltage global HTUtemperature, HTUhumidity global totalRain
global inTemp
global block1, block2 # turn I2CBus 0 on if (config.TCA9545_I2CMux_Present): tca9545.write_control_register(TCA9545_CONFIG_BUS0)
print “—————– “
print " Local WeatherRack Weather Sensors Sampling" print "----------------- " # currentWindSpeed = weatherStation.current_wind_speed() currentWindGust = weatherStation.get_wind_gust() totalRain = weatherStation.get_current_rain_total() currentWindDirection = weatherStation.current_wind_direction() print("Rain Total=\t%0.2f in")%(totalRain/25.4) print("Wind Speed=\t%0.2f MPH")%(currentWindSpeed/1.6) print("MPH wind_gust=\t%0.2f MPH")%(currentWindGust/1.6) if (config.ADS1015_Present or config.ADS1115_Present): print "Wind Direction=\t\t\t %0.2f Degrees" % weatherStation.current_wind_direction() print "Wind Direction Voltage=\t\t %0.3f V" % weatherStation.current_wind_direction_voltage() else: print "No Wind Direction Available - No ADS1015 or ADS1115 Present" print "----------------- " print "----------------- "
if (config.DS3231_Present == True):
print ” DS3231 Real Time Clock”
else:
print ” DS3231 Real Time Clock Not Present”
print “—————– “
#
if (config.DS3231_Present == True):
currenttime = datetime.utcnow()
deltatime = currenttime – starttime
print “Raspberry Pi=\t” + time.strftime(“%Y-%m-%d %H:%M:%S”)
print “DS3231=\t\t%s” % ds3231.read_datetime()
print “DS3231 Temperature= \t%0.2f C” % ds3231.getTemp()
inTemp = ds3231.getTemp()
print “—————– “
print “SecondCount=”, secondCount
print “—————– “
print “—————– “
print "----------------- " if (config.BMP280_Present == True): print " BMP280 Barometer" else: print " BMP280 Barometer Not Present" print "----------------- " if (config.BMP280_Present): print 'Temperature = \t{0:0.2f} C'.format(bmp280.read_temperature()) print 'Pressure = \t{0:0.2f} KPa'.format(bmp280.read_pressure()/1000) print 'Altitude = \t{0:0.2f} m'.format(bmp280.read_altitude()) print 'Sealevel Pressure = \t{0:0.2f} KPa'.format(bmp280.read_sealevel_pressure(config.BMP280_Altitude_Meters)/1000) print "----------------- " bmp180Pressure = bmp280.read_pressure()/100 bmp180Altitude = bmp280.read_sealevel_pressure(config.BMP280_Altitude_Meters)/100 print "----------------- " if (config.HTU21DF_Present == True): print " HTU21DF Temp/Hum" else: print " HTU21DF Temp/Hum Not Present" print "----------------- " # We use a C library for this device as it just doesn't play well with Python and smbus/I2C libraries if (config.HTU21DF_Present): HTU21DFOut = subprocess.check_output(["htu21dflib/htu21dflib","-l"]) splitstring = HTU21DFOut.split() HTUtemperature = float(splitstring[0]) HTUhumidity = float(splitstring[1]) print "Temperature = \t%0.2f C" % HTUtemperature print "Humidity = \t%0.2f %%" % HTUhumidity else: HTUtemperature = 0.0 HTUhumidity = 0.0 print "----------------- " print "----------------- " # turn I2CBus 0 on if (config.TCA9545_I2CMux_Present): tca9545.write_control_register(TCA9545_CONFIG_BUS0) print "----------------- " if (config.AM2315_Present == True): print " AM2315 Temperature/Humidity Sensor" else: print " AM2315 Temperature/Humidity Sensor Not Present" print "----------------- " if (config.AM2315_Present): outsideTemperature, outsideHumidity, crc_check = am2315.sense() print "outsideTemperature: %0.1f C" % outsideTemperature print "outsideHumidity: %0.1f %%" % outsideHumidity print "crc: %s" % crc_check print "----------------- " print "------------------------------"
if name == “main“:
import weeutil.weeutil
driver = GrovePiDriver()
for packet in driver.genLoopPackets():
print weeutil.weeutil.timestamp_to_string(packet[‘dateTime’]), packet

Now lets edit WeeWx config.

You will need to edit your Station Name, Lat Lon, Height above sea level. Handy if you havent already set them. If you have, just hit ENTER to use existing data.

sudo nano /etc/weewx/weewx.conf

This is the main weewx config file.

Scroll down through the first few lines of data until you find the following

rain_year_start = 1 # Start of week (0=Monday, 6=Sunday) week_start = 6

#######################################
[GrovePi]
driver = user.GrovePi
poll_interval = 30
#######################################

[Simulator]
# This section is for the weewx weather station simulator
# The time (in seconds) between LOOP packets. loop_interval = 2.5

Enter the [GrovePi] data with copy and paste

Now run

sudo wee_config –reconfigure

Skip (enter button) the station name and location etc… when you get to station type, select GrovePi as station type

One last install, and you should be able to run WeeWx and see if it works

cd

cd SDL_Pi_GroveWeatherPi

sudo git clone https://github.com/adafruit/Adafruit_ADS1X15.git

Ok, lets try it!

cd

sudo weewxd /etc/weewx/weewx.conf

If you see the data scrolling across your screen, you are in luck. The Switchdoc Labs weather station with WeeWx weather programme is working!

If so, you can run it as a service

sudo /etc/init.d/weewx start

Once you have it started, you can check it at any time by using

sudo tail -f /var/log/syslog

Edit the FTP section in /etc/weewx/weewx.conf for uploading data to a website. You can check Weather2880.com/sdl for weather updates on this project until I use it as primary data.

COMING MONTHS:

Wind turbine to recharge the battieres at night time

Weather camera for hourly snap shots of the sky conditions

Air quality sensor needs attention as its not recording

LoRa modules to be returned and installed for remote (outside) recording of data.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: