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