Augment weather station data with level of ionizing radiation

71 views
Skip to first unread message

anb...@gmail.com

unread,
Apr 5, 2021, 1:42:26 PM4/5/21
to weewx-user

Hello,

 I have idea to augment weather station data with level of ionizing radiation. Simple and inexpensive geiger counter model was chosen. Device is Radex One.
Primarily unit works with dedicated Windows software via USB port.
After some playing with serial port monitor is possible to send request and then receive response from device.
Below is sample response from dosimeter.

7AFF208016000A0000004480000800000C0000007103000004020000710300000DEF

Where bytes x000371 = 8,81uSv/h (dose rate), x000204 = 5,16 uSv (accumulated dose), x000371 = 881 CPS (counts per minute)

Is possible to fix phyton script below to adopt it for my device?

Need to say, program below is written to comunicate with same manufacuter device, but device purpose differs,  it measures radon gas concetration in air, also it measures temperature and humidity.
According data bytes is represented with IEEE754 format, but for my dosimeter is just simple  conversion from hex to dec and data string length is smaller (34 bytes vs 70 bytes from radon meter)

import serial
import struct

ser = serial.Serial(
    port='/dev/ttyACM0',
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)

ser.isOpen()
packet = bytearray(b'x7bxffx20x00x06x00x83x04x00x00xdaxfbx04x08x0cx00xefxf7')
ser.write(packet)

raw_temp = ""
raw_hum = ""
raw_rad2 = ""
raw_rad3 = ""

exp_timer = 0;

for x in range(0, 70):
    c = ser.read()
    print '{0:x}'.format(ord(c), 10), " ",

    if x in range(28, 32):
       raw_rad3 = raw_rad3 + c
    if x in range(32, 36):
       raw_temp = raw_temp + c
    if x in range(36, 40):
       raw_hum = raw_hum + c
    if x in range(56, 60):
       raw_rad2 = raw_rad2 + c
    if x == 64:
       exp_timer = ord(c);
    if x == 65:
       exp_timer = ord(c) * 256 + exp_timer;

print ""
[temperature] = struct.unpack('f', raw_temp)
print "Temperature: " + str(temperature)
[humidity] = struct.unpack('f', raw_hum)
print "Humidity: " + str(humidity)
[radoncur] = struct.unpack('f', raw_rad3)
print "Radon Cur: " + str(radoncur)
[radonmax] = struct.unpack('f', raw_rad2)
print "Radon Max: " + str(radonmax)
print "Exposure countdown: " + str(exp_timer)



Thanks

Andrej


anb...@gmail.com

unread,
Apr 24, 2021, 6:04:41 AM4/24/21
to weewx-user
Dear community,

Need some help regarding geiger counter integration for Weewx.
Below is code which works fine and give output to console.
Routine is pretty simple -serial port initialization, sending special hex string to device, then decoding some bytes range in hex string answer. Code is below.

import serial
import struct

ser = serial.Serial(
    port='/dev/ttyUSB0',

    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)

ser.isOpen()
packet = bytearray(b'\x7b\xff\x20\x00\x06\x00\x0a\x00\x00\x00\x54\x00\x00\x08\x0c\x00\xf3\xf7')
ser.write(packet)

raw_rate = ""
raw_cpm =  ""

for x in range(0, 34):
        c = ser.read()
#       print '{0:x}'.format(ord(c), 10), " ",

        if x in range(20, 22):
                raw_rate = raw_rate + c
        if x in range(28, 30):
                raw_cpm = raw_cpm + c

print ""
[doserate] = struct.unpack('<h', raw_rate)
print "Dose rate uSv/h: " + str(doserate / 100.0)
[cpm] = struct.unpack('<h', raw_cpm)
print "Counts per minute: " + str(cpm)




Console output is like this:

Dose rate uSv/h: 0.16
Counts per minute: 24

But I stuck when creating proper data service for weewx.

import struct
import serial
import syslog
import weewx
import weewx.manager
from weewx.wxengine import StdService

ser = serial.Serial(
    port='/dev/ttyUSB0',

    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)


VERSION = "0.6"

if weewx.__version__ < "3.2":
    raise weewx.UnsupportedFeature("weewx 3 is required, found %s" %
                                   weewx.__version__)

schema = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
          ('usUnits', 'INTEGER NOT NULL'),
          ('interval', 'INTEGER NOT NULL'),
          ('DRate', 'REAL'),
          ('Counter', 'INTEGER')]


def get_default_binding_dict():
    return {'database': 'radex',
            'manager': 'weewx.manager.Manager',
            'table_name': 'archive',
            'schema': 'user.radex.schema'}


def logmsg(level, msg):
    syslog.syslog(level, 'radex: %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 Radexwx(StdService):

    def __init__(self, engine, config_dict):
        # call our parent's initialisation
        super(Radexwx, self).__init__(engine, config_dict)

        loginf("service version is %s" % VERSION)
        # get the database binding to use
        data_binding = svc_dict.get('data_binding', None)
        loginf("data_binding=%s" % data_binding)
        # obtain a database manager from our binding
        self.dbm = self.engine.db_binder.get_manager(data_binding=data_binding,
                                                     initialize=True)
        # be sure schema in database matches the schema we have
        if self.dbm:
            # get the columns in our archive table
            dbcol = self.dbm.connection.columnsOf(self.dbm.table_name)
            # get a database manager dict
            dbm_dict = weewx.manager.get_manager_dict(config_dict['DataBindings'],
                                                      config_dict['Databases'],
                                                      data_binding,
                                                      default_binding_dict=get_default_binding_dict())
            # get a list of the columns from the database manager dict
            memcol = [x[0] for x in dbm_dict['schema']]
            # if the two don't match raise an exception
            if dbcol != memcol:
                raise Exception('radex: schema mismatch: %s != %s' % (dbcol, memcol))

        # bind ourself to the NEW_ARCHIVE_RECORD event
        self.bind(weewx.NEW_ARCHIVE_RECORD, self.new_archive_record)

    def new_archive_record(self, event):
        # read Radex data
        self.read_data(event)
        # save the Radex data to our database
        self.dbm.addRecord(event.record)

    def read_data(self, event):
        """read Radex data and augment the archive record"""

        # initialise a dict to hold our data
        data = {}
    try:
        ser.isOpen()
        packet = bytearray(b'\x7b\xff\x20\x00\x06\x00\x0a\x00\x00\x00\x54\x00\x00\x08\x0c\x00\xf3\xf7')
        ser.write(packet)
        raw_rate = ""
        raw_cps =  ""
    for x in range(0, 34):
            c = ser.read()
    if x in range(20, 22):
                raw_rate = raw_rate + c
        if x in range(28, 30):
                raw_cpm = raw_cpm + c
    print ""
    [doserate] = struct.unpack('<h', raw_rate)
        except TypeError:
            doserate = None
        data['DRate'] = + str(doserate / 100.0)
    [cpm] = struct.unpack('<h', raw_cpm)
    except TypeError:
            cpm = None
    data['Counter'] = + str(cpm)
        # now augment the event record with our data
        event.record.update(data)

    def shutDown(self):



Got Invalid Syntax for function for x in range(0, 34):

Big Thanks!
Reply all
Reply to author
Forward
0 new messages