Google Assistant updates.
It us what it is. Probably.
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
Program listing
![]() |
| Fat man in the greenhouse. |
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?
![]() |
| 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…
![]() |
| 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,
# 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