Hi Patrick,

I had some time to wrapped the wind_direction_byo.py file into a class
object and incorporate it into the driver. Here is the latest driver file,
I haven't pushed it to github yet because I want to make su it works first.
I'll be incorporating one sensor at a time to make debugging a bit easier.

Give it a try and let me know of any issues.

Jardi.

On Thu, Jan 31, 2019 at 1:51 PM <[email protected]> wrote:

> Hello everyone,
>
> After lots of debugging with Patrick today I converted his script in a
> basic but functional weeWX driver. I wrapped the functions in his script in
> a class object to keep it separate from the class that inherits from
> weewx.drivers.AbstractDevice.
> Code is hosted in gitHub:
> https://github.com/jardiamj/BYOWS_RPi/blob/master/byows_rpi.py
>
> Next steps are:
> - To incorporate the code in the other 3 files: bme280_sensor_2.py
> <https://github.com/jardiamj/BYOWS_RPi/blob/master/bme280_sensor_2.py>,
> ds18b20_therm.py
> <https://github.com/jardiamj/BYOWS_RPi/blob/master/ds18b20_therm.py> and
> wind_direction_byo_5.py
> <https://github.com/jardiamj/BYOWS_RPi/blob/master/wind_direction_byo_5.py>.
> To make it just one single file containing the driver.
> - Make the configuration variables available through the weewx.conf file.
>
> Jardi.
>
> --
> 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.
>

-- 
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/env python
"""
Copyright 2018 Jardi A. Martinez Jordan <[email protected]>

This is an weeWX driver implementation of the Build Your OWN Weather
Station usin the Raspberry Pi: 
https://projects.raspberrypi.org/en/projects/build-your-own-weather-station/

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

"""
import math
import syslog
import time
import datetime

# Imports specific for BYOWS_RPi
from gpiozero import Button, MCP3008
import math
import bme280_sensor_2
import statistics
import ds18b20_therm

import weewx.drivers
import weewx.wxformulas

DRIVER_NAME = 'BYOWS'
DRIVER_VERSION = '0.1'

wind_interval = 1 # How often (secs) to sample speed
interval = 5 # measurements recorded every 5 seconds
CM_IN_A_KM = 100000.0
SECS_IN_AN_HOUR = 3600
ADJUSTMENT = 1.18
BUCKET_SIZE = 0.2794
WIND_VANE_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 loader(config_dict, _):
    return BYOWS_RPi(**config_dict[DRIVER_NAME])

"""
def confeditor_loader():
    return BYOWS_RPiConfEditor()
"""

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

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

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

def logerr(msg):
    logmsg(syslog.LOG_ERR, msg)
    
class BYOWS_RPi(weewx.drivers.AbstractDevice):
    """weewx driver for the Build Your Own Weather Station - Raspberry Pi
    
    """
    def __init__(self, **stn_dict):
        self.hardware = "BYOWS_RPi"
        loginf('using driver %s' % DRIVER_NAME)
        loginf('driver version is %s' % DRIVER_VERSION)

        self.station = BYO_RPi_Station()
        
    @property
    def hardware_name(self):
        return self.hardware
    
    def genLoopPackets(self):
        temp_probe = ds18b20_therm.DS18B20()
        wind_vane = self.station.wind_vane
        while True:
            self.station.wind_count = o
            wind_direction = wind_vane.get_value(interval) # seconds interval
            wind_speed = self.station.calculate_speed(interval)
            rainfall = self.station.get_rainfall()

            ground_temp = temp_probe.read_temp()
            humidity, pressure, ambient_temp = bme280_sensor_2.read_all()

            packet = {'dateTime': int(time.time() + 0.5),
                      'usUnits': weewx.METRIC}
  
            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 )

            yield packet

class BYO_RPi_Station(object):
    """ Object that represents a BYO_Station. """
    def __init__(self):
        """ Initialized Object. """
        self.wind_count = 0 # Counts how many half-rotations
        self.radius_cm = 9.0 # Radius of your anemometer
        self.rain_count = 0
        self.gust = 0

        self.wind_speed_sensor = Button(5)
        self.wind_speed_sensor.when_pressed = self.spin
        self.rain_sensor = Button(6)
        self.rain_sensor.when_pressed = self.bucket_tipped
        self.wind_vane = WindVane(channel=0)

    # Every half-rotations, add 1 to count
    def spin(self):
        self.wind_count = self.wind_count + 1
        #print("spin" + str(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) / CM_IN_A_KM
        # Speed = distance / time
        km_per_sec = dist_km / time_sec
        km_per_hour = km_per_sec * SECS_IN_AN_HOUR
        # Calculate Speed
        final_speed = km_per_hour * ADJUSTMENT
        return final_speed
    
    def get_rainfall(self):
        rainfall = self.rain_count * BUCKET_SIZE
        self.reset_rainfall()
        return rainfall

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

    def reset_rainfall(self):
        self.rain_count = 0

    def reset_wind(self):
        self.wind_count = 0

    def reset_gust(self):
        self.gust = 0

class WindVane(object):
    """ Object that represents a Wind Vane sensor. """
    def __init(self,channel=0):
        # pass channel of MCP3008 where wind vane is connected to
        self.count = 0
        self.adc = MCP3008(channel)
        
    def get_value(self, length=5):
        # Get the average wind direction in a length of time in seconds
        data = []
        print("Measuring wind direction for %d seconds..." % length)
        start_time = time.time()
        while time.time() - start_time <= length:
            wind =round(self.adc.value*3.3,1)
            if not wind in WIND_VANE_VOLTS: # keep only good measurements
                print('unknown value ' + str(wind))
            else:
                data.append(volts[wind])
        return self.get_average(data)
        
    def get_average(angles):
        # Function that returns the average angle from a list of values
        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


Reply via email to