I'm trying to get bidirectional communication using RS485 2 wires and everything I've tried so far failed.
I can send data and have my peripheral react as expected (so the wiring is correct), but I never receive any reply.
I'm using the .NET SerialPort
, I've tried using the DataReceived
event and also a loop in a Thread
polling the port. I've even tried just blocking on read until enough data is received.
I have tried several hardware options:
I have played with driver settings: - FIFO Interrupt Trigger levels - Receiver FIFO Flow Control Thresholds - RS485 Buffer enable (Normal, Active High, Active Low)
Following various leads (like Can't receive serial data in .net 2.0, using rs232 to rs485 converter), I've tried setting DtrEnable
to true, or false, or switching it.
I've also tried switching RtsEnable
when sending and receiving (following http://en.wikipedia.org/wiki/RS-232#RTS.2FCTS_handshaking).
I don't see anything else to try right now without resorting to different wiring. What could be wrong?
As requested, some code (it's only a snapshot after many attempts):
Open:
_serialPort = new SerialPort(comboBoxSerialPort.Text, 9600, Parity.None, 8, StopBits.One)
{
WriteTimeout = 500,
ReadTimeout = 500,
Handshake = Handshake.None
};
_serialPort.Open();
_serialPort.DtrEnable = true;
_serialPort.RtsEnable = true;
Send:
_serialPort.RtsEnable = false;
_serialPort.Write(data, 0, data.Length);
_serialPort.RtsEnable = true;
Thread.Sleep(1);
_dataSent.Set();
Reader thread:
var port = form1._serialPort;
byte[] buffer = new byte[128];
int read = 0;
do
{
Array.Clear(buffer, 0, buffer.Length);
read = 0;
try
{
form1._dataSent.WaitOne();
//if (port.BytesToRead > 0)
read = port.Read(buffer, 0, buffer.Length);
}
catch (TimeoutException)
{
}
catch (Exception ex)
{
form1.Invoke(form1.AddErrorMethod, ex.ToString());
continue;
}
if (read > 0)
{
form1.Invoke(form1.AddOutputMethod, ByteListToString(buffer));
}
Thread.Sleep(20);
}
while (_continue);
Note: data packets are 10 bytes long, in both directions.
I've fixed the issue on one hardware configuration (the RS485 card) by:
My send code now looks like this:
// Enable send mode
SerialPort.DtrEnable = false;
SerialPort.Write(data, 0, data.Length);
// Wait a little, then enable response mode.
Thread.Sleep(15);
SerialPort.DtrEnable = true;