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.

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.


# -*- 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 =



# 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(








    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:


                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) = \


                            + str(os.getpid())

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

                            + pir_id + “‘”, ‘GET’)


                debounce = False



                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) = \


                                    + 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’)




                    if GPIO.input(pir_no):

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

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

                        (resp, content) = \


                                       + 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) = \


                                       + 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) = \


                                       + 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))



                        (resp, content) = \


                                       + 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(‘’, ‘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) = \


                                           + lightoff

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


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


                        debounce = True



                print (” + pir_id)

                (resp, content) = \


                + ” shut down”

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

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



    print (” + pir_id)

    (resp, content) = \


    + ” shut down”

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

    + pir_id + “‘”, ‘GET’)



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(“”, “GET”)

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

for myvars in process_values:

    if myvars > “”:

        tmpvars = myvars.split(“,”)


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

        p = Process(target=pirthread,







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

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

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



    for Process in process_list:


    for Process
in process_list:


except (KeyboardInterrupt,

    for Process in process_list:


    mcp.gpioa.valuemcp.gpioa.value & 227


    print (”’


 Started PIR daemons