I am new to C# and programming in general.
I am trying to communicate with a ohmmeter which is conneted via usb to my computer.
I am able to configurate the device and even recieve data.
But i can not acces this data. I can just print it on to the console.
(Was inspired by the code on the microsoft site)
Here is the constructer of my "communication"-class where i configurate the port:
public SCPI_Commands()
{
_SerialPort.PortName = SetPortName(_SerialPort.PortName);
_SerialPort.BaudRate = 115200;
_SerialPort.Parity = Parity.None;
_SerialPort.DataBits = 8;
_SerialPort.StopBits = StopBits.One;
_SerialPort.Handshake = Handshake.None;
_SerialPort.ReadTimeout = 500;
_SerialPort.WriteTimeout = 500;
_SerialPort.Open();
_SerialPort.DataReceived += _serialPort_DataReceived;
}
Here is my function which sends a query to the device (The constant Measurment_Value represents a scpi command which is understood by my ohmmeter) :
public void get_measurement()
{
_SerialPort.WriteLine(Measurment_Value);
}
And here is the private function which checks if the device is sending data and printing it on the console (not sure how this function works) :
private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Console.WriteLine(_SerialPort.ReadLine());
}
Unfortunately i am not able to return the data as a string. My goal is to do some calculations with the received data.
Does someone has any ideas ?
Greetings from Germany.
Luke
You can read from buffer to temp byte array and then get it as string, see the below example. Put this in _serialPort_DataReceived
// this the read buffer
byte[] buff = new byte[9600];
int readByteCount = _serialPort.BaseStream.Read(buff, 0, _serialPort.BytesToRead);
// you can specify other encodings, or use default
string response = System.Text.Encoding.UTF8.GetString(buff);
Side Note
If you want to keep your sanity while working with SerialPort, always send and receive as byte array. Then, get the equivalent string using Encoding.
Related
I created a wpf application to control and monitor a sensor invented at my university. I connect to the device with 2 comports of which one is exclusively for sending data from the device. The device encodes each dataset to 5 bytes and starts sending them as soon as I give it the order via the other comport. Internally the sensor has a buffer of ~40 kilobytes.
Problem:
It works very will until a sampling rate above 25kHz (25000 times 5 bytes each second) is chosen. Then data seems to be lost and the device sends an error, that the internal buffer ran full (which explains the lost data)
I tried several approaches without success yet, the latest was trying to apply this solution: https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport
I fail to understand what determines how often I receive an event that grabs the data from the serialport. The problem doesn't change whether my program is fast or slow .. always ~25kHz = ~200kBytes/s
Code:
private SerialPort _comPortData;
_comPortData.DataReceived += new SerialDataReceivedEventHandler(PortDataReceived);
The Connect() function, stripped-down:
void connect()
{
comPort.BaudRate = 115200;
comPort.DataBits = 8;
comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "One");
comPort.Parity = (Parity)Enum.Parse(typeof(Parity), "None");
comPort.PortName = port;
comPort.Open();
Console.WriteLine(comPort.PortName + " opened | Baud Rate: " + comPort.BaudRate);
}
The (edited) PortDataReceived function:
private void PortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (!_comPortData.IsOpen) return;
// Obtain the number of bytes waiting in the port's buffer
int numberOfBytes = _comPortData.BytesToRead;
// Create a byte array buffer to hold the incoming data
byte[] buffer = new byte[numberOfBytes];
// Read the data from the port asynchronously and store it in the buffer
await _comPortData.BaseStream.ReadAsync(buffer, 0, numberOfBytes);
}
The problem is, that I can trigger scanner using Serial Port software "Hercules" sending command <SYN>T<CR><LF>, in datasheet is said to use command [SYN]T[CR] to trigger scanner, but I cant trigger it (both commands) using my serial port comunication bellow.
I get input when use scanner manually but can't trigger it... What is a problem?
(The port is virtual)
private static SerialPort port;
private static bool _continue = false;
public static void Main(string[] args)
{
port = new SerialPort();
port.PortName = "COM8";
port.BaudRate = 115200;
port.Parity = Parity.None;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Handshake = Handshake.None;
port.RtsEnable = true;
port.DtrEnable = true;
port.ReadTimeout = 500;
port.WriteTimeout = 500;
port.Open();
_continue = true;
Thread thr = new Thread(SerialPortProgram);
thr.Start();
}
private static void SerialPortProgram()
{
Console.WriteLine("Writing to port: <SYN>T<CR><LF>");
string command = "<SYN>T<CR><LF>";
port.WriteLine(command);
while (_continue)
{
try
{
string input = port.ReadLine();
Console.WriteLine("Input is - " + input);
}
catch (TimeoutException) { }
}
}
Python barcode scanner serial trigger is an article that I answered similar Python question.
The contents are shown below.
This happens because you coded the abstract expression written in the document as raw output data.
The document represents 3 bytes of data transmission.
'SYN' and 'CR' are the following hexadecimal numbers.
'SYN' = \x16
'CR' = \x0d or escape sequence \r
'T' is an ordinary ASCII character.
Whitespace and < > [ ] { } are used to delimit the data in the document, not the data to send.
And, even you need to command prefix it.
Also use Write instead of WriteLine as written by #Turbofant.
You should write like this. Please try it.
string command = "\x16M\x0d\x16T\x0d";
port.Write(command);
I guess the problem is, that you are sending the wrong command string.
The <Syn>, <CR> and <LF> stands for the special, non printable ascii characters synchronous idle, Carriage return and line feed.
You need to encode them correctly in the string
Try sending:
string command = "\x16t\r\n";
port.Write(command);
\x16is <Syn> (Because Syn is ascii character 0x16, or 22 in decimal )
\r is <CR>
\n is <LN>
And use port.Write instead of port.WriteLine, because WriteLine automatically adds the \r\n at the end of the string.
I have tried the following:
(This "whatever" is a 4 digit pin asked to enter after sending a AT+STGR=3,1 to the port)
1. this.port.WriteLine("whatever\0x1A");
2. this.port.WriteLine("whatever"+ char.ConvertFromUtf32(26));
3. this.port.WriteLine("whatever\u0001");
4. this.port.WriteLine("whatever"+(char)26);
5. this.port.WriteLine("whatever");
SendKeys.Send("^(z)");
6. this.port.WriteLine("whatever");
this.port.Write(new byte[] { 0x1A }, 0, 1);
7. this.port.WriteLine("whatever");
this.port.Write(new byte[] { 0x26}, 0, 1);
None of them works, but when using putty and entering the code followed by ctrl+z key everything works perfectly, so can anyone tell me exactly how does putty sends this ctrl+z to the serial port? Or if possible give a solution to this problem in c#?
The reply back from the modem every time I try the c# codes given above is:
+CME ERROR: 100
Serial Port Initialization:
port.PortName = "COM3";
port.BaudRate = 115200;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.ReadTimeout = 300;
port.WriteTimeout = 300;
port.Encoding = Encoding.GetEncoding("iso-8859-1");
port.DataReceived += new SerialDataReceivedEventHandler(this.port_DataReceived);
port.Open();
port.DtrEnable = true;
port.RtsEnable = true;
Find a ASCII map like this for the ctrl codes. Looks like for ctrl Z you need an ASCII 0x26. I would define it something like
char CtrlZ = (char)26;
char CR = (char)13;
serialport1.WriteLine(string.Format("whatever{0}{1}",CtrlZ, CR));
Try "whatever\u001A" or "whatever" Sleep "\u001A".
Also check the whole sequence of commands/responses you're sending/receiving through the connection.
This is an example, to be adapted to your specific case.
//TODO initialize the serialConnection and open it
//TODO specific commands...
serialConnection.WriteLine("AT+CPIN=\"1234\""); // replace according to your real situation
var response = serialConnection.ReadExisting();
Console.WriteLine("pin resp: " + response);
Thread.Sleep(200);
//TODO other specific commands?
serialConnection.Write("whatever");
//Thread.Sleep(200); uncomment this if it helps
serialConnection.Write(new byte[]{26}, 0, 1); // or Write("\u001A")
response = serialConnection.ReadExisting();
Console.WriteLine("ctrl-z resp: {0}", response);
//closing stuff, etc...
I create small test app to test connection between app and some device which measure temperature. When I write some command to device it's ok, but when device return me response, a string, for that I use ReadExisting() method. But app reads just first character of the string. If I send command again, it's same situation. I try to test connection with program called Terminal.exe, it's happens the same. But when I change BaudRate at some value and return BaudRate on 9600 ( it's ok rate ), then it's worked fine. Also I try to change BaudRate in my app, but it give me the same, just first character of string. Also I have an app written in LabView which works fine.
Also I tested my app with another PC with Terminal.exe , and it's worked fine.
private void SetUpPort()
{
port = new SerialPort();
port.PortName = port_name;
port.BaudRate = 9600;
port.Parity = Parity.None;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Handshake = Handshake.None;
port.ReadTimeout = 1000;
p.DataReceived += new SerialDataReceivedEventHandler(PortDataReceived);
}
private void PortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
recived_data += port.ReadExisting();
}
I would be very thankful for any help.
That is not how to use the SerialPort component. You need to attach the DataReceived event handler, which is called every time data comes in on the serial port. An example is found on the page I linked.
You need to append data until you know you're done! You can't just call ReadExisting and assume you get all the information. Do something like this:
private string inBuffer = String.Empty;
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
inBuffer += indata;
if (<inBuffer fulfills some criteria that tells you it's a complete message>)
{
ProcessInBuffer(inBuffer);
inBuffer = String.Empty;
}
}
It is your task to determine the criteria to fulfill. This may be that the received data as a certain length (if the records are fixed length), or maybe they end with newline characters or something else.
you will use datareceived event to store all the data in a array or string and after you can use every data of that string indata += sp.ReadExisting();
hello i have problem with receiving data from serial port in c# in am inserting a new line operator at the end of data buffer. then i send this data buffer on serial port, after this my c# GUI receiver will take this data via Readline() function but it always give me raw data not the actual one how to resolve this problem.
//configuring the serial port this code in c# with problem
serialPort.PortName = "COM1";
serialPort.BaudRate = 9600;
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
//opening the serial port
if(!serialPort.IsOpen)
serialPort.Open();
//read 2byte data for msG code from serial port
string strReadData=serialPort.ReadLine();
char[] temp=new char[350];
//strReadData.CopyTo(1, temp, 0, strReadData.Length - 2);
//strReadData = temp.ToString();
//string strReadData = serialPort.ReadExisting();
//strReadData.Replace(' ', '\0');
//strReadData.Replace(' ', '');
byte[] RecievedData = Encoding.ASCII.GetBytes(strReadData);
RecievedDataDecoder(RecievedData);
//close the port
if(serialPort.IsOpen)
serialPort.Close();
but my c++ receiver is working perfectly i dont know what is the problem here is working c++ code
// variables used with the com port
BOOL m_bPortReady;
HANDLE m_hCom;
DCB m_dcb;
COMMTIMEOUTS m_CommTimeouts;
BOOL bWriteRC;
BOOL bReadRC;
DWORD iBytesWritten;
DWORD iBytesRead;
DWORD dwCommEvent;
DWORD dwRead;
char sBuffer[128];
m_hCom = CreateFile("Com1",
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security
OPEN_EXISTING,
0, // no overlapped I/O
NULL); // null template
m_bPortReady = SetupComm(m_hCom, 128, 128); // set buffer sizes
m_bPortReady = GetCommState(m_hCom, &m_dcb);
m_dcb.BaudRate = 9600;
m_dcb.ByteSize = 8;
m_dcb.Parity = NOPARITY;
m_dcb.StopBits = ONESTOPBIT;
m_dcb.fAbortOnError = TRUE;
m_bPortReady = SetCommState(m_hCom, &m_dcb);
m_bPortReady = GetCommTimeouts (m_hCom, &m_CommTimeouts);
m_CommTimeouts.ReadIntervalTimeout = 50;
m_CommTimeouts.ReadTotalTimeoutConstant = 50;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 10;
m_CommTimeouts.WriteTotalTimeoutConstant = 50;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 10;
m_bPortReady = SetCommTimeouts (m_hCom, &m_CommTimeouts);
if (!SetCommMask(m_hCom, EV_RXCHAR))
{
printf("Error in set comm mask");
}
while(1)
{
if (WaitCommEvent(m_hCom, &dwCommEvent, NULL))
{
if (ReadFile(m_hCom, &sBuffer, 128, &iBytesRead, NULL))
printf("");
else
{
printf("Error in reading");
break;
}
}
else
{
printf("Error in Waiting");
break;
}
printf("%s",sBuffer);
strcpy(sBuffer,"");
}
CloseHandle(m_hCom);
getch();
exit(0);
Your question is a bit vague, but the ReadLine() method will return when the port receives a carriage return and line feed byte combination by default on Windows. Or \r\n, or 0x0d 0x0a if you prefer.
If the 'buffer' you are sending in the fist place contains several messages delimited by \r\n, then ReadLine() will only return the first one, then the port will close in the C# code you have posted.
Maybe your code is in a loop, but it is not shown.
Beyond that, after any data that you have received, your are converting it back to an array of bytes, determined by ASCII encoding. Are you sending ASCII in the first place? If not, it is likely that you could be missing information.
Also, if all you do is convert the received string into bytes, you could just receive the data as bytes in the first place.
I think you need to explain in a bit more detail exactly what is in the buffer you are sending, and what exactly do you receive.
Most of my serial port errors are caused by bad baude rate settings. This might be your problem too. (You can set the baude rate in some constructors of the SerialPort class, or with the BaudRate property)