"fread(serial)" and "fscanf(serial)" from Matlab to C# - c#

everyone,
now i'm writing a C# programm according to a piece of matlab code.
In matlab code there are two commands to read data from the COM-Port:
A=fscanf(com_Port1,'%s');
A=fread(com_Port1,1008); //two sentences are next to each other like i write here.
For the first command "A=fscanf(com_Port1,'%s');" i used:
string A = com_Port1.ReadExisting();
and it seems all right, because no error warning;
for the second command "A=fread(com_Port1,1008);" i used:
double[] B = new double[1008];
for (int i = 0; i <= 1008 - 1; i++)
{
B[i] = com_Port1.ReadByte() ;
}
then it shows an error:
"A first chance exception of type 'System.TimeoutException' occurred
in System.dll".
So i'm assuming that "ReadExisting" has read all the data, and "ReadByte" can't read available data any more, is that right?Could someone tell me where i war wrong? thank you.
Yours
Adam
Add at Nov.20.2013, below is the code i have wrote, i have tried "Read()","ReadTo()","ReadLine()", but i still get the error at "otdr_Portobject.ReadByte()", i have no idea any more.
otdr_Portobject = new otdr_Port(cB_portNames.SelectedItem.ToString());
otdr_Portobject.Open();
btn_Stop.Enabled = true;
btn_Start.Enabled = false;
/*if (!otdr_Portobject.IsOpen)
{
MessageBox.Show("not open");
}
else {
MessageBox.Show("Serial Port opened");
};*/
//string start = "start";
otdr_Portobject.Write("start");
char[] b9 = new char[7];
otdr_Portobject.Read(b9, 0, 7);
Thread.Sleep(5000);
//string isready = "isready";
otdr_Portobject.Write("isready");
char[] b10 = new char[10];
otdr_Portobject.Read(b10, 0, 10);
//A = otdr_Portobject.ReadTo("\n");
//string rdatb = "rdatb";
int int32_Auslesekommando = Convert.ToInt32(pointsCon.Value-1);
otdr_Portobject.Write("rdatb " + int32_Auslesekommando.ToString("X4") + "\n");
Thread.Sleep(50);
char[] b11 = new char[18];
otdr_Portobject.Read(b11, 0, 18);
//A = otdr_Portobject.ReadTo("\n");
//A = otdr_Portobject.ReadTo("\n");
//int A1=otdr_Portobject.ReadByte();
//brechnen Y Axis
int pointNum = Convert.ToInt32(pointsCon.Value);
double[] B = new double[pointNum];
//int byteNum=otdr_Portobject.BytesToRead;
//if ( byteNum== 0) return;
try
{
for (int i = 0; i <= pointNum - 1; i++)
{
B[i] =System.Convert.ToDouble( otdr_Portobject.ReadByte() )* 256;
}
}
catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}

From the c#-docs:
ReadExsting: Reads all immediately available bytes, based on the encoding, in both the stream and the input buffer of the SerialPort object..
MATLAB:
%s format for fscanf: Read series of characters, until find white space.
So you should probably switch to ReadTo, specifying a white-space character to stop.
Or call Read yourself until the returned value is a whitespace-character.

Related

C# - SerialPort Encoding help needed

I need help with my program with which I want to read codes from several microcontrollers simultaneously and translate them into plain text. There is only one serial interface where all codes are collected. The translation of the codes works, but I have the problem that the codes are not read correctly. He makes pauses again and again where there are no gaps and where there are gaps (500 micro sec. ) He doesn't always recognize them correctly.
Here's part of the code:
public byte[] block = new byte[4096];
public int posBlock = 0;
public void Read(object sender, SerialDataReceivedEventArgs e)
{
console_.WriteLine("--------------------------------------------------");
console_.WriteLine("Void: Read(object sender, SerialDataReceivedEventArgs e)");
int offset = 0, count = serialPort.BytesToRead, i = 0;
byte[] rd = new byte[count];
serialPort.Read(rd, offset, count);
for (int buffer = 0; buffer < count; buffer++) { block[posBlock + buffer] = rd[buffer]; i = buffer; }
i++;
posBlock += i;
string rcpausgabe = null;
for (int i2 = 0; i2 < posBlock; i2++) { rcpausgabe += " " + (int)(block[i2]); }
//WriteProtocol(global_.variables.protocol_other, rcpausgabe, true);
console_.WriteLine("ReadCode: " + rcpausgabe);
if (IsDecode == false) { Zersetzten(); } else { console_.WriteLine("Add but not Zersetzen()"); }
IsDecode = false;
console_.WriteLine("--------------------------------------------------");
}
bool IsDecode = true;
public int ib = 0;
public string bs = null;
private void Zersetzten()
{
IsDecode = true;
console_.WriteLine("--------------------------------------------------");
console_.WriteLine("Void: Zersetzten()");
byte[] b = new byte[4096];
while (!(ib >= posBlock))
{
for (int i7 = 0; i7 < b[1] + 3; i7++)
{
string rcpausgabe1 = null;
b[i7] = block[ib];
ib++;;
if (i7+1 == (b[1] + 3))
{
Thread.Sleep(500);
console_.WriteLine("Decoding b");
for (int i2 = 0; i2 < b[1]+3; i2++) { rcpausgabe1 += " " + (int)(b[i2]); }
console_.WriteLine("Decoding Code: " + rcpausgabe1);
bs = rcpausgabe1;
Decoding(b);
}
}
}
IsDecode = false;
block = new byte[4096];
posBlock = 0;
ib = posBlock;
console_.WriteLine("--------------------------------------------------");
}
I have programmed my own console (console_) to help me with this, which allows me to track all processes in real time.
I also thank everyone for their answers in advance.
(I translated this text with Pons translator because my english is not so good)
I can't comment, so I have to use post to help you clarify your question.
I'll edit my answer if you could provide more detail.
Make your question clearer.
What result do you expect and what kind of phenomena do you observe.
Make minimal, reproducible example
Apparently Read(object sender, SerialDataReceivedEventArgs e) is not called inside of your post.
While your problem is reading is "paused", which piece of code is calling Read could be essential.
What is "pause" and what is "Gap".
He makes pauses again and again where there are no gaps and where there are gaps (500 micro sec.
I could only guess your program will "pause" when there is a gap, but having no idea about what "gap" and "pause" are.
What does for (int i7 = 0; i7 < b[1] + 3; i7++) and for (int i2 = 0; i2 < b[1]+3; i2++) want do achieve?
You're using b[1] for indexing and b[1] is changed while you're receiving data.
Edit: Adding How to create a Minimal, Reproducible Example.
Edit2: Point out a strange piece of code in for loop.
I am not sure what is wrong with you about the code you provided.
However, you could refer to [C#, need to receive data from microcontroller to receive data from microcontroller)
to know how to achieve the data from the microcontroller.

New to c#, not understanding online compiler

so I wrote some C# code and I am trying to test it incrementally, do to something that would take a while to explain, but bottom line, I'm new to c# and not understanding the online compiler error messages. Here is the error message I get when I try and compile, but the strings look good to me.
string solutionSet = "white|black|beige|pink|green|blue|red|yellow|orange|cyan|purple|brown";
string[] solutionSetArray = new string[12];
string ret = "";
string delimeter = "|";
int tempPos = 0;
int counter = 0;
int successFlag = 0;
int patternLength = 5;
for (int index = 0; index < solutionSet.Length; index++)
{
if (solutionSet[index] == delimeter)
{
solutionSetArray[counter] = solutionSet.Substring(tempPos, index);
tempPos = index + 1;
counter++;
}
if (solutionSet.Length - index == 1)
{
solutionSetArray[solutionSetArray.Length-1] = solutionSet.Substring(tempPos, solutionSet.Length);
}
}
for (int i = 0; i < patternLength; i++)
{
Random rnd = new Random();
int randIndex = rnd.Next(solutionSetArray.Length);
if (i != patternLength - 1)
{
ret += solutionSetArray[randIndex] + "|";
successFlag++;
}
else
{
ret += solutionSetArray[randIndex];
}
}
if (successFlag == patternLength - 1)
{
Console.WriteLine(ret);
}
else
{
Console.WriteLine("ERROR");
}
The error (which, according to the message, is on line 1, column 11) is being caused by your very first line of code, which begins string.
I can't tell the context from just your post, but my guess is that you are declaring solutionSet in a block that is not inside of a class or function. You should enclose your code in a class or method, e.g.
public class MyClass
{
static public void Main()
{
string solutionSet = "white|black|beige|pink|green|blue|red|yellow|orange|cyan|purple|brown";
//Rest of code goes here
}
}
By the way, if you're trying to convert solutionSet to an array, you can just write
var solutionSetArray = solutionSet.Split("|");
the problem with your code is
solutionSetArray[counter] = solutionSet.Substring(tempPos, index);
after 6 iterations tempPos=34 and index=37 which is running out of bounds of solutionSet. I would suggest to use var solutionSetArray = solutionSet.Split("|"); and also use LinqPad which can be easy for you to debug if possible,.

c#-how to convert arduino data to int array

Would like to seek help. I am new with C# and want to integrate arduino. Would like to know on how to convert the code i sent from arduino to C#. I want to assign the data into an array int.
Here's the sample i want to send from arduino.
Serial.println(1);
Serial.println(2);
Serial.println(3)
and my code in c#
int[] data = new int[3];
data[3] = Int32.Parse(serialPort.ReadLine());
data[2] = Int32.Parse(serialPort.ReadLine());
data[1] = Int32.Parse(serialPort.ReadLine());
Kindly please advise
array's indexes in c# start from 0.
this code line is your problem and the reason to the failure:
data[3] = Int32.Parse(serialPort.ReadLine());
change your code to:
int[] data = new int[3];
data[2] = Int32.Parse(serialPort.ReadLine());
data[1] = Int32.Parse(serialPort.ReadLine());
data[0] = Int32.Parse(serialPort.ReadLine());
Edit: (answer to the comment...)
This class provide you 2 extensions method one for unknown sequence length(but you have to create a stop condition) use the second method if you know the exact number of ints.
Note:
4 years ago i used SerialPort with a graphical tablet.
I used the event: DataReceived as a reading trigger.
for more information see this example.
//to use extension methods do: serialPort.ReadKnownLength(3);
public static class SerialPortExtensions
{
public static int[] ReadUnknownLength(this SerialPort serialPort)
{
var list = new List<int>();
while (true)
{
try
{
var input = serialPort.ReadLine();
//change the condition to your own break condition
if (String.IsNullOrEmpty(input))
break;
list.Add(int.Parse(input));
}
catch (TimeoutException)
{
}
}
// if you don't need to reorder
//return list.ToArray();
var result = new int[list.Count];
for (var i = 0; i < result.Length; i++)
{
//reorder the input(you did it in your question...)
result[i] = list[list.Count - (i + 1)];
}
return result;
}
//match your question behavior
public static int[] ReadKnownLength(this SerialPort serialPort, int length)
{
var result = new int[length];
for (int i = length - 1; i >= 0; i--)
{
result[i] = Int32.Parse(serialPort.ReadLine());
}
return result;
}
}

How to fix this error: nullreferenceexception was unhandled

I have a problem with C# and need help.
I created a text file which included an IP Address and Port pairs; one pair per line. It's structure is like this:
xxx.xxx.xxx.xxx:xxxx
xxx.xxx.xxx.xxx:xxxx
xxx.xxx.xxx.xxx:xxxx
This is the code.
public void Filter()
{
// Read proxy from text file
string ppath = #"C:\Program Files\HTE\IP.txt";
StreamReader sr = new StreamReader(ppath);
/*
Proxies in the text file have a contruction like this: xxx.xxx.xxx.xxx:xxxx
It includes more than 11k proxies
Now start to collect ip
*/
for (int i = 0; i < 11000; i++)
{
if (i > 0)
{
// Create a loop to ignore the line(s) which has been filter
for (int j = 0; j < i; j++)
{
// When j = 0, that mean it has an ignore line
sr.ReadLine();
GC.Collect();
}
// Read new line
string str_2 = sr.ReadLine();
int position_2 = str_2.IndexOf(":");
// Get ip
string str_ip_2 = str_2.Substring(0, position_2);
int tail_2 = str_2.Length - position_2;
string str_tmp_2 = str_2.Substring(position_2, tail_2);
int subtraction_2 = str_tmp_2.Length - 1;
// Get port
string str_port_2 = str_tmp_2.Substring(1, subtraction_2);
GC.Collect();
}
else if (i == 0)
{
string str = sr.ReadLine();
// find ":" in the postion of the first line
int position = str.IndexOf(":");
// Get ip
string str_ip = str.Substring(0, position);
// The tail of string in line is proxy port
int tail = str.Length - position;
string str_tmp = str.Substring(position, tail);
int subtraction = str_tmp.Length - 1;
// Get port
string str_port = str_tmp.Substring(1, subtraction);
GC.Collect();
}
}
Error code:
string str_2 = sr.ReadLine();
int position_2 = str_2.IndexOf(":");
I have tried many ways, but I couldn't fix it.
Thanks in advance.
Your call to sr.ReadLine() is most likely returning null, making str_2 null, and causing str_2.IndexOf to throw the exception.
You have 2 calls to .ReadLine(). How many lines of data are you actually reading? If only one line, the 2nd call will return null, causing the above.

function works correctly from MATLAB, but not when called from .NET

I'm using MATLAB Builder NE for interoperability to call MATLAB functions from a C# .NET program built as a plug-in for the open source application ClearCanvas. When I run the code normally from the .NET program, I usually (but not always) get the error message
MWMCR::EvaluateFunction error ... Reference to non-existent element of a cell array. Error in => ComputeT1Maps.m at line 178.
The line of MATLAB code in question is as follows:
seriesHeader = currentSlab.Slice{1}.MetaData{1}.Header;
Header is a struct of the form given by MATLAB's dicominfo function and MetaData{n} is a struct that contains the filename and image header struct for the nth image file.
The function signature for the ComputeT1Maps function is:
function ComputeT1Maps(data, options)
To try to figure out this bug I put the following line in at the beginning of the ComputeT1Maps function in order to preserve state so I could see what values were passed to MATLAB from .NET:
save(fullfile('F:\MATLAB\T1Mapping', 'T1_debug.mat'), 'data', 'options', ...
'-mat', '-v7.3');
So, having preserved the inputs to this function (received from the .NET program that called it), I then tried running my ComputeT1Maps function from an interactive MATLAB session after loading in the saved variables, so that I could utilize MATLAB's debugging tools to figure out why I was getting the error. That's when things got really bizarre. The function works just fine from the interactive MATLAB session when given the exact same operands that were given to it when it was called from my .NET program. How can this be? How can the function fail when called from C# .NET, but run properly when given the exact same input in an interactive MATLAB session? Also, this same code used to work before and the error only began to happen after I updated both my local installation of MATLAB and the MCR to the latest version (2011b).
On the .NET side, the data that is passed to MATLAB is constructed by the following function:
public void ExchangeData(MultidimensionalDataCollection mdc, string outputPath, bool generateAncillaryTestImages,
bool excludeAcquisitions, double[] exclusionList, bool showProgressBar, bool displayComputedImages,
bool pauseAtEachSlice, bool softwareDiagnostics, bool displayProgressBar)
{
try
{
int subspaceIndex = 0;
int slabIndex = 0;
int sliceIndex = 0;
int imageIndex = 0;
MWStructArray topLevelGrouping;
MWCellArray geometricSubspaceList;
MWStructArray geometricGrouping;
MWCellArray slabList;
MWStructArray slabGrouping;
MWCellArray sliceList;
MWStructArray sliceGrouping;
MWCellArray imageMetaData;
MWStructArray perImageData;
MWArray[] result;
MWLogicalArray successFlag;
MWStructArray header;
MWCellArray sopInstanceUids;
MWStructArray t1MapOptions;
topLevelGrouping = new MWStructArray(1, 1, new string[] { "GeometricSubspace",
"GeometricSubspaceCount" });
topLevelGrouping["GeometricSubspaceCount", 1] = mdc.Count;
geometricSubspaceList = new MWCellArray(1, mdc.Count);
subspaceIndex = 0;
foreach (GeometricSubspace subspace in mdc)
{
subspaceIndex++;
geometricGrouping = new MWStructArray(1, 1, new string[] { "Slab",
"SlabCount" });
geometricGrouping["SlabCount", 1] = subspace.Count;
slabList = new MWCellArray(1, subspace.Count);
slabIndex = 0;
foreach (Slab slab in subspace)
{
slabIndex++;
slabGrouping = new MWStructArray(1, 1, new string[] { "Slice",
"SliceCount" });
slabGrouping["SliceCount", 1] = slab.Count;
sliceList = new MWCellArray(1, slab.Count);
sliceIndex = 0;
foreach (Slice slice in slab)
{
sliceIndex++;
sliceGrouping = new MWStructArray(1, 1, new string[] {
"ImageCount", "MetaData", "MultidimensionalPixelData",
"SliceLocation", "SopInstanceUids" });
sliceGrouping["ImageCount", 1] = slice.Count;
imageMetaData = new MWCellArray(1, slice.Count);
int rows, columns;
short[,,,] multidimensionalPixelData = null;
imageIndex = 0;
foreach (Image image in slice)
{
imageIndex++;
short[,] imageMatrix = null;
if (!image.ImageSopClass.DicomUid.Equals(DicomUids.MRImageStorage))
throw new NotSupportedException("SopClass " + image.ImageSopClass.Name + " is not supported.");
else
{
DicomUncompressedPixelData rawPixelData = image.PixelData;
imageMatrix = GetCCImageMatrix(rawPixelData, out rows, out columns);
if (imageIndex == 1)
{
multidimensionalPixelData = new short[slice.Count, 1, columns, rows];
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
// Remember that C# array indices start with 0 while in MATLAB they start with 1
multidimensionalPixelData[imageIndex - 1, 0, i, j] = imageMatrix[i, j];
}
}
}
perImageData = new MWStructArray(1, 1, new string[] { "FileName", "Header" });
perImageData["FileName", 1] = image.FileName;
result = _mlT1Mapping.QT1GetDicomHeader(2, image.FileName);
if (result == null)
throw new Exception("GetDicomHeader failed to read the header file for filename: " +
image.FileName);
else
{
// MWStructArray
successFlag = (MWLogicalArray)result[0];
bool[] headerObtained = successFlag.ToVector();
if (headerObtained[0])
{
header = (MWStructArray)result[1];
perImageData["Header", 1] = header;
imageMetaData[1, imageIndex] = perImageData;
}
else
{
Console.WriteLine("GetDicomHeader failed to read the header file for filename: " +
image.FileName);
}
}
}
sliceList[1, sliceIndex] = sliceGrouping;
sliceGrouping["MetaData", 1] = imageMetaData;
sliceGrouping["SliceLocation", 1] = slice.SliceLocation;
List<string> theSops = slice._sopList;
sopInstanceUids = new MWCellArray(1, slice._sopList.Count);
int count = 0;
foreach (string sop in theSops)
{
count++;
sopInstanceUids[1, count] = sop;
}
sliceGrouping["SopInstanceUids", 1] = sopInstanceUids;
sliceGrouping["MultidimensionalPixelData", 1] = (MWNumericArray)multidimensionalPixelData;
}
slabList[1, slabIndex] = slabGrouping;
slabGrouping["Slice", 1] = sliceList;
}
geometricSubspaceList[1, subspaceIndex] = geometricGrouping;
geometricGrouping["Slab", 1] = slabList;
}
topLevelGrouping["GeometricSubspace", 1] = geometricSubspaceList;
t1MapOptions = new MWStructArray(1, 1, new string[] { "DirectoryPath",
"ComputeDifferenceImages", "ComputeMultiplicationImages", "DisplayComputedImages", "PauseAtEachSlice",
"SoftwareDiagnostics", "DisplayProgressBar"
});
t1MapOptions["DirectoryPath"] = (MWCharArray)outputPath;
t1MapOptions["SaveS0Maps"] = (MWLogicalArray)generateAncillaryTestImages;
t1MapOptions["ExcludeAcquisitions"] = (MWLogicalArray)excludeAcquisitions;
t1MapOptions["ExclusionList"] = (MWNumericArray)exclusionList;
t1MapOptions["DisplayComputedImages"] = (MWLogicalArray)displayComputedImages;
t1MapOptions["PauseAtEachSlice"] = (MWLogicalArray)pauseAtEachSlice;
t1MapOptions["SoftwareDiagnostics"] = (MWLogicalArray)softwareDiagnostics;
t1MapOptions["DisplayProgressBar"] = (MWLogicalArray)displayProgressBar;
_mlT1Mapping.ComputeT1Maps(topLevelGrouping, t1MapOptions);
}
catch (Exception)
{
throw;
}
}
I'm not yet 100% certain that I've fixed everything, but so far the tests appear to be succeeding after a few changes. It seems that the crux of the problem was that the order of some assignments was transposed. This occurred in a few places. For example, instead of:
sliceList[1, sliceIndex] = sliceGrouping;
sliceGrouping["MetaData", 1] = imageMetaData;
it should have been ordered as:
sliceGrouping["MetaData", 1] = imageMetaData;
sliceList[1, sliceIndex] = sliceGrouping;
The strange thing about this bug was that the code worked just fine in the previous version of MATLAB. It should have never worked at all!

Categories

Resources