Click here to Skip to main content
16,016,489 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I receive a message from serial port that is passed to a variable once every few seconds. The message is generated by a microprocessor and it is basically a simple string containing "1/r" which represent one complete turn of a motor (every time a microswitch is pressed, the micro prints "1/r) on the serial port). In order to show in a text box the revolution per minute of such motor, based on the time interval between the update of the variable, I would like to implement a timespan method. I should therefore obtain the time elapsed between the start and the end of a turn and return the result for further actions to the original method.
This is what I have done so far but does not work:

C#
public void CalcolaRPM (string giriRicevuti, out double RPM)
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            {
                if (giriRicevuti == "1/r")
                {
                    stopWatch.Stop();
                }
            }
            double elapsedT = stopWatch.ElapsedMilliseconds;
            stopWatch.Restart();
            RPM = elapsedT;
            giriRicevuti = "";
        }
    
    }


The result I get is 0.0, how can I get the time in milliseconds between updates of the variable "giriRicevuti"?
Posted

The first thing to do is to realize that that code is never going to work.
giriRicevuti is a string parameter to your method, so the world outside cannot in any way change the value once the method is called (strings are immutable, so even a change to the outside world string will just produce a new reference and the string in the method will be unaffected).

So your test will only ever time the performance of the line:
C#
if (giriRicevuti == "1/r")
Which has nothing at all to do with the speed at which data is received from your uProcessor.

There are a large number of problems here which you need to look at. Some of the most major are:
1) Data receive is not necessarily synchronous with the data transmitted by the uProcessor: Windows is not a real time system, and your task may not execute at any given time: if it "misses" a slot, it could conceivably not run for several seconds or even minutes.
2) All data received by the system is buffered, both in hardware and software so that data is not lost - this is great for normal applications, but will bugger your timing right up as you will never know when a bytes was received - the various buffers and windows messages may take significant time to be processed by your application.


The way I would do it is this:
Have a timer event which fires at an expected multiple of the rotation speed. So if you moter or rotating at around 100Hz, then I would set the time to 10HX, or possible less - 5Hz or even 1Hz, depending on how accurate you want to be.
Create two class level variables: and integer count, and a DateTime
Handle the serial port DataRecieved Event, and each time you receive a '1' followed by a '\r' (and remember that these may come is separate events, so you can't just check the data present this time) increment the count by one.
In the timer event, read the count, and zero it. Get the current time, calculate the timespan since the previous one, then save the current value for next time - DO NOT USE DateTime.Now more than once, or you will introduce a small (but significant) error.
You can now use the timespan and the count to work out the average rotation speed between timer events.
 
Share this answer
 
Comments
Millone 26-May-13 5:07am    
Thanks a lot. After you wrote it became very clear to me what is happening. I will try to implement your advice. My motor is turing at 5 to 10 rotation per minute.
OriginalGriff 26-May-13 5:16am    
You're welcome!

For something that slow you will probably be ok without averaging it too much, or probably even at all. Just use the DataRecieved event, check for the sequence (remember it may not come in a single event) and use a timestamp as I described - but you can work out the RMP directly from the difference and it shouldn't "float" too much.

If you speed doesn't vary quickly then I'd be tempted to introduce a moving average value just to smooth the display a little - depends on exactly what you are monitoring this for.
Thanks to your advices and especially to OriginallGriff, I ended up with this solution that is satisfying the requirement of my app. I also simplified the method using a return statement and some float variables to get more accuracy in the result.

C#
class Turns
    {
        static DateTime prevTimeInstance = DateTime.Now;
        static float RPM = 0;

        public float Counts(int getTurn)
        {
            TimeSpan currentTimeSpan = TimeSpan.Zero;
            if (getTurn.Equals(1))
            {
                currentTimeSpan = DateTime.Now.Subtract(prevTimeInstance);
                prevTimeInstance = DateTime.Now;
                if (currentTimeSpan.TotalSeconds != 0)
                    RPM = 60.0f / (float)currentTimeSpan.TotalSeconds;
            }
            return RPM;
        }
    }
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900