DigitalSignal abort function fails at low frequency

I had posted this topic in the SitCore forum when originally concerned if the hardware could handle pulse counting pulses in the 10nS width region. The answer is yes, but I am concerned about the tinyclr driver digitalSignal Abort function, so I am posting in the TinyCLR forum.
My object is to build a pulse counter that will work between 1kHz and 10MHz and return a valid reading every 125mS. Using the examples from the CHI website I tested this program and find that as the signal frequency decreases, the number of times that the OnReadPulseFinished fails and returns 0 for both the count, and the duration, increases.
Of course, as the frequency approaches 0, I would expect some readings to be count=0, but the duration to be >0, depending on when abort was called.

As a suggestion to making the digitalSignal ReadPulse function easier to use, being able to specify the integration time instead of the count would be nice.

using System.Collections;
using System.Text;
using System.Threading;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Native;
using GHIElectronics.TinyCLR.Pins;
using GHIElectronics.TinyCLR.Devices.Signals;
using System.Diagnostics;
using System;

namespace PulseCounter20260
{
    internal class Program
    {
        private Timer readPulseTimer;
        private TimeSpan elapsed;
        private Timer abortTimer;
        private DateTime startTime;
        private Boolean pulsesRead;

        private AutoResetEvent pulseReadFinishedEvent;
        static void Main()
        {
            var program = new Program();
            program. Run();
        }

        private void Run()

        {
            pulseReadFinishedEvent = new AutoResetEvent(false);

            elapsed = new TimeSpan();
            startTime = DateTime.Now;

            var digitalSignalPin = GpioController.GetDefault().OpenPin(SC20260.Timer.DigitalSignal.Controller2.PB3);
            var digitalSignal = new DigitalSignal(digitalSignalPin);
            var waitForEdge = true;

            Debug.WriteLine("Program started");

            digitalSignal.OnReadPulseFinished += new DigitalSignal.PulseReadEventHandler(this.Digital_OnReadPulseFinished);

            pulsesRead = true;

            while (true)
            {
                digitalSignal.ReadPulse(1000000, GpioPinEdge.RisingEdge, waitForEdge);
                Thread.Sleep(125);
                digitalSignal.Abort();

            }
        }

        private void Digital_OnReadPulseFinished(DigitalSignal sender, TimeSpan duration, uint count, GpioPinValue pinValue)
        {
            var ticks = duration.Ticks;
            if (ticks > 0) 
            {
                var microsecond = ((double)duration.Ticks) / 10;
                var freq = (count / microsecond) * 1000000;   
                Debug.WriteLine((DateTime.Now - this.startTime).TotalMilliseconds.ToString() + "s, count  " + count.ToString() + ", freq = " + (freq / 1000.0).ToString("F3") + " kHz");
            }
            else
            {
                Debug.WriteLine("No clock found. Event failed. Ticks = " + ticks.ToString() + ", count = " + count.ToString());
            }
            pulsesRead = true;
        }
    }
}


Here is an example of the output at 15kHz, followed a higher frequency.

type or paste code
No clock found. Event failed. Ticks = 0, count = 0
628116.6317s, count  1119, freq = 15.177 kHz
No clock found. Event failed. Ticks = 0, count = 0
No clock found. Event failed. Ticks = 0, count = 0
628493.4175s, count  72, freq = 12.313 kHz
No clock found. Event failed. Ticks = 0, count = 0
628744.6264s, count  1131, freq = 14.525 kHz

Source at ~55kHz follows. Note, the pulse train temporal distribution is random as generated by a radiation detector.  At the higher frequency, the results give excellent agreement with both a logic analyzer adn a Tek counter/timer/analyzer. There is no change in rise time between the two frequencies.

5958.7437s, count  5402, freq = 54.394 kHz
6084.742s, count  5416, freq = 55.499 kHz
6210.7421s, count  5804, freq = 54.831 kHz
6336.7449s, count  4673, freq = 56.098 kHz
6462.744s, count  5371, freq = 54.915 kHz
6588.7434s, count  5482, freq = 55.507 kHz
6714.7436s, count  4904, freq = 55.403 kHz
6840.7415s, count  5216, freq = 56.944 kHz
6966.741s, count  5645, freq = 54.874 kHz

All suggestions appreciated!

We will look into soon.

Thanks, Dat_Tran

I tried adding

 while (digitalSignal.CanReadPulse == false) {
     Debug.WriteLine((DateTime.Now - this.startTime).ToString(@"ss\.fffff", System.Globalization.CultureInfo.InvariantCulture) + ", CANNOT READ PULSE");
 }

Which stays in this loop for some 10s of mS until it emerges and immediately (300uS later) OnReadPulseFinished fires which you can see had read 3824 pulses over 70mS.

...
00:02:40.0329027, CANNOT READ PULSE
00:02:40.0331412, CANNOT READ PULSE
00:02:40.0334578, Count,3824, dur,70.61280,ms, freq = ,54.154, kHz

I clearly do not now what is going on and what the digitalSignal.CanReadPulse is supposed to do. I had used CanReadPulse at the beginning of the code to indicate that the hardware is fit to readpulses.

Also, I putchased a 2nd SCM20260D board just to make sure this was not a hardware issue, and it works the same as the first one.

digitalSignal.CanReadPulse is used to check if system is ready for a new read.

while (true)
{
      if (digitalSignal.CanReadPulse) {
               digitalSignal.ReadPulse(1000000, GpioPinEdge.RisingEdge, waitForEdge);
               Thread.Sleep(125);
               digitalSignal.Abort();
       }


}

Hi Dat_Tran:

It would be wonderful to learn a little more about this. In the example I posted, the output example seems to repeatedly report it cannot read pulses then suddenly it can? This would seem incorrect as a few hundred microseconds it reports that it has been reading pulses thousands of pulses - many times more that it could read in those few hundred microseconds?

Can you shed any light on how I can insure that I sample the pulse train for a fixed time over a wide range of frequencies as I clearly do not understand how this works?

Thanks,

I have done some more tests with the solution Dat_Tran suggested. It works in some conditions but either does not work at all or returns less than useful data in others: For example, using the suggested code, and a signal DDS Digital Generator/Counter, and verifying independently the pulse frequency and shape:
1.2kHz pulse, 0.1% duty cycle measured at 814nS width gives the following debug output:
1.2kHz, 0.1% duty cycle, 814nS pulse width, sharp rise and fall, 0 @168mV, 1@3.16V
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0
715.3765735s, count 1, duration = 1.143mS., freq = 0.875 kHz
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0
716.1065732s, count 1, duration = 1.147mS., freq = 0.872 kHz
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0
716.8365741s, count 1, duration = 1.147mS., freq = 0.872 kHz
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0
0 ticks! Event failed. Count = 0

Same source, but double the pulse width:
5.5669995s, count 125, duration = 104.581mS., freq = 1.195 kHz
5.7139997s, count 125, duration = 104.925mS., freq = 1.191 kHz
5.8609987s, count 125, duration = 104.378mS., freq = 1.198 kHz
6.0079997s, count 125, duration = 104.754mS., freq = 1.193 kHz

So is it the pulse width?
1000kHz, 1.8% duty cycle, 14nS pulse width
2057.7867559s, count 102118, duration = 102.114mS., freq = 1000.035 kHz
2057.9337566s, count 61070, duration = 61.066mS., freq = 1000.066 kHz
2058.0807572s, count 66301, duration = 66.297mS., freq = 1000.063 kHz
2058.2277559s, count 104016, duration = 104.011mS., freq = 1000.046 kHz
2058.3747568s, count 85016, duration = 85.011mS., freq = 1000.055 kHz
2058.5217559s, count 99014, duration = 99.010mS., freq = 1000.037 kHz
Apparently not.

Here is the full code used to make these measurements:

using System.Collections;
using System.Text;
using System.Threading;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Native;
using GHIElectronics.TinyCLR.Pins;
using GHIElectronics.TinyCLR.Devices.Signals;
using System.Diagnostics;
using System;

namespace PulseCounter20260
{
    internal class Program
    {
        private Timer readPulseTimer;
        private TimeSpan elapsed;
        private Timer abortTimer;
        private DateTime startTime;
        private Boolean pulsesRead;

        private AutoResetEvent pulseReadFinishedEvent;
        static void Main()
        {
            var program = new Program();
            program.Run();
        }

        private void Run()
                    {
            pulseReadFinishedEvent = new AutoResetEvent(false);
            elapsed = new TimeSpan();
            startTime = DateTime.Now;

            var digitalSignalPin = GpioController.GetDefault().OpenPin(SC20260.Timer.DigitalSignal.Controller2.PB3);
            var digitalSignal = new DigitalSignal(digitalSignalPin);
            var waitForEdge = true; 

            digitalSignal.OnReadPulseFinished += new DigitalSignal.PulseReadEventHandler(this.Digital_OnReadPulseFinished);
            pulsesRead = true;

            while (true)
            {
                if (digitalSignal.CanReadPulse)
                {
                    digitalSignal.ReadPulse(1000000, GpioPinEdge.RisingEdge, waitForEdge);
                    Thread.Sleep(125);
                    digitalSignal.Abort();
                }
            }
        }

        private void Digital_OnReadPulseFinished(DigitalSignal sender, TimeSpan duration, uint count, GpioPinValue pinValue)
        {
            var ticks = duration.Ticks;
            if (ticks > 0) 
            {
                var microsecond = ((double)duration.Ticks) / 10;
                var freq = (count / microsecond) * 1000000;   
                Debug.WriteLine((DateTime.Now - this.startTime) .TotalSeconds.ToString() + "s, count  " + count.ToString() + ", duration = " + (microsecond / 1000.0).ToString("F3") + "mS., freq = " + (freq / 1000.0).ToString("F3") + " kHz");
            }
            else
            {   Debug.WriteLine("0 ticks! Event failed.  Count = " + count.ToString());
            }
            pulsesRead = true;
        }
    }
}


We will look into it soon,

Thanks. I will try to work around the issue for now. But it is important to our project to get this resolved.

2 Likes