This project has moved. For the latest updates, please go here.

Very slow update of motor positions

Feb 27, 2014 at 7:42 AM
Hello All,

I'm trying to use this API to query the position of the servos. This is both necessary for a calibration process in my program, and I will also require the ability to query this information with reasonably low latency while running my robot.

I am finding that if I attempt to query the motor position with the following code:
float pos = brick.Ports[InputPort.A].SIValue;
The value 'pos' only updates maybe once every half a second or so. This will not be sufficient for my needs. I tried using a lower TimeSpan value during ConnectAsync (I tried 30 ms and 100 ms) without success. I also see a similar update rate for sensors.

Is this the issue described in the documentation regarding USB connections from desktop being "a bit laggy"? I can see some of the sensor input in the getting started video that this isn't an issue.

If the problem is USB, is the cause of this issue well understood? I'd like to maybe try to fix it because USB really would be the best way for me to control my robot.
Coordinator
Feb 27, 2014 at 1:56 PM
At present, the reason for the lag is not understood and I don't really have any pointers on where to begin. The source is in the .Desktop project in the UsbCommunication.cs file if you'd like to take a look.
Feb 28, 2014 at 2:05 AM
Thanks for the info!

There appears to be some relevant information here: https://www.microchip.com/forums/m653931-print.aspx

However, my immediate attempts to implement the suggestions there (SetNumInputBuffers and increasing the number of input reports read) did not really help the issue. I'm wondering if you think that the suggestions there are relevant to the EV3 brick?
Feb 28, 2014 at 6:38 AM
I think I found a way to fix this, simply make the implementation of UsbCommunication.WriteAsync use the synchronous version of FileStream.Write, i.e.:
        /// <summary>
        /// Write data to the EV3 brick.
        /// </summary>
        /// <param name="data">Byte array to send to the EV3 brick.</param>
        /// <returns></returns>
        public Task WriteAsync(byte[] data)
        {
            if(_stream != null)
            {
                data.CopyTo(_outputReport, 1);
                _stream.Write(_outputReport, 0, _outputReport.Length);
                return Task.FromResult(true);
            }

            // invalid stream, bail out, but don't tank who is awaiting us
            return Task.FromResult(false);
        }
With this, I can set the polling interval low and get quite low latency!
Coordinator
Mar 9, 2014 at 2:00 AM
Neat. But strange. :)

Are you only changing the Write method and not Read? Are you able to use _stream.ReadAsync and still get results from the brick with low latency?
Mar 9, 2014 at 2:18 AM
Yes, the read is still using ReadAsync, and the file is still an overlapped IO file handle. I'm pretty sure that all the changes I made are contained in that snippet of code I posted. I've been using it ever since with no problems that I've seen!

It is a bit strange, I don't understand why WriteAsync would behave this way. I suspect there is some buffering thing going on where it wants to wait for more data before flushing. If that's the case, you could probably also continue to use WriteAsync if you added a Flush/FlushAsync somehow, but to be honest, I'm a bit new to async/await and I stumbled around with that a bit before giving up and just using Write. All my attempts to change it in that way ended up with totally broken communication.

Either way, I can't promise that I've tested all the use cases you need to support, but as far as I can tell, using Write instead of WriteAsync solves the latency issue and does not introduce any other new issues.
Coordinator
Mar 9, 2014 at 2:20 AM
Thanks for the additional info. I'm away this week but will check it out when I get back and test here. If all looks good I'll toss in the new code. Thanks for the help on this!
Mar 9, 2014 at 2:44 AM
No problem, I hope it works out, it would be nice to have this change in the nuget repo :)

Thank you for writing this library, it is very useful!