I am using microcontroller to send data to computer. This is the code that I am using to get data:
serialPort1.PortName = "COM13";
serialPort1.BaudRate = 57600;
serialPort1.DataBits = 8;
serialPort1.Parity = Parity.Odd;
serialPort1.StopBits = StopBits.One;
serialPort1.Open();
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
output += sp.ReadByte() + " ";
}
But the problem is that I am getting wrong data, even sometimes I am missing one bytes. I am using "terminal" and it seems that I am sending data correctly with microcontroller but with c# I am getting wrong data.
Also is there any way to get the parameter of serial port automatically so that I dont need to set the parameters my self.
Related
Currently I am working on a project in which I have to send commands to a device by calling its IP address. I have already created a code that send the command by using the IP address on LAN. Here is code snippets.
private void cmdConnectRobot_Click(object sender, EventArgs e)
{
try
{
// Create object and connect with VRC
caoCtrl = caoWs.AddController("Robot", "CaoProv.DENSO.RC8", "", "Server=192.168.0.100");
caoRobot = caoCtrl.AddRobot("VS", "");
// Valiable of status of Machine lock SW
//caoVal = caoCtrl.AddVariable("#LOCK","");
caoValP = caoCtrl.AddVariable("P1", "");
you can see the robot can be accessed using LAN by putting server IP address. I want to call this device by using this IP address but over the internet.
Thank you!
I have 1 gsm 32 port with name is xr21v1414 USB UART
I have tested another AT COMMAND which works fine like
AT
USSD
but if i use COMMAND :
serialPort.WriteLine("AT" + System.Environment.NewLine);
Thread.Sleep(200);
serialPort.WriteLine("AT+CMGF=1" + System.Environment.NewLine);
Thread.Sleep(200);
serialPort.WriteLine("AT+CMGL=\"ALL\"" + System.Environment.NewLine);
Thread.Sleep(200);
responded with
serialPort.ReadExisting();
is empty (OK only)
AT
OK
AT+CMGF=1
OK
AT+CMGL="ALL"
OK
But if I switch to another gsm, Command work fine. I have list SMS.
This is my setting :
SerialPort serialPort = new SerialPort();
serialPort.PortName = m.ToString();
serialPort.BaudRate = 115200;
serialPort.DataBits = 8;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.StopBits = StopBits.One;
serialPort.Parity = Parity.None;
serialPort.ReadTimeout = 20000;
serialPort.WriteTimeout = 20000;
serialPort.WriteBufferSize = 1024;
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
How could i resolve the problem ,please ?
I am quite sure that the OK response you get is because you have aborted the current command line by using Thread.Sleep(200) instead of reading and parsing the response you get back from the modem, waiting for the Final Result Code before sending the next command.
The first linked answer above is to a question whose code which is slightly worse because it does not even have a sleep, but even having one is utterly wrong. Just as you would not write a HTTP client that ignores the responses a HTTP server send it, you should not write a AT command program that ignores the responses the modems sends it.
TL;DR You MUST change your code to read and parse every single response line that the modem sends you, waiting for the Final Result Code before sending the next command. See the linked answers for more details.
In Tera Term I'm connecting to a serial device over USB (on startup select radiobutton "serial" and correct port). Once connected I only change the default speed to 115200 (in setup=> serial port).
After this, tera term asks me to fill in commands like so:
Command>
I fill in the device specific command. In this case it's "PC" and I receive an expected response ie. "ABC"
Now I'm trying to do the same in C#. Unfortunately the response I get is always the same as the command I actually type in.
So If I type in "PC", the response is "PC", but I expect "ABC". Other commands have the same problem. Command "?" responds with "?" while I expect "CBA".
If I type in a faulty command => then I get the message "Unknown command"
So I suspect the device actually gets the right command.
I'm using the following code:
SerialPort COMport = new SerialPort(Port_Name, Baud_Rate); //Create a new SerialPort Object (defaullt setting -> 8N1)
COMport.DataReceived += new SerialDataReceivedEventHandler(sPort_dataReceived);
COMport.ErrorReceived += new SerialErrorReceivedEventHandler(sPort_ErrorReceived);
COMport.BaudRate = 115200;
COMport.Parity = Parity.None;
COMport.DataBits = 8;
COMport.StopBits = StopBits.One;
COMport.RtsEnable = true;
COMport.Handshake = Handshake.None;
COMport.Open();
COMport.WriteLine(Data);
Thread.Sleep(1000); // Just discovered after a lot of testing that this is necessary to read the response before the Comport closes
COMport.Close();
Then I do the following:
private void sPort_dataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
MessageBox.Show(indata);
}
I've tried different things, but I can't get this to work. Hopefully it's because I'm new to this. I've never worked with Tera term before.
Thanks in advance,
Some (but definately not all) things I've tried:
tried this guys advise and code: https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport
downloaded and tried from here: https://www.xanthium.in/building-opensource-gui-based-serial-port-communication-program-dot-net-framework-and-arduino#simple-serial-source-code (Although my device is not arduino)
Tried to add "\r\n" : C# Errors with SerialPort WriteLine commands
EDIT EDIT EDIT EDIT
So I found out more. If I use the following code (Write instead of WriteLine), I do get good results but not every time:
Sending the full command now: "Command>PC"
string Command1 = txtCommand.Text;
Command1 = Command1 + "\r\n";
string CommandSent;
int Length, j = 0;
Length = Command1.Length;
for (int i = 0; i < Length; i++)
{
CommandSent = Command1.Substring(j, 1);
ComPort.Write(CommandSent);
j++;
}
The first time, now I get good results. The second time I get "Unknow Command", the 3rd time => good results, 4th = "Unknown Command"... etc...
It always seems to work 1 time well, then 1 time not.
I can only get it to work consistently if I switch the command formatting:
First time command: "Command>PC"
Second time command: "PC"
Third time command : "Command>PC"
Fourth time command: "PC"
etc...
I've already tried to clear the buffer before sending but no effect.
ComPort.DiscardInBuffer();
ComPort.DiscardOutBuffer();
The Newline seemed to be a problem.
I needed to use Comport.Write (instead of WriteLine). Then Also I needed to append a carriage return "\r" but NO newline '\n' as I previously thought. (the incoming data showed a newline after the "Command>" making it impossible to send another meaningfull command => the cause of this was '\n' => removing it solved the problem)
This is my current code that seems to work (I no longer need to append "Command>", just sending the command as is):
if (thecommand == "")
{
ComPort.Write("\r"); //start from a clean slate
return;
}
ComPort.DiscardInBuffer();
ComPort.DiscardOutBuffer();
string Command1 = thecommand + "\r";
ComPort.Write(Command1);
I have a private function that creates a new serial port and opens it. From time to time, I get the "Safe handle has been closed" exception, that terminates the application. Now, I've been reading a few optional fixes and would like to know from your experience, what may be the real problem in my code.
1) Need to define the _serialPort variable outside of the scope of this private function.
2) The serial port's readTimeout property should not be infinite.
3) The using statement above disposes my portName variable.
SerialPort _serialPort;
string[] devices =
ConfigurationManager.AppSettings["GasAnalyzerDeviceName"].Split(',');
string portName;
using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity"))
{
portName = (from p in searcher.Get().Cast<ManagementBaseObject>()
let c = "" + p["Caption"]
where c != null
where devices.Any(d => c.Contains(d.Trim()))
from pn in SerialPort.GetPortNames()
where c.Contains(pn)
select pn).FirstOrDefault();
}
if (portName == null)
portName = ConfigurationManager.AppSettings["GasAnalyzerPortName"];
if (portName == null)
throw new Exception("Gas port not found");
// Create a new SerialPort object with default settings.
_serialPort = new SerialPort();
// Set Serial port properties
_serialPort.PortName = portName;
_serialPort.BaudRate = 115200;
_serialPort.DataBits = 8;
_serialPort.Parity = Parity.None;
_serialPort.StopBits = StopBits.One;
_serialPort.Handshake = Handshake.None;
_serialPort.ReadTimeout = Timeout.Infinite;//1200;
_serialPort.WriteTimeout = 1200;
Thanks!
I think you can discard options 2) and 3).
Number one is a possible candidate, but there is not enough code to be sure: If there are no other references to your SerialPort it becomes a candidate for garbage collection. Once it is garbage collected, any attempt to access it will result in an exception, tough I would expect a NullReferenceException.
There can be another cause: if your serial port is emulated over e.g. a USB device, and that device gets removed while your application is running, the underlying connection will be disposed.
When you try to use the SerialPort in your application after that has happened, you will get the 'safe handle has been closed' exception.
I'm trying to read and write to a usb modem that is using the com port 3 with this code.
SerialPort sp = new SerialPort();
sp.PortName = "COM3";
//sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.Open();
sp.Write("AT<CR>");
byte[] bytes = new byte[sp.BytesToRead];
sp.Read(bytes, 0, sp.BytesToRead);
textBox1.Text = Encoding.UTF8.GetString(bytes);
But I get this error :
Access to the port 'COM3' is denied.
Someone have an idea ...
Thanks
You can only open the port once. Maybe you're accidentally opening it more than once within your code or another program is using it?