Measuring pulses

My first attempt was a standalone program where the pulse of an ultrasonic distance meter is converted into a distance. Measuring the time between the flanks of the pulse is done by each edge of the pulse to generate an interrupt. The interrupt routine gets the call as an extra at the time of the interrupt system included. The difference of this interrupt time and that of the last interrupt time you can calculate the distance.
This method seemed to work well initially, but if you simple program expanded to include more features and multiple threads, the accuracy rapidly. In my test case it was not possible for distances less than 15 cm to measure because there is almost always more than 10 cm distance was determined.

Because of this I switched to the PinCapure ability to measure the time because I think that this possibility may have less overhead.
PinCapture the possibility does indeed give better results in higher loads of the processor.

However, the number of failed measurements is comparatively quite large.
I test the number of entries in the buffer PinCapture and ignore the measure if the number is not as expected. The number is still 0 after the timeout and I expect a number of 2.
I use the method PinCapture okay?


                while (true)
                {
                    for (int i = 0; i < maxSrf; i++)
                    {
                        srfOut = new OutputPort((Cpu.Pin)srfComponents[i].Pin, false);
                        srfOut.Write(true);
                        srfOut.Write(false);
                        srfOut.Dispose();
                        srfInp = new PinCapture((Cpu.Pin)srfComponents[i].Pin, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);
                        cnt = srfInp.Read(true, srfBuf, 0, 4, 50);  // timeout 50 ms.
                        srfTicks = (int)srfBuf[0]; 
                        srfInp.Dispose();                    
                        srfBuf[0] = 0;
                        if ((cnt == 2) && (srfTicks < 30000))  // 30 ms (1 tick = 1 microseconde)
                        {
                            if (System.Math.Abs(srfTicks - srfComponents[i].Value) > 58)
                            {
                                srfComponents[i].Value = srfTicks;
                                _args = new SrfEventArgs();
                                _args.Numb = i;
                                _args.Dist = (srfTicks / 58 + 1).ToString();
                                _args.Time = DateTime.Now;
                                OnSrfEvent(_args);
                            }
                        }
                        else
                        {
                            Debug.Print("srf error: nr=" + i.ToString() + " cnt=" + cnt.ToString() + " value=" + srfTicks.ToString());
                        }
                        Thread.Sleep((int)waitTime);
                    }
                }

The result is

[quote]srf error: nr=1 cnt=0 value=0
srf error: nr=1 cnt=0 value=0
srf error: nr=1 cnt=0 value=0
[/quote]
In the interrupt method, the accuracy of 100 nanoseconds and and a PinCapture method has the accuracy of 1 microsecond.
My preference is because of the accuracy of the interrupt method.

Another question is whether this type of measurements to do well without the use of RLP?

What is the maxSrf? Are you allowed to create inputs and outputs in a loop like this? Won’t the dispose() stop the pin capture?

Cheers Ian

maxSRF the number of ultrasonic sensors and also the number of gates which srfComponents in the array. In this way I do to code sharing, the ultrasonic sensors may only be used to take turns because of the mutual influence (40 kHz sound)

My concern was after creating the pin and setting up pin capture…you immediately dispose() of the resource surely the pin capture will stop before its supposed to.

Perhaps you should sleep for about 50ms before you dispose.

Cheers Ian

PinCapture is blocking untill it has received the number of state changes configured or a timeout occures.

Sorry!! I never really understood threading, blocking and locking.

I’ll have to read up about it.

Cheers Ian

@ IanR. Hi. Blocking just means the method does not return until finished. In this case, you don’t hit Dispose until prior method returns. In this case, no user threading or locking to get involved with. Just a method that works until finished and move to next statement. I guess in that respect, every method call is blocking (unless it returns an async result you then wait on) hth

William! I need to start a thread with you! I can’t get my head around threading and I really need to get my serial datalogger finished, Your Fez Term works brilliantly. Would you be able to help me!! if you can I’ll set a thread called William and serial…

Cheers Ian

The SRF05 ultrasonic distance sensor has a mode where the trigger pin and the pulse separation pins. This mode I have now been tested and works without errors.
The time between the trigger pulse and the resulting pulse is 700 microseconds. It appears that this time too little for the FEZ Panda to reliable operation. This mode of the sensor is designed for slower systems like the Basic Stamp BS2. I expected this with the FEZ Panda possible.

700us should not be a problem. Use the new pulsecapture class I can capture 70us pulses. Take a look at the time subsection of the microcontroller too. You can likely set up a very accurate pulse capture with the register class or RLP.

@ Jeff. The problem is not the capture of a pulse of 700us, but switching to form outputPin to capturePin (see below the code used for this), which in some cases with multiple trheads more time,
The start of the pulse is approximately 10% of cases missed. In a small standalone test program there are no problems.


  srfOut = new OutputPort((Cpu.Pin)srfComponents[i].Pin, false);
  srfOut.Write(true);
  srfOut.Write(false);
  srfOut.Dispose();
  srfInp = new PinCapture((Cpu.Pin)srfComponents[i].Pin, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);
  cnt = srfInp.Read(true, srfBuf, 0, 4, 50);  // timeout 50 ms.
  srfInp.Dispose();   

The capture of the sensor output pulse from 100us to 25 ms is no problem.

Looking at your code I see some way to dramatically improve things. Disposing of objects and instantiating new ones in the middle of trying to to a timing critical operation is not a good idea. Instantiate your objects, then do all the pin state setting and pulse reading in one shot. Finally don’t dispose of the objects unless you need to as presumably you’ll be wanting to read this sensor multiple times.


  srfOut = new OutputPort((Cpu.Pin)srfComponents[i].Pin, false);
  srfInp = new PinCapture((Cpu.Pin)srfComponents[i].Pin, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);

  srfOut.Write(true);
  srfOut.Write(false);
  cnt = srfInp.Read(true, srfBuf, 0, 4, 50);  // timeout 50 ms.
  
  srfOut.Dispose();
  srfInp.Dispose();

The same pin simultaneously to define output and capture gives runtime errors as expected.

[quote]
The thread ‘’ (0x2) has exited with code 0 (0x0).
#### Exception System.Exception - CLR_E_PIN_UNAVAILABLE (3) ####
#### Message:
#### Microsoft.SPOT.Hardware.Port::.ctor [IP: 0000] ####
#### Microsoft.SPOT.Hardware.InputPort::.ctor [IP: 0009] ####
#### Microsoft.SPOT.Hardware.InterruptPort::.ctor [IP: 0009] ####
#### GHIElectronics.NETMF.Hardware.PinCapture::.ctor [IP: 000c] ####
#### GHIElectronics.NETMF.FEZ.FEZ_Components+SrfReader::srfProcessing [IP: 00a1] ####
#### GHIElectronics.NETMF.FEZ.FEZ_Components+SrfReader::<.ctor>b__3 [IP: 0009] ####
A first chance exception of type ‘System.Exception’ occurred in Microsoft.SPOT.Hardware.dll
An unhandled exception of type ‘System.Exception’ occurred in Microsoft.SPOT.Hardware.dll[/quote]

So this is not a good solution

Use 2 pins connected together. See http://code.tinyclr.com/project/289/dht11—temperature-and-humidity-sensor/

I thought you said you were using two different pins?

With two different pins for Output and Capture it works well.
But that takes a lot of pins for multiple sensors

@ IanR “William! I need to start a thread with you!.. Would you be able to help me!!”

Sure. Just create a normal thread and we can all play along :slight_smile: