Question

I receive a string containing "1" every few seconds. I am trying to get the elapsed time between the received string and the next one to return the elapsed time. I am doing something wrong. The result I get is 0 and the string is instead updated exactly every second, so I should read 1. I am quite sure there is a mistake in the logic but I cannot see where it is. This should run for hours and update every time I get an update on the string "giriRicevuti".

class Rpm
{
    public void CalcolaRPM(string giriRicevuti, out long RPM)
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();

        if (giriRicevuti == "1")
        {
            stopWatch.Stop();
        }
            long duration = stopWatch.ElapsedMilliseconds;

            RPM =(duration/1000);
    }
}
Was it helpful?

Solution 2

Thanks to your comments and advices I ended up with this solution. I also simplified the method using a return and some floating variables to get more accuracy. This one is working for my app.

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;
    }
}

I would like to thank Mattew for the big help he gave me.

OTHER TIPS

You will need to keep a stopwatch around outside the CalcolaRPM() method if you want to time things inbetween calls to it.

The easiest thing to do is to add it as a private field in the class.

Another problem is that when giriRicevuti isn't "1" you will need to return the last known RPM - we can solve that by keeping the last known RPM in a private field too.

And yet another issue is that the very first time the RPM is calculated, it cannot be accurate because there is no preceeding time to compare it with. We will solve this by returning -1 until we have a correct time to report.

And next, you are calculating the elapsed RPM as an integer calculation. Now imagine if things were slightly out so the elapsed time was always 999 milliseconds. Only a millisecond out, but your calculation of RPM = 999/1000 would result in zero.

You have several options, but the most likely are:

  • Return a double instead.
  • Round the value to the nearest RPM.

I went for the rounding. The RPM calculation was incorrect, so I'm correcting that at the same time:

lastRPM = (int) Math.Round(60000.0/((int) stopWatch.ElapsedMilliseconds));

Putting that altogether, here's a compilable test program (console app):

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading;

namespace Demo
{
    class Rpm
    {
        private Stopwatch stopWatch = new Stopwatch();
        private int lastRPM = -1;

        // RPM will be -1 until we have received two "1"s       

        public int CalcolaRPM(string giriRicevuti)
        {
            if (giriRicevuti == "1")
            {
                if (stopWatch.IsRunning)
                    lastRPM = (int) Math.Round(60000.0/((int) stopWatch.ElapsedMilliseconds));

                stopWatch.Restart();
            }

            return lastRPM;
        }
    }

    class Program
    {
        void run()
        {
            test(900);
            test(1000);
            test(1100);
            test(500);
            test(200);
        }

        void test(int interval)
        {
            Rpm rpm = new Rpm();

            for (int i = 0; i < 10; ++i)
            {
                Thread.Sleep(interval);
                rpm.CalcolaRPM("0");
                rpm.CalcolaRPM("1").Print();
                rpm.CalcolaRPM("2");
            }
        }

        static void Main()
        {
            new Program().run();
        }
    }

    static class DemoUtil
    {
        public static void Print(this object self)
        {
            Console.WriteLine(self);
        }

        public static void Print(this string self)
        {
            Console.WriteLine(self);
        }

        public static void Print<T>(this IEnumerable<T> self)
        {
            foreach (var item in self) Console.WriteLine(item);
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top