zondag 17 augustus 2014

Pi-files: Frontdoor light switch based on local sunset/sunrise

I have a couple of front door LED lights which I would like to switch on automatically during the evening/night. The two conventional methods that are commonly available had their disadvantages:


A timer switch is the easiest and cheapest solution, but doesn't take into account day light savings. Besides that, in Einhoven, the Netherlands where I live in december the sun sets around 16:30 while in June it doesn't get dark before 22:00. A simple timer doesn't take that into account either.

Since you only want the lights on when it gets dark, instead of time you can also use a light sensor to distinguish day and night. You have these front door lights that have this built in. The problem that I had with these devices is that they start bouncing ('flickering') around sunset/sunrise. They constantly turn on/off which causes damage to the LED lights I was using. This cost me already several expensive led lights.

Since I already have a Raspberry Pi installed in the hall way (used for the doorbell alert) I might as well hook up the front door lights. You can find on the Internet all sorts of timetables for the sunset/sunrise, so my Rpi should be able to use that same information as well. A small search on the world wide web led me to a Python package called PyEphem. This package can be used to do astronomical calculations and can tell you for example where a certain object (e.g. the sun) is with respect to the observer (which is me standing in my front yard). Very conveniently it also can calculate for you the upcoming sunset and sunrise. Isn't that exactly what I need?!?

The LED lights are powered with a 12V AC-DC transformer. I put together a small electronics board to be able to use the GPIO's 3V3 of the Rpi to switch the 12V LEDs. I used a IRL3103 N-FET. This is not really a deliberate choice but like most of my transistor/FET choices based on what I have lying around in the lab. Be aware that the N-FET needs to be able to switch with a Gate-Source voltage of 3V3. For example an IRF540 (which I used for a motion detector for a 12V ledbar) doesn't switch with this voltage (Here I solved it by using a smaller BS170 N-FET and use that to switch a IRF 9540 P-FET). I added a manual switch to override the automatic switch in case I just want to turn on the lights. Parallel to the front door LEDs is a test led with a resistor onboard to be able to test the functionality without having to connect the actual front door lights.




I use GPIO pins 18 and 22 to switch the two LED's. You can switch LED's with only one output, but I thought it is a nice additional feature to switch them separately to be able to also create a spooky program for Halloween or something like that.
After including the PyEmphem package I have to indicated where the observer is located. I used itouchmap which can translate an address to a latitude and longitude coordinates. Being an observer in Eindhoven means you are located at [51.5, 5.5]. The PyEphem package calculated the next sunrise and sunset and returns these values. I do this every minute and compare the two; if the next sunset if further away in time than the next sunrise, it means it is night. The other way around means daytime. The LED lamps are switched based on the day/night status.

The code can be found here (link):






maandag 4 augustus 2014

Pi-files: Doorbell alert with pushmessage and mail with webcam footage

Actually the first 'project' I ever did with a Raspberry Pi was sending a push message to my Iphone. It was 2012, I was lying sick in bed and found a new app on my Iphone called Pushover (what else to do when you're sick?). With Pushover you can send and receive custom made push messages. On the website I found a simple Python script to send messages. I knew the Rpi was able to run Python code, so here my Rpi adventures started. Within 30 minutes I was able to receive 'hello world' on my phone (needless to say I wasn't lying in bed anymore). Seeing 'hello world' on your screen is like the software equivalent of the blinking led, THE coolest feature ever!

I decided to hook up this push message feature with my doorbell. The idea is that every time somebody rings the doorbell, I get a push message that there is somebody at the door. The wires of the doorbell were already connected to a wireless transmitter and I wanted to keep that functionality. I used a relay to combine the transmitter with a switch on the GPIO header of the Raspberry Pi.


The led and 330R resistor can be installed in the actual doorbell, so the person can find the doorbell and is triggered when the button is pressed in case he/she doesn't actual hear the bell (the led turns off when the doorbell is pressed). The 100u capacitor and flyback diode are to limit voltage peaks when using the relay. The 'test' switch is available close to the GPIO header to test the (software) functionality of the doorbell alert. The relay and test switch are connected to pin11 (GPIO0) of the Rpi.


The Python code looks as follows. First the necessary libraries are included and the GPIO header is configured:

#import libs
import RPi.GPIO as GPIO
import httplib, urllib
import time
from time import sleep, localtime, strftime

#display no warnings (on command line)
GPIO.setwarnings(False)
#set GPIO: use RPi board pin numbers
GPIO.setmode(GPIO.BOARD)  #alternative is GPIO.BCM (Broadcom names)
#set pin 11 as input
GPIO.setup(11, GPIO.IN)  #Input: doorbell (relay)

A seperate function is written for the push message. This is mainly copied from the Pushover FAQ section ('How do I send Pushover notifications in Python?'). The token ('push_token') and user ID ('push_user') you get when you sign in on the website. There you can also select the devices on which you want to receive the push messages.

#set up push message (pushover)
def push(text):

   push_token = 'xxx'
   push_user   = 'yyy'

   conn = httplib.HTTPSConnection("api.pushover.net:443")
   conn.request("POST", "/1/messages.json",
                urllib.urlencode({"token": push_token,
                                        "user": push_user,
                                        "message": text,}), 
             {"Content-type": "application/x-www-form-urlencoded" })
   conn.getresponse()

The main loop checks for the GPIO input regularly. I added a tiny bit of delay (sleep) to relieve the CPU. When the doorbell is pressed, it takes the current date and time and adds that to the push message.


while 1:

    sleep(0.1) #relieves CPU load big time!
      
    #if doorbell is pressed...
    if GPIO.input(11):

          #determine date/time and add to message
          timestr_date = strftime("%a %d %b %Y", localtime())  
          timestr_time = strftime("%H:%M:%S", localtime())      

          mess = "Doorbell pressed on {}, {}.".format(timestr_date,timestr_time)
          print "\n"
          print mess


          push(mess)

When this all worked it was time to extend the doorbell alert feature. Not only I want to know that there is someone at the door, I also would like to know who was at the door, especially when I am not at home. I added a Logitech C270 webcam to the setup to capture snapshots and a short movie.



A Python mail script is supposed to send it all to my mailbox. The mail functionality I didn't invent myself, I just relied on the beautiful internet community. On Kutuma's Ramblings I found almost exactly what I needed. The only difference is that I wanted to sent multiple attachments. For that I changed the mail function a little bit:

def mail(to, subject, text, attachments=[]):

   gmail_user = 'XXX@gmail.com'
   gmail_pwd  = 'YYY'

   #add attachments to a list
   assert type(attachments)==list

   msg = MIMEMultipart()

   msg['From']    = gmail_user
   msg['To']      = to
   msg['Subject'] = subject

   msg.attach(MIMEText(text))

   for attach in attachments:
     part = MIMEBase('application', 'octet-stream')
     part.set_payload(open(attach, 'rb').read())
     Encoders.encode_base64(part)
     part.add_header('Content-Disposition',
           'attachment; filename="%s"' % os.path.basename(attach))
     msg.attach(part)

   mailServer = smtplib.SMTP("smtp.gmail.com", 587)
   mailServer.ehlo()
   mailServer.starttls()
   mailServer.ehlo()
   mailServer.login(gmail_user, gmail_pwd)
   mailServer.sendmail(gmail_user, to, msg.as_string())
   mailServer.close()

You can now add the attachments as an comma separated array:

mail("xxx@gmail.com",mess,mess,["screen1.jpg","screen2.jpg","screen3.jpg","movie.avi"])



As you can see I added three snapshots and one movie as attachments. They all come from the Motion package which is a linux package to capture motion on a webcam. To be honest, I actually don't use the motion feature of that package, but I tried several other solutions (like FFMpeg or something) and came across a bunch of issues with compiling, frame rates etc. The Motion package served my purpose the best. 

NB. The Raspberry Pi that I am using is a model A, which is not capable of using the official Rpi camera module with its cool movie and snapshot features.

To install the Motion package, run the following command:
pi@raspberrypi ~ $  sudo apt-get install motion libv4l-0 uvccapture

I added some additional modules to the import section of the Python script described above and added the code below to the main loop. Starting the webcam is done right after the doorbell is pressed. After capturing the snapshots and sending the push message, the program waits 60 seconds until the webcam is stopped. After this the mail is send with the snapshots and movie.

import subprocess
import shutil #high-level file operations

    #if doorbell is pressed...
    if GPIO.input(11):

          #start webcam (motion package)
          print "\n"
          print "Start webcam (Motion)"
          
          #subprocess.call("sudo /etc/init.d/motion start", shell=True)
          subprocess.call("sudo motion", shell=True)

          #copy (save) most recent snapshot of webcam
          print "\n"
          for k in range(3):
               sleep(3)
               sour_path = '/home/pi/rpi/webcam/motion/snapshot.jpg'
               dest_file    = '/home/pi/rpi/webcam/motion/screen%d.jpg' %k
               shutil.copy2(sour_path, dest_file)
               print 'Snapshot captured:  %s' %(dest_file)


          ****** Sending push message (see above) ******

          print "wait 60 seconds"
          sleep(60)
          
          #stop webcam
          print "Stop webcam"
          subprocess.call("sudo /etc/init.d/motion stop", shell=True) 

          #send mail via Gmail
          mail("xxx@gmail.com",mess,mess,
 ["screen1.jpg","screen2.jpg","screen3.jpg","movie.avi"])



  video

The motion package has a pretty big configuration file where you can configure all sorts of things. Most of the items speak for their own. The file can be edited with nano:

pi@raspberrypi ~ $  sudo nano /etc/motion/motion.conf

For the doorbell alert let me highlight the most important sections:

# File to store the process ID, also called pid file. (default: not defined)
process_id_file /var/run/motion/motion.pid 

The folder /var/run/motion needs to be present. In my latest Raspbian (Debian Wheezy) OS I encountered a bug (as far as I can tell) that this folder is gone every time I boot up the Rpi. For that reason I added a check and create the folder if necessary:

import os

folder   = "/var/run/motion"

if not os.path.exists(folder):
  print "Folder does not exist. Create folder " + folder
  os.makedirs(folder)


# Image width/height (pixels). Valid range: Camera dependent, default: 352/288
width 1280
height 720
Bigger images won't hurt!

# Maximum number of frames to be captured per second.
# Valid range: 2-100. Default: 100 (almost no limit).
framerate 2

I only use two frames per second to keep the movie size as small as possible.

# Always save images even if there was no motion (default: off)
output_all on

I don't use the motion detection features so I want all images to be saved

# Use ffmpeg to encode a timelapse movie
# Default value 0 = off - else save frame every Nth second
ffmpeg_timelapse 0.5


# Make automated snapshot every N seconds (default: 0 = disabled)
snapshot_interval 1

Save snapshots every second

# Target base directory for pictures and films
# Recommended to use absolute path. (Default: current working directory)
target_dir /home/pi/rpi/webcam/motion

Location where all files are stored

# File path for snapshots (jpeg or ppm) relative to target_dir
snapshot_filename snapshot

All snapshots are given the same name (no timestamp) to save storage space.

# File path for motion triggered ffmpeg films (mpeg) relative to target_dir
movie_filename movie

Each movie is given the same name (no timestamp) to save storage space.

That's it for now! I am already thinking of new features like face recognition, direct videostream, and a call back option to actually talk to the person at the door wherever I am. The sky is the limit! Unfortunately my spare time as well :)

Below a picture of my custom storage box which is located in the meter cupboard (again, is that really the correct translation for the dutch word 'meterkast'?). It houses a Raspberry Pi model A, an interface board (on the right) with the well famous heartbeat led. On the left two boards for the doorbell and one for the front door light which I will explain in another post soon.




zondag 27 juli 2014

Pi-files: Heartbeat

It has been a bit quite here on Deddies lab's blog. That doesn't mean that nothing came out of the lab. Actually a lot has happened, but I didn't had the opportunity (or was a bit too lazy) to post it here. Since I took a lot from the DIY community, I feel obliged to return also my findings, struggles and results back to that same community. Only then we all can grow!

Last couple of years, I invested most of my (spare) time in the Raspberry Pi platform. I don't think I have to explain anything about this versatile mini computer. Just google around and you will find tons of projects. I myself was attracted at first to the Rpi because of the General Purpose IO's (GPIO) possibilities which can be used to connect simple inputs (switches) and outputs (nothing beats a blinking led!). I was (still am) used to work with Atmel microcontrollers, where also the pins can be configured as input and output pins. So being able to use the same IO functionality but then combined with ethernet, a decent user interface, etc. etc. etc. opened a whole new world of possibilities.

Let's start easy; Sometimes it is difficult to see from the outside of the Pi is running or not. It has some status leds onboard, but when built in a box and stuffed away in a cupboard (like I have) the status leds are not so easy to see. So for that purpose I made a simple heartbeat. It is just a blinking led, but starts automatically when the Pi boots up, so it indicates when the Pi is alive and kicking!

I have a revision A of the RPi in my 'meterkast' (is it really 'meter cupboard'?).  For this heartbeat and some other projects (doorbell alert, front door lights) I made a dedicated interface board. It also has a led which is clearly visible from the outside


This led is connected to pin 16 of the GPIO header, which is called GPIO4. No, this doesn't make sense, and apparently there is a difference between the physical Raspberry Pi names and Broadcom names. I made a Python script (called heartbeat.py) where I can first configure the IO's:

#Libraries/modules
import RPi.GPIO as GPIO
from time import sleep

#display no warnings (on command line)

GPIO.setwarnings(False)
#use RPi board pin numbers
GPIO.setmode(GPIO.BOARD)
#set pin 16 as output
GPIO.setup(16, GPIO.OUT)


The 'sleep' module is inserted to make the led blink. The while loop makes the led blink indefinite:

print "Start heartbeat\n"
while 1:

  GPIO.output(16,1)
  sleep(0.5)
  GPIO.output(16,0)
  sleep(0.5)

You can run this script from the command line:

pi@raspberrypi ~ $ sudo python /home/pi/gpio/scripts/heartbeat.py &

When you want to run the script automatically after boot up of the Rpi, you have to edit /etc/rc.local:

pi@raspberrypi ~ $ sudo nano /etc/rc.local

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.


python /home/pi/gpio/scripts/heartbeat.py &

exit 0

Save the file with Ctrl+X. Make sure that the Python script is executable:

pi@raspberrypi ~ $ sudo chmod 755 /home/pi/gpio/scripts/heartbeat.py

You can check if the script is executable if you see the 'x' in the permission overview:

pi@raspberrypi ~ $ ls -la

-rwxr-xr-x 1 root root   261 Jul 21 21:34 heartbeat.py

Reboot the Pi and see the led blink:

pi@raspberrypi ~ $ sudo shutdown -r now

donderdag 29 mei 2014

Motion Detection for 12V ledbar

On an electronic flea market I bought two 50cm 12V (700ma) ledbars. They were quite bright and only cost 6 euro a piece. I still needed a proper lighting solution for my work bench and thought these could perfectly serve that purpose.

With some two components conductive glue I glued them on a aluminum strip for thermal conductivity. A wooden frame prevents to look right into the leds when you enter the room. It definitely gives a nice bright even illuminated work bench.

 
I didn't want to use a switch to turn the lights on and off. It is just not cool! Recently I bought 10 PIR motion detection sensor modules (HC-SR501) on ebay for only 10 euro (How can they even make that for one euro?). I thought one of these can do the job for me when I approach my bench.

The PIR sensor module outputs 3V3 when motion is detected. Sensitivity and ON time can be adjusted on the module. It operates on supply voltages between 4.5 and 20V so the 12V (1.5A) adapter I need to power the ledbars can also power the PIR sensor. I wanted to use an IRF540 NFET to switch the leds, but this NFET doesn't open up completely with a Vgs of 3V3 which limits the current flowing through the leds. That is why I used a smaller BS170 NFET that can be triggered with 3V3. R1 is a 10K resistor to prevent a floating gate signal. Due to another 10K resistor (R2) at the drain of the BS170 an inverted signal of the PIR sensor is available, so a PFET (IRF9540) can invert back that signal to switch on the ledbars. For troubleshooting purposes I added a jumper to  put 12V directly on the ledbars and a test led (always add a test led!) to see the circuit works properly even if the ledbars are not connected.


 I stuffed everything into a small plastic storage box that I found in the kitchen and made it possible to rotate the whole box to be able to point the PIR sensor towards the workbench. It turned out to be a very nice local lighting solution. I doesn't turn on when I enter the room or walk around, only when I enter the work bench it turns on. Altogether it didn't cost me more then 15 euros, I don't believe you can buy something like this for so little money.




zondag 8 januari 2012

Mystery LED in a box: part 7

My friends were so pleased with my sewing craftmanship that they decided to releave us from our duty. No more morse code, no more assignments...

One day we blinked with our eyes and we found our selfmade wallet filled with a decent amount of dough. Our assigment was fullfilled!


A little trip down memory lane:

Mystery LED in a box: part 0: The suprise!
Mystery LED in a box: part 1: Reconnaissance mission
Mystery LED in a box: part 2: Tin soldier
Mystery LED in a box: part 3: Epromising website
Mystery LED in a box: part 4: Chat me up, baby
Mystery LED in a box: part 5: d2hhdCB0aGUgZnVjaw==
Mystery LED in a box: part 6: So sew me...

Thanks, buddies.... who's next by the way?

zondag 18 december 2011

Mystery LED in a box: part 6

see also: Mystery LED in a box: part 0
see also: Mystery LED in a box: part 1
see also: Mystery LED in a box: part 2 
see also: Mystery LED in a box: part 3
see also: Mystery LED in a box: part 4
see also: Mystery LED in a box: part 5

How do you respond to a sentence like the following:

U'2F'UBMU'SI'G'5HY'W'KGZ'W'V'UI'H'B'VCNR'LBW'9UBMV'LI'G'1LDC'B'QDW'XSAW'U'
GBMF'TZ'W'4GZ'W'4GDH'J'VDX'DKY'X'R'1BS'4GQ'MV'3AW'PZI'H'Z'PY'S'B'IBG'9NL'I4UT


Anyone? Nobody? ANYthing? The last clue kept us busy for a few weeks. 
Shortly after presenting the world our latest progress we found a rather scary letter in our mailbox:
 

"All your base are belong to us". Not only one of the most famous internet memes ever but as from now also a big hint to solve our mysterious sentence that should lead us to our wedding gift. Googling it didn't result in a lot of usefull stuff other then a huge amount of odes and also parodies to the subject. After a week of puzzling, googling and trying to tear some usefull information from my friends a little birdy (Thank you!) remerbered my of a mental note that I took during part 2 of the queste. The clue of part 2 ended with the number 64 ("VIERENZESTIG"), which was not intended for that assignment. It seemed a bit lost standing there, but I kept it in mind. Maybe it is usefull here.
Adding '64' to the Google search string 'All your base are belong to us' didn't actually give me something new (except some way too nerdy Microsoft stuff). But hurray, my luck changed when I shortened the string to 'All your base 64'. It showed me various leads to the term 'Base64'. Base64 is an encoding/decoding method that uses a base of 64 characters to encode 8 bit ASCII data. It has various applications and it makes a normal sentence look like it is heavily encrypted. For that it is also used to obfuscate passwords. The Wikipedia site showed with a small example how to decode Base64 encoded data, and manually decoding the first part showed my the first letters of my own name, so I knew I was going the right way. Base64 is not very difficult to encode/decode so there has to be somebody that already made a script for the world wide web. Lucky me!
There was only one thing. Base64 encoding makes a distinction between small and capital letters while Morse code doesn't make this distinction. That was an easy one. It immediately explained the apostrophe ( ' ) characters in the mysterious sentence. A letter followed by an apostrophe means a capital letter, otherwise it is used as a small letter.


"SANNE, NAAI EEN PORTEMONNEE MET JULLIE 
NAMEN EN TROUWDATUM. BEWIJS VIA BLOG..." 

(Sanne (That's my nickname), sew a wallet with your names 
and wedding date. Show the proof via the blog...) 

The assignment is a wink to my wife's hobby: Sewing and other sorts of crafting. In part 2 she had to do some soldering on the mystery box, so now it was my turn. And here is the result... And yes, it is geeky and nerdy!



What's next? 

zaterdag 26 november 2011

Mystery LED in a box: part 5

see also: Mystery LED in a box: part 0
see also: Mystery LED in a box: part 1
see also: Mystery LED in a box: part 2 
see also: Mystery LED in a box: part 3
see also: Mystery LED in a box: part 4

I promised in the previous item to provide an update after my vacation. That was in August! Unfortunately my vacation doesn't take more then 3 months (I wish!). 

It took me quite some time to make the mystery box actually listen to me. I was able to tell it stuff with the IR transmitter that I had to build, but it looked pretty deaf. The last hint I got was a little assigment to tell the box 'something':

"JIPPIE NU KAN IK OOK LUISTEREN. ZEG EENS IETS..."

 I figured out that this 'something' had to be the word 'IETS', which is the dutch word for 'something'. 'IETS' has also the advantage to be fairly easy in morse code. Three dots, one dash and again three dots is all it takes (** *- ***).

Just two weeks ago I found out why me and the box were not on the same level. I made a little mistake with one of the resistors.... 3K3 IS NOT THE SAME AS 33K, IDIOT!
The 2K and 3K3 resistors serve as a voltage reference for the incoming photo transistor signal, and using a 33K resistor resulted in a 4.7V reference instead of the intended 3V.

 

Having that fixed the box and I renewed our vows and we were finally on speaking terms again. Telling 'IETS' to it with IR remote control waked it up and gave me a new sequence of morse pulses. I quickly hooked up my datalogger to log the sequence and let Matlab crunch the data:


"WIE ZIJN JE BESTE VRIENDEN? (IN ALFABETISCHE VOLGORDE)"

Translated: "Who are your best friends? (in alphabetical order)"

Damn, that looks like a tricky question. This really could cost (or gain) me friends... I took the safe road and picked the names of the people that actually contributed to the wedding present.


But some use their real name and others jotted down their nickname in the card. Some of the guys have actually nicknames that are used so often, their real names are already long forgotten (Bart? And who's Frank?). So multiple options here:


Regardless the right answer it promised to be a challenge to send this huge morse code sequence manually, although I realized that is exactly what they did back in the days in WW2. But then they didn't had microcontrollers like we have now so I followed Deddies Labs slogan ("Because anything deserves a microcontroller") and start putting together a morse code generator.



That worked! A little bird had told me in the meantime what the most likely answer was to the friends question, and finally the mystery box gave me the next morse sequence. Again twice as fast as the previous clue which was also double as fast as the one before that....
Inevitably the datalogger needed some more tuning since the last upgrade which boosted up the sampling frequency to a whopping 40Hz (!!!) proved not to be fast enough (C'mon guys, cut me some slack here). I actually compressed the data before storing it to the USB stick and decompressed it with Matlab (I will explain this later on in a different topic). It is now so freakin' fast that I myself don't even now how fast it is. I probably can expect some phonecalls from the CERN...

This clue is probably also the last clue the mystery box will give me, a running led sequence after the hint gives me the impression that its job is finished. I am shedding no tears, it is still electronics and it can't withstand salty water very well:


U'2F'UBMU'SI'G'5HY'W'KGZ'W'V'UI'H'B'VCNR'LBW'9UBMV'LI'G'1LDC'B'QDW'XSAW'U'
GBMF'TZ'W'4GZ'W'4GDH'J'VDX'DKY'X'R'1BS'4GQ'MV'3AW'PZI'H'Z'PY'S'B'IBG'9NL'I4UT


What the hell? Is this my final hint? This is not human readable. No easy "Congratulations, the present can be picked up at the trainstation in locker 1306"? Did I read the morse code right? Yes, I think I did! Did something went wrong with compressing the data or did Matlab had a bad day? Not likely.

Chuckles of recognition of some of my friends gave me definitely the idea that I got the clue right. As you all can understand, more to follow...

see also: Mystery LED in a box: part 6
see also: Mystery LED in a box: part 7