I've actually run out of time for today. 

Gary, I could use some help if you (or anyone else) has some time. I 
haven't done much special on the driver other than try to bolt everything 
together from the Tutorial's code 
<https://projects.raspberrypi.org/en/projects/build-your-own-weather-station/2> 
and some of Patrick's code provided in this thread. Since I don't have the 
hardware it's a logical first step to me. 

In bolting things together it's making calls to other files which seems a 
bit sloppy for a driver. Perhaps there's a quick way to clean this up and 
consolidate? 

Secondly, in the genPackets function, there's a while loop which is 
counting the wind speed from the wind_direction_byo_5.py file and it delays 
things for roughly 60 seconds in 5 second intervals. Seems like there could 
be a better way to let weewx handle the wind speed counter?

This is where some of my inexperience with driver making starts to show up 
with wind speed counting and rain bucket tip counting. :)

Help is appreciated to try and finish this driver. 

Thanks


On Tuesday, January 1, 2019 at 2:31:16 PM UTC-5, Pat wrote:
>
> Exactly correct. I'm SSH'd to his Pi and debugging now. Will probably need 
> more help soon but for now the driver is at least working. Unsure on 
> validity of sensor values quite yet. 
>
> On Tuesday, January 1, 2019 at 2:30:19 PM UTC-5, gjr80 wrote:
>>
>> In this case the problem is your code is trying use a BYOWS object before 
>> the BYOWS class has been defined. You need to re-structure your code to 
>> avoid calling the class before it is defined.
>>
>> Gary
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"weewx-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#!/usr/bin/python
# Created by Pat O'Brien 2019 - https://obrienlabs.net
#
# This driver takes the sensors used in the Raspberry Pi
# build your own weather station project and converts it
# into a format that can be used with weewx.
#
# The Raspberry Pi project can be found here:
# https://projects.raspberrypi.org/en/projects/build-your-own-weather-station
#

import os # POB REMOVE
os.environ['GPIOZERO_PIN_FACTORY'] = os.environ.get('GPIOZERO_PIN_FACTORY', 'mock') # POB REMOVE
from gpiozero import Button
import time
import math
import bme280_sensor_2
import wind_direction_byo_5
import statistics
import ds18b20_therm
import datetime
import syslog

import weedb
import weewx.drivers
import weeutil.weeutil
import weewx.wxformulas

temp_probe = ds18b20_therm.DS18B20()

def logmsg(dst, msg):
    syslog.syslog(dst, 'BYOWS: %s' % msg)

def loginf(msg):
    logmsg(syslog.LOG_INFO, msg)

def logerror(msg):
    logmsg(syslog.LOG_ERROR, msg)

def logdebug(msg):
    logmsg(syslog.LOG_DEBUG, msg)

def loader(config_dict, engine):
    station = BYOWS(**config_dict['BYOWS'])
    return station

class BYOWS(weewx.drivers.AbstractDevice):
    """ Driver for the Raspberry Pi Bring Your Own Weather Station. """

    def __init__(self, **stn_dict) :
        """ Initialize object. """
        self.station_hardware = stn_dict.get('hardware')
        # TODO CONVERT TO WEEWX OPTIONS?
        self.interval = 60 # Measurements recorded every 1 minute
        self.wind_count = 0 # Counts how many half-rotations
        self.radius_cm = 9.0 # Radius of your anemometer
        self.wind_interval = 5 # How often (secs) to sample speed
        self.wind_gust = 0
        self.cm_in_a_km = 100000.0
        self.secs_in_an_hour = 3600
        self.adjustment = 1.18
        self.bucket_size = 0.2794 # mm
        self.rain_count = 0
        self.store_speeds = []
        self.store_directions = []
	self.wind_speed_sensor = Button(5)
	self.wind_speed_sensor.when_pressed = self.spin() # is this a valid call for the below class function?
	self.rain_sensor = Button(6)
	self.rain_sensor.when_pressed = self.bucket_tipped() # is this a valid call for the below class function?

    def hardware_name(self):
        return self.station_hardware

    # Every half-rotations, add 1 to count
    def spin(self):
        self.wind_count = self.wind_count + 1
        #print("spin" + str(self.wind_count))

    def calculate_speed(self, time_sec):
        circumference_cm = (2 * math.pi) * self.radius_cm
        rotations = self.wind_count / 2.0

        # Calculate distance travelled by a cup in km
        dist_km = (circumference_cm * rotations) / self.cm_in_a_km

        # Speed = distance / time
        km_per_sec = dist_km / time_sec
        km_per_hour = km_per_sec * self.secs_in_an_hour

        # Calculate Speed
        final_speed = km_per_hour * self.adjustment

        return final_speed

    def bucket_tipped(self):
        self.rain_count = self.rain_count + 1
        #print (self.rain_count * self.bucket_size)

    def reset_rainfall(self):
        self.rain_count = 0

    def reset_wind(self):
        self.wind_count = 0

    def reset_gust(self):
        self.wind_gust = 0


    #===============================================================================
    #                         LOOP record decoding functions
    #===============================================================================

    def genLoopPackets(self):
        """ Generator function that continuously returns loop packets """
        for _packet in self.genPackets():
            yield _packet

    def genPackets(self):
        """ Generate measurement packets. """
        global temp_probe
        while True:
            start_time = time.time()
            while time.time() - start_time <= self.interval:
                wind_start_time = time.time()
                self.reset_wind()
                while time.time() - wind_start_time <= self.wind_interval:
                    self.store_directions.append( wind_direction_byo_5.get_value() )
                    final_speed = self.calculate_speed( self.wind_interval ) # Add this speed to the list
                    self.store_speeds.append( final_speed )
            wind_average = wind_direction_byo_5.get_average( self.store_directions )
            self.wind_gust = max( self.store_speeds )
            wind_speed = statistics.mean( self.store_speeds )
            rainfall = self.rain_count * self.bucket_size # mm. if units are US, do we need to convert to inch?
            self.reset_rainfall()
            self.store_speeds = []
            self.store_directions = []
            ground_temp = temp_probe.read_temp()
            humidity, pressure, ambient_temp = bme280_sensor_2.read_all()

            # Build the weewx loop packet
            packet = { 'dateTime': int( time.time() ), 'usUnits': weewx.US }
            packet['outTemp'] = float( ambient_temp )
            packet['outHumidity'] = float( humidity )
            packet['soilTemp1'] = float( ground_temp )
            packet['pressure'] = float( pressure )
            packet['rain'] = rainfall
            packet['windDir'] = float( wind_average )
            packet['windSpeed'] = float( wind_speed )
            packet['windGust'] = float( self.wind_gust )

            # Send to the loop
            yield packet

            # Delay reading sensors for the interval time?
            #time.sleep( self.interval )
import bme280
import smbus2
from time import sleep

port = 1
address = 0x76 
bus = smbus2.SMBus(port)

bme280.load_calibration_params(bus,address)

def read_all():
    bme280_data = bme280.sample(bus,address)
    return bme280_data.humidity, bme280_data.pressure, bme280_data.temperature
import math
from gpiozero import MCP3008
import time
adc = MCP3008(channel=0)
count = 0
values = []
volts = {0.4: 0.0,
         1.4: 22.5,
         1.2: 45.0,
         2.8: 67.5,
         2.7: 90.0,
         2.9: 112.5,
         2.2: 135.0,
         2.5: 157.5,
         1.8: 180.0,
         2.0: 202.5,
         0.7: 225.0,
         0.8: 247.5,
         0.1: 270.0,
         0.3: 292.5,
         0.2: 315.0,
         0.6: 337.5}


def get_average(angles):
    sin_sum = 0.0
    cos_sum = 0.0

    for angle in angles:
        r = math.radians(angle)
        sin_sum += math.sin(r)
        cos_sum += math.cos(r)

    flen = float(len(angles))
    s = sin_sum / flen
    c = cos_sum / flen
    arc = math.degrees(math.atan(s / c))
    average = 0.0

    if s > 0 and c > 0:
        average = arc
    elif c < 0:
        average = arc + 180
    elif s < 0 and c > 0:
        average = arc + 360

    return 0.0 if average == 360 else average

def get_value(length=5):
    data = []
    print("Measuring wind direction for %d seconds..." % length)
    start_time = time.time()
    while time.time() - start_time <= length:
            wind =round(adc.value*3.3,1)
            if not wind in volts: # keep only good measurements
                    print('unknown value ' + str(wind))
    else:
            data.append(volts[wind])

    return get_average(data)



#while True:
#    wind =round(adc.value*3.3,1)
#    if not wind in volts:
#        print('unknown value' + str(wind) + ' ' + str(volts[wind]))
#    else:
#    print('found ' + str(wind) + ' ' + str(volts[wind]))



Reply via email to