Zero clearance USB adapter

On the time lapse camera, there was too much complexity in connecting the USB data lines from the female USB on the camera case to the USB data lines of the Raspberry Pi so I fashioned what I call a zero clearance USB adapter

that is inserted into the center lower USB connection on the back of the  Raspberry Pi and the four pin header then connects to the female USB on the camera case.  The 5 VDC lines from the female USB on the camera case is run directly to the  Pi-EzConnect board  

eliminating the acrylic sheet also gained some room on top of the Pi-EzConnect board   for the future  addition of the pan/tilt stepper motor controls.

To make the adapter I cut a rectangular opening, exactly the size of a male USB A, in some .1 proto-board and placed a male USB connector through the opening and put the connector into one of the female USB connectors.  Then I scratched a line on the same face of the USB connector as the plastic separator and on the outer side of the proto-board.  I cut the metal shield just a bit on the inside of the line so the metal housing does not contact my connections.  I reinserted the male USB into the female and on the outer side of the USB I soldered a wire between the two sides and the uncut face of the USB and the proto-board on the side away from the female connector.  This secures the metal housing to the proto-board.  Then I cut away the rest of the metal housing of the USB above the solder joint.  I added the 4 pin header then as it is easier than waiting till the rest of the USB is exposed.  The plastic insulator of the USB was carefully trimmed away to expose the metal of the USB connector.  The four leads of the USB were soldered to the 4 pin header with wires placed as low on the USB as possible.  The rest of the insulator and leads on the USB were cut away and a  plastic film cover laid over it all to insulate it.

Now the USB can be inserted and connected and still clear the back of the fake camera housing.

Raspicam Time Lapse

Our new home is being built and I wanted to create a time lapse video of the construction.

It’s outside and required an outside enclosure. So we ordered a dummy bullet camera case to hold the Raspberry Pi computer.

24 hour video with a night time IR flood light requires an IR shutter for proper daytime color. Solved with a Raspicam compatable camera with a “motorized” IR-Cut. Not sure if motorized is a good translation but it means the IR-Cut filter can be switched in and out via software.

Unboxing the dummy bullet camera case presented some pleasant surprises.

In the rear cover is a dummy connector housing with a fake cord.  remove the fake cord and the opening has the same shape and is just a tiny bit larger than a female USB A connector. This was perfect as the camera needs 5VDC power and a hard disk attached and the case is too narrow to fit a micro USB and the female USB A will supply 5VDC to the RPi It will also feed USB signals to the RPi.

The center piece bottom has small vertical braces on the sides that are conveniently the same width apart as a Raspberry Pi 3 B+ and one can rest nicely on the curved bottom. The back of the case neatly covers the ethernet and USB ports maintaining water resistance.

 

The front of the case has a dummy IR array that is replaced by a 36 LED IR illuminator .  Replacing the existing fake LEDs is accomplished by cutting the fake LEDs off of the front mounting plate. The standard 36 LED array is just a bit larger than the housing and needs to be trimmed slightly to fit inside the front housing.

The Arducam camera module fits conveniently on the inside of the front mounting plate and the attached lens and shutter place the lens at exactly the place the dummy lens sat.

The IR LED array replacing the dummy requires 12VDC and a boost converter fits well at the bottom of the case where the camera mount is located. 

The USB size opening on the back was almost completely sealed but it was simple to cut the back of the connector opening. The USB A female connector was attached to some .1 in center perforated proto-board and a header added to mate to a connector on another small proto-board that the boost converter was mounted on. A couple of wraps of vinyl electrical tape made the USB connector fit tightly in the connector opening however there was a 4mm gap on the narrow side so 2ea 2mm plastic spacers were added to shim out the USB to completely fill the opening .

 

 

To make the camera easily maintainable some clear acrylic sheet cut to the exact size of the Raspberry Pi was used. On the boost board another USB female vertical mount connector was added. It was just the right height to fit under the acrylic sheet.An opening was cut in the acrylic sheet to fit a matching male connector. A roto tool was used to cut a male A USB connector so when it is mated to the female USB, it is flush with the Rpi side of the board.

[EDIT] I may eliminated the USB to USB on the acrylic sheet and moved the connection to the back USBs with a cut male A USB connector mating to the standard USB input on a zero clearance board (see next blog).

With a lot of care, the male USB can be cut with a roto tool such that the leads from the connector are not cut off but folded over and connected to wires.

The Pi generates heat and a fan is needed to cool it. The fan is a MakerFocus 2pcs Raspberry Pi DC Brushless Cooling FanThe 5VDC from the USB needs to be connected to the Pi. However the case has a battery compartment that limits the height allowed on a HAT board. A perfect solution was to use an unpopulated Pi-EzConnect board. The rear side of the board is mostly ground and can be trimmed to fit the fan and still have room for stepper motor drivers for when the camera becomes a streaming security cam. 

The Pi-EzConnect board has another big advantage because it has a fuse in the 5VDC line. The power from the USB is fed to the board’s 5VDC line which bypasses the Raspberry Pi’s fuse. Now with the Pi-EzConnect board the Pi is fused. Note that due to the height restriction due to the battery compartment, the connector for 5VDC is on the bottom of the board. It just clears the components on the Pi.

As this project is wrapped up, the USB will connect to a hard disk in a separate housing. Another blog will complete the assembly and show the code for 12 hour recordings with 1 second frames.

I2C 12 bit binary counter

While building my weather station, I needed to count the output of a Hall effect device in the anemometer and in the tipping bucket rain gauge.
Everything is on the I2C bus and I could not find an I2C binary counter and didn’t want the complexity of another processor and program just to count pulses.

This board I have designed uses two 74LS590 counters in series.  These 8 bit counters have a buffered output stored by an input and a clear counters  input.  They count on a positive going pulse*.  When the first counter in the series of two rolls over at 256 it triggers the second to count one.  The buffered outputs of these two chips are read by an MCP23017 GPIO expander.  Only four of the count buffer outputs from the second 74LS590 are used leaving four GPIOO from the MCP23017.  These are used one each for the CLR pins and the RCK (store buffer) pins, one to enable an LED so the count pulse can be seen and one left open. *The Hall effect sensor out is pulled high by a 1oK resistor and the LED count circuit. When the Hall Effect is triggered, it pulls the count low and when it inactivates again the input is again pulled high and the counter increments.   On the board I designed, I included two QWIIC connectors for daisy-chaining I2C devices and a more common 4 pin .1 centers connection point.  There are three address jumpers on the board bottom,

The eagle files for the board can be downloaded from http:/hiddenridge.net/download/I2C_Counter.zip

The BOM for the board can be downloaded from http:/hiddenridge.net/download/oneboard.html

The correct board files are now on OSH Park
I had my boards made by OSH park I intend on writing a post about this experience. Bottom line, I love OSH Park,
I wrote a Python object that sets up and read/writes the  MCP23017 counter.  Below is my the object file:

The code is available on Git Hub https://github.com/Doug-Wyman/I2C-12-bit-binary-counter

Below this code is the code I use to read my anemometer.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  mcpcounter.py
#  
#  Copyright 2018 Doug Wyman <doug@stretchmain>
#  
#  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 2 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, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#  
# 
import smbus

class counter():
    def __init__(self,busnum, deviceaddr, **kwargs):
        if busnum is None:
            self.busnum = int(1)
        else:
            self.busnum = busnum
        if deviceaddr is None:
            self.deviceaddr = int(0x20)
        else:
            self.deviceaddr = deviceaddr
        chip = smbus.SMBus(int(self.busnum))
        chip.write_word_data(int(self.deviceaddr), 0x00, 4095) #set the first 12 bits to inputs 
        self.i2c = chip
        self.i2c.write_byte_data(int(self.deviceaddr), 19, 208) # Set the LED on, NOT reset, and enable count 
        self.isready = 'I am ready'
    def getcount(self):
        tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting
        mask1 = tmp & 176
        mask2 = tmp & 240
        self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1))
        self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask2))
        return self.i2c.read_word_data(int(self.deviceaddr), 18) & 4095
        
    def resetcount(self):
        tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting
        mask1 = tmp & 112
        mask2 = tmp & 240
        self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1))
        self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask2))
        return self.i2c.read_word_data(int(self.deviceaddr), 18) & 4095
        
    def LEDon(self):
        tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting
        mask1 = tmp | 16
        self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1))
        return "Set Pin High"

    def LEDoff(self):
        tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting
        mask1 = tmp & 224
        self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1))
        return "Set Pin Low"
        
    def AUXon(self):
        tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting
        mask1 = tmp | 32
        self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1))
        return "Set Pin High"

    def AUXoff(self):
        tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting
        mask1 = tmp & 208
        self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1))
        return "Set Pin Low"

print("loaded device")

 

Anemometer Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import mcp_i2c
from time import sleep
import time
import datetime
import sys
import mysql.connector

if len(sys.argv) > 1:
    deviceaddr = sys.argv[1]
else:
    deviceaddr = 0x27
print (deviceaddr)
WindCount = mcp_i2c.counter(1,int(deviceaddr))
WindCount.resetcount() 
LastCount= int(0)
Last24 = [int(0)] * 24



for num in range(1,25):
    RegisterLong = WindCount.getcount()
    if LastCount <= RegisterLong:
        Last24.append(RegisterLong-LastCount)
        print(RegisterLong-LastCount)
    elif LastCount > RegisterLong:
        Last24.append((int(4096) -LastCount) + RegisterLong)
        print((int(4096) -LastCount) + RegisterLong)
    LastCount = RegisterLong
    Last24.pop(0)
    sleep(1.9)
    
#print("INSERT INTO `WindSpeed`(`datetime`, `twosec`) VALUES ( NOW() , '" + str(Last24).strip('[]') + "')")
try:
	cnx = mysql.connector.connect(user='Weather', password='iamweather',
							  host='192.168.0.11',
							  database='Weather')
	#query = "INSERT INTO WindSpeed (`datetime`, `twosec`) VALUES ( NOW() , '" + str(Last24).strip('[]') + "')"
	query = "INSERT INTO anemometer (`datetime`, `01`, `02`, `03`, `04`, `05`, `06`, `07`, `08`, `09`, `10`, `11`, `12`, `13`, `14`, `15`, `16`, `17`, `18`, `19`, `20`, `21`, `22`, `23`, `24` ) VALUES ( NOW() , " + str(Last24).strip('[]') + ")"
	print(query)
	cursor = cnx.cursor()
	cursor.execute(query)
	cnx.commit()
	cursor.close()
	cnx.close()
	print ("updated db WX")
except Exception as e: 
	print(e)
	print ("Error Updating WxDB")
	pass
try:
	cnx = mysql.connector.connect(user='Weather', password='iamweather',
							  host='192.168.0.158',
							  database='weather')
	#query = "INSERT INTO WindSpeed (`datetime`, `twosec`) VALUES ( NOW() , '" + str(Last24).strip('[]') + "')"
	query = "INSERT INTO anemometer (`datetime`, `01`, `02`, `03`, `04`, `05`, `06`, `07`, `08`, `09`, `10`, `11`, `12`, `13`, `14`, `15`, `16`, `17`, `18`, `19`, `20`, `21`, `22`, `23`, `24` ) VALUES ( NOW() , " + str(Last24).strip('[]') + ")"
	print(query)
	cursor = cnx.cursor()
	cursor.execute(query)
	cnx.commit()
	cursor.close()
	cnx.close()
	print ("updated db 158")
except Exception as e: 
	print(e)
	print ("Error Updating 158")
	pass

Put your Pi in a pipe but don’t smoke it.

Earlier this year someone asked on Google+ what to make for a science project.  A number of us suggested a weather station.  That set me off on a project.  I had been playing with temperature sensors and had played with the DHT-22 and the TI HDC1000EVM.  I exposed most everything to the harsh mountain climate and even after damaging a couple of them, I settled on the BME-280.

But now the project would be to build a nice looking and fully functional weather station.  Understand from the start that this project wasn’t to just build it but to learn.  After all many of the components can be purchased and modified for less that the cost of building one from scratch.  Although the image above is of the first prototype, you can still see the Pi in the pipe. Project Video at  https://youtu.be/UXCIHt9ciaI

 

 

Don’t let micro USB connectors impact the ground

Just knocked my weather computer mock-up to the ground!

Oh dang!  The damn thing hit on the power connector.
Off to the work table we go.
The 5V power feeds to my PiZ-Uptime UPS which I treasure.
Sure enough, the USB micro SMD female connector has been knocked to one side
and the SMD from the USD are hanging.
Arghhh…  Well I’ll just unsolder the battery holder and realign the pins and resolder.

Done! now to reinstall the battery holder
let’s see…  Positive end is that one with the
fragment of a pad and a bit of trace that I have torn from the board.
“Hello Amazon I need to….

Test of the PiZ-Uptime

This is a test of the PiZ-Uptime UPS.

Some time ago I posted on Google+ that I liked the PiZ-UpTime UPS for the Raspberry Pi Zero manufactured by Alchemy Power.  It was suggested in comments that I report on the battery up time.  How long will it keep the Pi Zero up with power disconnected.  A very reasonable request.

 

For the test I ran Raspbian Jessie Lite loaded with the lighttpd web server and PHP5.  The PiZero averaged an hour and a half without power.  I tested the time by having another computer run a simple Python program that recorded the test start time and sent four ping requests to the PiZero every 10 seconds.  If the PiZero failed to answer more than two of the pings the test stopped and recorded the stop time.  The PiZ-UpTime also provides another USB jack but I did no testing of the USB.

 

At the top is an image of the PiZ-UpTime mounted on my PiZero.  It will be used as a weather recorder. So on top I placed a proto-board to connect the I2C BME-280 sensor to record temperature, humidity and barometric pressure. The engineer who designed the UPS supplied a board.  To clear the battery I used an extra tall header.

 

When the PiZ-UpTime is charging the battery rather bright green and blue LEDs are lit. The nice thing is they can be blanked by removing a standard jumper.  I intend on replacing the jumper with a small push button so I can check the device.When the  battery is fully charged, the blue LED is turned off and an amber led between the red and green ones lights.  One feature I really like is a small momentary push button on the board which powers off (resets) the PiZero.  This is especially useful when removing and replacing the SMB card.  Just hold it in when removing or replacing the card and the SMB card is not likely to get scrambled as it easily can when it is removed with the PiZero under power.  The PiZ-UpTime will extinguish the bright LEDs when external power is lost, saving valuable battery life.  When the battery gets down to a limit, the PiZ-UpTime shuts down the PiZero nicely.  Alchemy Power makes the code for shutdown available. During tests it never once corrupted the SMB card.

 

As I stated in the original Google+ posting, I really like this.  When I wrote that I was living on Tiger Mountain in the Issaquah alps and power was rather erratic.

 

I will still use the UPS because it makes it so easy to take the PiZero and unplug it to move it to another location.  I will be looking at the maker’s other products.  Especially the PiUptimeUPS which claims up to ten hours of battery life.  It would be nice to be able to carry one of my Raspberry Pi model 3s around on a belt device with a GPS recording…  Heck they are only sixty bucks.

Thermal mass and the TI HDC1000EVM

Thermal mass:

The thermal mass of the TI HDC1000EVM is very low which is excellent for instantaneous temperature or fine resolution

temperature sensing.  However you may want a more moderated response.  In graphing my sensors over time the TI HDC1000EVM

was wildly erratic but it is mounted outside and the low thermal mass means the sensor reacts to the momentary temperature.  If a

breeze blows it will change the temperature to reflect the instantaneous temperature and not the average temperature.

Since I wanted a nice smoothed graph of outside temperature I added thermal mass by putting some modeling clay around the sensor.

What ever you use it has to be non-conductive of course.  Now I get a nice smooth graph of outside temperatures.

Python Sunrise and Sunset

My page on PIR  sensing and the coop mentioned needing to have the PIRs on only after sundown.
The Raspberry Pi’s controlling code for the PIR units is written in Python.
After tying a few methods, I found Astral and the companion time zone
calculation in PYTZ.
Caveat. If the computer does not reset at midnight as mine does,
the code saved sunrisa and sunset will be a day behind and since the current
day’s sunrise and sunset are later than yesterday’s. the PIRs will be active.
A code change has been added to check this
I have added my own latitude and longitude. Seattle is close enough I would not have to do so
but I tend to be a bit anal when it comes to exact locations.
What follows is the Python code with the added Sunrise and Sunset calculations.

#!/usr/bin/python

# -*- coding: utf-8 -*-

 

from multiprocessing
import Process

import RPi.GPIO as GPIO

import httplib2

import pifacecommon.mcp23s17 as p

import os

import time

import datetime

import pytz

from astral import Astral

a =
Astral()

 

 

# This program reads PIR sensors and turns on or off a relay or relays depending on the

# values in the table.

# ==========NOTE!!!  The relays this set controls are inverse logic.

# ===================i.e. an inactive output (high) on piface turns the relay on

# =================== and an active low turns it off.  This is all dependant on the

# =================== relay board common negative being pulled low by an active

# =================== piface output on the relay board common negative.

# =================== thus on boot the relays are not activated.  Until a low is presented

# =================== to the relay board common.  Then any relay that does not have an active

# =================== piface output (low) is turned on so the board needs to be activated by

# =================== setting the common negative and both relay controls low at the same time.

# =================== print(“Setting Up”)

# =================== mcp.gpioa.value = mcp.gpioa.value | 28

# =================== print(“Activated GPIO binary 4,8 & 16”)

 

def pirthread(

    id,

    pir,

    no,

    andval,

    orval,

    ):

 

    pir_id = id

    pir_no = int(no)

    pir_high = int(andval) & 0xff

    pir_low = int(orval) & 0xff

    lighton = pir + ‘_Light_On

    lightoff = pir + ‘_Light_Off

    debounce = False

    h = httplib2.Http()

    ##############set up times

    city = a[‘Seattle’]

    city_name = ‘Tiger Mountain’

    print(‘Information for %s/%s\n’ % (city_name, city.region))

    timezone = city.timezone

    print(Timezone: %s’ % timezone)

    mylocal = pytz.timezone(timezone)

    city.latitude = 47.473436

    city.longitude = -122.015253

    sun = city.sun(date=datetime.date.today(), local=True)

    mysunset = sun[‘sunset’]

    mysunrise = sun[‘sunrise’]

    ########### now I can check if it is daylight out

    print(“my pid is “ + str(os.getpid()))

    while True:

            try:

                if not(debounce):

                    print(pir_id + ‘ waiting for input ‘ + str(pir_no) \

                        + ‘ at ‘ + str(time.strftime(‘%H:%M:%S’)))

 

                    # print(str(pir_no) + ” is ” + str(GPIO.input(pir_no)))

                (resp, content) = \

                        h.request(“http://192.168.0.159/wd-db.php?sqlcmd=UPDATE%20WD_Master%20SET%20Action_Formula%20=%20′”

                            + str(os.getpid())

                            + “‘%20WHERE%20Equipment=%20’Coop_RPI’%20and%20System%20%20=%20′”

                            + pir_id + “‘”, ‘GET’)

 

                debounce = False

                GPIO.wait_for_edge(pir_noGPIO.RISING)

                time.sleep(.2)

                mynow = datetime.datetime.now(mylocal)

# added code to check to insure we are on the same day

                if mynow.day != mysunset.day:

                    sun = city.sun(date=datetime.date.today(), local=True)

                    mysunset = sun[‘sunset’]

                    mysunrise = sun[‘sunrise’]

                if (mynow > mysunrise) and (mynow < mysunset):

                    print(“Its daylight”)

                    mydiff = mysunsetmynow

                    (resp, content) = \

                        h.request(“http://192.168.0.159/wd-db.php?sqlcmd=UPDATE%20WD_Master%20SET%20Char_Value%20=%20′”

                                    + id

                                    + “%20Sleeping%20till%20sunset’,Last_Active%20=%20NOW()%20,Active%20=%20’0’%20WHERE%20Equipment=%20’Coop_RPI’%20and%20System%20%20=%20′”

                                    + pir_id + “‘”, ‘GET’)

                     print(mydiff.seconds)

                    time.sleep(mydiff.seconds)

                else:

                    if GPIO.input(pir_no):

                        print (pir_id + ‘ setting output ‘ + str(pir_no) + ‘ high’)

                        mcp.gpioa.value = mcp.gpioa.value & pir_high

                        (resp, content) = \

                            h.request(“http://192.168.0.159/wd-db.php?sqlcmd=UPDATE%20WD_Master%20SET%20Char_Value%20=%20′”

                                       + id

                                      + “%20Active’,Last_Active%20=%20NOW()%20,Active%20=%20’1’%20WHERE%20Equipment=%20’Coop_RPI’%20and%20System%20%20=%20′”

                                       + pir_id + “‘”, ‘GET’)

                        (resp, content) = \

                            h.request(“http://192.168.0.159/wd-db.php?sqlcmd=UPDATE%20WD_Master%20SET%20Char_Value%20=%20′”

                                       + lighton

                                      + “‘,Last_Active%20=%20NOW()%20,LastCheck%20=%20NOW()%20WHERE%20Equipment=%20’Coop_RPI’%20and%20System%20%20=%20’Coop_Outside_Lights'”  , ‘GET’)

                        (resp, content) = \

                            h.request(“http://192.168.0.159/wd-db.php?sqlcmd=INSERT%20INTO%20`pir_alarms`(`pir`,%20`alarm`)%20VALUES%20(‘”

                                       + lighton + “‘,%20NOW())”‘GET’)

                        print (lighton)

 

        #                with open(“/var/log/pir_log“, “a”) as f:

        #                    f.writestr(time.strftime(“%m-%d%H:%M:%S”)) + ” – ” + pir_id + chr(13) + chr(10))

 

                        time.sleep(300)

                        (resp, content) = \

                            h.request(“http://192.168.0.159/wd-db.php?sqlcmd=UPDATE%20WD_Master%20SET%20Char_Value%20=%20′”

                                       + id

                                      + “%20Clear’,Last_Inactive%20=%20NOW()%20,Active%20=%20’0’%20WHERE%20Equipment=%20’Coop_RPI’%20and%20System%20%20=%20′”

                                       + pir_id + “‘”, ‘GET’)

                        (resp, content) = \

                            h.request(‘http://192.168.0.159/getlight.php’, ‘GET’)

                        print (content.decode())

                        if  (content.decode() == lighton):

                            print (“Match”)

                            print (pir_id + ‘ setting output ‘ + str(pir_no) \

                                + ‘ low’)

                            mcp.gpioa.value = mcp.gpioa.value | pir_low

                            (resp, content) = \

                                h.request(“http://192.168.0.159/wd-db.php?sqlcmd=UPDATE%20WD_Master%20SET%20Char_Value%20=%20′”

                                           + lightoff

                                          + “‘,Last_Inactive%20=%20NOW()%20,LastCheck%20=%20NOW()%20WHERE%20Equipment=%20’Coop_RPI’%20and%20System%20%20=%20’Coop_Outside_Lights'” )

                        else:

                            print (content.decode() + “<>” + lighton)

                    else:

                        debounce = True

                GPIO.remove_event_detect(pir_no)

            except:

                print (” + pir_id)

                (resp, content) = \

                h.request(“http://192.168.0.159/wd-db.php?sqlcmd=UPDATE%20WD_Master%20SET%20Action_Formula%20=%20′”

                + ” shut down”

                + “‘%20WHERE%20Equipment=%20’Coop_RPI’%20and%20System%20%20=%20′”

                + p ir_id + “‘”, ‘GET’)

                GPIO.cleanup()

                break

    print (” + pir_id)

    (resp, content) = \

    h.request(“http://192.168.0.159/wd-db.php?sqlcmd=UPDATE%20WD_Master%20SET%20Action_Formula%20=%20′”

    + ” shut down”

    + “‘%20WHERE%20Equipment=%20’Coop_RPI’%20and%20System%20%20=%20′”

    + pir_id + “‘”, ‘GET’)

    GPIO.cleanup()

 

mcp = p.MCP23S17()

h = httplib2.Http()

print(“Setting Up”)

mcp.gpioa.value = mcp.gpioa.value | 28

print(“Activated GPIO binary 4,8 & 16”)

process_list = []

(resp, content) = h.request(“http://192.168.0.159/pir-threads.php”, “GET”)

process_values = content.decode().split(“|”)

for myvars in process_values:

    if myvars > “”:

        tmpvars = myvars.split(“,”)

        GPIO.setmode(GPIO.BCM)

        GPIO.setup(int(tmpvars[2].strip()), GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

        p = Process(target=pirthread,

              args=(tmpvars[0].strip(), 

             tmpvars[1].split()[0].strip(), 

             tmpvars[2].strip(),

             tmpvars[3].strip(),

             tmpvars[4].strip()))

        process_list.append(p)

        # print(tmpvars[0].strip())

        # print(tmpvars[1].split()[0].strip())

        # print(tmpvars[2].strip())

 

try:

    for Process in process_list:

        Process.start()

    for Process
in process_list:

        Process.join()

except (KeyboardInterrupt,
SystemExit):

    for Process in process_list:

        Process.terminate()

    mcp.gpioa.valuemcp.gpioa.value & 227

    GPIO.cleanup()

    print (”’

 

 Started PIR daemons

 

”’)