Main Site Documentation

Asynchronous IR readings


#1

While I am impatiently awaiting the arrival of my Domino I wanted to test out some code concepts first.

The sensors have an approx 38ms read time (if I am reading the document correctly). If I have multiple sensors, and read them synchronously, then the get readings becomes n * 38ns. Depending on the speed, it can add up if these are mounted on a servo and you are scanning side to side.

So I was trying to work out a framework to do asynchronous readings with a blocking method. This is my first attempt and it seems to work (granted there’s no sensors and I’m randomly generating wait times and sensor readings).

Conceptually, does this make sense in the FEZ world? Is the Mutex too expensive, negating the time savings?

I may have went overboard with mutex wrapping of the array access. But I was thinking that I wanted to make sure that only 1 thread would access the array at a time. Otherwise, I could see 2 threads finishing up at almost the same time and the _signal.Set(); not being called. Eventually there would need to be a timeout in the WaitOne();


static void Main(string[] args)
        {        
            var irsm = new IR.IRSensorManger();
            irsm.GetReadings();
            Console.WriteLine("....");
            irsm.GetReadings();
            Console.WriteLine("....");
            irsm.GetReadings();
            Console.WriteLine("....");
            irsm.GetReadings();

            Thread.Sleep(Timeout.Infinite);
        }


    class IRSensorManger
    {
        AutoResetEvent _signal = new AutoResetEvent(false);
        Mutex _arrayMutex = new Mutex();
        Random r = new Random();                
        byte?[] _sensorData = new byte?[3];
        Thread sensor1;
        Thread sensor2;
        Thread sensor3;

        void clearSensorData()
        {
            _arrayMutex.WaitOne();
            for (int i = 0; i < _sensorData.Count(); i++)
                _sensorData[i] = null;
            _arrayMutex.ReleaseMutex();
        }

        void setSensorData(int index, byte? value)
        {
            _arrayMutex.WaitOne();
            _sensorData[index] = value;
            _arrayMutex.ReleaseMutex();
        }

        byte? getSensorData(int index)
        {            
            _arrayMutex.WaitOne();
            byte? val = _sensorData[index];
            _arrayMutex.ReleaseMutex();

            return val;
        }

        public void GetReadings()
        {
            clearSensorData();           
            sensor1 = new Thread(readSensor);
            sensor2 = new Thread(readSensor);
            sensor3 = new Thread(readSensor);

            sensor1.Start(0);
            sensor2.Start(1);
            sensor3.Start(2);

            Console.WriteLine("Start : " + DateTime.Now.ToString());
            _signal.WaitOne();
            Console.WriteLine("Finish: " + DateTime.Now.ToString());
        }

        void readSensor(object data)
        {
            Thread.Sleep(r.Next(500, 2500));            
            setSensorData((int)data, (byte)r.Next(0,80));

            Console.WriteLine("Thread {0} finished at {1}.{2}", ((int)data).ToString(), DateTime.Now.ToString(), DateTime.Now.Millisecond);

            if (getSensorData(0) != null && getSensorData(1) != null && getSensorData(2) != null)
                _signal.Set();        
        }
    }

Thanks for any comments


#2

Fixed an issue with how I restarted the threads. That’s what happens when make a change after it works and don’t retest :wink:

Also attached is an output of the test.


#3

It doesn’t have to be blocking. This is on my to do list but I would love to see some help.

Setup and interrupt port and in the event handler you can start recording values. A buffer can be passed down to get filled with samples of times which can be used later for decoding


#4

Well in my (inexperienced) mind I was thinking the process would be synchronous:

  1. Get sensor readings
  2. Process sensor readings to determine if an obstacle is in the way
  3. If so, make adjustment, else continue on current path.
  4. Go back to step 1

If that’s a typical approach, would you just continually process each sensors one at a time? Or would get all of them, then process the result.

This code was setup on the assumption that you’d get all the sensor readings, and then process the results. Further, the idea is to encapsulate all of that logic into a seperate class.

This class, in concept, would eventually:

  1. Start all the sensor reading process
  2. As results come in asychronously, store them into an array
  3. Wait unti all have returned (so you have a “complete” picture)
  4. Process the array to determine if there’s an object ahead
  5. If so, raise an event to be caught by a different module for it to act upon.

The main class would not be making the calls directly into this class to fire off the reading of data from the sensors, as it’s doing now in the POC. Rather this class would have it’s own thread doing the processing. Once it detects an obstacle, it would raise an event that the main module would act upon.

The name IR is a bit of a misnomer in my code - I want this to work with my ultrasonic, and to control the servo that the IRs are mounted upon.


#5

Here’s a quick flowchart to show what I was thinking for this sensor module.

If an obstacle was detected, the main controller thread would start this one over again after it adjusted course.

The array (which is 3 positions) would also eventually be position based, meaning the relative angle to the bot. The middle element would be the reading “straight” ahead - or 90 degrees on the servo. Whereas the first and last would represent the readings all the way to the left and right.


#6

You can do it in many ways but what I wanted is a class that is completely separate from the rest of the system and then anyone can use it. It would be exactly the opposite from our OutputCompare…it will by InputCapture class.


#7

I’ll have to check out that section again in the eBook. My first reading was mostly a scan through, as I don’t have the hardware as of yet. Once I am programming it, I’ll pay more attention.

If I can be of any assistance, I would be glad to help.


#8

So basically you want a background sensor thread that somehow interupts or notifies the main thread when it detects an obstacle?


#9

That was my goal.

Since I’ve started to work on this, I’ve changed my thought process. I still want to come back to this though.

I have a synchronous loop where I:

  1. Read sensor 1
  2. Read sensor 2
  3. Act upon data
    (go back to step 1)

Here’s what I came up with for my first iteration: