Tuesday 24 February 2015

Pi-based Domestic Electricity Monitor - Part 5 - 'Connecting' the LDR + RPi to the meter

In this post, I've connected the Raspberry Pi to the electricity meter and created a python program to work out the consumption rate:

With the Raspberry Pi and the LDR sensor able to detect changes in light levels, it was time to 'connect' the LDR to the electricity meter's LED. Since I've read that you are not permitted to tamper with the meter at all, this consisted of taping the LDR to the front of the meter with insulating tape. (Image to follow). Should hold long-term, but easy to remove.

The meter's LED flashes 800 times for 1 kWh. From the interval between flashes, the instantaneous rate of consumption can be calculated. I made it (1/interval x 4.5). See working out below.


I made a few errors along the way, by waiting for the LED to go off but not factoring in this wait time, and messing up my maths the first time round.

Here's the output. The first colomn is the interval between flashes in seconds, the second is the power consumption in kW:


That's if my code is correct:





#!/usr/bin/env python

#First go with the LDR picking up the flashes from the electrcity meter.

import RPi.GPIO as GPIO, time, os

#procedure to wait for LED flash front edge
def wait_for_flash():
    try:
        GPIO.wait_for_edge(23,GPIO.RISING)
    except KeyboardInterrupt:
        GPIO.cleanup()       # clean up GPIO on CTRL+C exit 

#initialise pins     
DEBUG = 1
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)


#timing and kW calcs based on 800 imp / kWh

start_time=time.time()

for i in range (0,20):
    wait_for_flash()
    elapsed_time = time.time()-start_time
    start_time=time.time()
    kW=((1/elapsed_time)*4.5)
    print (elapsed_time,kW)
    time.sleep(0.3) #to allow for LED to turn off

GPIO.cleanup()           # clean up GPIO on normal exit        

print("Ending PRogram")



The next steps are to write values to a database with SQLite:
current consumption rate to 3 d.p., date and time, calculated meter reading as a check of accuracy against actual meter reading.

Then I would like to have a new program to process and analyse the data.




Monday 23 February 2015

Debugging a lesson on Debugging - Mobile Mistakes #1

iPads are wonderful devices. No really, they are. Even if they make you start a sentence without a capital letter.

This post however, is about what can go wrong in an IT lesson using mobile devices and the lessons learned.

I am working with a school that has amazing IT provision, with one-to-one across the board: iPads in LKS2 and Macbooks in UKS2, plus a suite of networked machines. I have occasional use of an iPad, so I borrowed one with 'Hopscotch' installed, to plan my Computer Science lesson on debugging for a year 3 class.

I put together what I hoped was a well-structured plan for making a tilting 'etch-a-sketch' game, with debugging being the focus, but with some cross-curricular maths work on angles included.

However, what I did not plan for was that within the class set of iPads, two different versions of hopscotch were installed, neither of which were the same as the one I had used to plan with!

You would not think that this would be so significant for something as simple as a tilting 'etch-a-sketch' game. However, what if one version of Hopscotch required using angles to set the direction of motion of the sprite, and the other used +ve and -ve co-ordinates for the same task? Some advice: don't try teaching angles to 360° and cartesian co-ordinates and negative numbers to 2 sections of a Year 3 class simultaneously. It doesn't go well.

Despite this, and the fact that it was the last hour of the last day of half term, and that there'd been a cake sale immediately prior to the lesson, the children were great. Most of the 'angle' children succeeded, and some of the x-y group got something working. But was it a great lesson on debugging? Only for me.

Lessons learned:

  • Check all the mobile devices you are going to use have the software you want installed.
  • Check it is the same version on all devices.
  • Plan your lesson using the same device the children will use (or at least the same software)






Saturday 21 February 2015

Pi-based Domestic Electricity Monitor - Part 4 - Timing intervals between flashes of the LED

The next stage in developing the electricity monitor, using the flashing LED on my domestic meter and an LDR connected to the PI, is to try to detect when the LED is on / off and log the time between flashes.

Hardware changes:

Instead of using an RC circuit, I swapped the capacitor for a 1kΩ resistor, as I am no longer interested in the analogue light level, just whether a light input is on or off. (Diag. to follow once I get Fritzing working!) [edit - Fritzing is cool]




I also added a mini voltmeter I've had kicking around for ages from a previous project, so that I could see what was happening to the voltage level on pin 23 for debugging.

Software

This was very helpful: http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio

I had an 'unusual' set up for testing, in that I was having a lie-in on a Saturday morning. I could control the blinds in my room from the bed, and that was enough to set Pin 23 high or low.

here's the code and output. It still needs a few tweaks but it works well enough for testing. Next job is to rebuild the hardware and attach it to the electricity meter.





#!/usr/bin/env python
     
# Example for edge sensing on pin 23 using a LDR and Resistor in series

#thanks to Alex Eames @ http://raspi.tv for the useful hints

#Outline:
#1)set pin low
#2)wait for falling edge
#3)start timer
#4)Wait for next falling edge
#5)stop timer and log or print time since last event
#6)reset and restart timer
#7) repeat
     
import RPi.GPIO as GPIO, time, os

#procedure to wait for transit light-->dark: 
 
def wait_for_dark():
    try:
        GPIO.wait_for_edge(23,GPIO.FALLING)    
    except KeyboardInterrupt:
        GPIO.cleanup()       # clean up GPIO on CTRL+C exit 

#initialise pins:     
DEBUG = 1
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)


wait_for_dark()

#timing
for i in range (0,5):
    start_time =time.time()
    wait_for_dark()
    elapsed_time = time.time()-start_time
    print (GPIO.input(23),elapsed_time)
    time.sleep(2)

GPIO.cleanup()           # clean up GPIO on normal exit        

print("Ending PRogram")  

Monday 16 February 2015

Pi-based Domestic Electricity Monitor - Part 3 - Writing data to a file

Warning! This post is just my rough notes as I learn how to do this, so I can find the info again. It may not be as cohesive as I would like, in the short term. I'll tidy it up when I'm done, honest I will.  

Now I can collect the data from the light sensor, I need to be able to write it to a database file.

Looking around, SQLite would seem to be a good choice for this. It's lighter weight than MySQL and, I hope, easier to work with. Also, it's recommended for local file hosting, and since the data will always live on the Pi, that's OK.

I wasted too much time trying to install SQLite, before I discovered ITS ALREADY INCLUDED WITH PYTHON!

I think I'll be needing some help with using it, so here's a tutorial or two I'll use

https://docs.python.org/3/library/sqlite3.html

http://www.tutorialspoint.com/sqlite/sqlite_installation.htm



Time-handling info:

https://docs.python.org/3/library/time.html


Before I start using the light sensor to detect the little flashing light on my electricity meter, I want to test writing to a database with live light level data. Which I'm off to try next...

(Later that same day...)

...I captured sunset light levels tonight! (My daughters went into the room to watch TV though, and turned the lights on). Actual sunset is listed as 5:31pm.


The chart was made by copying and pasting the raw text data from the screen to LibreOffice Calc and post-processing it, so that it went down and not up as the sun went down. Raw values for 'light level' went from about 1000 (bright) to 700,000(dark) as the capacitor took longer to charge in the dark.

 Here's the code I used:

#!/usr/bin/env python
     
# Example for RC timing reading for Raspberry Pi
     
import RPi.GPIO as GPIO, time, os
import sqlite3

#initiaise database tools
conn = sqlite3.connect('lightlevels.db')
c =  conn.cursor()

#create database
#c.execute("CREATE TABLE lightlevel (data text, level integer)")



     
#read light level from GPIO
DEBUG = 1
GPIO.setmode(GPIO.BCM)
  
def RCtime (RCpin):
    reading = 0
    GPIO.setup(RCpin, GPIO.OUT)
    GPIO.output(RCpin, GPIO.LOW)
    time.sleep(0.1)
     
    GPIO.setup(RCpin, GPIO.IN)
    # This takes about 1 millisecond per loop cycle
    while (GPIO.input(RCpin) == GPIO.LOW):
        reading += 1
    return reading
     
for i in range (0,90):
    lilev= (RCtime(23)) # Read RC timing using pin #23
    print (lilev) 
    print (time.asctime())
    c.execute("INSERT into lightlevel VALUES(?,?)",(time.asctime(),lilev))
    conn.commit()
    time.sleep(60)

conn.close()


Not a bad day's work play.

Next up, logging flashes of a LED, and converting the interval to a kW consumption value.


PS
I found these commands here which could be very useful later:


  • gpio wfi <pin> rising/falling/both
This causes GPIO to perform a non-busy wait on a single GPIO pin until it changes state to that indicated.


  • gpio edge <pin> rising/falling/both/none
This enables the given pin for edge interrupt triggering on the rising, falling or both edges. (Or none which disables it)

Thursday 12 February 2015

Pi-based Domestic Electricity Monitor - Part 2 - Programming the Light Sensor


It works! Here's the program (see below) running on the Pi:






















This is a very useful link:

http://www.raspberrypi-spy.co.uk/2012/08/reading-analogue-sensors-with-one-gpio-pin/

as is this:

https://learn.adafruit.com/basic-resistor-sensor-reading-on-raspberry-pi/basic-photocell-reading

If you just want the code:

  1. #!/usr/bin/env python
  2.  
  3. # Example for RC timing reading for Raspberry Pi
  4. # Must be used with GPIO 0.3.1a or later - earlier verions
  5. # are not fast enough!
  6.  
  7. import RPi.GPIO as GPIO, time, os
  8.  
  9. DEBUG = 1
  10. GPIO.setmode(GPIO.BCM)
  11.  
  12. def RCtime (RCpin):
  13. reading = 0
  14. GPIO.setup(RCpin, GPIO.OUT)
  15. GPIO.output(RCpin, GPIO.LOW)
  16. time.sleep(0.1)
  17.  
  18. GPIO.setup(RCpin, GPIO.IN)
  19. # This takes about 1 millisecond per loop cycle
  20. while (GPIO.input(RCpin) == GPIO.LOW):
  21. reading += 1
  22. return reading
  23.  
  24. while True:
  25. print RCtime(18) # Read RC timing using pin #1
or

#!/usr/local/bin/python

# Reading an analogue sensor with
# a single GPIO pin

# Author : Matt Hawkins
# Distribution : Raspbian
# Python : 2.7
# GPIO   : RPi.GPIO v3.1.0a

import RPi.GPIO as GPIO, time

# Tell the GPIO library to use
# Broadcom GPIO references
GPIO.setmode(GPIO.BCM)

# Define function to measure charge time
def RCtime (PiPin):
  measurement = 0
  # Discharge capacitor
  GPIO.setup(PiPin, GPIO.OUT)
  GPIO.output(PiPin, GPIO.LOW)
  time.sleep(0.1)

  GPIO.setup(PiPin, GPIO.IN)
  # Count loops until voltage across
  # capacitor reads high on GPIO
  while (GPIO.input(PiPin) == GPIO.LOW):
    measurement += 1

  return measurement

# Main program loop
while True:
  print RCtime(4) # Measure timing using GPIO4