Shayan Riyaz
Shayan Riyaz

Reputation: 92

Storing data in real time from Serial port to csv file using C#

I am currently working on a project that requires data collection. The project is a simulation made on Unity and the segment I’m trying to design uses the serial port and an Arduino. The Arduino prints out 5 of these strings, these strings are IMU outputs so the change all the time.

12343,123.4,122.4,45.7,62.2,43.5,76.9,89.2,43.1,42.2,65.1

when given the input “s" and then automatically pauses. The strings are off the type

So far I have written this code which is a C# script to read from the Serial port and store the values in a list.


using UnityEngine;
using System.Collections;
using System.IO.Ports;

public class Communication : MonoBehaviour
{

    SerialPort stream = new SerialPort("COM5", 115200);
    public string receivedstring;
    public GameObject carrito;
    public Vector3 rot;
    public Vector3 rot2;
    public string[] data;
    public string[] data_received;


    void Start()
    {
        stream.ReadTimeout = 500;
        stream.WriteTimeout = 5000;
        stream.Open(); 
        stream.Write("s");
    }

    void Update()
    {
        receivedstring = stream.ReadLine(); 
        stream.BaseStream.Flush(); 

        string[] data = receivedstring.Split(','); 
        if (data[0] != "" && data[1] != "" && data[2] != "" && data[3] != "" && data[4] != "" && data[5] != "" && data[6] != "" && data[7] != "" && data[8] != "" && data[9] != "" && data[10] != "")  
        {
            data_received [0] = data[0];
            data_received[1] = data[1];
            data_received[2] = data[2];
            data_received[3] = data[3];
            data_received[4] = data[4];
            data_received[5] = data[5];
            data_received[6] = data[6];
            data_received[7] = data[7];
            data_received[8] = data[8];
            data_received[9] = data[9];
            data_received[10] = data[10];




            stream.BaseStream.Flush(); 
        }
    }


}


The code splits the value from the incoming string and stores it in data_received. I want to be able to store the 5 lines of data_recieved into a new csv file everytime the command s is given to the serial port. The catch is that throughout the project the Serial port cannot close so it will on paused (“x”) until I want to it to stream again by pressing s. There can be multiple times during the project where the unity script wants data from the serial port so a new .csv file has to be created every time.

This is the output I am trying to get enter image description here

enter image description here

Upvotes: 1

Views: 1554

Answers (1)

curiousBoy
curiousBoy

Reputation: 6834

First of all, you can just wrap that whole if statement- that is not dynamic and you would have to update your code if there would be 12,13,14th element etc....

 if (data[0] != "" && data[1] != "" && data[2] != "" && data[3] != "" && data[4] != "" && data[5] != "" && data[6] != "" && data[7] != "" && data[8] != "" && data[9] != "" && data[10] != "")  

into this:

var data = receivedstring.Split(',').ToList(); // notice I grab this as a list, not string array
if (data.All(x => !string.IsNullOrEmpty(x)))

Also instead of assigning indexes one by one, you can simply loop through in your code. So instead of

data_received [0] = data[0];
data_received[1] = data[1];
data_received[2] = data[2];
data_received[3] = data[3];
data_received[4] = data[4];
...
...
...

You can simply do like below:

 for (var i = 0; i < data.Count; i++)
  {
     data_received[i] = data[i];
  }

Based on your question, If I didnt get it wrong, you can do something like below:

private void Update() {
      receivedstring = stream.ReadLine();
      stream.BaseStream.Flush();
      int lineLimit = 5; // if you dont want to limit this, just use data.ToList().Count in for loop so it writes all of them

      // WHATEVER IS YOUR COMMAND AND NOT SURE HOW YOU GET THIS BUT ASSUME IT CAME AS X
      // JUST ASSIGN THIS TO YOUR COMMAND I CANT SEE THE WAY YOU PULL IT IN YOUR CODE
      string command = "X"; // hardcoded for the sake of example
      var data = receivedstring.Split(',').ToList();
      if (data.All(x => !string.IsNullOrEmpty(x))) {
       for (var i = 0; i < lineLimit; i++) {
        data_received[i] = data[i];
       }

       WriteToCsv(command, "YOUR_CSV_FILE_PATH_LIKE_C:\test\",data); // Write to csv here...

       stream.BaseStream.Flush();
      }
     }

     public void WriteToCsv(string command, string csvFilePath, List < string > dataToWriteToCsv) {
      var csv = new StringBuilder();
      var fullPath = $ "{csvFilePath}{command}.csv"; // create your full path with file name.

      // add your data line by line
      foreach(var data in dataToWriteToCsv) {
       csv.AppendLine(data);
      }

      // write to csv
      File.WriteAllText(fullPath, csv.ToString());
     }

Upvotes: 2

Related Questions