I am using the driver located 
here: https://github.com/David-Enst/WeeWX-BCRobotics

I am also attaching the file



On Tuesday, 16 February 2021 at 16:53:24 UTC-8 [email protected] wrote:

> What driver are you using?
> It's going to be really tough to help with this because you have unique 
> hardware and aren't asking a very answerable question. 
>
> On Tue, Feb 16, 2021 at 3:26 PM Terry Steneker <[email protected]> 
> wrote:
>
>>
>> I just purchased the BCRobotics board and tried to install the required 
>> software for it. I ran into problems when I tried to test the BME280 using 
>> the Adafruit ADS1x15 library. Kept getting errors and the python 
>> Adafruit_BME280 library is deprecated. 
>>
>> Instead of trying to fix the errors I went the hard way and upgraded to 
>> the adafruit-circuitpython libraries so I can also run Python3
>>
>> sudo pip3 install adafruit-circuitpython-bme280
>>
>> sudo pip3 install adafruit-circuitpython-ads1x15
>>
>> I then modified the BCRobotics-test-app.py to run under Python3 and the 
>> upgraded Adafruit libraries.
>> Tested the program and it works!
>>
>> I have attached the modified program.
>>
>> I need to modify the driver to work the same as the updated code but not 
>> sure how to do that. Can I just substitute the same modifications that I 
>> made to the test program? 
>>
>> Thanks
>> Terry
>>
>> On Sunday, 24 November 2019 at 10:25:09 UTC-8 [email protected] wrote:
>>
>>> Louis,
>>>
>>> thank you very much for your reply.
>>>
>>> I didn't realize they first did it with Python 2.7. I though you used it 
>>> in order for it to work with the interceptor driver.
>>>
>>> I'll keep using python 2.7 and your code but it seems that I'm missing 
>>> some libraries.
>>>
>>> (I think I had them all but I keep getting a " BME280_OSAMPLE_8' is not 
>>> defined 
>>> " etc. errors) 
>>>
>>> I'll try and find the original code and libraries for Python 2.7 and do 
>>> the necessary adjustments.
>>>
>>> Thanks again!
>>>
>>> On Sun, Nov 24, 2019 at 7:15 PM Louis De Lange <[email protected]> 
>>> wrote:
>>>
>>>> George,
>>>>
>>>> At the time when I completed that project the tutorial on the 
>>>> BC-Robotics website was written in Python 2.7 so I used all the 2.7 
>>>> libraries in my code.  With some research you should be able to convert 
>>>> the 
>>>> original code to work with python 3 libraries.
>>>>
>>>> Sorry, I have not updated anything because if it works why break it.
>>>>
>>>> LDL
>>>>
>>>> On Saturday, 23 November 2019 13:06:57 UTC-8, George Nimrodel wrote:
>>>>>
>>>>> Hey Louis,
>>>>>
>>>>> I'm trying to do exactly what you've done with the difference that I 
>>>>> have weewx running on the RPi and I'm using only the BME280 for 
>>>>> temperature 
>>>>> in a separate enclosure.
>>>>>
>>>>> I'm having a bit of a trouble with your code. I keep getting errors 
>>>>> regarding the libraries.
>>>>>
>>>>> I've noticed that you are not using the python 3 libraries from the 
>>>>> tutorial.
>>>>>
>>>>> I would appreciate it if you could tell me which steps you took that 
>>>>> are not included in the tutorial in order for your code to work.
>>>>>
>>>>> Any other pointers would also be appreciated
>>>>>
>>>>> Thank in advance!
>>>>>
>>>>> On Wednesday, December 12, 2018 at 5:53:25 AM UTC+2, Louis De Lange 
>>>>> wrote:
>>>>>>
>>>>>> I recently came across a really excellent solution for putting 
>>>>>> together your own weather station on the cheap with high quality sensors 
>>>>>> - 
>>>>>> and most importantly a very useful weather HAT to use with a Raspberry 
>>>>>> PI 
>>>>>> to connect all the sensors.
>>>>>>
>>>>>> It comes complete with a 4 part step by step tutorial to assemble the 
>>>>>> whole station, and basic code to upload the data to and online service - 
>>>>>> see link below:
>>>>>>
>>>>>>
>>>>>> https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-1/
>>>>>>
>>>>>> I completed my own installation based on the instructions in the 
>>>>>> tutorial and my station running on weewx is active at the link below
>>>>>>
>>>>>> http://peachlandweather.ca/mystation/
>>>>>>
>>>>>> For the outdoor portion I used a Raspberry Pi Zero W, with the 
>>>>>> weather HAT.  Weewx is running indoors in a FreeBSD jail, using a stock 
>>>>>> Interceptor driver.  I modified the basic upload code provided in the 
>>>>>> tutorial quite extensively to generate upload loops that matched the 
>>>>>> Observer URLs supported by the Interceptor driver, and also to produce 
>>>>>> derived observations not included in the original code.
>>>>>>
>>>>>> The upload code is attached for anyone who might be interested in 
>>>>>> trying to assemble their own.
>>>>>>
>>>>>> I   tested the results from using the station against my Vantage Pro 
>>>>>> 2 and so far it seems to be pretty close - for less than 20% of the cost 
>>>>>> of 
>>>>>> a Vantage Pro.
>>>>>>
>>>>> -- 
>>>> You received this message because you are subscribed to a topic in the 
>>>> Google Groups "weewx-user" group.
>>>> To unsubscribe from this topic, visit 
>>>> https://groups.google.com/d/topic/weewx-user/udZCCCJlNE8/unsubscribe.
>>>> To unsubscribe from this group and all its topics, send an email to 
>>>> [email protected].
>>>> To view this discussion on the web visit 
>>>> https://groups.google.com/d/msgid/weewx-user/db1a607e-3fb0-4ed1-974e-0930406e7e6a%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/weewx-user/db1a607e-3fb0-4ed1-974e-0930406e7e6a%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>> -- 
>>
> 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].
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/weewx-user/3ddea820-bf91-44ff-9a93-90a3214241c3n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/weewx-user/3ddea820-bf91-44ff-9a93-90a3214241c3n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>
>
> -- 
> Peter Quinn
> (415)794-2264 <(415)%20794-2264>
>

-- 
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].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/weewx-user/95c558e3-8772-492e-a9e1-7fbdebf6dd97n%40googlegroups.com.
# Copyright 2019 David W. Enstrom, all rights reserved
# Distributed under the terms of the GNU Public License (GPLv3)
"""
Driver to collect data from the "Spark Fun" SEN-08942 RoHS
weather meters and the BC Robotics interface.
See:    https://www.sparkfun.com/products/8942 
        https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-1/
"""

import syslog
import threading
import time
import math

from w1thermsensor import W1ThermSensor
from Adafruit_BME280 import *
import Adafruit_ADS1x15
import RPi.GPIO as GPIO

import weewx.drivers
import weewx.units
import weewx.accum

DRIVER_NAME = 'BCRobotics'
DRIVER_VERSION = '1.0.24'

windTick = 0     # Count of the wind speed input trigger
rainTick = 0     # Count of the rain input trigger
interval = 3     # Set now to define scope of variable
rainTime = 0     # Use this to detect erroneous rain events
out_Temp = 0     # Set now to define scope for rain check

try:
     ds18b20 = W1ThermSensor()
except Exception as err:
     loginf('Error setting up Temperature Sensor %s' % err)
     TempSensor = False
else:
     TempSensor = True

bme = BME280(t_mode=BME280_OSAMPLE_8, p_mode=BME280_OSAMPLE_8, h_mode=BME280_OSAMPLE_8)
adc = Adafruit_ADS1x15.ADS1115()



def loader(config_dict, _):
    return BCRoboDriver(**config_dict[DRIVER_NAME])

def confeditor_loader():
    return BCRoboConfEditor()

class BCRoboConfEditor(weewx.drivers.AbstractConfEditor):
    @property
    def default_stanza(self):
        return """
[BCRobotics]
    # This section is for the "Spark Fun" SEN-08942 / BC Robotics weather stations.
    # See: https://www.sparkfun.com/products/8942
    #      https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-1/
    # The time (in seconds) between LOOP packets. Default is:
    loop_interval = 3
    # Driver mode - tcp, udp, or serial
    mode = serial
    # If serial, specify the serial port device. (ex. /dev/ttyS0, /dev/ttyUSB0,
    # or /dev/cuaU0)
    # If TCP, specify the IP address and port number. (ex. 192.168.36.25:3000)
    port = /dev/ttyS0
    # The amount of time, in seconds, before the connection fails if there is
    # no response
    timeout = 3
    # Debug level - the level of message logging. The higher
    # the number, the more info is logged.
    debug_read = 0
    # The driver to use:
    driver = user.BCRobotics
    
"""

# flags for enabling/disabling debug verbosity
DEBUG_COMM = 0
DEBUG_CONFIG_DATA = 0
DEBUG_WEATHER_DATA = 0
DEBUG_HISTORY_DATA = 0
DEBUG_DUMP_FORMAT = 'auto'


def logmsg(dst, msg):
    syslog.syslog(dst, 'BCRobo: %s: %s' %
                  (threading.currentThread().getName(), msg))
    
def logdbg(msg):
    logmsg(syslog.LOG_DEBUG, msg)


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


def logcrt(msg):
    logmsg(syslog.LOG_CRIT, msg)


def logerr(msg):
    logmsg(syslog.LOG_ERR, msg)


def logtee(msg):
    loginf(msg)
    print "%s\r" % msg


class BCRoboDriver(weewx.drivers.AbstractDevice):
    """weewx driver that communicates with a "Spark Fun" SEN-08942 / BC Robotics station
    mode - Communication mode - TCP, UDP, or Serial.
    [Required. Default is serial] 
    
    port - Serial port or network address.
    [Required. Default is /dev/ttyS0 for serial,
     and 192.168.36.25:3000 for TCP/IP]
    loop_interval - The time (in seconds) between LOOP packets.
    [Required. Default is loop_interval = 3]
    
    timeout - The amount of time, in seconds, before the connection fails if
    there is no response.
    [Optional. Default is 3]
    debug_read - The level of message logging. The higher this number, the more
    information is logged.
    [Optional. Default is 0]
    
    """
    def __init__(self, **stn_dict):
         
         loginf('Driver version is %s' % DRIVER_VERSION)
         global interval
         interval = int(stn_dict.get('loop_interval', 3))
         #loginf('Interval is %s' % interval)
         global rainTime
         rainTime = int(time.time())   # used to detect erronious rain ticks

         try:
              # Set GPIO pins to use BCM pin numbers
              GPIO.setmode(GPIO.BCM)
              
              # Set digital pin 17 to an input and enable the pullup (wind speed)
              GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)

              # Set digital pin 23 to an input and enable the pullup (rain)
              GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)

              # Define event to detect wind (4 ticks per revolution)
              #  1 tick/sec = 1.492 mph or 2.4 km/h
              #  So: wind = (windTick * 2.4) / loop_interval
              GPIO.add_event_detect(17, GPIO.BOTH)
              def windtrig(self):
                  global windTick
                  windTick += 1
                
              GPIO.add_event_callback(17, windtrig)

              # Define event to detect rain (0.2794mm per tick)
              # with a 1hr time period where the first tick is ignored
              # which is used to detect an improper single tick
              GPIO.add_event_detect(23, GPIO.FALLING)
              def raintrig(self):
                  global rainTick
                  global rainTime
                  global out_Temp
                  if out_Temp <= 0:    # can't rain in the winter
                      loginf('Bad rain tick')
                  else:
                      if int(time.time())-rainTime >= 3600:
                          loginf('Possible bad rain tick')
                          rainTime = int(time.time())
                      else:
                          rainTime = int(time.time())
                          rainTick += 1
              
              GPIO.add_event_callback(23, raintrig)
              
         except Exception as err:
               loginf('Error setting up GPIO: ' % err)
         else:
               loginf('GPIO setup fine.')

    @property
    def hardware_name(self):
        return "BCRobotics"
    
    def genLoopPackets(self):
        while True:
            packet = {'dateTime': int(time.time() + 0.0),
                      'usUnits': weewx.METRIC}
            readings = StationData.get_readings()
            packet.update(readings)
    #        self._augment_packet(packet)
            yield packet

    #def _augment_packet(self, packet):
    #    # calculate the rain delta from rain total
    #    if self.last_rain is not None:
    #        packet['rain'] = packet['rain_total'] - self.last_rain
    #    else:
    #        packet['rain'] = None
    #    self.last_rain = packet['rain_total']

# ======================================================================= #
#       StationData class - setup stn and get data from the device        #
# ======================================================================= #


class StationData():
    def __init__(self):
       # Initialize the setup and define ports
       last_rain = None
       global windTick
       global rainTick
       windTick = 0   # Count of the wind speed input trigger
       rainTick = 0   # Count of the rain input trigger



    @staticmethod
    def get_readings():
        """ The "Spark Fun" SEN-08942 / BC Robotics station emits data
         through a BME280 interface, a ds18b20 temperature sensor plus
         a ADS1015 Analog to Digital chip for the wind direction.
        https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-2/
        The following data is provided by the sensor hardware:
          windSpeed    - from total ticks (1 tick/sec = 2.4 km/h)
          windDir      - wind direction (0-255)
          out_Temp     - outdoor temperature (in Deg C)
          rain         - rain during the loop_interval (1 tick = 0.2794 mm)
          pressure     - pressure (in Pascals)
          case_temp    - hardware case temperature (in Deg C)
          out_humidity - outdoor humidity (calculated, see below)
          in_humidity  - humidity inside the case (+/-0.1 %)
          
        """
        #
        # Get the readings, define the data list, and fill it in from readings
        # NOTE: The pressure reading is 'pressure', not 'barometer'
        #

        #if global TempSensor
        # Get temperature from DS18B20 sensor in degrees_C
        global out_Temp
        out_Temp = ds18b20.get_temperature()
        
        # Get Temperature from BME280 in degrees_C
        case_temp = bme.read_temperature()
        
        # Get Barometric Pressure from BME280 in Pascals
        #   and convert to mbar
        #   100 pascal = 1 mbar, or 0.00029529983071445 inhg
        pressure = bme.read_pressure() / 100
        
        # Get Humidity (inside the case) from BME280 in %
        in_humidity = bme.read_humidity()
        
        # This humidity is measured inside the case, which is warmer than the 
        # ambient air. Therefore it is converted to external humidity based
        # upon the case_temp, in_humidity, pressure, and out_Temp. 
        # 
        # Use NOAA formulae:
        VapPress = (6.112 * math.exp(17.67 * case_temp / (case_temp + 243.5))) * (in_humidity/100)
        DewPoint = (243.5 * math.log(VapPress / 6.112))/(17.67 - math.log(VapPress / 6.112))
        absVapPress = 6.11 * math.pow(10, (7.5 * DewPoint / (237.7 + DewPoint)))
        actMixRatio = 621.97 * absVapPress / (pressure - absVapPress)
        
        # Adjust humidity reading to the outside temperature
        # using NOAA values:
        out_humidity = actMixRatio * 10 / (0.42 * math.exp(out_Temp * 0.06235394))
        if out_humidity > 100:
            out_humidity = 100.0

        # Calculate wind direction (angle) based on ADC reading
        #   Read ADC channel 0 with a gain of 1
        windDir = 1.5

        val = adc.read_adc(0, gain=1)

        if 19600 <= val <= 20999:
            windDir = 0

        if 9000 <= val <= 10799:
            windDir = 22.5

        if 10800 <= val <= 13999:
            windDir = 45

        if 2000 <= val <= 2299:
            windDir = 67.5

        if 2300 <= val <= 2999:
            windDir = 90

        if 1000 <= val <= 1999:
            windDir = 112.5

        if 4000 <= val <= 4999:
            windDir = 135

        if 3000 <= val <= 3999:
            windDir = 157.5

        if 6600 <= val <= 8999:
            windDir = 180

        if 5000 <= val <= 6599:
            windDir = 202.5

        if 15900 <= val <= 17499:
            windDir = 225

        if 14000 <= val <= 15899:
            windDir = 247.5

        if 24000 <= val <= 24999:
            windDir = 270

        if 21000 <= val <= 21999:
            windDir = 292.5

        if 22000 <= val <= 23999:
            windDir = 315

        if 17500 <= val <= 19599:
            windDir = 337.5

        if windDir == 1.5:
            value = str(val)
            loginf('Wind direction error: ' + value)


        # Calculate the average wind speed over this 'interval' (km/h)
        #  1 tick/sec = 1.492 mph or 2.4 km/h
        #  So: (windTick * 2.4) / loop_interval
        global windTick
        windSpeed = (windTick * 2.4) / interval
        windTick = 0

        # Calculate the rainfall over this 'interval' (cm)
        # 1 tick = 0.011 inches or 0.02794 cm 
        global rainTick
        rain = rainTick * 0.02794
        
        if rain > 0:
            raintxt = str(rain)
        #    loginf('Rain is falling: ' + raintxt)
            rainRate = (rain / interval) * 3600  # cm/h
            rainTick = 0
        else:
            rainRate = None
            rain = None 
            
        data = dict()
        data['windSpeed'] = windSpeed       # km/h
        data['windDir'] = windDir           # compass deg
        data['outTemp'] = out_Temp          # degree_C
        data['rain'] = rain                 # cm as per default
        data['rainRate'] = rainRate         # cm/hr
        data['pressure'] = pressure         # mbar
        data['inTemp'] = case_temp          # degree_C
        data['inHumidity'] = in_humidity    # percent
        data['outHumidity'] = out_humidity  # percent
        
        rain = 0
        rainRate = 0
        return data

    def __exit__(self, _, value, traceback):
        #self.close()
        return 

    def __enter__(self):
        #self.open()
        return self


# Define a main entry point for basic testing of the station without weewx
# engine and service overhead.  Invoke this as follows from the WeeWX root dir (i.e., /usr/bin/weewxd):
#
# sudo PYTHONPATH=/usr/share/weewx python /usr/share/weewx/user/BCRobotics.py
# 

if __name__ == '__main__':

    syslog.openlog('BCRobotics', syslog.LOG_PID | syslog.LOG_CONS)
    syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_DEBUG))
    
    with StationData() as s:
        #s.set_logger_mode()

        time.sleep(interval)
        while True:
            print time.time(), s.get_readings()

© 2021 GitHub, Inc.

Reply via email to