Huge struggle with Google Assistant

 Google Assistant

I really like this thing, it’s a Raspberry Pi 3B+, with a Google AIY Voice HAT, and a nifty acrylic case instead of the original cardboard one.


I’ve had it for a while though, and it was still running Raspbian Jessie. Nothing wrong with that, but there are new versions of the AIY Voice software, that can do more things than the original software. I’d rather like my other Raspberry Pi systems to be able to use it as a voice input and output, for example. To do that requires Raspbian Buster…

So that I wouldn’t lose all the setup information on the Micro SD card, I decided to upgrade in place. Bad idea!


The upgrade, two steps, via Raspbian Stretch, takes hours. Stretch booted OK, though, so I continued. Buster wouldn’t boot up…

All that took over half a day, and it didn’t work.

After a bit of head scratching, and a certain amount of exercising my extensive vocabulary of rude words, I did what anyone sensible would have done in the first place, and downloaded a ready-made image, from GitHub and flashed the micro SD card with Balena Etcher.

I had saved copies of the setup information files handy, which I copied in with WinSCP (freeware that’s so great I paid for it!), rebooted the Pi, and suddenly it worked!

The Nebra Anybeam HAT

 Is the Nebra AnyBeam “HAT” a secret?

I ask, because I have still seen no reviews at all of this fine thing in any of the magazines, or online. Here’s mine. The paint on the study wall is not an ideal screen, and there’s too much ambient light, but still..
 
I’ve put HAT in quotes, because this is technically not a HAT, as it doesn’t have the usual ROM for the Pi to recognise it by.
 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
I used a Pibow case from Pimoroni to house it, with some extension pieces to raise the top high enough, and a Lego compatible base, in case I want to build it into anything made from Technic pieces at some point. The case made the Pi 3B run hot, so I added a few spacers and a heat sink, and it currently runs at about 63°C when nothing is happening.
 
Still trying to think of a list of things it can do…

Scrolling text on a UnicornHatHD

Scrolling text on UnicornHatHD


I wanted scrolling text on the UnicornHatHD which has a 16×16 LED array, and could only find a program that would do it on the old UnicornHat with its 8×8 array. 

https://github.com/topshed/UnicornHatScroll

If you change a couple of lines in UHScroll.py, it works on the UnicornHatHD.

Change the definition of flip to:-

flip = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]

and change the start of show_letter() to:-

def show_letter(letter,colour,brightness): 

    UH.rotation(0)        

    for i in range(16):

        for j in range(8):

That’s all you need to scroll text on the top 8 rows of LEDs. It should be fairly easy to use the lower 8 rows as well…

Useful? 

#RaspberryPi #Pimoroni #UnicornHatHD

Raspberry Pi motion detection and notification program

PiDoorCam updated

This is the amended, latest version of my Raspberry Pi program to watch the street outside, detect change, and send a picture to another computer for storage, and to my phone. I’m often in the back garden, and can’t hear the doorbell; missing deliveries is rather annoying!

It no longer tries to take pictures when it’s dark, not just because I don’t have an infra-red camera and infra-red floodlights, but mainly because the street light outside flashes on and off all night, and I don’t want hundreds of pictures of that!

You’ll need to set up a Pushover account, which is free provided you don’t send too many notifications, and a Ramdisk with a directory called /var/tmp on the Pi.

Program listing

# Program for PiDoorCam

# Detects motion, and when it spots some, takes a high resolution
# picture, and sends the picture to another computer, also
# a notification via Pushover, to my phone.

import io
import os
import picamera
import ftplib
import time
import datetime
from PIL import Image
import requests
import json
import schedule

camera = picamera.PiCamera()
picamera.PiCamera.CAPTURE_TIMEOUT = 30

# If we detect 100 pixels that changed by 30, we have seen movement.
pixels = 100
difference = 30

# Use the maximum resolution of the camera.
# This is for V1. V2 is 3280 x 2464.
# It’s also correct for the ZeroCam.
width = 2592
height = 1944

# Internet lookup of sunrise and sunset at our location
def sunrise_sunset():
    global sunrise, sunset
    
    # Location of greenhouse is lat = yyyyy lon = xxxxx
    url = ‘https://api.sunrise-sunset.org/json?lat=yyyyy&lng=xxxxx’
    response = requests.get(url)
    dict = response.json()
    res = dict.get(‘results’)

    curtim = datetime.datetime.now()
    hm = res.get(‘sunrise’).split(“:”)
    sunrise = curtim.replace(hour=int(hm[0])-1, minute=int(hm[1]))
    print(“An hour before sunrise “,sunrise)
    
    hm = res.get(‘sunset’).split(“:”)
    sunset = curtim.replace(hour=int(hm[0])+13, minute=int(hm[1]))
    print(“An hour after sunset   “,sunset)

# I copied this voodoo motion detection from somewhere. Changed the timeout
#  setting above to prevent the occasional failures to complete captures.
# Only alter this if you know what you are doing!
def compare():
   camera.resolution = (100, 75)
   stream = io.BytesIO()
   format = ‘bmp’
   camera.capture(stream, format)
   stream.seek(0)
   im = Image.open(stream)
   buffer = im.load()
   stream.close()
   return im, buffer

# Function to take a new high resolution picture, send it to another computer,
# send it to my phone, and then delete it.
def newimage(width, height):
    when = datetime.datetime.now()
    filename = “door-%04d%02d%02d-%02d%02d%02d.jpg”
               % (when.year, when.month, when.day, when.hour, when.minute, when.second)
    camera.resolution = (width, height)
    camera.capture(“/var/tmp/”+filename)

    connected = True
    ftp = ftplib.FTP()
    ftp.connect(“computer-name”)
    
    try:
        ftp.login(“user-name”,”password”)
    except ftplib.all_errors:
        connected = False
        print (“Failed to login to server.”)
        ftp.quit()
        
    if connected:
        ftp.storbinary(‘STOR ‘+filename, open(“/var/tmp/”+filename, “rb”))
        print (“Sent to server “, filename)

    ftp.quit()

# Code to send the Pushover message. Make picture smaller first.
# Note this uses a Ramdisk you must set up elsewhere.
    im = Image.open(“/var/tmp/”+filename)
    im.resize((324,243),Image.ANTIALIAS)
    im.save(“/var/tmp/”+filename)
    
    r = requests.post(“https://api.pushover.net/1/messages.json”, data = {
        “token”: “you-need-to-get-a-token-from-pushover”,
        “user”: “you-need-to-get-a-user-name-from-pushover”,
        “device”: “your-device”,
        “sound”: “intermission”,
        “message”: filename
    },
    files = {
        “attachment”: (filename, open(“/var/tmp/”+filename, “rb”), “image/jpeg”)
    })
   # Check r for problems – maybe put a delay here?
    if r.status_code != 200:
        print(“Pushover message failed.”)
    else:
        print(“Pushover accepted the message.”)
         
# Now delete the file.
    os.remove(“/var/tmp/”+filename)
    # Delay to avoid being nasty to Pushover server.
    time.sleep(5)

# Main program.

camera.rotation = 0
print(“Running door.py”)
image1, buffer1 = compare()

# Find sunrise and sunset times at two in the morning, and once
# at startup.
schedule.every().day.at(“02:00”).do(sunrise_sunset)
sunrise_sunset()
while (True):
   # See if it’s time to get sunrise and sunset.
   schedule.run_pending()

   image2, buffer2 = compare()

   changedpixels = 0
   for x in range(0, 100):
      for y in range(0, 75):
         pixdiff = abs(buffer1[x,y][1] – buffer2[x,y][1])
         if pixdiff > difference:
            changedpixels += 1

   # See if we think something moved.
   if changedpixels > pixels:
   # See if it’s light enough to take a picture.
      now = datetime.datetime.now()
      if now > sunrise and now < sunset:
          newimage(width, height)
      else:
          print(“A bit dark at “,now)

   image1 = image2
   buffer1 = buffer2

Greenhouse computer ravings continued.

Fat man in the greenhouse.
In the end, I got fed up with the temperate readings being messed up by the Sense HAT being inside the case, and no cooling fan being able to keep its sensors cool enough. I dispensed with the Sense HAT, which I will find some other use for, and put a cheap temperature and humidity sensor on wires lead out of the case.
Having arranged a shade to keep direct sunlight off the sensor, I now get sensible readings. I missed being able to look at the greenhouse and see the temperature scroll past, so I had the computer report temperature and humidity to another Pi indoors. 
Simple web site

That computer runs the Apache web server, and uses the incoming readings to make a simple web page, which I can look at from my main computer…






Code…

textA = [“<!doctype html>n”,”<html lang=”en”>n”,”<head>n”,”<meta charset=”utf-8″>n”,
         “<title>Greenhouse</title>”,”<link rel=”stylesheet” href=”mystyle.css”>”,
         “<meta http-equiv=”refresh” content=”150″ >”,
         “</head>”,”<body>”,”<h1>Greenhouse</h1>”,”<p>”]
textZ = [“</body>n”,”</html>n”]
def update_greenhouse_website():
    global previous_time, greenhouse_temp_file_modified
    greenhouse_temp_file_modified = os.stat(‘/home/pi/ftp/files/gth.txt’).st_mtime
    if greenhouse_temp_file_modified == previous_time:
        #print(‘Same time’)
        textM = “No greenhouse data received.nCheck greenhouse computer!”
    else:
        #print(‘New time’)
        fp = open(‘/home/pi/ftp/files/gth.txt’, ‘r’)
        textM = fp.read()
        fp.close()
    
    fp = open(‘/var/www/html/greenhouse.html’, ‘w’)
    for line in textA:
        fp.write(line)
    fp.write(textM)
    fp.write(“n”)
    for line in textZ:
        fp.write(line)
    fp.close()
    
    previous_time = greenhouse_temp_file_modified  
    return

Weather Station woes….

If you were making a weather station, you would try to make it waterproof. But you have to try harder, Fine Offset of China. Your WH1040 dies when the rain gets in…




Rain may only fall vertically in China, perhaps, so the marvellously cheap weather station I got from Maplin, just before they mysteriously went bust, would do there. But this is Wales, and the wind blows up the hill, carrying rain upwards with it, and it gets into the electronics and stops it working. It should look like this on the computer, although those maximum wind speeds are just plain wrong, thanks to EasyWeather corrupting its database.





I have a spare control unit, found on eBay, and wanted to swap them round, but the clever cover that keeps rain from above off somehow welded itself to the control unit. I removed it with BF&I.





Data is coming through! And it has even uploaded to Weather Underground!

And, now, having typed that, I look again, and it has stopped working.


Oh, well… Hang on, it’s back! Electronics, don’t you just love them?

Greenhouse computer, part the third.

Click for bigger!

































Here’s the greenhouse computer in situ. The air from the fan is now directed across the sensors on the Sense HAT, with the intention of measuring the temperature of the air in the green house, rather than the air in the case that the Pi 3 has warmed up. It’s just a balsawood duct, as thats an easy material to cut and glue.

The small case above the main one contains a Pi compatible camera with a fish eye lens and two infra red lights, for night photography.


The program it runs is fairly long, and specific to this hardware combination, but I can add it if anyone asks…

Greenhouse Computer Version 2

Work in progress…

























Well, the previous greenhouse computer could report the temperature, barometic pressure, and humidity, but it didn’t control anything, and the electric fan heater’s thermostat wasted a lot of electricity during the previous winter, as it wasn’t accurate, and the greenhouse got warmer than necessary.


The greenhouse needs to be kept above 5°C, to keep the citrus plants that over-winter in it alive, but not much warmer, and the fan heater doesn’t have any decent form of regulation.

Anyway… Here comes Version 2 of the greenhouse computer. The three boards are, starting at the bottom of the stack,

  • A Raspberry Pi 3B+
  • A Relay card with four mains relays
  • and a Pi Sense HAT.
The problem you get with putting these units in a case is that the Pi warms up the air in the case, so the Sense HAT gives false temperature readings. In Version 1 of the computer, there was a fan blowing air from outside the case onto the HAT’s sensors, and that’s what I’m doing in Version 2. The fan has just gone in, but I still need to put trunking to direct its air stream over those sensors.

You can see a nice long camera lead on the left, so the camera can go in a separate case. The mains wiring feeds mains to a couple of sockets on the back of the case, one for the heater, and one spare. The relays switch the sockets on and off.


More to follow…

Recent python door cam code – ugly, but works.

Updated version of the code…
It deals with the occasional hangs in the camera capture process by
rebooting when they happen. A line in /etc/rc.local runs the program again.

# Program for PiDoorCam

# Detects motion, and when it spots some, takes a high resolution
# picture, and sends the picture to PiScreen

import io
import os
import picamera
import ftplib
import time
from datetime import datetime
from PIL import Image
import requests

camera = picamera.PiCamera()
picamera.PiCamera.CAPTURE_TIMEOUT = 30

# If we detect 100 pixels that changed by 30, we have seen movement.
#difference = 30
#pixels = 100
# Desensitise!
#difference = 30
difference = 50
pixels = 150

# May as well use the maximum resolution of the camera.
# This is for V1. V2 is 3280 x 2464.
width = 2592
height = 1944

# I copied this voodoo motion detection from somewhere. Changed the timeout
#  setting above to prevent the occasional failures to complete captures.
def compare():
   camera.resolution = (100, 75)
   stream = io.BytesIO()
   format = ‘bmp’
   # Handle occasional ‘Timed out waiting for capture to end’
   try:
      camera.capture(stream, format)
   except:
      print (“Camera timed out, reboot needed!”)
      os.system(“sudo reboot now”)
       
   stream.seek(0)
   im = Image.open(stream)
   buffer = im.load()
   stream.close()
   return im, buffer

# Function to take a new high resolution picture, send it to PiScreen
# send it to my phone, and then delete it.
def newimage(width, height):
    when = datetime.now()
    filename = “door-%04d%02d%02d-%02d%02d%02d.jpg” % (when.year, when.month, when.day, when.hour, when.minute, when.second)
    camera.resolution = (width, height)
    camera.capture(filename)

    connected = True
    ftp = ftplib.FTP()
    ftp.connect(“PiScreen”)
   
    try:
        ftp.login(“pi”,”******************”)
    except ftplib.all_errors:
        connected = False
        print (“Failed to connect to server %s” % e)   
       
    if connected:
        ftp.storbinary(‘STOR ‘+filename, open(filename, “rb”))
        print (“Sent “, filename)

    ftp.quit()

# Code to send the Pushover message. Make picture smaller first.
    im = Image.open(filename)
    im.resize((324,243),Image.ANTIALIAS)
    im.save(filename)
   
    r = requests.post(“https://api.pushover.net/1/messages.json”, data = {
        “token”: “***********************************”,
        “user”: “*************************************”,
        “device”: “***********”,
        “sound”: “intermission”,
        “message”: filename
    },
    files = {
        “attachment”: (filename, open(filename, “rb”), “image/jpeg”)
    })
# Check r for problems – maybe put a delay here?
    if r.status_code != 200:
        print(“Pushover message failed.”)
    else:
        print(“Pushover accepted the message.”)
       
# Now delete the file.
    os.remove(filename)
    # Delay to avoid being nasty to Pushover server.
    time.sleep(5)

# Main program.

camera.rotation = 180
print(“Running door.py”)
image1, buffer1 = compare()

newimage(width, height)

while (True):

   image2, buffer2 = compare()

   changedpixels = 0
   for x in range(0, 100):
      for y in range(0, 75):
         pixdiff = abs(buffer1[x,y][1] – buffer2[x,y][1])
         if pixdiff > difference:
            changedpixels += 1

   if changedpixels > pixels:
      newimage(width, height)

   image1 = image2
   buffer1 = buffer2



Code below is an older version, the “error handling” doesn’t actually work.

# Program for PiDoorCam

# Detects motion, and when it spots some, takes a high resolution
# picture, and sends the picture to PiScreen

import io
import os
import picamera
import ftplib
import time
from datetime import datetime
from PIL import Image
import requests

camera = picamera.PiCamera()
picamera.PiCamera.CAPTURE_TIMEOUT = 30

# If we detect 100 pixels that changed by 30, we have seen movement.
#difference = 30
#pixels = 100
# Desensitise!
difference = 30
pixels = 150

# May as well use the maximum resolution of the camera.
# This is for V1. V2 is 3280 x 2464.
width = 2592
height = 1944

# I copied this voodoo motion detection from somewhere. Changed the timeout
#  setting above to prevent the occasional failures to complete captures.
def compare():
   camera.resolution = (100, 75)
   stream = io.BytesIO()
   format = ‘bmp’
   # Handle occasional ‘Timed out waiting for capture to end’
   try:
      camera.capture(stream, format)
   except:
      print (“Retrying camera.capture()”)
      camera.capture(stream, format)
 
   stream.seek(0)
   im = Image.open(stream)
   buffer = im.load()
   stream.close()
   return im, buffer

# Function to take a new high resolution picture, send it to PiScreen
# send it to my phone, and then delete it.
def newimage(width, height):
    when = datetime.now()
    filename = “door-%04d%02d%02d-%02d%02d%02d.jpg” % (when.year, when.month, when.day, when.hour, when.minute, when.second)
    camera.resolution = (width, height)
    camera.capture(filename)

    connected = True
    ftp = ftplib.FTP()
    ftp.connect(“PiScreen”)
 
    try:
        ftp.login(“pi”,”**********************************”)
    except ftplib.all_errors:
        connected = False
        print (“Failed to connect to server %s” % e) 
     
    if connected:
        ftp.storbinary(‘STOR ‘+filename, open(filename, “rb”))
        print (“Sent “, filename)

    ftp.quit()

# Code to send the Pushover message. Make picture smaller first.
    im = Image.open(filename)
#    im.resize((648,486),Image.ANTIALIAS)
    im.resize((324,243),Image.ANTIALIAS)
    im.save(filename)
 
    r = requests.post(“https://api.pushover.net/1/messages.json”, data = {
        “token”: “**********************************”,
        “user”: “********************************”,
        “device”: “************”,
        “sound”: “intermission”,
        “message”: filename
    },
    files = {
#        “attachment”: (“image.jpg”, open(filename, “rb”), “image/jpeg”)
        “attachment”: (filename, open(filename, “rb”), “image/jpeg”)
    })
# Check r for problems – maybe put a delay here?
    if r.status_code != 200:
        print(“Pushover message failed.”)
    else:
        print(“Pushover accepted the message.”)
       
# Now delete the file.
    os.remove(filename)
    # Delay to avoid being nasty to Pushover server.
    time.sleep(5)

# Main program.

camera.rotation = 180
print(“Running door.py”)
image1, buffer1 = compare()

newimage(width, height)

while (True):

   image2, buffer2 = compare()

   changedpixels = 0
   for x in range(0, 100):
      for y in range(0, 75):
         pixdiff = abs(buffer1[x,y][1] – buffer2[x,y][1])
         if pixdiff > difference:
            changedpixels += 1

   if changedpixels > pixels:
      newimage(width, height)

   image1 = image2
   buffer1 = buffer2

The Wisdom of the Ancients – Part 94

I tried to find this one one Google, but there was no sign of it!


mpirun mca_oob_tcp_recv_handler  invalid message type: 43


Basically, it means you have not noticed you are trying to control a cluster of Raspberry Pi 3 B+ computers that are running Raspbian Stretch with a Raspberry Pi that has somehow still got Raspbian Jessie on it.


You’re welcome!

Oyster, before I got all the bricks.