I have a relatively short C# program that feeds data over an RS232 port using the following format:
'STX' Header 'Checksum' 'ETX'
'STX' data1 'Checksum' 'ETX'
'STX' ... 'Checksum' 'ETX'
'STX' dataN 'Checksum' 'ETB'
The receiving end is supposed to reply with either an ACK or NAK byte upon receiving the ETX/ETB.
This works fine running on computers with Windows 7 64 bit.
However there was a problem getting the program to start on a Win XP 32 machine, because I had built the program to target .NET version 4.5 (which apparently isn't supported by that version of Win XP).
I changed it to target .NET version 4 instead and now the program starts just fine. But the receiving end doesn't respond with ACK or NAKs anymore, only the first time (upon sending the datafile header).
I printed out the byte buffer on the console and at the place where the ETX byte is supposed to be there is an UP DOWN ARROW WITH BASE symbol (↨) which tells me it somehow didn't send an ETX at all.
What's weird about this is that it works fine on windows 7 machines, and the first transmission (header) returns an ACK just like it's supposed to, but when the first data packet is sent no more replies... no ACK or NAK.
In case anyone run into similar problems; my problem was that I used a USB to serial converter. It caused the timings to become all messed up. What I did to solve it was to subscribe to the SerialPort's DataReceived Event, and then grab the data inside the event handler with serialport.ReadExisting() (which also clears the receive buffer). So the thread would roughly do:
Send data -> wait for DataReceive to fire -> handle data -> repeat.
Just be sure to put a timeout in the waiting loop.
Related
I developed a Windows Form application, using C#, that receives data through the serial port sent by a microcontroller. I'm receiving the data using the serialPort_DataReceived event in which I use ReadLine() to read the serial port. Then I use the Invoke method to call a function that will print the received string into a textBox. The problem is that the app can't keep up with the rate at which it receives the strings, for example, the string that I send from the microcontroller has the time at which it was sent and even though it has already passed 2 or 3 seconds the app is still printing the strings that were sent at the 0.2 second. And when I send a string to the microcontroller to stop sending data, the app onlys stops ptinting the data after a while, this is, it keeps printing the values stored in the receiving buffer.
I believe that is happens given the large amount of data that the app receives and the rate (I'm using a baud rate of 115200), one string for every millisecond. This is, I think that the app is always being interrupted by the DataReceived event and it doesn't has time to print the data and starts falling behind.
One way I though of overcome this problem was with multi-threading but I can't figure it out how. I already tried a few examples using the BackgroundWorker but I didn't manage to make it work at all. I'm still a noob in terms of programming Windows Form apps and even C#.
Can anyone confirm the cause of the problem? And how do I make a thread to print the received data?
You can utilize SerialPort.ReceivedBytesThreshold property and SerialPort.ReadExisting() method (or a StringBuilder instance) to update UI with a batch of strings at once rather than a single string.
For more information check:
Serial port DataReceived firing too much discussions on StackOverflow
Top 5 SerialPort Tips article by Kim Hamilton
Serial Port ReadLine vs ReadExisting or how to read the data from serial port properly discussion on StackOverflow
Quickest way to Update Multiline Textbox with Large Amount of Text discussion on StackOverflow
I noticed the Arduino IDE automatically resets on startup/exit by the built in serial application due to
one of the hardware flow control lines (DTR) of the FT232RL is connected to the reset line of the ATmega1280 via a 100 nanofarad capacitor. When this line is asserted (taken low), the reset line drops long enough to reset the chip.
I noticed that behaviour does not happen with my serial C# application. I would like the reset feature to work with my C# application. What am I not doing to get my Arduino Mega to reset by my C# application?
Working Code for Arduino and C#:
I got it working in about 5 minutes by hooking up a wire from PWM Port12 to the RESET Port. On the Arduino, I checked for the text RESET on the incoming SerialEvent3. When RESET is found do:
pinMode(7, OUTPUT);
digitalWrite(7, LOW);
As for as the C# it was as simple as:
if (serialPort1.IsOpen)
{
serialPort1.Write("RESET");
}
Reset seems to work as expected.
DTR works fine for me from the .NET SerialPort class.
Just set the property:
port.DtrEnable = true;
I have noticed different defaults if you use the SerialPort in the WinForms designer, but DtrEnable is in fact true (by default) when using it from a console app.
I've got a homegrown app (Master) that has a bunch of hotkeys defined. I need to automate the app with another external app (Control). I cannot rebuild the Master app, it runs, is already installed and can't be messed with.
Using hotkeys on Master works like a charm if I use a keyboard.
So, I figure I an use SendKeys.SendWait or SendKeys.Send to send the commands. While my code works fine with other apps (such as Notepad) it is not working with my custom app, Master. This could be for a number of reasons - Master is older, has .NET, C++ mixed... some low level video controls... who knows what's under the covers.
I need to get something higher level. I need to be able to send the keystrokes as if they are coming from the keyboard itself. I don't want the computer to be able to differentiate between the physical keyboard sending the keys and my app sending the keys.
What can I use and how will it be different?
The problem was not SendKeys.
I tried SendKeys.Send, SendKeys.SendWait, SendInput and keybd_event.
I later realized that the time between activating the application and the time sending the keystrokes was too short. I was waiting 200ms but simply by increasing this to 500ms I solved my problem.
The application took a long time to draw because of the embedded video players. Giving it another 300ms allowed it to be ready for the keystrokes I was sending it.
I'm using the Input Simulator library to simulate input to another application using C#, this uses the SendInput API calls. Does anyone know if there is a way I can monitor the windows message queue for the external application to see if those messages have been processed?
For example, let's say I want to send the keystrokes for the word "Hello" to notepad, but I don't want my application to continue until notepad has received and processed the input and the word "Hello" has appeared in the notepad window. We'll know this has happened once the keypress messages are no longer in the message queue for notepad, but I can't work out how to find that out.
I was using the .NET SendKeys class and using SendWait, but this seems unstable and causes occasional freezes in the external application, so after weeks of trying to fix that I'm looking for a new method.
Many thanks
You can't. Calling SendInput ultimately results in posted messages which are delivered asynchronously.
Why fake input to Notepad when you can send the text direct to the edit window? Not only would it be way simpler it would be robust and synchronous.
I'm using the VNCsharp .NET control to attach to remote XenServer sessions using their VNC protocol. This control has been working great except for one when the VM's resolution is increased. For example from 800x600 to 1024x768. The console viewer in XenCenter handles this situation fine!
In that case, it appears as if the XenServer stops sending screen updates. However, I hooked up Wireshare and there are clearly still packets being sent to my client. I've checked to make sure that VNCsharp is handling the boundary conditions (stream changes) and that looks OK. If the resolution request times out then the screen will work again when Windows goes back to the original resolution.
If I drop the connection and reconnect then the client happily renders the new resolution.
I suspect that there is some reset signal that I'm missing. Is there something in the VNC RPC about this? If so, I could not find it.
Suggestions?
I resolved this problem, but it feels like a hack. I had to add a stream timeout (5 seconds) to the ReadByte call. The host drops the stream and the client does not detect it.
In order to keep the timeout from firing due to inactivity, I had to add a keepalive thread that sends a mouse move if the client is idle. I think there is a more elegant way to do the keep alive, but it's working for now.