Pulse counter

I have a SCM20260D and I would like to prototype a pulse counter for pulses that are typically 20nS duration with a similar or greater space between pulses. I have no idea where to go to find the input specificatons for this board in order to determine if it is suitable. Can you please help me find such data. I have seen examples at Signal Control that seem like a good place to start, but I would like to know if the board will support these fast signals.
Many thanks for your good products.
Rocky

Yes, SignalControl i is the right one, take a look on ReadPusle on that page

20ns = 50MHz, try and share to us your result

That is really fast! I would be surprised if it worked.

Hi: I am having issues using the DigitalSignal pulse reading on a SCM20260D board. I am inputting a 1.000kHz square wave 3.3v amplitude. I get erratic counts, and readings around 65Hz.
I have verified the waveform and frequency. If I remove the source, the program stalls as expected as count does not complete.
Here is my code - I am used to VB so it is rough…

using System.Collections;
using System.Drawing;
using System.Text;
using System.Threading;
using Demos.Properties;
using GHIElectronics.TinyCLR.Devices.Adc;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.I2c;
using GHIElectronics.TinyCLR.Devices.Rtc;
using GHIElectronics.TinyCLR.Devices.Storage;
using GHIElectronics.TinyCLR.Devices.Uart;
using GHIElectronics.TinyCLR.Drivers.Omnivision.Ov9655;
using GHIElectronics.TinyCLR.Native;
using GHIElectronics.TinyCLR.Pins;
using GHIElectronics.TinyCLR.UI;
using GHIElectronics.TinyCLR.UI.Controls;
using GHIElectronics.TinyCLR.UI.Media;
using GHIElectronics.TinyCLR.Devices.Signals;
using GHIElectronics.TinyCLR.Devices.Gpio.Provider;
using GHIElectronics.TinyCLR.Devices;
using System.Diagnostics;
...
        private uint pulses = 1000;

        private void ThreadTest() {

            this.isRunning = true;

            var digitalSignalPin = GpioController.GetDefault().OpenPin(SC20260.Timer.DigitalSignal.Controller2.PB3);

            var digitalSignal = new DigitalSignal(digitalSignalPin);

            var waitForEdge = true;// wait for first pulse before starting the measurement
                                   // Subscribe event when done reading

            digitalSignal.OnReadPulseFinished += this.Digital_OnReadPulseFinished;
            while (this.isRunning= true) {

                this.countReached = false;

                // Start reading 1000 pulses
                digitalSignal.ReadPulse(this.pulses, GpioPinEdge.RisingEdge, waitForEdge);

                while (this.countReached = false) { }  // wait here for pulses to be read

            }
            this.isRunning = false;

            return;

        }
        // the event
        void Digital_OnReadPulseFinished(DigitalSignal sender, TimeSpan duration, uint count, GpioPinValue pinValue) {
            var ticks = duration. Ticks; // ticks  are 0.1uS'
            var microsecond = ((double)duration.Ticks) / 10;
            var millisecond = ((double)duration.Ticks) / 10000;
            var freq = (this. Pulses / microsecond) * 1000000;

            Debug.WriteLine(DateTime.Now.TimeOfDay.TotalSeconds +", GpioPinValue = " + ((pinValue == GpioPinValue.High) ? "High" : "Low"));
            Debug.WriteLine("PulseCount = " + count);
            Debug.WriteLine("Duration ticks = " + ticks);
            Debug.WriteLine("Duration microsecond = " + microsecond);
            Debug.WriteLine("Duration millisecond = " + millisecond);
            Debug.WriteLine("freq = " + freq + " Hz");
            this.UpdateStatusText("Freq " + freq.ToString("N2") + "Hz, pulse count " + count + ",  duration " + millisecond.ToString("n5") + "mS" , true);
            this.countReached = true;
        }

Any suggestions would be appreciated.
type or paste code here

type or paste code here

I also tried Capture from Tinyclr/tutorials/pin level control/Capture also on a SCM20260D with 2.2.0.5 library. I cannot compile the example as it throws error No overload for ‘Digital_OnCaptureFinished’ matches delegate ‘DigitalSignal.PulseCaptureEventHandler’. I would appreciate it if anyone out there realizes what stupid error I am causing and lets me know!.


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

            bool waitForEdge = false;// Start capturing as soon as Capture is called

            // Subscribe event when done capturing
            digitalSignal.OnCaptureFinished += Digital_OnCaptureFinished;

            // start capture 100 samples, timeout is 15seconds
            digitalSignal.Capture(100, GpioPinEdge.RisingEdge | GpioPinEdge.FallingEdge, waitForEdge, TimeSpan.FromSeconds(15));

            // Wait for finish capture
            // do other work
            Thread.Sleep(Timeout.Infinite);
        }

// The event
private static void Digital_OnCaptureFinished(DigitalSignal sender, uint[] buffer, uint count, GpioPinValue pinValue) {
            if (count == 0) {
                Debug.WriteLine("no data was captured!");
                return;
            }
            for (int i = 0; i < count; i++) {
                Debug.WriteLine("Sample [" + i + "]: " + buffer[i] + " ns");
            }
        }

H i, I am not sure if this is exactly your code when you tested, if so then I know why it does not work.

while (this.countReached = false) { }

I think it should be ‘==’ instead of ‘=’.

Your fw is 2.2.0.5, latest is 2.3.0.0, a lot of changes or fixes.

First, update latest firmware, try generating pwm 1.000KH on any PWM pin on SCM20260D. Short that output PWM to PB3 (or the pin you are using to readpulse, capture).

When the result is 1.000KHz, (it could be 9.99999 or 1000001…), mean your code is good to go, now you can connect the digital signal pin to the one you want to read pulse.

And recommend connect GND between them.

Also, instead of using a flag, it is not bad but there is another option is, using “CanReadPulse” property.

Something like this, but you are using flag also OK

While (true) {
   if (digitalSignal.CanReadPulse) {
        digitalSignal.ReadPulse(....)
   }
}

Let us know your status then,

Thanks. When I try to update I get this:

Could not install package ‘GHIElectronics.TinyCLR.Core 2.3.0.1000’. You are trying to install this package into a project that targets ‘.NETFramework,Version=v4.5.2’, but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

How to I retarget NetFramework Version?

Open csproj, change to 4.8 if your project 4.5.2.

<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>

And if you want your system runs smoothly when you make new project later, you should install latest TinyCLR SDK 2.3.0.1000

Thanks for the reply. I have searched for “csproj” but cannot find anything that seems to have a reference to the Target framework version. I am new to C#, so can you be more specific?

hi, when you created a project in C#, Visual Studio will generate a file with extension csproj. You can find this file on your project folder.

Example:

Hi: I am making some progress, but somewhow I am getting an error CS0433 “The type ‘Debug’ exists in both ‘System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’ and ‘mscorlib, Version=2.3.0.1000, Culture=neutral, PublicKeyToken=null’”

I suspect that this has come into conflict with the library, but no luck after hours of trying different solutions. Copilot suggests fixes, but all I have tried have broken the code in other spots.

using System;
using System.Collections;
using System.Drawing;
using System.Text;
using System.Threading;
using Demos.Properties;
using System.Diagnostics;

using GHIElectronics.TinyCLR.Devices.Adc;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.I2c;
using GHIElectronics.TinyCLR.Devices.Rtc;
using GHIElectronics.TinyCLR.Devices.Storage;
using GHIElectronics.TinyCLR.Devices.Uart;
using GHIElectronics.TinyCLR.Drivers.Omnivision.Ov9655;
using GHIElectronics.TinyCLR.Native;
using GHIElectronics.TinyCLR.Pins;
using GHIElectronics.TinyCLR.UI;
using GHIElectronics.TinyCLR.UI.Controls;
using GHIElectronics.TinyCLR.UI.Media;
using GHIElectronics.TinyCLR.Devices.Signals;
using GHIElectronics.TinyCLR.Devices.Gpio.Provider;
using GHIElectronics.TinyCLR.Devices;
using GHIElectronics.TinyCLR.Devices.Pwm;
using System.Runtime.CompilerServices;

Here is an example of the error 0433 with the word Debug highlighted:
Debug.WriteLine(“Thread started”);

somehow you mixed Full NET from PC and NET from TinyCLR together.

TinyCLR project needs “mscorlib, Version=2.3.0.1000” only.

You need to close VS, then go to package folder (same your project folder), delete all of them and rebuild again.

There is object and bin folders, need to be deleted too.

Other solution is, make complete new project and start from that.

I think I have my code all sorted out. I am finding somewhat unusual results in the testing I have been doing. First of all, the board is SCM20260D, Rev C. I have a short jumper between PB3 and PC6. I have a logic probe that I can connect to this jumper, and have verified that the behavior does not seem to change if it is connected or not. I log to the PC the PWM frequency, duty cycle, count, duration, calculated frequency…
As an example, inputing 5MHz with 50% duty cycle reads as expected, 5000.542 (stdev .27), and as I increase to 7Mhz, 50%, I get 6858.121 (stdev .287), but at 8Mhz, it is again correct at 7.999.447 (stdev .047).
At 7Mhz there is a double pulse as seen in the logic probe.
I have more data, but I would like it if you can look at the code and see if there is anything there that might cause the less than optimum results. I would like to be able to count pulses dependably up to 20MHz.

using System;
using System.Collections;
using System.Drawing;
using System.Text;
using System.Threading;
using Demos.Properties;
using GHIElectronics.TinyCLR.Devices.Adc;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.I2c;
using GHIElectronics.TinyCLR.Devices.Rtc;
using GHIElectronics.TinyCLR.Devices.Storage;
using GHIElectronics.TinyCLR.Devices.Uart;
using GHIElectronics.TinyCLR.Drivers.Omnivision.Ov9655;
using GHIElectronics.TinyCLR.Native;
using GHIElectronics.TinyCLR.Pins;
using GHIElectronics.TinyCLR.UI;
using GHIElectronics.TinyCLR.UI.Controls;
using GHIElectronics.TinyCLR.UI.Media;
using GHIElectronics.TinyCLR.Devices.Signals;
using GHIElectronics.TinyCLR.Devices.Gpio.Provider;
using GHIElectronics.TinyCLR.Devices.Pwm;
using System.Diagnostics;`type or paste code here
...........
  private void CreateWindow(bool enablebutton) {
      var startX = 5;
      var startY = 40;

      Canvas.SetLeft(this.textFlow, startX); Canvas.SetTop(this.textFlow, startY);
      this.canvas.Children.Add(this.textFlow);

      if (enablebutton) {
          var buttonY = this.Height - ((this.testButton.Height * 3) / 2);
          Canvas.SetLeft(this.testButton, startX); Canvas.SetTop(this.testButton, buttonY);
          this.canvas.Children.Add(this.testButton);
      }
  }
  private double freqOut = 7000000;          //   var freqout = 500000; // <<<<<<<<<<<<<<<<<<<<<<<<<<<< FREQUENCY <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  private double duty = 0.2;                // 3000000 at @ 0.18 duty cycle works, 58nS pulses

  private void ThreadTest() {

      Debug.WriteLine("Thread started");

      this.isRunning = true;

      // PB3 is for measurement
      // PC6 is to source pulses

      // generate a pulse train with the PWM controller. Pulse out on PC6
      var controller = PwmController.FromName(SC20260.Timer.Pwm.Controller3.Id);
      var led = controller.OpenChannel(SC20260.Timer.Pwm.Controller3.PC6);  // pb0

      Debug.WriteLine("PWM Crontoller set to output " + this.freqOut / 1000 + "kHz. Duty cycle " + this.duty * 100 + "%");

      led.SetActiveDutyCyclePercentage(this.duty);
      controller.SetDesiredFrequency(this.freqOut);
      led.Start();


      var digitalSignalPin = GpioController.GetDefault().OpenPin(SC20260.Timer.DigitalSignal.Controller2.PB3);
      var digitalSignal = new DigitalSignal(digitalSignalPin);
      var waitForEdge = true; // Start capturing as soon as Capture is called


      if (digitalSignal.CanReadPulse) {
          Debug.WriteLine(" ++++++++++++++Can Read Pulse");
      }
      else {
          Debug.WriteLine("----------------- CanNOT ReadPulse");
      }
  

      digitalSignal.OnReadPulseFinished += this.Digital_OnReadPulseFinished;  //subscribe to the event

      while (this.isRunning) {

          digitalSignal.ReadPulse(100000, GpioPinEdge.RisingEdge, waitForEdge); // start reading the 1000 pulses

          this.countReached = false;
          while (this.countReached == false) {
              // Wait for finish capture
              Thread.Sleep(1000);
          }
      }
  }

      void Digital_OnReadPulseFinished(DigitalSignal senderX, TimeSpan duration, uint countX, GpioPinValue pinValue) {
          var ticks = duration.Ticks; // ticks  are 0.1uS'
          var microsecond = ((double)duration.Ticks) / 10;
          var millisecond = ((double)duration.Ticks) / 10000;
          var freq = (countX / microsecond) * 1000;
          var s = "Digital_OnReadPulseFinished; Source, " + this.freqOut/1000 + ",kHz, DutyC," + this.duty+",count =," + countX + ", duration = ," +
                      duration.ToString() + ", ticks = ," + ticks +  ", millisecond =, " + millisecond + ", freq = ," + freq + ", kHz";
      Debug.WriteLine(s); 
      this.UpdateStatusText("Src " + this.freqOut/1000 + "kHz, meas Freq " + (freq).ToString("N2") + "kHz,  S/M  = " + ((this.freqOut /1000.0) / freq) + " cnt " + countX +", "+  millisecond.ToString("n5") + "mS", true);
          this.countReached = true;
      }

Thanks

Can you make sure PWM output is 7MHz?

private double freqOut = 7000000;
....
controller.SetDesiredFrequency(this.freqOut);  => this does not guarantee 7MHz

On scops, I am seeing 6.8569, mean you capture it correctly.

Hi: Using the code shown here is I have accomplished:
Using the internal PWM generator the minimum positive pulse width I have been able to program and measure correctly was 20MHzwith a duty cycle of 50%. Higher frequency requests generated:
22000000/50% reported 21817kHz confirmed by Logic probe,
21000000/50% reports 19999.6kHz confirmed by Logic Probe.
20000000/50% reports 19999.6kHz confirmed by Logic probe with a mean pulse width of 16nS (Sdev 91.5as).
Also, using an external signal source (DDS Signal Generator/Counter) I could produce an 8nS pulse at 15MHz and could correctly read the frequency.

To duplicate this, it is very important to not using the internal debugging ability of VS/C# as this degrades the performance erratically above several MHz. Also care with wires is needed at the higher frequencies (as most of you know).

So I would call this success! Gus can be surprised, Dat_Tran was right.

1 Like

Dat is always right :grin:

1 Like

Another question. Does Endpoint / Domino offer the same signal processing hardware? How about any other of the TinyCLR boards? If so, could I expect similar performance?
Thanks!

It shows Signal Control in the Endpoint documentation.

https://docs.ghielectronics.com/endpoint/tutorials/signal-control.html

Thanks, I was more asking about the hardware as the performance levels are determined by the hardware which may or may not be the same the particular board (Domino).