[ SOLVED ] C# win10 serial terminal MISSING FIRST BYTE !

C# win10 serial terminal not receiving STRINGS from pico + arduino ide

so, since I have a project for a relay system that requires the development of a dedicated serial terminal to control the relay system by exchanging standard text messages /strings/, I decided to make my own with functionalities necessary to control the entire relay system through the USB serial port . I'm using the pico's USB serial port, with the commands in the software, which is a standard example for all arduino/pico boards:
MyStringON = "BOARD1NUMBER1RELAY1ON\n";
Serial.begin(9600);
Serial.println(MyStringON);
you know how this code works without giving the full version of the source code.

for developing the serial terminal I use visual studio enterprise 2022
the driver for the pico is Earl Philopower version 2.7.1

the pico is the LAN pico with the wiznet W5100s lan controller, but the lan network and strings there work without a problem. the whole system will be controlled via the Internet, there are 4 boards with 8 relays in total, each board having a radio module EBYTE E32 >> Serial2.xxx();

the central board also has the same radio module for connection with the other boards in a radius of 400 meters, which is in the picture, there is also a LAN module that will be a client connecting to the other LAN pico in another city trough internet, which will be a server in other town of owner of system.

I want through the serial port of the USB board shown in the picture to be able to receive/send the same strings that I receive/send over the lan network. a kind of echo for the commands that pass through the LAN link between the client and the server.

viber_image_2023-01-22_10-33-32-041|666x500

however, there was a communication problem that I assume has happened to other users. I make my serial terminal program in visual studio C# programming language, standard windows application project with ready made serial port module/component from visual studio.

and I've made a serial terminal with visual studio before to connect to peak micro processors, I didn't have a similar problem communicating to and from the peak processors with the string messages.

to the board, as you can see, there is a connected module of the company EBYTE E32 radio module 433MHZ, through which the string messages are received and transmitted normally, just as they were written in advance in the source code of the terminal or as you can send yourself a random string message from the command line at -down in the program.
terminal_not_show_string|644x500

the problem is that on the USB serial port of the LAN PICO BOARD connected with a cable to the computer, the messages are sent normally and in the serial monitor of the arduino ide 1.8.19, the strings are visible normally. also in the COOL TERM program when I connect to the USB serial port Serial.xxx(); strings are also received and transmitted normally. only my program developed in C# does not want to accept and pass them from the board and to the board.

if anyone has had this happen to me using C# with visual studio for serial port please share how they solved this problem.

I am also giving you some screenshots of the code I made in the serial terminal. one picture shows the code of the button to connect to the serial port, the other picture is of the code that is logging the event when receiving the strings and/or other data through the serial port.

some other pictures for code from visual studio to can see what a code i use for receiving and connect to serial port. but is standart for all terminals is NOT some strange code it is regular.

have a read thru how-to-get-the-best-out-of-this-forum
in particular avoid posting images of code - they waste space, are difficult ro read and imposible to copy a segment of code to test
you C# serialport code looks similar to mine so no idea why it does not work
e.g. my Form1.cs may give you some ideas

using System;
using System.Windows.Forms;
using System.IO.Ports;

namespace CsharpTerminal
{
    public partial class Form1 : Form
    {
        // delegate to transfer received data to TextBox
        public delegate void AddDataDelegate(String myString);
        public AddDataDelegate myDelegate;
        
        public Form1()
        {
            InitializeComponent();
            this.myDelegate = new AddDataDelegate(AddDataMethod);
            // Get a list of serial port names.
            string[] ports = SerialPort.GetPortNames();

            textBox1.AppendText("The following serial ports were found:");

            // Display each port name to the console.
            foreach (string port in ports)
            {
                textBox1.AppendText("  " + port);
                ToolStripMenuItem item = new ToolStripMenuItem(port);   // create a new menu item
                item.Click += comPortsStripMenuItem_Click;  // add event handler
                comPortsStripMenuItem.DropDownItems.Add(item);  // add to the menu of COM ports
            }


            // scan for COM ports and add to menu item if found
          /*  for (int port = 0; port <= 20; port++)
				{
				serialPort1.PortName = "COM" + port.ToString();
				try
					{
					serialPort1.Open();			// attempt to open serial port
					serialPort1.BaudRate=115200;			
					textBox1.AppendText("Found " + serialPort1.PortName + "\n");
					Console.WriteLine("serial port open OK {0}", serialPort1.PortName);
					serialPort1.Close() ;														//open OK, close it
					ToolStripMenuItem item = new ToolStripMenuItem(serialPort1.PortName);	// create a new menu item
                    item.Click += comPortsStripMenuItem_Click;	// add event handler
                    comPortsStripMenuItem.DropDownItems.Add(item);	// add to the menu of COM ports
 					}
				catch ( Exception ex)
					{ Console.WriteLine("serial port open fail {0} ", serialPort1.PortName, ex); }
			}

        Console.WriteLine("COM ports found {0} ", comPortsStripMenuItem.DropDownItems.Count);
		textBox1.AppendText(String.Format("{0} COM ports found - select from COM ports menu\r\n\r\n", comPortsStripMenuItem.DropDownItems.Count));
        */
        // if no COM ports were found display message
        if(comPortsStripMenuItem.DropDownItems.Count == 0 )
           textBox1.AppendText("\r\n  No COM ports found\r\n");
        else textBox1.AppendText("\r\n  Found " + comPortsStripMenuItem.DropDownItems.Count + " COM ports \n");
        }

        // key on textbox pressed, read key and transmit down serial line
        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {        
        if(echoOFFToolStripMenuItem.Text == "Echo ON") e.Handled = true; // if echo is off don't display on textbox
        if( serialPort1.IsOpen)
            serialPort1.Write(e.KeyChar.ToString());
        else
            textBox1.AppendText("No COM port open" + Environment.NewLine);
        }

     // data received from serial port - display on textbox
     private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            //textBox1.AppendText(serialPort1.ReadExisting());  // not thread safe
            string s = serialPort1.ReadExisting();
            textBox1.Invoke(this.myDelegate, new Object[] { s });
        }

     // display seral data on textbox
     public void AddDataMethod(String myString)
     {
         textBox1.AppendText(myString);
     }

     // COM port selected
     private void comPortsStripMenuItem_Click(object sender, EventArgs e)
     {
         try
         {
             Console.WriteLine("item selected {0} {1}", e.ToString(), sender.ToString());
             serialPort1.Close();
             serialPort1.PortName = sender.ToString();
             serialPort1.Open();
             textBox1.AppendText("Opened Port " + sender.ToString() + " baud rate " + serialPort1.BaudRate.ToString() + "\r\n");
             Text = "Port " + sender.ToString() + " baud rate " + serialPort1.BaudRate.ToString();
         }
         catch (Exception e1)
            //{ textBox1.AppendText("Failed to open Port " + sender.ToString() + "\r\n" + e1 + "\r\n"); }
            { textBox1.AppendText("Failed to open Port " + sender.ToString() + 
                    "\r\n   Is it already open in another program?? \r\n"); }
            // serialPort1.RtsEnable = true;
            // serialPort1.Handshake =  Handshake.RequestToSend;
        }

        // baud rate selected
        private void baudRateToolStripMenuItem_Click(object sender, EventArgs e)
     {
        Console.WriteLine("item selected {0} {1}", e.ToString(), sender.ToString());
        serialPort1.BaudRate = Convert.ToInt32(sender.ToString());
        textBox1.AppendText('\n' + " baud rate " + serialPort1.BaudRate.ToString() + '\n');
        Text = "Port " + serialPort1.PortName.ToString() + " baud rate " + serialPort1.BaudRate.ToString();

     }

     // echo selected
     private void echoONToolStripMenuItem_Click(object sender, EventArgs e)
     {
        // invert echo ON/OFF  display
        if(echoOFFToolStripMenuItem.Text == "Echo ON")
            echoOFFToolStripMenuItem.Text = "Echo OFF";
        else
            echoOFFToolStripMenuItem.Text = "Echo ON";
     }

     private void Form1_FormClosed(object sender, FormClosedEventArgs e)
     {
         serialPort1.Close();
     }

        // handshake mode selected
        private void handShakeNone(object sender, EventArgs e)
        {
            serialPort1.Handshake = Handshake.None;
        }

        private void handShakeRequestToSend(object sender, EventArgs e)
        {
            serialPort1.Handshake = Handshake.RequestToSend;
        }

        private void handShakeXonXoff(object sender, EventArgs e)
        {
            serialPort1.Handshake = Handshake.XOnXOff;
        }

        private void handShakeRequestXonXoff(object sender, EventArgs e)
        {
            serialPort1.Handshake = Handshake.RequestToSendXOnXOff;
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }
    }
}

the code running
image

I scan the COM ports , list them under Com Ports menu item and then selected COM11
you can see the output of an Arduini Mega

so, after 3 days of hard programming, reading and trying all sorts of software and serial port codes, I finally found two lines of code on the internet and after copying it into the serial terminal connection function, everything fell into place and the strings as and other communication and data went smoothly.

at first I couldn't even understand what this code meant for the correct operation of communication through the serial port to the terminal, but later it turned out that there was also a lot of sense in these two lines of code that started the whole process as it should.

first let me clarify what these two lines are and what they do in the code of the hardware serial port connection function of the computer which is wired to the hardware serial port of the raspberry pico or arduino or other processor systems.

these two lines of code allow the hardware serial port to receive and transmit information. these are DTR / Data Terminal Ready/
/link here >> https://en.wikipedia.org/wiki/Data_Terminal_Ready/
RTS /Request To Send/
/link is here >>> Difference between RTS/CTS and DTR/DSR flow control - GeeksforGeeks

IBM link >>> https://www.ibm.com/docs/it/aix/7.2?topic=communication-flow-control

so, serial ports are as communication interface as there are computers on this planet. the older and more experienced know that all sorts of machines and systems have been controlled through serial ports over the years of the computer industry. there is an awful lot of information about this on the Internet, you can read until retirement.

these two commands given in the connect function enable the hardware serial port to receive data to the program that connects to it to receive the data. the terminal program's connect button sets both hardware serial port flags to one so that when you press the connect button, the hardware serial port will tell the opposite serial port that it is ready to accept data from it.

exactly these two flags in C# visual studio are disabled by default and you have to manually put them as code on the corresponding serial port to say that you are ready to receive information and transmit as well.

because the raspberry pico is connected through the usb port which is a direct serial port to the RP2040 processor when these flags are not set there is no communication !!!!!

for that, in the code of the connect button function, you put these two lines BEFORE THE CONNECT FUNCTION !!! so that the flags can be set to unity and when the hardware serial port /computer USB cable/ is connected to the raspberry pico USB port, the flags will be raised and the receive and transmit will go as it should.

there is no change in the event function /interruption when receiving data/ through the serial port. these two lines are placed in the CONNECT button function !!!

here's some code for an example:

private void button2_Click(object sender, EventArgs e)
         { // CONNECT SERIAL PORT
             serialPort1.PortName = comboBox1.SelectedItem.ToString();
             try
             {
                 if (!(serialPort1.IsOpen))
                 {
                     serialPort1.RtsEnable = true; // IMPORTANT RECEIVE FROM USB ARDUINO/PICO !!!!
                     serialPort1.DtrEnable = true; // IMPORTANT RECEIVE FROM USB ARDUINO/PICO !!!!
                    // paste these two lines before serialPort1.Open(); // !!!! IMPORTANT
serialPort1.Open();
                     richTextBox1.AppendText(serialPort1.PortName.ToString() + " is CONNECTED" + "\n");
                 }
                 button2.Text = "CONNECTED";
                 button2.BackColor = Color.LightGreen;
                 button1.Enabled = false;
                 button2.Enabled = false; button3.Enabled = true;
                 button14.Enabled = true; button15.Enabled = true;
                 button16.Enabled = true;
                 comboBox2.Enabled = true;

                 // IMPORTANT BUTTON STATUS AUTO CLICK AFTER SELECT BOARD NUMBER
                // button15.PerformClick();

             }
             catch (Exception ex)
             {
                 //MessageBox.Show("Error opening/writing to serial port::" + ex.Message, "Error!");
                 richTextBox1.AppendText("\nserial port already open >> " + ex.Message + "\n\n");
                 button3.Enabled = false;
             }
         }

as I showed in the previous pictures, there was no communication on KOM3, unlike other com ports and other programs, now everything is OK !!! :slight_smile: after 3 days of struggle and sleepless nights, everything is now OK

in the C# documentation these two lines of code on the Microsoft Help site by default these two flags are disabled. why that is i have no idea.

here are links:

true to enable Data Terminal Ready (DTR); otherwise, false. The default is false.

true to enable Request to Transmit (RTS); otherwise, false. The default is false.

once again the code you need to put in order to be OK with serial communication terminal programs in C# programming for Windows 10:

serialPort1.RtsEnable = true; // <<<<< IMPORTANT RECEIVE FROM USB ARDUINO/PICO !!!!
serialPort1.DtrEnable = true; // <<<<<< IMPORTANT RECEIVE FROM USB ARDUINO/PICO !!!!
 // paste these two lines before serialPort1.Open(); // !!!! IMPORTANT
serialPort1.Open();
 richTextBox1.AppendText(serialPort1.PortName.ToString() + " is CONNECTED" + "\n");

and everything works perfectly. :slight_smile: thanks to the colleague for the code he gave me in his comment.

it turns out there's a lot to know about serial ports before you even get started. one can always learn something as long as one wants to :slight_smile:

if i have some new data about serial communication will let all you know. here is a picture from ok read/write terminal on COM3

1 Like

I have been searching for the past few hours as I suspected was wrong with the properties of the serial port. You nailed it. Too bad I did not find this earlier. Thank you for tracking this down and following up with your finding.

i am glad to be helpfully for all community of electronics and programming. now i make a LAN network local/global chat app for win10 to can apps on win10 and boards talk each other trough internet. have some results which is still in beginning, but need some time to make it right send/receive functions of commands and data between hardware. will make a progress, but need more work. :slight_smile :slight_smile:

wait for more from my website : www.karadev.net and tell to all friends and colleges about this to know how to make solutions of rs323 win10 terminal communications :slight_smile:

I had the same problem with an STM32F103 USB serial virtual com port and Visual Studio not receiving the data I was sending, which otherwise appeared fine in the Arduino IDE serial monitor.
Spent hours until I found this solution and put those 2 lines in. It worked!!!. Thanks!!! :grinning: :grinning: :grinning:

NEW UPDATE FOR C# TERMINAL SOFTWARE FOR RECEIVE CORRECT DATA AND COUNT RECEIVED BYTES IF THEY ARE REALLY RECEIVED IN SERIAL PORT !!!! GRAPHIC MATERIAL FOR EXPLAIN THE PROBLEM AND HOW TO SOLVE IT !!!!

serial port in c# receive byte but some time event is triggered but byte are not coming !!! that is problem and also how you can see in next line first by missing !!! that is problem when have a continuously received data like for example read data from eeprom or other memory in hardware pic micro and / other hardware platforms.

i spend 5 days to disassembly my program in c# and firmware code for pic micro to found out where is problem. at last i try to use a other serial program >> dock light and there all transferred data was super OK. that say to me that my c# program have a serius bug in receive. i try to avoid with some c# code wonders, but no success or have some other problems.
at last i found way with standart class function in serial port class directly from c# vs studio. works fine and have no struggles with so much writing wonders in c#. just some code lines and all is good :slight_smile:

as you can see in yellow paint is wrong byte receive detected. lines are not so much, but in this case and just one is a problem. example writing data to big eeprom memory like spi mcp25lc1024 wich is 128kb size will be read and write wrong message when and what is or not read or write correctly.

next slide is standart event received function in c# serial port class

ok, here is my function edited to avoid this problem

as you can see, just a simple line of code to make it flow correctly and next is result :slight_smile:

option is to show line where are not received bytes BUT is trigered event in serial port and that is problem in serial port communication in C#. but with this little code line in event never will have not problem to receive correct count bytes and correct bytes values :slight_smile:

important fix of new function to work well from first time. add one code line like picture bellow for triggered if construction after receive and count bytes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.