So something odd just happened...
I have a project that has been working just fine for awhile now. An arduino Mega running a dual axis solar tracker. I built a GUI on and for my old Win 7 machine. It's been running great... until I upgraded my PC to a fancy new gaming rig... The GUI now seems to be missing comms from the arduino.
I thought the problem might be that my new PC was too fast, so I upped the Baud rate from 57600 to 115000. But that made it worse. Then I slowed them both down to 9600 and it works just fine again. Kinda counter-intuitive.
Serial.println() on the Mega worked fine with serialport1_DataReceived() on the PC end at 57600 baud on my old Win 7 PC but not my new Win11 PC. I didn't make any code changes when I migrated the VS2022 data to the new machine, and as far as I know the serialPort1 Properties are the same too...
I was using VS2017 on my old PC and VS2022 on the new.
Here's the C# code for the GUI:
> private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
> {
> // new data has arrived in in buffer
> vbl_newData = true; // this volatile bool is checked by the Form1_FormClosing() function
> // and prevents the system from hanging when closing
> //
> try
> {
> if (vbl_disconnect)
> {
> // user has commanded a close
> serialPort1.DiscardInBuffer();
> vbl_newData = false;
> this.BeginInvoke(new MethodInvoker(this.Close));
> //return;
> }
> else
> {
> // read the data
> inString = serialPort1.ReadLine();
> // this volatile bool is used in btn_Connect_Click() handler
> // to flag that a reply has arrived from remote device
> vbl_connected = true;
> // Serial Port Handler operates on its own thread, therefor Invoke is required
> // for regular event handlers
> Invoke(new CrossThreadDelegate(ref ProcessData));
>
> // new data has been processed, reset flag
> vbl_newData = false;
> }
> }
> catch (TimeoutException)
> {
> if (!vbl_disconnect) Invoke(new CrossThreadDelegate(ref timeOut));
> vbl_newData = false;
> }
> catch (InvalidOperationException ex)
> {
> MessageBox.Show
> (
> text: ex.ToString(),
> caption: "serialPort1_DataReceived() handler",
> buttons: MessageBoxButtons.OK,
> icon: MessageBoxIcon.Exclamation
> );
> //vbl_newData = false;
> }
> catch (IOException ex)
> {
> MessageBox.Show
> (
> text: ex.ToString(),
> caption: "serialPort1_DataReceived() handler",
> buttons: MessageBoxButtons.OK,
> icon: MessageBoxIcon.Exclamation
> );
> //vbl_newData = false;
> }
> }
Anyone care to venture some thoughts as to why I needed to slow the comms down with a new PC?...
Stephen Kurth
where do I find that data? is it at C:\Program Files (x86)\Arduino\drivers\x86?
I did install a newer version of the IDE, 1.8.18 vs 1.8.6 (I think...) on the old PC...
I'll have to reassemble the old PC to check what I was running on it.
So I think I may have solved my own issue here...
I rewrote the _DataReceived() handler without using the .ReadLine() method. I don't really understand why .ReadLine() worked at 57600 baud on Windows 7 but not Windows 11, nor why it does work at 9600 baud on Windows 11... So, in case there is anybody out there struggling with a Windows11 dotNET GUI app for their arduino project, this code works at 57600 baud!
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// new data has arrived in in buffer
vbl_newData = true; // this volatile bool is checked by the Form1_FormClosing() function
// and prevents the system from hanging when closing
try
{
char c;
if (vbl_disconnect)
{
// user has commanded a close
serialPort1.DiscardInBuffer();
vbl_newData = false;
this.BeginInvoke(new MethodInvoker(this.Close));
//return;
}
else
{
//inString = serialPort1.ReadLine();
while (serialPort1.BytesToRead > 0)
{
c = (char)serialPort1.ReadChar();
if (c == '\n')
{
// copy buffer to main variable
inString = InBuffer;
// reset the buffer
InBuffer = string.Empty;
/* process the new, complete code */
// this volatile bool is used in btn_Connect_Click() handler
// to flag that a 'Ping' reply has arrived from remote device during the initial connection
vbl_connected = true;
// Serial Port Handler operates on its own thread, therefor Invoke is required
// for regular event handlers
Invoke(new CrossThreadDelegate(ref ProcessData));
// new code has been processed, reset flag
vbl_newData = false;
/* skip the InBuffer += c; line,
the '\n' byte has been read from the port buffer but doesn't need to be added to the local string buffer.*/
continue;
}
InBuffer += c;
}
}
}
catch (TimeoutException)
{
if (!vbl_disconnect) Invoke(new CrossThreadDelegate(ref timeOut));
vbl_newData = false;
}
catch (InvalidOperationException ex)
{
MessageBox.Show
(
text: ex.ToString(),
caption: "serialPort1_DataReceived() handler",
buttons: MessageBoxButtons.OK,
icon: MessageBoxIcon.Exclamation
);
//vbl_newData = false;
}
catch (IOException ex)
{
MessageBox.Show
(
text: ex.ToString(),
caption: "serialPort1_DataReceived() handler",
buttons: MessageBoxButtons.OK,
icon: MessageBoxIcon.Exclamation
);
//vbl_newData = false;
}
}
Also, ReadTimeOut property set to -1
Note: the volatile booleans are there to act as flags to make sure the GUI connects and disconnects from the arduino properly so the GUI doesn't hang on close();
Here's that code:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// User wants to shut down app, set bool true
vbl_disconnect = true;
// save settings
Properties.Settings.Default.Latitude = LAT;
Properties.Settings.Default.Longitude = LONG;
Properties.Settings.Default.UTC = UTC;
Properties.Settings.Default.Theme = lightToolStripMenuItem.Checked;
Properties.Settings.Default.toolTips = toolTip1.Active;
//
Properties.Settings.Default.Save();
try
{
// tell Arduino to stop sending data
if (serialPort1.IsOpen)
{
//serialPort1.WriteLine($"Lat, {LAT}");
//serialPort1.WriteLine($"Long, {LONG}");
//serialPort1.WriteLine($"UTC, {UTC}");
//
serialPort1.WriteLine("disconnect");
}
// close any other open forms
if (diagnosticsIsOpen) Application.OpenForms["Diagnostics"].Close();
if (userSettingsIsOpen) Application.OpenForms["userSettings"].Close();
if (ChartsIsOpen) Application.OpenForms["Charts"].Close();
if (AboutIsOpen) Application.OpenForms["About"].Close();
// check if _DataReceived() handler is finished
if (vbl_newData) e.Cancel = true;
}
catch (Exception ex)
{
MessageBox.Show
(
text: ex.ToString(),
caption: "Form1_FormClosing() handler",
buttons: MessageBoxButtons.OK,
icon: MessageBoxIcon.Exclamation
);
}
}
Hmmm...
Both old and new PC are using dotNet 4.8 I believe. I have an inkling it might have something to do with the ReadLine() method being a blocking function... but I really don't have a fine enough understanding of how the data stream works, how and/or when the OS decides to fire the DataReciecved() handler and and what happens while it's doing that ... and on and on. That's why you need to go to school to learn that stuff...
But the code works again at 57600. Just for laughs, I'll try it at 115200!