reichley
Published © GPL3+

Solar-Powered Squirrel Kam (Pi Zero W) UPDATED

Combines basic woodworking (house/feeder) with a Pi Zero W/cam powered by batteries/solar & turned on/off w/ an ATtiny85 and BH1750

IntermediateFull instructions provided3 hours9,786
Solar-Powered Squirrel Kam (Pi Zero W) UPDATED

Things used in this project

Hardware components

Raspberry Pi Zero Wireless
Raspberry Pi Zero Wireless
×1
Camera Module
Raspberry Pi Camera Module
×1
Adafruit Raspberry pi zero v1.3 camera cable
×1
Adafruit Raspberry pi camera board case
×1
Pimoroni LiPo SHIM
×1
ATTiny85
Microchip ATTiny85
×1
SparkFun 8-pin DIP socket
×1
ALL POWERS 2.5W 5V 500mAh solar panel
×4
tp4056 lithium charging module
×4
3 x 2 Velleman Plastic Project Case
×1
bh1750 lux sensor module
×1
1N4001 diode
×4
Adafruit JST 2-pin connector
×1

Software apps and online services

motioneye
squirrelkam os (raspbian lite [april 2018], motioneye, homebridge, homebridge-camera-ffmpeg, etc.)
I built this with base april 2018 raspbian lite build, added motioneye, nodejs, homebridge, some python libraries, sensors

Story

Read more

Schematics

squirrelhaus/squirrelkam fritzing

Code

attiny85_bh1750 code

Arduino
#include <Wire.h>
#include <BH1750.h>
#include <avr/power.h>
//#include <avr/sleep.h>
//#include <SoftwareSerial.h>

//#define RX 5
//#define TX 1
//SoftwareSerial Seriall(RX, TX);

BH1750 lightMeter;
const int enablePin = 3;
const int shutdownPin = 4;

void setup(){
  pinMode(enablePin, OUTPUT);
  digitalWrite(enablePin, HIGH);
  /*pinMode(0, INPUT);
  digitalWrite(0, HIGH);
  pinMode(1, INPUT);
  digitalWrite(1, HIGH);*/
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);  
  pinMode(shutdownPin, OUTPUT);
  digitalWrite(shutdownPin, LOW);
  //ADCSRA = 0; 

  //Seriall.begin(9600);
  Wire.begin();
  delay(50);
  lightMeter.begin(BH1750::ONE_TIME_LOW_RES_MODE);

  //Seriall.println(F("BH1750 One-Time Test"));

}


void loop() {
  delay(50);
  uint16_t lux = lightMeter.readLightLevel();
  delay(50);
  //uint16_t lux2 = lightMeter.readLightLevel();
  //Seriall.print("Light: ");
  //Seriall.print(lux);
  //Seriall.println(" lx");
  if (lux < 100) {
    digitalWrite(shutdownPin, HIGH);
    delay(15000);
    digitalWrite(enablePin, LOW);
    delay(50);
    digitalWrite(shutdownPin, LOW);
  } else {
    digitalWrite(enablePin, HIGH);
  }
  //delay(60000 * 5);
  delay(60000 * 3);
}

Shutdown Workday (python)

Python
python script that runs on boot to send "wake" and "sleep" emails, monitor GPIO 17, power off when light levels low or after 8 hours of work
#!/usr/bin/env python
import smtplib
from datetime import datetime as t
import RPi.GPIO as GPIO
import os
import time
import subprocess
import sys
from multiprocessing import Process

# listen on pi GPIO 17 for high signal
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN)

# keeps track of system timestamp, meant to hold squirrelkam ops to 8 hours
workday = '/home/pi/workday.txt'

# email info, if you want to receive wakeup and shutdown notifications.
MAIL_USER = 'emailaddress'
MAIL_PASS = 'emailpassword'
SMTP_SERVER = 'emailserver' #usually smtp.xxxx.com
MAIL_RECIPIENT = 'emailrecipient'
SMTP_PORT = 587 # may be a different port, gmail uses 465


def send_email(recipient, subject, text):
    """Sends an email when provided a recipient email address, subject, and text."""
    if MAIL_USER != 'emailaddress':
        server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
        server.ehlo()
        server.starttls()
        server.ehlo()
        server.login(MAIL_USER, MAIL_PASS)
        header = 'To:' + recipient + '\n' + 'From: ' + MAIL_USER
        header = header + '\n' + 'Subject:' + subject + '\n'
        msg = header + '\n' + text + ' \n\n'
        # server.set_debuglevel(1)
        server.sendmail(MAIL_USER, recipient, msg)
        server.close()
    else:
        pass


def workday_start():
    """Writes system start time to file. If exists and < 8 hours old, passes. If >, overwrites."""
    if os.path.isfile(workday):
        if (time.time() - os.stat(workday).st_ctime < 28800):
            print('#shutdown_workday.py# file exists and less than 8 hours old.')
            pass
        else:
            with open(workday, 'w') as f:
                f.write(str(time.time()))
                print('#shutdown_workday.py# file existed but was 8 hours old, overwriting.')
    else:
        with open(workday, 'w') as f2:
            print('#shutdown_workday.py# file didn\'t exist so was created.')
            f2.write(str(time.time()))


def shutdown_check():
    """Checks for HIGH signal on GPIO 17. This indicates light level has dropped below 100 lux.""" 
    while True:
        if GPIO.input(17) == 1:
            print('#shutdown_workday.py# squirrelhaus going to sleep: ({:})'.format(t.now().strftime('%d-%b-%y %H:%M')))
            send_email(MAIL_RECIPIENT, 'squirrelhaus sleep', 'squirrelhaus is going to sleep. ({:})'.format(t.now().strftime('%d-%b-%y %H:%M')))
            with open(os.devnull, 'w') as too_dark:
                powerdownpi2 = subprocess.Popen(('sudo', 'poweroff',), stdout=too_dark)
            sys.exit(0)
	else:
	    pass
        time.sleep(0.50)


def workday_over():
    """Checks to see if difference between current time and time in file > 8 hours. If, shuts down."""
    while True:
        with open(workday, 'r') as g:
            time_card = float(g.read())
        if (time.time() - time_card) > 28800:
            print('#shutdown_workday.py# squirrelhaus has completed 8 hours of work: ({:})'.format(t.now().strftime('%d-%b-%y %H:%M')))
            send_email(MAIL_RECIPIENT, 'squirrelhaus clocking out', 'squirrelhaus has completed 8 hours of work. ({:})'.format(t.now().strftime('%d-%b-%y %H:%M')))
            with open(os.devnull, 'w') as day_over:
                powerdownpi1 = subprocess.Popen(('sudo', 'poweroff',), stdout=day_over)
            os.remove(workday)
            sys.exit(0)
        else:
            pass
        time.sleep(180)


if __name__ == "__main__":
    send_email(MAIL_RECIPIENT, 'squirrelhaus wake', 'squirrelhaus just woke up. ({:})'.format(t.now().strftime('%d-%b-%y %H:%M')))
    print('#shutdown_workday.py# squirrelhaus just woke up: ({:})'.format(t.now().strftime('%d-%b-%y %H:%M')))
    workday_start()
    process1 = Process(target = shutdown_check)
    process1.start()
    process2 = Process(target = workday_over)
    process2.start()

Credits

reichley

reichley

2 projects • 2 followers
Contact

Comments