Thursday 31 August 2017

Control BirdBox LED lights via a simple webpage

This year's 'Double Camera' bird box has a variety of illumination options...

I wasn't sure how best to setup the internal lighting, so I, well threw a selection of LEDs at it in three separate circuits/loops, These are on 12v circuits, and are isolated from & switched by the (5v) raspberry pi via a ULN2003AN transistor ic.  I used all 7 base input channels, with the collector outputs switching the 12v LED loops through a selection of resistors as follows:

Loop 1) 4x 'Warm' LEDs: LOW (10k ohm) and HIGH (330 ohm)
Loop 2) 3x 'White' LEDs: LOW (10k ohm) and HIGH (330 ohm)
Loop 3) 36 IR LED array: LOW (10k ohm), 'MED' (5k ohm potentiometer) and ('HIGH' 330 ohm)

+ An opaque perspex 'windows' at either end for the natural light options..

Once the birdbox was in-situ, I wanted a simple way to fiddle about with the lighting, and came across Matt Richardson's excellent Flask  tutorial, specifically his weblamp.py script example.  This creates a webserver within python that allows me (and the kids...) to turn LEDs on, off up or down via a simple webpage:


The tutorial is an excerpt from his Getting Started with Raspberry Pi: An Introduction to the Fastest-Selling Computer in the Worldbook

Just for fun - someone's at home....
I've adapted this for my needs as follows:

import RPi.GPIO as GPIO
from flask import Flask, render_template, request
app = Flask(__name__)

#http://mattrichardson.com/Raspberry-Pi-Flask/

GPIO.setmode(GPIO.BCM)

# Create a dictionary called pins to store the pin number, name, and pin state:
pins = {
   25 : {'name' : 'LED_IR_High', 'state' : GPIO.LOW},
   8 : {'name' : 'LED_IR_Med', 'state' : GPIO.LOW},
   7 : {'name' : 'LED_IR_Low', 'state' : GPIO.LOW},
   16 : {'name' : 'LED_Warm_High', 'state' : GPIO.LOW},
   12 : {'name' : 'LED_Warm_Low', 'state' : GPIO.LOW},
   21 : {'name' : 'LED_WHITE_High', 'state' : GPIO.LOW},
   20 : {'name' : 'LED_WHITE_Low', 'state' : GPIO.LOW}
   }

# Set each pin as an output and make it low:
for pin in pins:
   GPIO.setup(pin, GPIO.OUT)
   GPIO.output(pin, GPIO.LOW)

@app.route("/")
def main():
   # For each pin, read the pin state and store it in the pins dictionary:
   for pin in pins:
      pins[pin]['state'] = GPIO.input(pin)
   # Put the pin dictionary into the template data dictionary:
   templateData = {
      'pins' : pins
      }
   # Pass the template data into the template main.html and return it to the user
   return render_template('main.html', **templateData)

# The function below is executed when someone requests a URL with the pin number and action in it:
@app.route("/<changePin>/<action>")
def action(changePin, action):
   # Convert the pin from the URL into an integer:
   changePin = int(changePin)
   # Get the device name for the pin being changed:
   deviceName = pins[changePin]['name']
   # If the action part of the URL is "on," execute the code indented below:
   if action == "on":
      # Set the pin high:
      GPIO.output(changePin, GPIO.HIGH)
      # Save the status message to be passed into the template:
      message = "Turned " + deviceName + " on."
   if action == "off":
      GPIO.output(changePin, GPIO.LOW)
      message = "Turned " + deviceName + " off."
   if action == "toggle":
      # Read the pin and set it to whatever it isn't (that is, toggle it):
      GPIO.output(changePin, not GPIO.input(changePin))
      message = "Toggled " + deviceName + "."

   # For each pin, read the pin state and store it in the pins dictionary:
   for pin in pins:
      pins[pin]['state'] = GPIO.input(pin)

   # Along with the pin dictionary, put the message into the template data dictionary:
   templateData = {
      'message' : message,
      'pins' : pins
   }

   return render_template('main.html', **templateData)

if __name__ == "__main__":
   app.run(host='0.0.0.0', port=90, debug=True)

Make it executable as follows:
chmod 755 weblamp.py

Add the following toward the end of /etc/rc.local to make it run at boot:
python /home/pi/Documents/BirdCam2/flask/WebLamp/weblamp.py &

The IR sensitive camera is a v2 Raspberry pi Pi Noir (Camera 1).  Unsurprisingly, the IR HIGH setting to just too bright, with the MED setting being the sweet spot.  IR_Low (10k ohm) barely registers... At the moment I've got it set to IR_Medium.

I haven't made much use of the non IR LEDs yet, but the LifeCam Cinema webcam (Camera 2) does not see very well without them being on, which is bit of a shame.  Maybe a ver 2018 box could have bigger natural light windows (Or I'll take a hacksaw to this one...).


We've seen a fair number of wasps taking an early interest and this Hornet (I think) taking a look... This is using the IR LED array and Pi Noir v2 camera


The LifeCam version looks like this.. the lesson is that I need a motion trigger on the non IR LEDs as there is only natural daylight illuminating this:



Some thoughts...
36 IR leds is excessive.
The raspberry v2 Pi Noir daylight light sensitivity is not good (with IR cut, so conceivably this is reducing the 'useful' daylight sensitivity).
I dont use the 'LOW' setting on the WARM or WHITE leds
LifeCame Cinema needs more natural light for unassisted daylight video (bigger windows)
Need an 'on-motion' event to turn on non-IR leds.