C# - SerialPort Encoding help needed - c#

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.

Related

C# program Slowing down due to function

I am writing a C# program to interface with an Arduino through a serial port and I have a function updateRPMs() that slows down the program so much it is unusable. It gets called every 1 second when it is used. The program runs a few PWM fans.
Here is the function:
private void updateRPMs()
{
TextBox[] RPMS = { Fan1RPM, Fan2RPM, Fan3RPM, Fan4RPM, Fan5RPM, Fan6RPM, Fan7RPM, Fan8RPM, Fan9RPM, Fan10RPM, Fan11RPM, Fan12RPM };
List<String> sepData = new List<String>();
if (CONNECTED)
{
String data = serialPort1.ReadLine();
// MessageBox.Show(data);
sepData = (data.Split(';').ToList());
if (sepData.Count == 12)
{
for (int i = 0; i < 12; i++)
{
RPMS[i].Text = sepData[i];
}
}
serialPort1.DiscardOutBuffer();
}
}
This is something the Arduino would send to the program:
a840.00;b885.00;c0;d0;e0;f0;g1635.00;h2070.00;i0;j0;k0;l0
I know I can push this to a different thread but I am trying to have it update as soon as the timer fires.
I was wondering if there is anything I could change or if there was anything stupid I did. I am new to C# and any help would be appreciated.
For reading from serial, I suggest you to avoid using a timer to read from the serial. You can use the DataReceived event, which is fired every time some data is received from the serial.
Of course you could receive a partial packet, so it's better to store the data in a buffer and then analyze it.
String readBuffer = "";
private static void DataReceivedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
readBuffer += sp.ReadExisting();
int newLineIndex = -1;
while ((newLineIndex = readBuffer.IndexOf("\n")) >= 0)
{ // Analyze buffer
String currentLine = readBuffer.Substring(0,newLineIndex);
if (currentLine.length() > 0)
analyzeLine(currentLine);
readBuffer = readBuffer.Substring(newLineIndex+1);
}
}
public void analyzeLine(String data)
{
static TextBox[] RPMS = { Fan1RPM, Fan2RPM, Fan3RPM, Fan4RPM, Fan5RPM, Fan6RPM, Fan7RPM, Fan8RPM, Fan9RPM, Fan10RPM, Fan11RPM, Fan12RPM };
List<String> sepData = (data.Split(';').ToList());
if (sepData.Count == 12)
{
for (int i = 0; i < 12; i++)
{
RPMS[i].Text = sepData[i];
}
}
}
I assume you know how to attach to an event, since you already used the timer one ini your code ;)

Saving raw detph-data

I am trying to save my kinect raw depth-data and i dont want to use the Kinect Studio, because i need the raw-data for further calculations. I am using the kinectv2 and kinect sdk!
My problem is that i just get low FPS for the saved data. Its about 15-17FPS.
Here my Framereader ( in further steps i want to save colorstream also):
frameReader = kinectSensor.OpenMultiSourceFrameReader(FrameSourceTypes.Depth);
frameReader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;
Here the Event:
void Reader_MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e)
{
var reference = e.FrameReference.AcquireFrame();
saveFrameTest(reference);
frame_num++;
}
Here the saving-function:
private unsafe void saveFrameTest(Object reference)
{
MultiSourceFrame mSF = (MultiSourceFrame)reference;
using (var frame = mSF.DepthFrameReference.AcquireFrame())
{
if (frame != null)
{
using (Microsoft.Kinect.KinectBuffer depthBuffer = frame.LockImageBuffer())
{
if ((frame.FrameDescription.Width * frame.FrameDescription.Height) == (depthBuffer.Size / frame.FrameDescription.BytesPerPixel))
{
ushort* frameData = (ushort*)depthBuffer.UnderlyingBuffer;
byte[] rawDataConverted = new byte[(int)(depthBuffer.Size / 2)];
for (int i = 0; i < (int)(depthBuffer.Size / 2); ++i)
{
ushort depth = frameData[i];
rawDataConverted[i] = (byte)(depth >= frame.DepthMinReliableDistance && depth <= frame.DepthMaxReliableDistance ? (depth) : 0);
}
String date = string.Format("{0:hh-mm-ss}", DateTime.Now);
String filePath = System.IO.Directory.GetCurrentDirectory() + "/test/" +date+".raw";
File.WriteAllBytes(filePath, rawDataConverted);
rawDataConverted = null;
}
}
}
}
}
Further Infomration:
I included my code in a simple Console-Application on a Intel® Xeon® Processor E5-1620 3,7GHz with 16 GB RAM.
i think the for-loop is taking to much time:
for (int i = 0; i < (int)(depthBuffer.Size / 2); ++i)
{
ushort depth = frameData[i];
rawDataConverted[i] = (byte)(depth >= frame.DepthMinReliableDistance && depth <= frame.DepthMaxReliableDistance ? (depth) : 0);
}
I could improved my framerate. Now, i am accessing the kinectbuffer directly and resign the for-loop.
Microsoft.Kinect.KinectBuffer depthBuffer = frame.LockImageBuffer();
Marshal.Copy(depthBuffer.UnderlyingBuffer, rawData_depth, 0, (depthImageSize));
depthBuffer.Dispose();
frame.Dispose();
However i couldnt get the 30FPS-rate. Now it is about 25 FPS.
You could try something like this to get your array.
It's what I normally use.
var frame = frameReference.AcquireFrame();
var frameDescription = frame.FrameDescription;
ushort[] frameData = new ushort[frameDescription.Width * frameDescription.Height];
frame.CopyFrameDataToArray(frameData);

c# How to run a application faster

I am creating a word list of possible uppercase letters to prove how insecure 8 digit passwords are this code will write aaaaaaaa to aaaaaaab to aaaaaaac etc. until zzzzzzzz using this code:
class Program
{
static string path;
static int file = 0;
static void Main(string[] args)
{
new_file();
var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789+-*_!$£^=<>§°ÖÄÜöäü.;:,?{}[]";
var q = alphabet.Select(x => x.ToString());
int size = 3;
int counter = 0;
for (int i = 0; i < size - 1; i++)
{
q = q.SelectMany(x => alphabet, (x, y) => x + y);
}
foreach (var item in q)
{
if (counter >= 20000000)
{
new_file();
counter = 0;
}
if (File.Exists(path))
{
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine(item);
Console.WriteLine(item);
/*if (!(Regex.IsMatch(item, #"(.)\1")))
{
sw.WriteLine(item);
counter++;
}
else
{
Console.WriteLine(item);
}*/
}
}
else
{
new_file();
}
}
}
static void new_file()
{
path = #"C:\" + "list" + file + ".txt";
if (!File.Exists(path))
{
using (StreamWriter sw = File.CreateText(path))
{
}
}
file++;
}
}
The Code is working fine but it takes Weeks to run it. Does anyone know a way to speed it up or do I have to wait? If anyone has a idea please tell me.
Performance:
size 3: 0.02s
size 4: 1.61s
size 5: 144.76s
Hints:
removed LINQ for combination generation
removed Console.WriteLine for each password
removed StreamWriter
large buffer (128k) for file writing
const string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789+-*_!$£^=<>§°ÖÄÜöäü.;:,?{}[]";
var byteAlphabet = alphabet.Select(ch => (byte)ch).ToArray();
var alphabetLength = alphabet.Length;
var newLine = new[] { (byte)'\r', (byte)'\n' };
const int size = 4;
var number = new byte[size];
var password = Enumerable.Range(0, size).Select(i => byteAlphabet[0]).Concat(newLine).ToArray();
var watcher = new System.Diagnostics.Stopwatch();
watcher.Start();
var isRunning = true;
for (var counter = 0; isRunning; counter++)
{
Console.Write("{0}: ", counter);
Console.Write(password.Select(b => (char)b).ToArray());
using (var file = System.IO.File.Create(string.Format(#"list.{0:D5}.txt", counter), 2 << 16))
{
for (var i = 0; i < 2000000; ++i)
{
file.Write(password, 0, password.Length);
var j = size - 1;
for (; j >= 0; j--)
{
if (number[j] < alphabetLength - 1)
{
password[j] = byteAlphabet[++number[j]];
break;
}
else
{
number[j] = 0;
password[j] = byteAlphabet[0];
}
}
if (j < 0)
{
isRunning = false;
break;
}
}
}
}
watcher.Stop();
Console.WriteLine(watcher.Elapsed);
}
Try the following modified code. In LINQPad it runs in < 1 second. With your original code I gave up after 40 seconds. It removes the overhead of opening and closing the file for every WriteLine operation. You'll need to test and ensure it gives the same results because I'm not willing to run your original code for 24 hours to ensure the output is the same.
class Program
{
static string path;
static int file = 0;
static void Main(string[] args)
{
new_file();
var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789+-*_!$£^=<>§°ÖÄÜöäü.;:,?{}[]";
var q = alphabet.Select(x => x.ToString());
int size = 3;
int counter = 0;
for (int i = 0; i < size - 1; i++)
{
q = q.SelectMany(x => alphabet, (x, y) => x + y);
}
StreamWriter sw = File.AppendText(path);
try
{
foreach (var item in q)
{
if (counter >= 20000000)
{
sw.Dispose();
new_file();
counter = 0;
}
sw.WriteLine(item);
Console.WriteLine(item);
}
}
finally
{
if(sw != null)
{
sw.Dispose();
}
}
}
static void new_file()
{
path = #"C:\temp\list" + file + ".txt";
if (!File.Exists(path))
{
using (StreamWriter sw = File.CreateText(path))
{
}
}
file++;
}
}
your alphabet is missing 0
With that fixed there would be 89 chars in your set. Let's call it 100 for simplicity. The set you are looking for is all the 8 character length strings drawn from that set. There are 100^8 of these, i.e. 10,000,000,000,000,000.
The disk space they will take up depends on how you encode them, lets be generous - assume you use some 8 bit char set that contains the these characters, and you don't put in carriage returns, so one byte per char, so 10,000,000,000,000,000 bytes =~ 10 peta byes?
Do you have 10 petabytes of disk? (10000 TB)?
[EDIT] In response to 'this is not an answer':
The original motivation is to create the list? The shows how large the list would be. Its hard to see what could be DONE with the list if it was actualised, i.e. it would always be quicker to reproduce it than to load it. Surely whatever point could be made by producing the list can also be made by simply knowing it's size, which the above shows how to work it out.
There are LOTS of inefficiencies in you code, but if your questions is 'how can i quickly produce this list and write it to disk' the answer is 'you literally cannot'.
[/EDIT]

Duplicate math result in Bakery Algorithm (C# code)

Index out of bounds when create new thread with parameters? - Continue to my previous topic , now i got a new problem with my my Bakery Algorithm code !
Here's my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace BakeryAlgorithm
{
class Program
{
static int threads = 10;
static string x = "";
static int count = 0;
static int[] ticket = new int[threads];
static bool[] entering = new bool[threads];
public static void doLock(int pid)
{
for (int i = 0; i < threads; i++)
{
ticket[i] = 0;
entering[i] = false;
}
entering[pid] = true;
int max = 0;
for (int i = 0; i < threads; i++)
{
if (ticket[i] > ticket[max]) { max = i; }
}
ticket[pid] = 1+max;
entering[pid] = false;
for (int i = 0; i < threads; ++i)
{
if (i != pid)
{
while (entering[i])
{
Thread.Yield();
}
while (ticket[i] != 0 && (ticket[pid] > ticket[i] ||
(ticket[pid] == ticket[i] && pid > i)))
{
Thread.Yield();
}
}
}
if (x == "C" || x == "c")
Console.WriteLine("[System] PID " + pid.ToString() + " get into critical section");
}
public static void unlock(int pid)
{
ticket[pid] = 0;
count++;
Console.WriteLine("[Thread] PID " + pid.ToString() + " complete.");
}
public static void arrayInit()
{
for (int i = 0; i < threads; i++)
{
ticket[i] = 0;
entering[i] = false;
}
}
public static void simThread(int i)
{
doLock(i);
if (x == "C" || x=="c")
Console.WriteLine("[Thread] PID " + i.ToString() + " begin to process...");
//Do some thing ????
Random rnd = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
int a = rnd.Next(1,99);
int b = rnd.Next(1,99);
int c = rnd.Next(1,4);
int d = 0;
string o="";
if (c == 1)
{
d = a + b;
o="+";
}
else if (c == 2)
{
d = a * b;
o="*";
}
else if (c == 3)
{
d = a / b;
o="/";
}
else
{
d = a - b;
o="-";
}
if (x == "C" || x == "c")
Console.WriteLine("Math Result : " + a.ToString() + o + b.ToString() + "=" + d.ToString());
unlock(i);
}
[STAThread]
static void Main(string[] args)
{
arrayInit();
string choice="C";
while (choice == "C" || x == "c")
{
Console.WriteLine("Process log (C=Yes,K=No) : ");
x = Console.ReadLine();
if (x == "")
x = "C";
Console.Clear();
Console.WriteLine("----------------------------------");
Console.WriteLine("Bakery Algorithm C#");
Console.WriteLine("Number of threads : " + threads.ToString());
Console.WriteLine("Process Log...");
Console.WriteLine("----------------------------------");
Thread[] threadArray = new Thread[threads];
for (int i = 0; i < 10; i++)
{
int copy = i;
threadArray[i] = new Thread(() => simThread(copy));
if (x == "C" || x == "c")
Console.WriteLine("[System] PID " + i.ToString() + " created");
threadArray[i].Start();
}
Console.ReadLine();
Console.WriteLine("----------------------------------");
Console.WriteLine("Complete processed " + count.ToString() + " threads !");
count = 0;
Console.WriteLine("----------------------------------");
Console.WriteLine("You want to restart (Yes=C or No=K)");
choice = Console.ReadLine();
if (choice == "")
choice = "C";
}
}
}
}
The result are here :
2*2=4
2*2=4 << duplicated
3*2=6
4*2=8
4*6=24
4*2=8 << duplicated
.... and continue with duplicate values ( random position ) !
Hope somebody here can help !
There's many things wrong with your code, but the most important part is that you didn't read the requirements that make Lamport's bakery work:
Lamport's bakery algorithm assumes a sequential consistency memory model.
You will be hard-pressed to find a modern computer that has sequential consistency.
So even if your implementation was correct with respect to those constraints, it would still be wrong on pretty much any computer that runs .NET. To make this work on a modern CPU and in .NET, you'll need to insert memory barriers to prevent instruction reordering and introduce cache refreshing to make sure each CPU core sees the same values... and by then you're probably better off using different synchronization primitives altogether.
Now, fixing these kinds of algorithms tends to be rather hard - multi-threading is hard on its own, doing lock-less multi-threading just pushes this to absurd territory. So let me just address some points:
1) You can't just use new Random() and expect statistically random numbers from that. Random has an internal state that's by default initialized to the current OS tick - that means that creating 10 Randoms in a row and then doing Next on each of those is pretty likely to produce exactly the same "random" numbers.
One way of handling that gracefully would be to have a thread-local field:
ThreadLocal<Random> rnd
= new ThreadLocal<Random>(() => new Random(Guid.NewGuid().GetHashCode()));
Each of your threads can then safely do rnd.Value.Next(...) and get reliable numbers without locking.
However, since the whole point of this excercise is to allow shared access to mutable state, a solution more in line with the task would be to use a single shared Random field instead (created only once, before starting the threads). Since the Bakery algorithm is supposed to make sure you can safely use shared stuff in the critical section, this should be safe, if implemented correctly :)
2) To actually make the Bakery part work, you need to enforce the only proper instruction ordering.
This is hard. Seriously.
I'm not actually sure how to do this safely.
The best way to start is to insert an explicit memory barrier before and after each read and write of shared state. Then you can go one by one and remove those that aren't necessary. Of course, you should only need this in the doLock and unlock methods - the rest of simThread should be single-threaded.
For a short sample:
Thread.MemoryBarrier();
entering[pid] = true;
Thread.MemoryBarrier();
int max = 0;
for (int i = 0; i < threads; i++)
{
if (ticket[i] > ticket[max]) { max = i; }
}
Thread.MemoryBarrier();
ticket[pid] = 1+max;
Thread.MemoryBarrier();
entering[pid] = false;
Thread.MemoryBarrier();
So, which one of those is it safe to remove? I have no idea. I'd have to use a lot of mental power to make sure this is safe. Heck, I'm not sure if it's safe as is - do I need to rewrite the for cycle too? Are ticket[i] and ticket[max] going to be fresh enough for the algorithm to work? I know some are definitely needed, but I'm not sure which can safely be left out.
I'm pretty sure this will be slower than using a simple lock, though. For any production code, steer clear away from code like this - "smart" code usually gets you in trouble, even if everyone in your team understands it well. It's kind of hard finding those kinds of experts, and most of those wouldn't touch lock-less code like that with a meter-long stick :)
You must create a different random number for each thread (more details)
so try this code in your main method:
for (int i = 0; i < 10; i++)
{
int temp = i;
threadArray[i] = new Thread(() => simThread(temp));
Console.WriteLine("[He Thong] PID " + i.ToString() + " duoc khoi tao");
threadArray[i].Start();
Thread.Sleep(20);
}
and the following code in you threads:
Random rand = new Random((int) DateTime.Now.Ticks & 0x0000FFFF);
now you can ensure you produce different random number for each thread.
Try:
Random rnd = new Random(Environment.TickCount / (i + 1));
This will give different seeds to each RNG.

"fread(serial)" and "fscanf(serial)" from Matlab to 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.

Categories

Resources