Monday, August 26, 2013

Raspberry Pi and the Nokia 5110 LCD: contrast value is important

There comes a time in every tinkerer’s life that you think of a project for which a small display device would be a nice addition. Think of displaying a temperature, the time, status ‘on’ or ‘off’, etc.

It is of course easy to go to Adafruit or Maplin’s and order an LCD and for roughly $20 you would get something useful. Plus shipping naturellement.

I happened to stumble on the blog of scruss and his Quite Rubbish Clock. He uses a Nokia 5110 LCD, a 1.6” device. I believe these are surplus from old Nokia 5110 phones from around the year 2000. I had me one of those phones, nothing fancy but very reliable. The first text message I ever received was on it!

Anyway, I searched around on dx.com (Deal Extreme) and ordered 3 of these displays for the grand price of $16.20. Wait a few weeks for them to arrive and voila: time to play.

I followed the installation instructions contained in scruss’ blog. I won’t repeat them here.

However, when I ran my first test, the back light came on but then: nothing. After checking and rechecking my wiring, re-installing the software and still nothing, I decided to browse the Raspberry Pi forums to see if anyone had any advice. After a few fruitless hours, I found that the right contrast value of the display is crucial to its ability to display something.

User ‘bgreat’ on the Raspberry Pi forum had written a Python class to make using this device possible (NokiaSPI.py). User ‘pest’ on the same forum had enhanced this class even further to the point where, if the class is run as ‘main’, it goes through a number of self tests, which I think test every possible scenario. So I downloaded that version and am using it for my next project. Which, by the way, is almost ready for public showing…

Sunday, July 07, 2013

Raspberry Pi Ultra Cheap Camera Mount and Remote Bird Photography

So I got me a Raspberry Pi camera and have experimented a little bit with it. Now, it is somewhat inconvenient to have the camera dangling at the end of the ribbon cable all the time. For one thing, it makes it very hard to aim, never mind vibration control.

So, without doing much planning ahead, I started constructing a camera mount. The only thought I put into it from the outset was that it probably shouldn’t be made out of metal, in order to a) prevent accidentally shorting out any components and b) to prevent electro-magnetic interference in some of the high speed circuits that are undoubtedly part of the camera’s innards.

So I scoured the garage and found a strip of PVC, left over from the basement reno from a couple of years ago. This strip is 1 1/2”  by 3/16” (38mm x 5mm), available at most home improvement stores, usually 8’ (2.44 m) in length. It is lightweight, relatively strong and easy to work with.

I cut 3 pieces, a 5 1/2” (140mm), a 3 1/2” (90mm) and an 1 1/2” (38 mm) piece. The latter piece I diagonally cut in half, so I ended up with 2 little triangles. I then used PVC glue to weld these together, using the little triangles as braces. Then I mounted the camera on the short upright, predilling 2 holes in the PVC and using 2 very fine self tapping screws I had left over from disassembling an old piece of electronics some time ago. I figure more than 2 screws would be overkill.

Then I mounted the PI on the long 5 1/2” (140mm) strip, using 2 screws and nuts. To offset the PI from the PVC, I used a short strip of plastic tubing left over from what I believe was a Heathkit project back in the seventies!

The result looks something like this:

raspberrypi_cameramount

What’s the purpose of having a camera mount without a purpose? So I got to thinking, how about some bird photography? There are plenty of birds that gather around our back yard bird feeder.

Then I remembered that I had an old X10 pan and tilt in a box somewhere. I had previously modified this to see if I could mount and control my DSLR with this: FAIL!!!, way to heavy. As part of that process, I had mounted a modified construction bracket on it with a couple of screws, plus a hole which would fit a 1/4-20 UNC screw, normally used on consumer cameras for tripod mounting.

So I used one of those screws along with a nut to fasten the PVC camera mount to the construction plate below it (It is not visible in the picture as it is behind the front triangular brace.)

I even found the remote control for the pan and tilt. Since this Raspberry Pi is the model ‘A’, I couldn’t hook up an Ethernet cable to it (I need to order a dongle that allows me to do this to the USB port), so I used a wireless dongle based on the Ralink RT5370 chip set.

The bird feeder is about 75’ (25m) into the backyard, but at least 150’ (50m) from the router, which is stationed in the basement to begin with. So connecting to it from the bird feeder was a no-go, believe me, I tried. And tried. And tried.

Then I remembered I had an old router still available. I replaced it because the wireless on it had gone flaky (Dlink DIR-615). But it still worked (most of the time). So I hauled it out, hooked the Pi up to my monitor, keyboard, mouse combination using a powered hub, plugged in the dongle, powered up, powered up the old router next to it and used the Wifi Config (wpa_gui) utility in startx (LXDE) to connect to the router.

Once this was working, I mounted the pan-and-tilt on my tripod and mounted the camera with Pi on it. I placed the whole contraption near the bird feeder (about 5’ (1.5m)) away. I placed the router on the ground, right close to it. Here’s how it looked.

raspberrypi_cameramountandpantilthead

raspberrypi_birdfeedercamerasetup

I started up the router first, gave it some time to stabilize, then fired up the Pi. Then I went to sit on the deck and used Remote Desktop (xrdp) to connect to the Pi using my note book. From there, I started up a console session (LXTerminal) and played around with raspistill and raspivid. I also streamed video back to my lap top using raspivid on the Pi and mplayer on the laptop. I found that I couldn’t do this for an indeterminate amount of time, as the Pi would become unreachable. I don’t believe it locked up, I think just the network dropped out, but since it was running headless, there was no way to tell.

Anyway, from my position on the deck operating the laptop I could see birds on the feeder, so I waited, patiently for an exotic bird to land. Then I fired the raspistill command, with varying output file names to capture still images.

I then downloaded these using WinSCP to my laptop and modified them in Photoshop 5 for color and contrast. Since this was my first attempt, I don’t consider it bad at all. Here’s about the best one of the lot, an American finch, trespassing in Canada:

raspberrypi_americanfinch

With the remote for the pan and tilt, I can adjust where the camera looks.

Since the whole camera/Pi/pan-and-tilt combination is fairly light weight I bet it could be mounted on a mini tripod as well for use just about anywhere. Oh, to be a kid again…

Sunday, June 30, 2013

Raspberry Pi Garage Door Status Indicator with Ultrasonic GPIO without ‘sudo’

As anybody who has a garage knows, sometimes the door get left open inadvertently. Since the door is usually not visible from inside the house, that is easily done. Most of the time, there is no harm, but, if left overnight, raccoons and other undesirables may enter and create havoc.

Raspberry Pi to the rescue. In short, what I did was mount an ultrasonic sensor (HC-SR04, from eBay, $2.00, free shipping from China) on the ceiling in one of the bays of the garage (our garage is a double with a single 5 m door). When operating, if the sensor finds that is measure less than 20 cm, then the garage door is open. If the distance is between 50 and 150 cm, then the garage door must be closed with a car parked in the spot. If the distance is greater than 150 cm, the door is closed with the car gone. (Total distance from ceiling to floor is 244 cm)

sensorandgarageceiling

My primary Pi does temperature logging every minute (see earlier posts), so I decided to make the the garage door check a part of this process.

Since I used the wiringpi library as part of the temperature logging process, I do not need to invoke ‘sudo’ before starting python. However, the sample ultrasonic sensor script did use sudo, so I was forced to find a way around. In the end, I used Richard Ryniker’s gpio_control C program to export the required GPIO pins. I found it gives great results. Now I can run my Python program without using sudo.

Sometime the ultrasonic sensor gives erroneous results. Therefore, I take 20 readings (only takes less than 200 millisecond the accomplish), then drop the highest 3 and the lowest 3 readings and average the rest. This gives very accurate results. Then I write the output, i.e. the distance and the time to a text file so I can use it when a web request comes in.

Here’s the final code:

   1: def write_once(path, value):
   2:     f = open(path, 'w')
   3:     f.write(value)
   4:     f.close()
   5:     return
   6:  
   7: def checkGarageDoorStatus():
   8:     trigger = '/sys/class/gpio/gpio25/'   #TRIGGER
   9:     write_once(trigger + 'direction', 'out\n')
  10:     ftrigger = open(trigger + 'value', 'w')
  11:     
  12:     #pin_base24a = '/sys/class/gpio/gpio24/'   #RESET ECHO TO LOW FIRST
  13:     #write_once(pin_base24a + 'direction', 'out\n')
  14:     #f24a = open(pin_base24a + 'value', 'w')
  15:     #f24a.write('1')
  16:     #f24a.flush()
  17:     #f24a.close()
  18:     
  19:     echo = '/sys/class/gpio/gpio8/'  #ECHO
  20:     write_once(echo + 'direction', 'in')
  21:     write_once(echo + 'edge', 'both') #'both','rising', 'falling' are the keywords
  22:     #Note: On a longer (40'), thinner cable (24 AWG), I had to change the parameter in the above line to 'falling'.
  23:     #Also needed to subtract a constant of 6 cm from the distance total to arrive at the correct result.
  24:     #print "Ultrasonic Measurement"
  25:     #time.sleep(0.5)
  26:     z = 0
  27:     while z < 20:
  28:         fecho = open(echo + 'value', 'r')
  29:             
  30:         zero_last = fecho.read(1)
  31:         #sys.stdout.write('Initial pin value = {}\n'.format(repr(state_last)))
  32:     
  33:         po = select.poll()
  34:         po.register(fecho, select.POLLPRI)
  35:     
  36:     
  37:         z = z + 1
  38:         ftrigger.write('0')
  39:         ftrigger.flush()
  40:     
  41:         # Allow module to settle
  42:         #time.sleep(0.5)
  43:     
  44:         # Send 10us pulse to trigger
  45:     
  46:         ftrigger.write('1')
  47:         ftrigger.flush()
  48:     
  49:         time.sleep(0.00001)
  50:     
  51:         ftrigger.write('0')
  52:         ftrigger.flush()
  53:     
  54:         events = po.poll(1000)
  55:         t1 = time.time()
  56:         fecho.seek(0)
  57:         first_last = fecho.read(1)
  58:     
  59:     
  60:         events = po.poll(1000)
  61:         t2 = time.time()
  62:         fecho.seek(0)
  63:         second_last = fecho.read(1)
  64:     
  65:         if len(events) == 0:
  66:             #sys.stdout.write('  timeout  delta = {:8.4f} seconds\n'.format(t2 - t1))
  67:             nDistance = 0
  68:         else:
  69:             #sys.stdout.write('value = {}  delta ={:8.4f}\n'.format(state_last, t2 - t1))
  70:             TimeElapsed = t2 - t1
  71:             nDistance = TimeElapsed * 34300/2
  72:             #print zero_last
  73:             #print first_last
  74:             #print second_last
  75:             
  76:         #print ("Distance: ={:8.1f}".format(nDistance)) + " cm"
  77:         fecho.close
  78:         if z == 1:
  79:             lResult = [nDistance]
  80:         else:
  81:             lResult.append(nDistance)
  82:             
  83:     lResult.sort()
  84:     #print lResult
  85:     del lResult[19]
  86:     del lResult[18]
  87:     del lResult[17]
  88:     del lResult[2]
  89:     del lResult[1]
  90:     del lResult[0]
  91:     #print '\n'
  92:     #print lResult
  93:     
  94:     nTotalDistance = 0
  95:     for l in lResult:
  96:         nTotalDistance = nTotalDistance + l
  97:     
  98:     nAverageDistance = nTotalDistance/14
  99:     #print nAverageDistance
 100:     dDateTimeRecorded = datetime.datetime.now()
 101:     if (nAverageDistance > 5 and nAverageDistance  < 20):
 102:         cStatus = "OPEN"
 103:     else:
 104:         if (nAverageDistance > 30 and nAverageDistance  < 150):
 105:             cStatus = "CLOSEDWITHCAR"
 106:         else:
 107:             cStatus = "CLOSEDWITHOUTCAR"
 108:     with open('GarageDoorStatus','w') as file:
 109:         file.write("{}\n".format(cStatus))
 110:         file.write("{}\n".format(dDateTimeRecorded))
 111:         file.close()
 112:     return cStatus    

This is how it is called:



   1: def main():
   2:     os.system("gpio export 11 out")
   3:     os.system("gpio export 18 out")
   4:     os.system("gpio_control 25 export")
   5:     os.system("gpio_control 8 export")
   6:     wiringpi.wiringPiSetupSys()
   7:     wiringpi.GPIO(wiringpi.GPIO.WPI_MODE_SYS)
   8:     wiringpi.pinMode(11,wiringpi.OUTPUT)
   9:     wiringpi.pinMode(18,wiringpi.OUTPUT)
  10:     #wiringpi.pinMode(24,wiringpi.OUTPUT)
  11:     loadDrivers()
  12:     nSlaveCount = findNumberOfSensors()
  13:     lSlave = findSlaves(nSlaveCount)
  14:     cAmbientTemperature = "N/A"
  15:     while True:
  16:         wiringpi.digitalWrite(18,1)
  17:         checkTemps(nSlaveCount,lSlave)
  18:         wiringpi.digitalWrite(18,0)
  19:         if (checkGarageDoorStatus() == "OPEN"):
  20:             print "Open"
  21:             wiringpi.digitalWrite(11,1)
  22:         else:
  23:             print "Closed"
  24:             wiringpi.digitalWrite(11,0)
  25:         nCurrentSecond = datetime.datetime.now().second
  26:         time.sleep(60-nCurrentSecond)

Note that when the status is found to be open, GPIO Pin 11 is turned high. This I use to turn on an LED which I mounted next to the furnace thermostat in the living room. Now, in order to make this more attention grabbing, I wanted it to be a flashing LED. Of course the Pi could do this, but in this case that seemed like overkill. So I bought an LED that flashes all on its own, at about 2 Hz. (KLF-336HD-3P).


thermostatwithled


I also made it part of the web page that my Pi can produce (see earlier posts).


garagedoorstatusonwebpage


In case you are wondering, the first 7 lines show temperatures inside, outside and in my generation housing (see earlier posts).


Although it seems a rather trivial project, it was nonetheless very time consuming. Pulling wires from the utility room where the Pi  is located to the garage, as well as to the living room next to the thermostat (doing it decently, that is) takes far more time than you wish it would. Then, finding a workaround for sudoless ultrasonic sensing, fitting the new into the existing Pi setup, testing a flashing LED on the Pi (ya never know what it might do) all took its sweet time. But then, hey, it is all worth it when in the end it works and it is useful.

Tuesday, June 25, 2013

Raspberry Pi Ultrasonic Sensor. Use GPIO Without Sudo

Search the web, and you’ll find quite a few pages discussing the HC-SR04 ultrasonic distance sensor. It is cheap, easy to configure and great for experimenting or non crucial measuring jobs. When used on the Raspberry Pi, however, almost all examples I have seen force you to run the sensor application as superuser (sudo). This means that the entire application has elevated privileges. In general, this is not a good idea.

Search as I might, I was not able to find an example of a non sudo application that used an interrupt where timing was crucial. So I decided to do some research to find a way around this.

Background: I am trying to add distance measurement capability to my Pi, which already does temperature measurements and tracks the sump pump level using a second Pi. All this is done without using ‘sudo’, and since the new functionality is to be integrated into the existing functionality I had to find a solution. I am using Python 2.7 as my main development language.

I am using wiringPi in the existing setup, but it does not handle interrupts. So a Google search is next.

First, I found an article in the November 2012 edition of MagPi by Richard Ryniker entitled ‘GPIO and Interrupts’, which gave a good overview of sudo, interrupts and the like. You can read a pure text version of the article here, without having to look up the magazine version.

The first thing to take away from that is that if you want to use GPIO pins without using sudo you need to download and compile gpio_control.c from Richard’s site. All the instructions on how to compile and then copy and chmod the executable are embedded in the text of the download.

Once you have done that, then you can give a command like this

$ gpio_control export 23

which simply means any user can now use pin 23 without using sudo

To revert control once you do not need this anymore:

$ gpio_control unexport 23

Next, I studied his application for the maximum LED blink rate in Python. This explains how to write a value to a pin. After that, I studied his interrupt example, showing how to detect when a designated pin goes high (or low), i.e how to read the value of a pin.

I then modified the ultrasonic sensor ‘sudo’ application that Matt Hawkins wrote over at Raspberry Pi Spy, to account for the new sudo free approach using interrupts. When running the sudo version and this version, the results are virtually identical, any differences are probably due to the CPU load at that very instant.

Here is the application:

   1: #!/usr/bin/python
   2:  
   3: # Test interrupts.
   4:  
   5: import time,select,sys
   6:  
   7: def write_once(path, value):
   8:     f = open(path, 'w')
   9:     f.write(value)
  10:     f.close()
  11:     return
  12:  
  13: pin_base23 = '/sys/class/gpio/gpio23/'   #TRIGGER
  14: write_once(pin_base23 + 'direction', 'out\n')
  15: f23 = open(pin_base23 + 'value', 'w')
  16:  
  17: pin_base24 = '/sys/class/gpio/gpio24/'  #ECHO
  18: f24 = open(pin_base24 + 'value', 'r')
  19: write_once(pin_base24 + 'direction', 'in')
  20: write_once(pin_base24 + 'edge', 'both') #'rising', 'falling' are other keywords
  21:  
  22: print "Ultrasonic Measurement"
  23: state_last = f24.read(1)
  24: #sys.stdout.write('Initial pin value = {}\n'.format(repr(state_last)))
  25:  
  26: po = select.poll()
  27: po.register(f24, select.POLLPRI)
  28: f23.write('0')
  29: f23.flush()
  30:  
  31: # Allow module to settle
  32: time.sleep(0.5)
  33:  
  34: # Send 10us pulse to trigger
  35:  
  36: f23.write('1')
  37: f23.flush()
  38: time.sleep(0.00001)
  39:  
  40: f23.write('0')
  41: f23.flush()
  42: events = po.poll(600)
  43: t1 = time.time()
  44: f24.seek(0)
  45: state_last = f24.read(1)
  46: #print state_last
  47: events = po.poll(600)
  48: f24.seek(0)
  49: state_last = f24.read(1)
  50: #print state_last
  51: t2 = time.time()
  52: if len(events) == 0:
  53:     sys.stdout.write('  timeout  delta = {:8.4f} seconds\n'.format(t2 - t1))
  54: else:
  55:     #sys.stdout.write('value = {}  delta ={:8.4f}\n'.format(state_last, t2 - t1))
  56:     TimeElapsed = t2 - t1
  57:     nDistance = TimeElapsed * 34300/2
  58:     print ("Distance: ={:8.1f}".format(nDistance)) + " cm"

 


In theory, using interrupts is cleaner and leaner than the old way where the application sits in a loop, uses a lot of CPU cycles to check continuously whether or not the state of the pin has changed.