0

I've wrote this code to simulate serial port reading writing for an application.

I want to send data every 3 milisecond and before sending I log the data to a chart and a file. also after sending data, the DataRecieved function is called to depict the data on the chart and to log the data to file.

but when I execute it shows false results at some points and also it couldn't be executed every 3 millisecond.(sometimes every 6 milisecond , ..., the files of output and input is attached)

also it sometime throw this error on lines where I write to file:

Object reference not set to an instance of an object.

what can i do to resolve it?

class SignalControllerSimulator
{
       public SignalControllerSimulator(SignalReaderSimulator reader, SignalWriterSimulator writer, LineSeries PitchInputLine, LineSeries RollInputLine, LineSeries YawInputLine, LineSeries PitchOutputLine, LineSeries RollOutputLine, LineSeries YawOutputLine)
       {
             ....
              //do some initialization

           SentFileLogger = new WriteFileLogger(SentFolderName);
           RecFileLogger = new ReadFileLogger(RecFolderName);
           SentFileLogger.Open(true);
           RecFileLogger.Open(true);

           rampTime = SenarioTime = SineTime = StepTime = 320;//1000ms
           reader.DataReceived += DataReceived;
       }
    #region readSection
    ObservableCollection<ChartItem> PitchInputItems = new ObservableCollection<ChartItem>();
    ObservableCollection<ChartItem> RollInputItems = new ObservableCollection<ChartItem>();
    ObservableCollection<ChartItem> YawInputItems = new ObservableCollection<ChartItem>();

    int PitchIndex = 1; int RollIndex = 1; int YawIndex =1 ;

    public void DataReceived(ReadSignal signal)
    {

        this.PitchInputLine.Dispatcher.Invoke(new Action(() =>   
        {
            PitchInputItems.Add(new ChartItem(signal.PitchLocation, PitchIndex++)); 
            RollInputItems.Add(new ChartItem(signal.RollLocation,  RollIndex++));              
            YawInputItems.Add(new ChartItem(signal.YawLocation, YawIndex++));
            PitchInputLine.ItemsSource = PitchInputItems;
            RollInputLine.ItemsSource = RollInputItems;
            YawInputLine.ItemsSource = YawInputItems;
        }));
            RecFileLogger.Write(true, signal.PitchLocation, signal.RollLocation, signal.YawLocation, DateTime.Now.ToString("h:m:s:fff"));

    }

    public void Stop()
    {
      ...
    }
    #endregion
    #region writeSection

    public void StartSendingLocations()
    {

        EndIndex = setEndIndex();
        timer = new System.Timers.Timer(interval);
        timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        timer.Start();
    }
    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (Index>=EndIndex)
        {
            Stop();
            return;
        }
         ...
        // some switch case and function calling...
            CreateCommand();
        //setting reader settings


            //log to file the data sent:
            SentFileLogger.Write(true, writer.WSignal.PitchLocation,                           writer.WSignal.PitchAngularVelocity, writer.WSignal.RollLocation,
                    writer.WSignal.RollAngularVelocity, writer.WSignal.YawLocation, writer.WSignal.YawAngularVelocity,
                    DateTime.Now.ToString("h:m:s:fff"));
            SignalWriter_DataSent(writer.WSignal);
            TimeWriter.WriteLine("end:------------>" + DateTime.Now.ToString("h:m:s:fff"));
            TimeWriter.WriteLine();

            reader.ThreadMain(reader.RSignal);


            Index++;
    }

    ObservableCollection<ChartItem> PitchOutputItems = new ObservableCollection<ChartItem>();
    ObservableCollection<ChartItem> RollOutputItems = new ObservableCollection<ChartItem>();
    ObservableCollection<ChartItem> YawOutputItems = new ObservableCollection<ChartItem>();

    int PitchIndex1 = 1; int RollIndex1 = 1; int YawIndex1 = 1;

    void SignalWriter_DataSent(WriteSignal signal)
    {
        RollInputLine.Dispatcher.Invoke(new Action(() =>
        {
            PitchOutputItems.Add(new ChartItem(signal.PitchLocation, PitchIndex1++)); //PitchOutputItems.Add(new ChartItem(signal.PitchLocation, interval * PitchIndex1++));
            RollOutputItems.Add(new ChartItem(signal.RollLocation,RollIndex1++)); //RollOutputItems.Add(new ChartItem(signal.RollLocation, interval * RollIndex1++));
            YawOutputItems.Add(new ChartItem(signal.YawLocation,YawIndex1++)); //YawOutputItems.Add(new ChartItem(signal.YawLocation, interval * YawIndex1++));
            PitchOutputLine.ItemsSource = PitchOutputItems;
            RollOutputLine.ItemsSource = RollOutputItems;
            YawOutputLine.ItemsSource = YawOutputItems;
        }));
    }

    private int setEndIndex()
    {
        return EndTime / interval;
    }

}

attached files:

data Receiving file

data sending file

time between sendings

abdolah
  • 546
  • 1
  • 4
  • 13
  • Isn't that kind of the point of simulating this? To get the multi-threading bugs out of your code, induced when the data changes after you invoked? And deal with unpredictable timing, just like you'd get with a serial port? Further improve it by making the number of received bytes unpredictable as well, the Random class is handy for that. Never try to fix the perceived timer problem, that just hides bugs. – Hans Passant Jan 15 '14 at 17:16

1 Answers1

1

You will not be able to get 3 ms resolution from a .NET Timer. For example see Why are .NET timers limited to 15 ms resolution?.

You could use a dedicated thread that yields with Thread.Sleep (also not great accuracy), or possibly Thread.SpinWait if accuracy is really important.

Community
  • 1
  • 1
James World
  • 29,019
  • 9
  • 86
  • 120