Sending data from Arduino to a C# GUI - Page 1
Forum section: electronics / general

author: BRetonDP
author_rank: Contributor
timestamp: October 03, 2014, 10:30:12 pm
content: Hello, everyone! I need some help communicating my Arduino with a C# program. I'm using an Arduino PING ranging sensor in order to read a value (an int). I want that value to set the X location of a component (in this case, a picture box) in a C# program. I'm having some issues, however, and I hope you guys can help me out.My Arduino code is the following:Code:const int trig = 8;const int echo = 7;int info;void setup(){Serial.begin(9600);pinMode(trig, OUTPUT);pinMode(echo, INPUT);}void loop(){digitalWrite(trig, LOW);delayMicroseconds(5);digitalWrite(trig, HIGH);delayMicroseconds(10);digitalWrite(trig, LOW);info = pulseIn(echo, HIGH); // en microsegundosSerial.write(lowByte(info));Serial.write(highByte(info));delay(500);}Now, I have no idea if usingCode:Serial.write()and splitting the int is a good way to go, but there are so many ways to do this and I'm very lost.I am even more lost, however, on my C# program. I created a Serial port and then run getPosicion after every Tick on a timer (which is set to Intervals of 500). When doing this, all I get is 0's.Code:SerialPort port = new SerialPort("COM3", 9600);int getPosicion(){int posicion = 0;port.Open();int bytes = port.BytesToRead;byte[] byte_buffer = new byte;posicion = port.Read(byte_buffer, 0, bytes);port.Close();return posicion;}I tried usingCode:Serial.println()andCode:port.ReadLine(), which somehow seems to work, but my program lagged heavily. Even though I'm not sure if performance should be better, I want to send the information as bytes to learn how to use it and to learn.How can my code be fixed? I guess I'm doing something inherently wrong, after all most of what I display here was a desperate copy-paste attempt. I'm lost. Thanks in advance!

author: vvanders
author_rank: Regular Contributor
timestamp: October 03, 2014, 11:32:10 pm
content: Read up about blocking IO, you're read call is probably blocking and may need to be moved to another thread or async api(if one exists for serial) to make it more responsive.

author: BRetonDP
author_rank: Contributor
timestamp: October 03, 2014, 11:50:19 pm
content: I will do so, makes sense. Thank you.

author: daveatol
author_rank: Regular Contributor
timestamp: October 04, 2014, 12:41:02 am
content: The problem in your C# code is that you're opening and closing the port every time you try to read data. The port should be opened once (at the start of your program), and closed once (at the end of your program).You also haveCode:posicion = port.Read(buff, 0, bytes);, but the port.Read function simply returns the number of bytes read. You need to convert the two bytes that you read from the serial port to an integer; you can use the BitConverter class for that

author: zapta
author_rank: Super Contributor
timestamp: October 04, 2014, 08:33:41 am
content: Quote from: daveatol on October 04, 2014, 12:41:02 amIn addition, there is not guarantee that it will read exactly two bytes and from the same sensor reading.It simpler to write the data out in text format. For each reading print the decimal value (as ASCII characters) followed by a line end. You can verify that it sends the correct data using the Arduino serial monitor (upper right corner). Then, in your C# program, open the port (once, and keep it open) and then read one text line at a time and convert it to a binary number.In Arduino it will look like:Code:...Serial.println(info);delay(500)...And in C# you need to figure out how to read a line of text at a time.

author: Jeroen3
author_rank: Super Contributor
timestamp: October 06, 2014, 08:43:02 am
content: Think of a little protocol that would make your life a bit easier. Fast example:PC sends 0x05 0x?? (ENQ + command)Device sends 0x06 (ACK) [your ascii or hex coded integer coordinates] 0x0A (LF), maybe include a checksum byte here.PC sends ACK or NAK.You can also do this with printable characters. Look here for the full list of control codeshttp://www.ascii-code.com/.Don't bother with sending binary data, .NET isn't fast enough to keep up with a full 9600 baud bus for more than a few seconds.

author: daveatol
author_rank: Regular Contributor
timestamp: October 06, 2014, 09:01:45 am
content: Quote from: Jeroen3 on October 06, 2014, 08:43:02 amHave you ever used .NET? Do you have any basis for that baseless claim?

author: mikerj
author_rank: Super Contributor
timestamp: October 06, 2014, 09:13:32 am
content: Quote from: Jeroen3 on October 06, 2014, 08:43:02 amI'm not a big fan of .NET but that simply isn't true.

author: Jeroen3
author_rank: Super Contributor
timestamp: October 06, 2014, 12:14:08 pm
content: All the Microsoft Java fanboys immediately have sore toes. Sorry.http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialportThe serial port implementation of.NETWindows isn't perfect, go and put your mcu to continuously send data. Notice how the application will lag and eventually fail. Even at 9600 baud. Not to blame .NET only, Qt will also lag. Only naked COM operation seems fast enough in processing bulk data. Proper interface handling on any platform isn't easy, especially on Windows.But I don't think the discussed application requires bulk data. Which makes the above irrelevant for this topic.

author: rs20
author_rank: Super Contributor
timestamp: October 06, 2014, 12:25:39 pm
content: Quote from: Jeroen3 on October 06, 2014, 12:14:08 pmNo, I have to agree with mikerj -- given the choice between a) believing that .NET being intrinsically incapable of handling 9600 baud, and b) believing that you just failed to write your software correctly, I'm going to choose B overwhelmingly. And I'm not a fan of .NET at all.If it's anything like Java, if you write an app that accumulates data in a String through simple concatenation (instead of using a proper string accumulation class like StringBuffer/EDIT:StringBuilder), and/or you fail to use background threadsproperlyand/or you naively display the accumulated string in a TextView, read bytes one system call at at time rather than reading a 1kB block at a time and working your way through it, etc, etc; then sure, it'll be slow. But that's the coder's fault, not the language's. PM me a link to your source code and I'll tell you what you did wrong.

author: daveatol
author_rank: Regular Contributor
timestamp: October 06, 2014, 01:04:55 pm
content: Quote from: Jeroen3 on October 06, 2014, 12:14:08 pmI've used the windows serial port for years, and not had these issues. I've had data going in and out of the serial port continuously (i.e. no idle time) for days while checking a microcontroller product for communications errors. The CPU usage was bugger all, and there were no errors. I've used the port at 2.5Mbps to receive serial data from a logic analyser without loss of data or 'lag', or even moderate CPU usage. I wouldn't expect there to be either. I've used multiple serial ports to log multiple channels. I've used it for debugging projects many times, without issue.The things that I have seen cause a slow down in response include naively putting too much text into text boxes, charts or tables (e.g. a serial port data logger), and naive concatenation of strings (just use the StringBuilder). (Jeroen3 already stated this).Quote from: Jeroen3 on October 06, 2014, 12:14:08 pmI'm glad you at least realised that.

author: BRetonDP
author_rank: Contributor
timestamp: October 08, 2014, 02:07:31 am
content: Thank you everyone for taking the time to respond.I now no longer open and close the port in the same method; I only open the comms port when my main form loads.Also, as I stated in the body, when I use the arduino Serial.println() command and C#'s SerialPort.ReadLine(), I do kind of get the expected behavior, but my form lags heavily.Attached to this post is a screenshot of what my little GUI, which runs on fullscreen, looks like. The yellow roadstripes move downwards and once the game begins colored Rectangles are drawn and they begin to fall down from the top as obstacles. As soon as I hit 'calibrate' and my port opens and the communication begins, the yellow stripes begin lagging horribly and I can no longer click the form's buttons until the program crashes a few moments later.I wanted to send bytes instead of the actual string with println() because I thought it would help my case and reduce the lag. The movement should also be pretty quick, pretty much realtime, but I'm now doubting my approach will suffice.

author: daveatol
author_rank: Regular Contributor
timestamp: October 08, 2014, 02:21:50 am
content: You will have a delay of up to 500ms using the method you have outlined, because your timer only runs every 500ms.

author: BRetonDP
author_rank: Contributor
timestamp: October 08, 2014, 02:35:25 am
content: I've messed around with that too, but I think that the shorter the delay (ideally, I would like it at... 100, maybe) the more my GUI lags.

author: daveatol
author_rank: Regular Contributor
timestamp: October 08, 2014, 02:38:37 am
content: Are you doing other things in the timer event also? That will obviously slow everything down. Without seeing any code, I can only make guesses of what you've done.

author: NiHaoMike
author_rank: Super Contributor
timestamp: October 08, 2014, 03:45:33 am
content: If you just have the Arduino send 4 hex characters plus a linefeed, you can greatly reduce the complexity of the encoding. Don't send decimal values since it takes modulus division to encode, which most 8 bit microcontrollers aren't going to be very good at. Hex characters just need some bitwise operations plus a lookup, which are very fast on most hardware.