Author Topic: Detecting an LED "blip" (Off/On/Off)  (Read 3643 times)

Carl B

  • Newbie
  • *
  • Posts: 4
Detecting an LED "blip" (Off/On/Off)
« on: September 11, 2013, 02:00:59 PM »
Via an opto-fet type of circuit, we'll be able to provide an LED status indicator to the pyMCU module.

The output will be 5V for when the LED is dark (most of the time), and 0V when the LED is active. The LED active duration is an approximate 5ms "blip" and happens perhaps once a second or so.


1) What input to the pyMCU might be best used to monitor for these LED events?

2) What might some very code look like to continuously monitor for "blips" and print out their time and rough duration? (If this is asking a bit much, anything to get us going in the right direction would be apprecaiated.)

Thanks!

riklaunim

  • Newbie
  • *
  • Posts: 48
Re: Detecting an LED "blip" (Off/On/Off)
« Reply #1 on: September 11, 2013, 03:33:48 PM »
Digital pin configured as input.

You can start with this code, but you will have to change it to work in a while True loop. This code looks only for one pulse (from a ultrasonic distance sensor)
Code: [Select]
from datetime import datetime
import pymcu

mb = pymcu.mcuModule()
mb.digitalState(1, 'input') # pin D1

for i in range(0, 500):
    ret = mb.digitalRead(1)
    if ret == 1:
        end = datetime.now()
        response_end = end
        if not response_start:
            response_start = end

if response_end and response_start:
    echo_delta = response_end - response_start
    delta = echo_delta.total_seconds()
    print delta


richard

  • Administrator
  • Jr. Member
  • *****
  • Posts: 95
Re: Detecting an LED "blip" (Off/On/Off)
« Reply #2 on: September 11, 2013, 08:17:21 PM »
riklaunim has the right approach, creating a loop and polling the pin to detect the blip is the easiest way to do it.... if your program does not need to be too complex and you can cycle your loop fast enough so that you don't possibly miss the blip then you should be good to go with that approach.

I was thinking though that another interesting approach would be to use a D-type flip-flop, I tested this on a simulator but not for real yet, put your blip source into CLK and then feed 1Q back into 1D which should cause 1Q to flip between 0 and 1 every time a blip occurs, if all your concerned with is that a blip occurred and not the length of the blip this might be a good solution. All you need to do is hook 1Q to a digital pin on pyMCU then just check for a change in state. if a blip only occurs once every few seconds your loop cycle could be much longer and still catch the blip although you would not always catch the blip at the exact moment it occurred it would be accurate within as much time as it takes your loop to cycle.
just a thought.

Carl B

  • Newbie
  • *
  • Posts: 4
Re: Detecting an LED "blip" (Off/On/Off)
« Reply #3 on: September 12, 2013, 03:39:33 PM »
Thank you both very much!

During the time we're looking for the "Blip Interval" and "Blip Duration," we won't be doing anything else. Could we reasonably achieve 1/2 millisecond loop times if we're just looking at the status of D1? (It wouldn't be too difficult to just try it and find out, of course.)

If polling can't happen fast enough, then yes we'll need to trigger a flip-flop. A set-reset wouldn't be bad, have the  DUT (Device Under Test) trip the flip-flop, have the pyMCU reset it once read. Or, a mono-stable 555 timer circuit could reset itself after a comfortable interval.

« Last Edit: September 12, 2013, 04:00:15 PM by Carl B »

richard

  • Administrator
  • Jr. Member
  • *****
  • Posts: 95
Re: Detecting an LED "blip" (Off/On/Off)
« Reply #4 on: September 12, 2013, 05:03:13 PM »
Yes I believe if my calculations are correct based on the number of bytes needed to send and receive for the pymcu protocol to do a digital read you should be able to get a .5 ms update rate and you can always increase the baud rate if I am off by a little.

Carl B

  • Newbie
  • *
  • Posts: 4
Re: Detecting an LED "blip" (Off/On/Off)
« Reply #5 on: September 13, 2013, 12:24:51 PM »
Our "just try it" numbers were 16 seconds for 1000 loops. Upped that to 10,000 loops for about 160 seconds. So, without optimization but with a pretty simple loop, we were at about 16ms per loop.

Looks like we'll be setting up a trap of some sort to poll for.  :)

Well, on the off-chance that a we could be doing something "the slow way," here's the simple test loop that yields 16 ms per loop for either 1000 or 10,000 loops:

import pymcu
import time
# ##################################################
# Name: PrintLabel
# Args: duration - number of seconds the script took to run
#       label - text to be displayed
# Description: Prints duration of script execution
# Return: None
# #################################################
def PrintLabel(duration, label):
   
    print "\n" + label +" is done and took [ ",
    print '%5.3f ' % duration + " secs ]"

# "Main"
mb = pymcu.mcuModule()
mb.digitalState(2, 'input') # pin D2
hic =0

pstart = time.clock()
for i in range(0, 10000):
    ret = mb.digitalRead(2)
    if ret == 1:
       hic=hic+1

print "Num: " + str(hic)
elapsed = (time.clock() - pstart)
PrintLabel(elapsed, "10000 times")
« Last Edit: September 13, 2013, 01:19:03 PM by Carl B »

richard

  • Administrator
  • Jr. Member
  • *****
  • Posts: 95
Re: Detecting an LED "blip" (Off/On/Off)
« Reply #6 on: September 13, 2013, 04:39:31 PM »
I tried your example and got the same results, I also tried upping the baudrate to 250000bps and 500000bps, no change so the limitation is not with the actual baudrate throughput, I know usb us more than capable and the ftdi chip can go up to 1,000,000bps.
it appears the issue is on the serial read, I'll have to dig deeper into the serial library and see what's going on.
if you turn down the timeout time you can get faster results but it could potentially be missing reads.
try adding mb.mcuserial.timeout = 0.01 after you initialize pymcu
theoretically you should be able to get down to one read every 276 ns I rounded up to 500 ns to be on the safe side but that doesn't even seem to be close... this is how I came up with that number:
115200 baud (bits per second) = (115200 / 8 ) = 14400 bytes a sec.
14400 / 1000 milliseconds in a second = 14.4 bytes every millisecond
pyMCU only needs 3 bytes to send the command and digital pin info for the protocol spec. then 1 byte to read the digital pin data so 4 byte round trip.
1ms / 14.4 = 0.069 which means 1 byte every 69.44 ns
since we only need to send 4 bytes to get a digital read thats 69.44 * 4 = 277.76 ns to send 4 bytes.
so in theory you would think it's safe to say one command every 500 ns or .5 ms but I guess there are other factors at play between the serial library, windows drivers, mcu signal processing and so on. but I would have thought it would be with in +/- .5 ms at the most not a factor of 30.

I'll do some more debugging and see if there is a way to improve performance.

Carl B

  • Newbie
  • *
  • Posts: 4
Re: Detecting an LED "blip" (Off/On/Off)
« Reply #7 on: September 17, 2013, 03:49:38 PM »
Hi Richard,

We did a bit of "end user" experimentation.

We supplied approximately 100ms pulses, periodic at 500ms,  to D2.

We queried D2 with the code at the bottom of this post. Our performance was best with USB speed at 500 kbaud or 750 kbaud, and mb.mcuserial.timeout = 0.001. Any faster on either and the read data was no longer as good.

We were dropping some reads especially toward the beginning of each run. Some reads did come back with incorrect values. Nevertheless, the following most often gave good data when the reads did come through.

From this testing it appears that the the read operation turn-around is much faster than what when it returns back, but I think that's what you were saying in your prior post. :)

import pymcu
import time
import cStringIO
# ##################################################
# Name: PrintLabel
# Args: duration - number of seconds the script took to run
#       label - text to be displayed
# Description: Prints duration of script execution
# Return: None
# #################################################
def PrintLabel(duration, label):
   
    print "\n" + label +" is done and took [ ",
    print '%5.3f ' % duration + " secs ]"

#8 = 250000 baud
#10 = 500000 baud
#11 = 750000 baud
#12 = 1000000 baud   
mb = pymcu.mcuModule()
#mb.mcuserial.timeout = 0.01
mb.mcuserial.timeout = 0.001
mb.mcuSetBaudRate(11)
mb.digitalState(2, 'input') # pin D2
#in memory file
output = cStringIO.StringIO()

hic =0
nloops = 8000
pstart = time.clock()

# main
for i in range(0, nloops):
    ret = mb.digitalRead(2)
    linebuf = str(ret) + "\n"
    output.write(linebuf)
    lpc=i
    if ret == 1:
       hic=hic+1

print "Num: " + str(hic)
elapsed = (time.clock() - pstart)
l1 = str(nloops) + " times"
PrintLabel(elapsed, l1)
# output to real file here
streamWriter = open("plot.txt", 'w')
contents = output.getvalue()
streamWriter.write(contents)
streamWriter.close()