How to send integer array through SerialPort - c#

I have an integer array d:int[] d = new int[]{1,2,3,4}
I want to send this through serial port (System.IO.Ports.SerialPort).
What I have written was
serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);//SerialPort.GetPortNames()[0].ToString(), 9600, Parity.None, 8, StopBits.One
serialPort.Handshake = Handshake.None;
serialPort.RtsEnable = true;
serialPort.DtrEnable = true;
if(serialPort.IsOpen == false)
serialPort.Open();
try
{
//serialPort.Write(buffer_2_send, 0, buffer_2_send.Length);
serialPort.Write(d, 0, d.Length);
serialPort.WriteLine("43665");
}
catch (Exception exp)
{
MessageBox.Show(exp.ToString());
}
And I am receiving this array d in another PC with Hercules RS232 software.
I am not seeing anything in Hercules screen for the line serialPort.Write(d, 0, d.Length);.
What would be the problem. The line serialPort.WriteLine("43665"); is writing the string "43665" to the Hercules screen.

You should convert your integer array to byte array before you send(serialPort.Write) it to device
int[] d = new int[] { 1, 2, 3, 4 };
byte[] buf = d.SelectMany(i => BitConverter.GetBytes(i)).ToArray();
But there are also other issues. What size does your device assume for int? 2,4,8 bytes? What is endianness, Little-endian or big endian etc. Maybe it is as simple as
byte[] buf = d.Select(i => (byte)i).ToArray();

In Hercules context menu (right click on data window) you need to set special char treatment to hex (away from text mode).
I'd suppose Hercules is filtering non text characters like 0x01, 0x02, 0x03, 0x04. You could test that, if you put 0x41, 0x42, 0x43, 0x44 (which is ABCD) in your array and see what happens.

Related

Trying to send data through HId interface, but error happend

I am using visual studio 2019 with C# .Netframework 4.7.2, I am trying to use jcoenraadts's HID project on github.
https://github.com/jcoenraadts/hid-sharp
I tried to send data through Hid, but error occur in the write function.
this is what I want to send
HIDInterface device = new HIDInterface(devicePath,false);
byte[] inputdata = { 0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00 };
device.write(inputdata);
and this is the write function
public void write(byte[] data)
{
if (data.Length > capabilities.OutputReportByteLength)
throw new Exception("Output report must not exceed " + (capabilities.OutputReportByteLength - 1).ToString() + " bytes");
//uint numBytesWritten = 0;
byte[] packet = new byte[capabilities.OutputReportByteLength];
Array.Copy(data, 0, packet, 1, data.Length); //start at 1, as the first byte must be zero for HID report
packet[0] = 0;
if (FS_write.CanWrite)
FS_write.Write(packet, 0, packet.Length);
else
throw new Exception("Filestream unable to write");
}
the error happend at FS_write.Write(packet,0,packet.Length);
the translate is IO operation can't complete the task,due to the data length is too long or the control code that supports synchronous IO operations has not been turned on.

SerialPort.BytesToRead return random number of bytes with EOL

I have an Arduino that constantly writes three hex's to the serial. My C# code defines two hex's (0x0d 0x0a) or \r\n as the EOL. I was expecting each ReadLine() reads out 1 byte of data (0x01) plus 2 bytes of EOL (0x0d and 0x0a), hence BytesToRead() should return 3 (1 data byte + 2 EOL bytes). DiscardInBuffer() then clears the OS's serial buffer to receive the next around of 3 fresh bytes {0x01, 0x0d, 0x0a}, supposedly.
But my BytesToRead() is returning some random count of bytes (e.g. 5,4,3,1,2,5,1,1,2,4...) while I was expecting them to be all 3's. If I remove or comment out serialPort.Newline (not giving the serial port a EOL), my BytesToRead() return all zeros (e.g. 0,0,0,0,0...). So clearly the EOL of \r\n (or 0x0d 0x0a) is doing something here but not in any predictable way.
Could someone explain why I'm getting this random byte counts? I could probably write a function to manually concatenate and chop up the serial data with each EOL and store the bytes in an array, but I want to understand what is happening here and why I can't do this with just the SerialPort class.
Arduino:
void loop() {
Serial.write(0x01);
Serial.write(0x0d); // Carriage Return, CR, \r
Serial.write(0x0a); // Line Feed, LF, \n
}
C#:
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 9600;
serialPort.PortName = "COM3";
serialPort.Parity = Parity.None;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
serialPort.NewLine = "\r\n";
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_OnReceiveData);
private void serialPort_OnReceiveData(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string a = sp.ReadLine();
int length = sp.BytesToRead;
sp.DiscardInBuffer();
Dispatcher.Invoke(new Action(() =>
{
tbLogger.AppendText(length.ToString() + ",");
}));
}

Sending CMD to PLC via TCP Client

I'm trying to send a command to a PLC that controls electronic lockers via a TCP Client. I am able to connect but it appears my command is not being read by the PLC.
I have the following code:
private const string STX = "0x02";
private const string ETX = "0x03";
private const string STATUS = "0x30";
private const string OPEN = "0x31";
private const string SUM = STX + ETX;
static void Main(string[] args)
{
var tcpClient = new TcpClient();
tcpClient.Connect("192.168.1.190", 4000);
if (tcpClient.Connected)
{
var networkStream = tcpClient.GetStream();
if (networkStream.CanWrite)
{
var ADDY = "00";
var asciiEncode = new ASCIIEncoding();
byte[] b = asciiEncode.GetBytes(STX + ADDY + OPEN + ETX + SUM);
networkStream.Write(b, 0, b.Length);
byte[] b1 = new byte[100];
var k = networkStream.Read(b1, 0, 100);
for (var i = 0; i < k; i++)
{
Console.WriteLine(Convert.ToChar(b1[i]));
}
}
}
}
STATUS/OPEN are the commands that can be sent. The PLC came with some documentation and here is a picture of it. I assuming my CMD is wrong, how do I fix it? This is my first time trying to connect to and send/retrieve commands from a PLC. Any help is appreciated.
You're on the right track, but the encoding of your command is wrong. Low-level protocols like these are tricky to get right.
Your byte array b contains the ASCII-encoded string "0x02000x310x030x020x03", encoded in ASCII, which translates to byte[22] { 48, 120, 48, 50, 48, 48, 48, 120, 51, 49, 48, 120, 48, 51, 48, 120, 48, 50, 48, 120, 48, 51 }while you want to be sending an array of the actual bytes 0x02, etc.
Try something like:
byte[b] = new byte { 0x02, 0x00, 0x31, 0x30, 0x02, 0x03 }
See also http://www.december.com/html/spec/ascii.html to see how STX and ETX relate to the other ASCII characters (eg a-z, 0-9, etc).

Python to C# TCP transfer corrupts data beyond 1523rd byte

I'm trying to send a long string from a python server to a C# client. The string is 230400 bytes long. I'm both sending and receiving in chunks of 64 bytes. Server code:
import socket
def initialize():
global s
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 1719))
s.listen()
initialize()
while(1):
sock, addr = s.accept()
msgstr = generate_msg_string() # irrelevant
msglen = len(msgstr)
totalsent = 0
while totalsent < msglen:
sent = sock.send(msgstr[totalsent:totalsent+64])
totalsent = totasent + sent
sock.close()
Client code:
TcpClient tcpClient = new TcpClient();
tcpClient.Connect(ip, 1719);
byte[] ba = new byte[230400];
byte[] buffer = new byte[64];
tcpClient.ReceiveBufferSize = 64
int i=0;
while(i != 230400)
{
stream.Read(buffer, 0, 64);
buffer.CopyTo(ba, i);
i += 64;
}
tcpClient.Close();
I've checked a few connections in a row - the first 1523 bytes are correct and all the rest are gibberish - at least seemingly random.
Any idea what might be the cause?
while(i != 230400)
{
stream.Read(buffer, 0, 64);
buffer.CopyTo(ba, i);
i += 64;
}
The fundamental error here is assuming that Read read 64 bytes. It can read any of:
0 if the socket gets closed for any reason
64 bytes if that happens to be available and it chooses to
1-63 bytes, just for fun
You are not guaranteed anything other than "non-positive if the stream is closed, else at least 1 byte and no more than 64 bytes"
You must must must read the return value of Read and only process that much of the buffer. This remains the case if you switch to Socket.Receive, by the way.
Also - why don't you just fill ba in the first place, increment in the offset and decrementing the count each time?
int count = 230400, offset = 0, read;
byte[] ba = new byte[count];
while(count > 0 && (read=stream.Read(ba, offset, count)) > 0)
{
offset += read;
count -= read;
}
if(read!=0) throw new EndOfStreamException();
It seems that I hurried with the question.
Changing TcpClient to Socket fixed the problem. The approach remained the same.

Serial Commands - NEC Projector

I'm working on a C# application that writes serial commands to an NEC projector. I can send the commands fine using RealTerm using the "Send Numbers" function but cannot seem to get it to work through my app.
The format of the commands are
POWER ON - 02H 00H 00H 00H 00H 02H
POWER OFF - 02H 01H 00H 00H 00H 03H
I've tried sending using WriteLine(command) - as a string as well as converting it to a byte array with the following code:
public static byte[] ToByteArray(string StringToConvert)
{
char[] CharArray = StringToConvert.ToCharArray();
byte[] ByteArray = new byte[CharArray.Length];
for (int i = 0; i < CharArray.Length; i++)
{
ByteArray[i] = Convert.ToByte(CharArray[i]);
}
return ByteArray;
}
Nothing seems to work, what shall I be sending down the port from my C# end? Hopefully someone can help soon :)
There is very little point in trying to convert these commands from a string. They are not strings. So just write them in your code in their native format:
private byte[] powerOnCmd = new byte[] { 0x02, 0x00, 0x00, 0x00, 0x02 };
private byte[] powerOffCmd = new byte[] { 0x02, 0x01, 0x00, 0x00, 0x03 };
Now it is simple:
private void sendCommand(byte[] cmd) {
serialPort1.Write(cmd, 0, cmd.Length);
}
private void PowerOn() {
sendCommand(powerOnCmd);
}
You can use the Write method, it takes a string as argument :
SerialPort.Write

Categories

Resources