PinCapture-ing on multiple pins simultaneously

Is it possible to execute a

PinCapture.Read

on multiple pins simultaneously? I have a set of 16 sensors, and I’d rather not read each in turn

One thought I had would be to run the reads in separate threads. Is this a good solution, and will the hardware allow it?

Is there a better way of doing this?

I would make a quick test. Connect your sensor to one FEZ input and measure the signal. After that connect the same sensor to two FEZ inputs simultaneously. Create two threads as you mentioned and read the signal from both pins. Compare if the two results are equal and if those result are equal to the result in first test. You can add more inputs and you will see how your reading is changing.

Here is a sample test that uses a FEZ Domino board. You need to connect one output to as many inputs as you like. The sample expects you connect Di10 to pins Di9-Di3. The output Di10 generates a signal with 100μ period. The results are:

When only D10 ↔ Di9

When Di10 ↔ Di9…Di3

So you can use multithreading for this and you will not loose accuracy. Is this right Gus ?


    public class Program
    {
        private const int TimingsCount = 100;
        private const int SignalWidth = 100;
        private static uint[][] _buffers;

        public static void Main()
        {
            var oc = new OutputCompare((Cpu.Pin) FEZ_Pin.Digital.Di10, false, TimingsCount);
            var timings = new uint[TimingsCount];
            for (var i = 0; i < timings.Length; i++) timings[i] = SignalWidth;
            oc.Set(false, timings, 0, timings.Length, true);

            while (true)
            {
                TestMultiPinCapture(
                    new[]
                        {
                            FEZ_Pin.Digital.Di9, FEZ_Pin.Digital.Di8,
                            FEZ_Pin.Digital.Di7, FEZ_Pin.Digital.Di6,
                            FEZ_Pin.Digital.Di5, FEZ_Pin.Digital.Di4,
                            FEZ_Pin.Digital.Di3
                        });
            }
        }

        private static void TestMultiPinCapture(FEZ_Pin.Digital[] pins)
        {
            var threadCount = pins.Length;
            var threads = new Thread[threadCount];
            _buffers = new uint[threadCount][];

            for (var i = 0; i < threadCount; i++)
            {
                var index = i;
                _buffers[i] = new uint[TimingsCount];
                threads[i] = new Thread(() => CapturePinIntoBuffer((Cpu.Pin) pins[index], ref _buffers[index]));
            }

            for (var i = 0; i < threadCount; i++)
            {
                threads[i].Start();
            }

            for (var i = 0; i < threadCount; i++)
            {
                threads[i].Join();
                Debug.Print("Avarage result of thread " + i + " = " + GetAverage(_buffers[i], 1));
            }
        }

        private static void CapturePinIntoBuffer(Cpu.Pin pin, ref uint[] buffer)
        {
            var pc = new PinCapture(pin, Port.ResistorMode.Disabled);
            pc.Read(false, buffer, 0, buffer.Length, 1000);
            pc.Dispose();
        }

        private static double GetAverage(uint[] data, int offset)
        {
            uint result = 0;
            for (var i = offset; i < data.Length; i++)
            {
                result += data[i];
            }
            return (double) result/(data.Length - offset);
        }
    }

You can use “kernel-mode tasks” in RLP to get very accurate reading on multiple pins

I wasn’t too concerned about accuracy - the signal has one of four duty cycles, so providing it doesn’t miss edges, its fine. I’m not sure RLP is worth the effort.

I’d assumed that there might be a hardware reason for it not to work. Glad to hear there isn’t

Thanks @ Gralin for running a test for me!

Hang on though. According to the documentation, calling Read blocks all managed threads. This, of course, defeats the purpose of multithreading, as it is equivalent to sequentially reading each sensor.

I missed that, sorry. You are right. In my sample code the OutputCompare is generating the signal infinitly so every thread can ‘take a bite’ and read the proper timings. If yoo change it however only the first thread will be able to read the signal as it the other need to wait for the Read to stop. No advantage using multithreading here.

The only option is to use RLP. Maybe GHI could expand the InputCapture class to accept more than one pin ?