EKM 25IDS Pulse Output Circuit & Python code

Forum is open to all questions, answers, and discussions related to electric meters, ours or others.
Post Reply
Posts: 1
Joined: Sat Feb 11, 2023 7:02 pm

EKM 25IDS Pulse Output Circuit & Python code

Post by Blackhawk »

I've been using my 25IDS for a few years and recently decided to try and read it remotely using 485 or the pulse output. I found the 25IDS does not have 485, so I started looking into the pulse output. As others have posted on this board, I found it very difficult to obtain detailed information on the Pulse output. Nothing on the spec sheet, etc. Support provided this somewhat cryptic response:
  • The Pulse Output of all of our electric meters is a non-powered open/close switch (though solid state - not a mechanical relay). Electrically the Pulse Output is very similar to the closing of a dry contact switch, such as a Reed switch. Your device would need to put a low voltage on the line and sense when the circuit closes at the meter end, indicating one pulse.

    Pulse Output Specs:
    Impulse width: 90ms
    Compatible voltage (the meter itself does not put out a voltage): 27V max
    Current range the meter's pulse output can handle: ≤27mA
    The EKM-25XDSE and older EKM-25IDS meters will produce 800 pulses per kWh
After doing some experiments, it seems that the 'solid state switch' is simply an opto-coupler with both the collector and emitter provided which is why the output has polarity. I provided a diagram of the EKM and two output configurations for Positive or Negative pulse outputs. The 27V spec would be the Maximum Voltage across the Collector-Emitter-Open (Vceo), and the 27mA would be the Max Current (Ic) of the opto-coupler. In general, you never want to approach these limits because if you damage the Opto output, you are done. Better to keep the voltages and currents low or provide an output buffer as shown below. Also note that long wires from the meter to your circuit are susceptible to induced voltage spikes so keep your circuit and close to the meter as possible and/or provide some type of transient surge protection.

I have a Raspberry Pi Zero, so I decided to use that to read and count the pulses. After some trial-and-error, I came up with the following Python3 code that just prints out the same reading as displayed on the LCD each second. This is just proof-of-concept code to see if I could read the pulses and make it match the display. More work needs to be done to log the readings and read them remotely. I also provided an LED that is turned on by the code while the pulse is active and it flashes in sync with the Red LED on the meter. To start the Python Demo script you just open a terminal window and type :

python3 pulse2.py -k 1234.75

where the number 1234.75 is the current reading on the LCD

Code: Select all

# EKM-25IDS KWHr meter Pulse counter Demo Program
# 25IDS has an Isolated Optocoupler output.
#   Collector is labeled (+)
#   Emitter is labeled (-)
# The Pulse output supplies 800 pulses per KwHr
# The number on the 25IDS LCD display is total-counts / 800
# The LCD reads in 0.01, which is 8 cnts per .01
# The output pulse stays active for ~90mS (has a little jitter)
# Connections to Pi :  https://pinout.xyz/
#   25IDS (+) to 3.3V on Raspberry Pi
#   25IDS (-) to GPIO24
#   Add external 2K pulldown from GPIO24 to Gnd
#   Internal Pulldown may work, not tested
# Added LED with series 680 ohm from GPIO25 to LED+, LED- to Gnd
#   LED flashes on each pulse, in sync with the Red LED on meter
#   Rising edge, turn on, Falling Off
# This program uses gpiozero module to interface with the R-pi I/O pins
# https://gpiozero.readthedocs.io/en/stable/index.html
# https://gpiozero.readthedocs.io/en/stable/recipes.html#pin-numbering
# To check if gpiozero is already on your Pi, type:
#   pinout    in a terminal window
# If you get a response, you have the library, if not, install it:
#   sudo apt update
#   sudo apt install python3-gpiozero

# We want to control 1 LED and read an input pin

from gpiozero import LED
from gpiozero import DigitalInputDevice

from time import sleep  # for time delays

PULSE_PIN = 24      # Pulse input GPIO24. Header pin 18
LED_PIN   = 25      # LED Output GPIO25.  Header pin 22. '1' == ON

led = LED(LED_PIN)

# A variable to count pulses.
# The Max the LCD display is 99999.99, or 100,000 kwh
# 100,000 kwh * 800pls/kwh = 80,000,000 pulses

pulseCnt = 0
                                      [ Read 123 lines ]
MAX_PULSE_CNT = 100000 * 800  # guess we should reset the pulse count here

def PulseRising(gpin): # Rising Pulse Callback function

    global pulseCnt
    global led

    #print('Pin value = ', gpin.value )

    led.on()   # Turn on the LED

    # Count the pulse, check for overflow
    pulseCnt += 1
    if pulseCnt >= MAX_PULSE_CNT :
        pulseCnt = 0
        print("Pulse count rollover!")

def PulseFalling(gpin) : # Falling Pulse Callback Function
    led.off()            # just turn off the LED

#Command line args, set default pulse count, etc
import argparse
cmdparser = argparse.ArgumentParser()
cmdparser.add_argument("port", help="Specify HTTP port other than default port 80", nargs='?'$
cmdparser.add_argument("-kwhrs",   "-k", help="Initial KwHours reading from LCD like 345.76")

args = cmdparser.parse_args()

print("Processing Command line args:", args)

if args.kwhrs :  # Set initial pulse count to get R-Pi to match LCD
    pulseCnt = int(800*float(args.kwhrs))
    if pulseCnt >= MAX_PULSE_CNT :
        pulseCnt = 0
        print("Max KwHrs is 99999.99! Setting to 0 ")

# Setup Pulse input Pin
# Not sure how bounce time works, using something less that 90mS.
# Maybe a hold-off before another interrupt can occur?
# Once Callback function is registered, it starts counting

# https://gpiozero.readthedocs.io/en/stable/api_input.html#gpiozero.DigitalInputDevice

# Setup input Pin, we define Active as High (True)

# The EKM Opto output shouldn't bounce, but we have 90ms to spare so use 30mS bounce time

pulseInput = DigitalInputDevice(PULSE_PIN, pull_up=None, active_state=True, bounce_time=0.030)

# Assign call back functions (what to do on Pulse goes active (rising)

pulseInput.when_activated   = PulseRising    # do NOT use () PulseRising() NO NO NO
pulseInput.when_deactivated = PulseFalling

# Main loop - Print the Pulse count

try :
    while True:
        print("PulseCnt = ", pulseCnt, pulseCnt/800 )

except : # trap Ctrl-C so I can do any cleanup

# These are not necessary, but this is how you do it manually...


EKM Pulse Output circuit
EKM Pulse Output circuit
EKM-Meter-Opto.JPG (78.21 KiB) Viewed 98722 times
90mS Pos Pulse with Pull-down to Gnd
90mS Pos Pulse with Pull-down to Gnd
EKM-Pos-Pulse.JPG (116.26 KiB) Viewed 98722 times
90mS Neg Pulse with Pull-up to 3.3V
90mS Neg Pulse with Pull-up to 3.3V
EKM-Neg-Pulse.JPG (103.24 KiB) Viewed 98722 times
Post Reply