Raspberry Pi motion sensitive camera

Other than messing around with a few FORTRAN benchmarks and learning how to code using Python, I haven’t really used my Raspberry Pi computers for very much that’s been practical. However, having bought a Raspberry Pi camera to play with over Christmas, I decided to have a go at building a motion sensitive camera for the garage. It’s cheap and easy to find passive infrared detectors these days, so I acquired three for the princely sum of £5.

The passive infrared detector
PIR detector

The first challenge was working out the function of the three pins in the foreground. A little bit of searching led me to the conclusion that the top pin is the ground, the bottom pin the 5v supply, with the middle being the status pin. If the middle pin goes high, it means that motion has been detected. The sensitivity of the device, and the length of time the status pin stays high for, can be adjusted using the two potentiometers.

I connected the power pins to a couple of the available 5v supply and ground pins on a Raspberry Pi 2. I used physical pin 26 (GPIO pin 7) to connect up to the status pin.

The code

The next challenge was writing some code to detect changes in the status pin and take a photograph when motion is detected. Fortunately, there are plenty of code snippets available that made this task relatively straightforward. The current version of my code is below.

import RPi.GPIO as GPIO
import time
from picamera import PiCamera
 
# Initialise the camera settings
camera=PiCamera()
camera.resolution=(1024,768)
camera.rotation=(180)
camera.meter_mode=('backlit')
 
# Use GPIO pin 7 (physical pin 26) for the PIR detector
GPIO.setmode(GPIO.BCM)
GPIO_PIR=7
GPIO.setup(GPIO_PIR,GPIO.IN)
 
# Variables used to determine when a picture should be taken.
# GPIO pin 7 => high (ts==1) from low (qs==0) 
# triggers the camera.
ts=0
qs=0
 
try:
 
  # Wait until PIR GPIO pin is low (0)  
  print "Waiting ..."
  while GPIO.input(GPIO_PIR)==1:
    ts=0    
  print "... detector is ready"     
 
  # Loop until quit signal
  while 1:
 
    # Read PIR state
    ts=GPIO.input(GPIO_PIR)
    # DEBUG print ts
    if ts==1 and qs==0:
      # Create unique filename with timestamp and set qs high
      t=time.localtime()
      timestamp=time.strftime('%Y%m%d-%H%M%S',t)
      filename=("img" + timestamp + ".jpg")
      camera.capture(filename)
      print "Movement detected - ",filename," created"
      qs=1
    elif ts==0 and qs==1:
      # GPIO pin 7 has returned to low, therefore set qs low
      qs=0
 
    # Wait for a second
    time.sleep(1)      
 
except KeyboardInterrupt:
 
  # Cleanup GPIO
  GPIO.cleanup()
  print "PIR-PiCamera program terminated"
The results

My Raspberry Pi 2 is now set up in the garage with the motion detector and camera. At the moment it’s simply saving the images onto a drive available to my home network, but I’m probably going to experiment with sending email alerts as well.

Raspberry Pi motion sensitive cameraI’m pleased to report my motion sensitive camera has already caught an intruder …

C7 thief!

Star Trek game – a Python port from Tiny BASIC

A while back I mentioned that I was in the process of porting an old Computing Today Star Trek game from Tiny BASIC to Python on my Raspberry Pi. This was before I’d taken the edX Python course and learned to code properly in the language.

Frankly, although my code works, it is truly horrible stuff. And I didn’t even have the excuse of being limited to a couple of kilobytes of memory that the original was designed to fit into. I’ve just never had the time since to go back and do it better.

However, a couple of people have asked for the code, so here it is, in all of its – ahem – glory.

The original Tiny BASIC version (pdf format) – you’ll need this to make sense of how to play the game.

My Python port (pdf format) – you’ll need to copy and paste this into a .py file to make it work with a Python 2.7 interpreter (obviously).

Have fun!

 

edX 6.00x – final thoughts

I completed the edX 6.00x final exam last weekend, but as its been a ridiculously busy week at work (which finally finished around 5pm yesterday) I haven’t had the time to put pen to paper (or finger to ipad) until now. So here are some brief reflections on the experience.

1. Content

As an introduction to computer science and computational thinking, it’s rather good. It’s reassuring to know that the fundamental principles I first learned around 30 years ago are still sound, albeit with the implementation method being Python rather than Pascal these days. The only significant criticism I have of the content is that not enough time was taken to introduce OOP principles. It first appeared 6 or 7 weeks in and was then rushed – even though it was absolutely essential to understand it properly to successfully complete the rest of the course. Too many people seemed to struggle with the way it was introduced and some gave up in despair. Splitting this week over 2 would definitely help. Unlike a significant number of other students I don’t think this was the “fault” of the lecturer who presented this part of the course – rather, that he needed to be given more time in the schedule to communicate the material.

2. Course Leadership

Woeful. I’ve already said a lot about this in previous posts and the mea culpa of the edX leadership team published on the course information page towards the end of the course was welcome, but was too little too late. The last third of the course between Midterm 2 and the final may as well have not happened. And yes, the course was “free” for those of us who took it, but the massive step backwards in delivery quality compared with 6.002x earlier on in 2012 should have traditional distance learning institutions heaving a sigh of relief.

3. Sustainability

On the basis of the overall experience of 6.002x but especially 6.00x, there’s still considerable investment required. As I still can’t figure out how MIT et al are going to make their particular MOOC business model work (material free at the point of delivery, no advertising, low cost invigilated exams and so on) I do wonder how long it will be around for. Don’t get me wrong – the model is perfect for those of us who are simply interested in learning for learning’s sake – I just don’t think that it will work for the funding institutions, their paying students, investors and the HE sector in general.

4. Personal Progress

I ended up with 88 on the final exam. I couldn’t get problem 8 to work at all which cost me 8 of the available marks, with the other 4 lost through “finger trouble” on a couple of the multiple choice questions rather than lack of knowledge. Oh well. 94 overall wasn’t too shabby a result I guess.

I really do wish the edX team well in future. It seems to me that their real challenge is not to make online distance learning work from a technical perspective (although heaven knows they failed at even that basic task enough times on this presentation of 6.00x) as there are lots of HE institutions that do so successfully already. Instead, it will be getting their business model to work which will be the real mark of success or failure in the future.

edX 6.00x – Midterm 2 review

With Midterm 2 safely over, I can now reveal that I have just gained enough marks to pass the course – with a few more weeks of lectures and finger exercises, two more problem sets and the final exam still to go. That’s rather pleasing, so I hope no-one minds me sharing my progress chart below:

6.00x progress - after Midterm 2

6.00x progress – after Midterm 2

This time the midterm exam consisted of eight questions and was marked out of 96. I ended up with 92 – having reversed the answers for the EDrunk and PhotoDrunk random walks on question 6, losing 4 marks in the process. All in all though, it seemed easier than the first Midterm exam, which may just be a case of having had more practice with Python now I suppose, but I did manage to complete it in under 4 hours from start to finish. I would have been faster, but I took the test on Friday evening, so that necessitated a substantial break in the middle for dinner and wine …

As with the first Midterm, questions 1 and 2 were on definitions and this time I managed to think them all through *before* hitting the submit button. Question 3 was on statistical distributions and identifying which of a number of graphs belonged to particular datasets generated by a piece of code. Tricky, as the rules stated that you couldn’t simply run the code provided through the IDLE interpreter. I resisted that (huge) temptation and managed to identify them correctly.

Question 4 was on classes – with the final two parts of the question being the first two pieces of code that we were asked to write. These were a small change to the __lt__ method of a class and the creation of a generator function. Question 5 was another pencil and paper exercise on a fragment of Python code and again managed to resist the temptation to take the easy way out and use IDLE.

Finally, questions 7 and 8 both required more code to be written. Question 7 was a Monte Carlo simulation followed by the plotting of a histogram using pylab. The second part of this caused me a small problem, as it wasn’t clear that only the plotQuizzes() function needed to be submitted to the grader and not the generateScores() function which also needed to be written to support it! The error message I received on my first failed attempt hinted that this was the problem (something along the lines of not being allowed to use a random function call) and it went through on my second attempt. It’s clear from the 12 hours extension given for just this part of the exam that others had problems too (and also found other issues with the grader). Question 8 was on probability, with a fairly simple piece of code to write. Well it was simple, provided that you could solve the first part of the question, for which only a single attempt was allowed! Without knowing the correct answer (or being able to subsequently guess it), the coding would have been rather difficult.

Tonight I’ve finished the week 10 lectures – for which there currently appears to be no finger exercise posted. Past experience suggests that some may appear between now and Wednesday so I’ll keep looking in the meantime, just in case.

edx 6.00x – week 8, week 9, a confession and onto Midterm 2

It’s been a while since I wrote about my progress on edX 6.00x. However,  the course has been fairly uneventful until a couple of evenings ago when I completed problem set 8 (which was part of week 9, due to the US Thanksgiving holiday). It’s a little more stressful now, as I’m trying desperately to work out where I might manage to fit in a few hours before 0459 GMT on Monday morning to take the second Midterm exam.

Week 8 consisted of a single lecture sequence and a few finger exercises on sampling and probabilities, hashing algorithms and Monte Carlo methods. All pretty straightforward fare, especially with no problem set to solve. Week 9 started with a lecture sequence on statistical thinking covering variances and standard deviations, followed by a sequence on distributions. So far, all of the statistics covered on the course have been descriptive and despite the original syllabus suggesting that some inferential statistics would be covered, there’s been no sign of them … yet! All in all, week 9 has been a reminder of some of the statistical concepts covered during my OU psychology courses. The difference this time has been that I’ve had to write my own code to calculate things rather than relying on an application like SPSS.

I have a confession to make about problem set 8 – which involved using Python and Pylab to implement a stochastic simulation of patient and virus population dynamics. It took me 12 of the allowed 30 submissions before I managed to get the big emerald tick for my ResistantVirus class. A large number of those resubmissions were down to user error. These went something like:

“Hmm. I have test case 7 wrong. Let’s look at my code. Oh – I see the problem. Hack hack hack hack … ok, select the class to copy from the IDLE window, control C. Over to edX browser window. Ah. my old code is still in the grader. Control A, Control C … whoops, no Control X. Time to post my new code in. Control V. Grade. What?!??! Still wrong? Ok, let’s tweak the code again …”

Anyway, I eventually got there – but I was right a couple of hours earlier on than I’d realised. I will need to be far more careful on Midterm 2 …

edX 6.00x week 7 – plots and simulations

After completing week 6, where the fundamentals of OOP were brain-dumped in half a dozen short videos, week 7 apparently changed tack. The first lecture sequence briefly introduced the NumPy and SciPy libraries and was followed by a lecture sequence on simulations and random walks.

I say that the course apparently changed tack as although problem set 7 was a simulation task, being successful relied heavily on applying the OOP concepts taught in week 6. I suspect that this will be true for the rest of the course. Although it may have seemed to some students (judging by the reaction on the forums) that spending more time on the introduction to OOP was needed, in reality I suspect that we’re going to get lots more practice as the course progresses.

I must be starting to feel more comfortable with the idea myself, as dealing with the OOP aspects of this week’s problem set didn’t seem to intrude on the main task, which was to create a couple of different classes of robots to clean tiles in a rectangular room using slightly different strategies. The ‘StandardRobot’ used a strategy of randomly changing direction when it was about to hit a wall, with the ‘RandomWalkRobot’ using a strategy of randomly changing direction before every move.

Probably the most interesting part of the task was deciding how best to represent the room and the tiles (cleaned or not). The discussion forums have seen students use two-dimensional lists of clean and dirty tiles, dictionaries, sets, multiple lists … all kinds of inventive solutions. Initially, I chose to record the position of each tile as it was cleaned in an unordered list, iterating through it each time a robot landed on the next tile and adding that tile if it hadn’t already been cleaned. It worked (and got me through the grader) – but it was only when I started playing with the solution on my Raspberry Pi that I realised how awful the representation I’d chosen was. It’s not a good representation as it takes longer to check the list as more tiles are cleaned – at the same time that it becomes less likely for the robot to land on a tile that hasn’t already been cleaned.

An obvious alternative that I’m sure is better would be to reverse the logic of data structure so that the position of the dirty (all) tiles are initially stored  and then removed as they are cleaned. However, in the end I settled for using a list of length room height* room width which simply contained True or False values representing clean and dirty tiles respectively. As each tile is cleaned, the position (y value*room width) + x value is set True (and if it wasn’t already True, the number of cleaned tiles in the room is incremented).

The results of the change were impressive:

Execution times for 1,000 trials, all tiles cleaned, speed 1, using a single StandardRobot on an Intel 2.5GHz x86 Family 6 Model 23 running Windows XP

Original data structure

Revised data structure

5×5 room

4.4 seconds

1.7 seconds

10×10 room

70.6 seconds

8.1 seconds

15×15 room

401.5 seconds

20.2 seconds

20×20 room

1374.9 seconds

39.1 seconds

Execution times for 1,000 trials, all tiles cleaned, speed 1, using a single StandardRobot on a 256Mb Raspberry Pi Model B running Raspbian

Original data structure

Revised data structure

5×5 room

62.4 seconds

24.1 seconds

10×10 room

961.7 seconds

113.3 seconds

15×15 room

 –

287.3 seconds

20×20 room

 –

551.7 seconds

Unfortunately, the automated graders used by 6.00x don’t give marks for style or efficiency(*) so I haven’t bothered to resubmit my answer. I suspect that on the actual 6.00 course run at MIT, marks are awarded for such considerations. They certainly were on my computing degree in the early 1980s. This therefore illustrates one of the limitations inherent in this type of online course. And sometimes even the efficiency with which the result is obtained isn’t a good predictor of elegance. I suspect that the most efficient answer to the 6,9,20 problem from Midterm 1 was the one which simply returned a True or False value for the function depending on whether the value was in a hard-coded list. Clever perhaps, but not a general solution to the three box problem!

(*) Well, provided that the answer you give produces the correct result against the 6.00x test suites in under 30 seconds of execution time I believe.

edX 6.00x week 6 – going up a gear

Whew. Suddenly, after five relatively straightforward weeks, 6.00x has kicked up into a higher gear. I’ve just got to the end of this week’s lectures, finger exercises and problem set and it’s been far more taxing than anything, including the midterm exam, that preceded it. The main theme of the week has been an introduction to object-oriented programming, with various concepts (exceptions, classes, instances, inheritance and so on) being used for the first time.

This is the part of the course, while not being totally new to me, is the part that I’m least familiar with. All of the ‘production’ code that I ever cut in my career was definitely not object-oriented – and what little OO code I have created has been for the purposes of demonstrating other software packages, rather than being something coded to form an integral part of such a package. There’s a difference – as if your code doesn’t need to go into production you start to get a little sloppy about things – and the edX grader definitely won’t let you get away with that!

This week’s problem set has involved writing a number of classes to complete a program which selects and displays content from rss feeds if particular trigger words or combinations of them appear in its configuration file. There was definitely some subtlety required to complete the task successfully and the very final part of it took me ages because I’d made a silly error. However, I appeared to be in good company, as at least two other people on the edX forum had made exactly the same error. (Hint: if you end up with the error message: ‘str’ object has no attribute ‘evaluate’, for the final part of problem set 6, have a look at what you’re passing to the boolean triggers. It should be the actual object from the triggerMap dictionary, not its constructor).

At the time of writing (Sunday afternoon), neither of the graders for the penultimate and final part of problem set 6 are up and running, which is a little frustrating. Adding to the frustration this week has also been the bug in the problem set that becomes apparent when doing filtering (the code is expecting methods like get_guid() instead of getGuid() as was required by the grader earlier on) – but this is simple to fix of course.

There was also a documentation issue in one of the earlier finger exercises. In it, the grader tests whether your isPrime() function can handle an input value of 0, whereas the problem definition says that the function only needs to consider numbers greater than or equal to 1. Fortunately, the diagnostic output from the grader is very useful in ironing out such wrinkles. Being able to debug other people’s code and documentation is an important skill for any programmer to pick up!

However these minor problems, grader outages, the availability of only the current week’s material and the push back of the release date for each week’s material from Mondays to Wednesdays all give an impression that the 6.00x course team are a little overstretched – much more so than was apparent on 6.002x earlier on this year. I don’t think anyone on the course this time around minds being a guinea pig (after all, the content is excellent and it’s free to participate), but it’s clearly something that will need addressing in future if the plan to charge for completion certificates is to come to fruition.

After all, one of the benefits of online or distance education should be that the material is available for you to work on when you have the time to study it. Getting ahead of the timetable was something I always tried to do on my OU courses, as you never know when real life is going to get in the way. And for me, I think real life is just about to do exactly that. But for the moment, I’m just waiting impatiently for week 7 to start.

Update 12th November

The graders for the final two parts of problem set 6 are now up and running. But guess what. Despite the docstring for makeTrigger() being explicit that it returns a value of None, it won’t pass the grader unless you return triggerMap[name]. Sighs again.

edX 6.00x – Midterm 1

With the deadline for the submission of the first midterm exam safely past, I’m now able to reflect on my performance here. 95/100 is respectable enough – although having dropped 4 out of 8 marks on the very first question, it wasn’t looking too promising early on Saturday morning. Note to self: read the question, read the question again and read the question again before submitting the answer for checking!

Fortunately I only lost one further mark (out of the 20 available for the sorting and complexity question) and managed all of the questions which required Python programs to be submitted (5 of the 8 questions on the paper) without any real difficulty at all – even though the final part of question 8 was a bit of a teaser. In real life, I think the way to have fixed the bug would have been to have thrown the code away and started again – with a solution that looked more like the second part of the question – rather than tweaking the rather strange code that was provided. But I guess the point of the exercise was to demonstrate an understanding of variable scope and how to pass functions as arguments to functions, rather than good coding style.

There was one question for which I’m particularly pleased with my answer, partly because  even though I’d not come across the puzzle before I managed to figure out an elegant and recursive answer in around 3 minutes!

The problem asked for a boolean function to determine if an arbitrary number of food items (I refuse to advertise the brand) could be packed exactly into boxes holding 6,9 and 20. For example, 21 should return True (9+6+6), whereas 7 will return False.

Recognizing that the problem is easy to solve recursively (i.e. for quantities of 20) led me to this solution outline very quickly:

If the quantity requested is less than 6, return False

else if the quantity requested is divisible by 3 with no remainder or the quantity requested is divisible by 20 with no remainder, return True

else return the value of this function for the quantity requested – 20

After I’d got to this answer I did try to think about how I might create an iterative version, but nothing I tried seemed to be particularly elegant. Searching the web after the exam had closed revealed a number of different iterative solutions to this and similar problems, but in this case, a recursive answer definitely seems to be both easier to understand and to program.

The week 6 material should be out later on today and we’re just about to get into the part of the course that wouldn’t have been taught when I was taking High Level Programming ‘A’ using Pascal at Warwick University in 1982 – object orientation.

edX 6.00x week 5 – Searching and sorting

Looking at searching and sorting algorithms is a logical way to follow on from an initial discussion of algorithmic complexity, so I wasn’t completely surprised when the material for this week addressed precisely those two topics. Linear searching, selection sort and merge sort algorithms were covered along with a discussion of how to calculate their complexity. There was also some light relief as the usual “talking head” videos were supplemented by a rather quirky video on how to amortize the cost of algorithms.

If I ever need to figure out the costs of storing and moving puppies I now know where to go … and no, that’s not me in the video, even if he is called Tim. One of us is definitely far better looking than the other …

I completed week 5 earlier on this week, so I’ve been working on the first midterm exam today. The honour code forbids students from talking about this until it has closed for everyone (just before 0500 GMT on Monday) so I’ll leave my reflections on it until a later post.

1 2