Directly connecting to Optical Pulse Counter with RPi?

I think there are several topics in here that could be useful

  • using the emonhub socket interfacer
    • setting one up, the options etc
    • using one across the LAN (ie handling UFW rules and using hostnames/IP addresses and ports
    • creating a simple script that posts data to an emonhub interfacer
  • Using the Pi’s GPIO
    • Physical conns
    • Addressing the gpio pins
    • catching pulses
    • hooking up surface mount Ethernet sockets to expand the Pi’s gpio to connect pulse counters and temp sensors with rj45 plugs
  • Writing a simple systemd unit to manage a bespoke script

but I wouldn’t know where to begin, that’s why I just tend to post stuff on the forum.

When i try to run pulses.py on a raspberry pi 3 running the latest emoncms image, I’m getting the following:

pi@emonpi(ro):~$ python pulses.py 
 Traceback (most recent call last):
 File "pulses.py", line 118, in <module>
  main()
 File "pulses.py", line 103, in main
  GPIO.add_event_detect(pulse_pin1, GPIO.BOTH, callback=eventHandler1, bouncetime=bounce)
 RuntimeError: Failed to add edge detection

Seems like the script is not able to communicate with the GPIO?

I get a similar result when using this gpio test script gpiotest.py

Thinking that this might be a case of the gpio not being accessible, I edited my conf to comment out the [[RFM2Pi]] interfacer since it looked like that was potentially tying up the gpio board. No change.

Anything I’m missing?

Sorry, I’ve not seen that before. I have just done a quick internet search and most (but far from all) discussions around that error seem to point to permissions or incorrect pin refs.

I’m afraid it’s going to be a while before I can get to checking this and it was quite a long time ago I wrote that script, I put it into service and it’s worked ever since, I’ve not had any cause to look at it again since, so off-hand I can’t really think of anything to try beyond checking the pin references are ok, perhaps even try running the script as sudo???

Ah,yeah, permissions issue apparently - running it as sudo worked; will have to make sure I figure out how to run with elevated permissions in systemd / startup.

Now however I’m getting an socket error:

socket.error [Errno 111] Connection refused

I have opened up 50012 using the command in the script

sudo ufw allow 50012

and
sudo ufw -f enable

I’ll look around the forums to see if this is seen by others.

Nevermind, Ok, I had the:

[[Pulse]]
    Type = EmonHubSocketInterfacer
    [[[init_settings]]]
            port_nb = 50012
    [[[runtimesettings]]]
            pubchannels = ToEmonCMS,
            timestamped = True

In the wrong section. ( I had it at the end of the conf so it was under the nodes section)

Now when i touch pin 13, i’m getting a pulse detection and it is writing to the node 18 pulsecnt1 as expected

Now that I have that working, I need to set up a wH Accumulator, right?

Personally I’ve never had much joy with the whaccumulator process, I use the “total pulse count to pulse increment” process.

If you search “total pulse count to pulse increment” here on the forum you can find more info, in particular the “Wh accumulator - strange behavior” thread discusses the issues you could have.

Thanks Paul,

If I want to sync to my current meter reading, say its 40644 kwH, would I set pulse_id =

{1:40644000,2:0}

My node is configured as:

[[18]]
nodename = pulsecounter
[[[rx]]]
    names = pulsecnt1, pulsecnt2
    scales = 1, 1
    units = Wh, Wh

I’m testing the script right now and it doesn’t always increment the pulse_id value:

1520357220.42 18 40664020 0
1520357277.69 18 40664020 0

I can understand why you might want to do this, but if you must, then consider trying a virtual feed, the data storage in emoncms is in 32bit floats, this equates to around 7 digits of accuracy so the next increment to 40664020 0 will be 40664030 0 and depending on how your processing is set up, you may need to see that whole jump in one update, it maybe that every update that doesn’t reach that increment is ignored/lost, so effectively it might only be registering use that is over 10 Wh in any one interval, that could be a large portion of your usage.

I want to track the actual meter reading as closely as possible (i need to report it monthly manually to earn my solar renewable energy credits for generation).

Is there a better way to do this?

Basically the datatype you are using (phpfina or phptimeseries) cannot offer you the scope and resolution to do what you want. You need to store the change in pulsecount and then add the starting meter reading back in afterwards, either by manually calculating it each month or by setting up a virtual feeds so that you are recording the “change in pulse count” but displaying the “meter tracking” because the virtual feed adds the starting reading to every value when graphed or displayed.

Alternatively you could look at other storage engines, but there may be other consequences, eg the apps module only works with phpfina (without hacking).

TBH, if you need to be submitting “meter readings” then that’s what you should be doing “reading the meter”, I’m pretty familiar with all this stuff to the point it’s pretty predictable, but if I submit a meter reading, I read the meter.

If the meter isn’t electronically “readable” eg registers accessible via modbus or infrared etc, and it’s not easily accessed, maybe you should be looking at a remote camera or cctv so you can remotely take a peek at the meter once an month.

Hi Paul, I’m struggling to find more info on the connections between the optical sensors and the GPIO pins. I’ve made my own surface mount ethernet sockets with jumper wires connected to each punch down. Looking at the RJ45 on the optical sensor it looks like there are connections to Pins 1,2, 5 and 6.

Sorry to be a pain, could you please advise what GPIO you have connected 1,2,5 and 6 to?
I’ve searched through other posts and the archive and can’t seem to find any schematics or guides for this.

Thanks

Mike

There are in fact only 3 active connections to the optical sensor. 2 & 5 are +5V & GND respectively, 6 is the output. It is not in fact a pulse, in that there is no control of the shape of the output using (say) a Schmitt trigger. I am measuring pin 6 at within 3 mV of GND in darkness and 35 mV of VCC in reasonably bright light. The output goes to an acceptable ‘high’ state long before the LED on the rear of the sensor lights up.

As Robert explains there is only really one “interesting” connection per optical sensor, that one wire can be connected to almost any gpio pin as long as you edit the sketch to use that gpio pin.

In my example script there are 2 gpio pins defined as this script happened to be used with 2 optical sensors.

The pins I used were as follows (physical pin numbers used rather than BCM/GPIO numbering for RPI GPIO)

optical sensor RPi
1 (nc)
2 (vcc) Pin 17 (vcc)
3 (nc)
4 (nc)
5 (gnd) Pin 9 (gnd)
6 (output) Pin 13 or 15
7 (nc)
8 (nc)

Note I used 3.3V rather than 5V to power the sensor as the Pi gpio input pins are not 5V tolerant and the sensor is designed to work at both 3.3V and 5V.

I’ve recently found this script and put it to use. I’ve also been on a mission to reduce CPU use and found the script uses 100% CPU. The problem was the way the while loop was working.

The while loop at the end is the main difference.

import RPi.GPIO as GPIO
import time
import socket

# a "pulse" is 1 unit of measurement use emonHub scales and unit to define
# eg if 100 pulses is 1m3, ie 0.01m3 each then emonHub should use scale = 0.01 and unit = m3
# Therefore "pulse_id" becomes an accumulating "total used" and should follow the meter reading

nodeid = 18
valueid = 1
bounce = 1
interval = 5
lastsend = 0
host = "localhost" #emonbase1"
port = 50012
pulse_pin1 = 21
pulse_pin2 = 15

pulse_id = {1:0,2:0}

def eventHandler1(channel):
    processpulse(1,GPIO.input(channel))
def eventHandler2(channel):
    processpulse(2,GPIO.input(channel))


#    print("event")

def processpulse(channel,status):
    global pulse_id
    global frame
    global lastsend
    if status: #GPIO.input(channel):
        pulse_id[channel] += 1
        print("Channel "+ str(channel) + "  on : " + str(pulse_id[channel]))
    else:
        print("Channel "+ str(channel) + " off : " + str(pulse_id[channel]))

    t = time.time()
    f = ' '.join((str(t), str(nodeid), str(pulse_id[1]), str(pulse_id[2])))
    if t > (lastsend + interval):
        lastsend = t
        print f
        send(f)


def send(f):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    f = f + '\r\n'
    s.send(f)
    s.close()


if rpi:
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(pulse_pin1, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.add_event_detect(pulse_pin1, GPIO.BOTH, callback=eventHandler1, bouncetime=bounce)
    GPIO.setup(pulse_pin2, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.add_event_detect(pulse_pin2, GPIO.BOTH, callback=eventHandler2, bouncetime=bounce)


try: # CTRL+C to break - requires graceful exit
    while True:
        time.sleep(5) # the value doesn't matter.
except KeyboardInterrupt:
    GPIO.cleanup() # clean up GPIO on CTRL+C exit
    exit()

GPIO.cleanup() # just in case

time.sleep() could be a millisecond, one second, 5000 seconds, makes no difference, as long as the program is running the interrupts will happen and callbacks are initiated immediately.
I hope that helps.

1 Like

Hi guys

Is there a summary of this?

I’m using the Lechacal boards on top of my RPi’s. They don’t know/understand the pulse sensor (and don’t have input points, they are however only using pins 1-10, thus there are open pins, so can hard wire the RG45 pins used to open GPIO pins + modify the above script to use the then selected pin,
(is this script going to flat line my CPU… cause problems for emonPi)?

(thinking I might connect a camera also, and take a photo once a day which can be used down the line as a sanity check against values stored/recorded by the pulse sensor.

optical sensor RPi
1 (nc)
2 (vcc) Pin 17 (vcc)
3 (nc)
4 (nc)
5 (gnd) Pin 9 (gnd)
6 (output) Pin 13 or 15
7 (nc)
8 (nc)

is there a how too, considering this seems to be a long running thread by now ?
seen some comments re the auto start of the script, and rc.local being phased out, so whats the preferred method.

G

My personal motivation for making a how-to is to get an item in the OEM shop alongside.
It’s somewhere around the top of the OEM related to-do list I have… to design an RJ45 pi hat for the optical sensors.

I think it’s now systemd? I used a guide online without much trouble.

Perhaps chop the optical lead and make up something like this for a simple plug into the Pi:

image
That image is actually a little misleading, the crimpy things go into the housing the other way around.

I’m pretty sure it helps to have a small ceramic cap on the signal line to GND for countering noise or flickering ambient light.

1 Like

Hi Dan,

thanks.

I’l rather plug the Optical sensor into a RG45 female plug, and then run out of there lines that i will plug into the RPI’s board, that way the optical sensor is untouched, should I change my mind later and get a OEM board and want to then plug it into a RG45 female connector.

G

1 Like

Sorry to revive an old thread. I am trying to use an optical sensor via RJ45 breakout socket. Headers soldered and jumpers connected to the Rpi as above. Some activity from monitor.py but no luck with the actual sensing. LED doesn’t light either, I’ve used a 3.3v pin as advice above, should I use 5v?

Now thinking about constructive vandalism, removing RJ45 plug and soldering directly. However, if I do this, any clues guidance about the cable colour codes inside?

I need just what’s in this thread, rather than the whole of emon, hence my rather direct approach. Thanks in advance.

If you’re looking for details of what’s inside to Optical Pulse sensor, there’s a link in post no.2.

Thanks! Will look.