Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Wednesday, October 18, 2006 7:07 AM
Hi
I'm back on VB after a long while. I'm having problem controlling the RTS and DTR signals of the serial port. I'm trying to use RTS (maybe DTR as an alternative) to control an RS485 comms data direction. I have set up 2 buttons as a test with the following code:
Private Sub Functionkey4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Functionkey4.Click
SerialPort1.RtsEnable = True
End Sub
Private Sub Functionkey5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Functionkey5.Click
SerialPort1.RtsEnable = False
End Sub
the program gets to both routines when the buttons are clicked but the RTS pin does not change, the port is working perfectly otherwise. According to another thread this should work but it isn't. I have tried both with Flow Control none and hardware. Any clues please? Must be something easy....
All replies (10)
Wednesday, October 18, 2006 11:30 PM âś…Answered
Fixed it, see below
>>Make sure that you use Hardware Flow control!!
If I do that then the hardware will take control of the RTS pin which is not what I want to do, so the Hardware Flow control has to be NONE for this to work (and it does now).
What the problem was that the port was being opened and CLOSED each time I was sending data out in another routine, so I was trying to manipulate the RTS pin on a closed port!
I am now changing that so that the port is opened at the start of the program and kept open untill exiting so the various output routines (different protocols fo different equipment) does not open and close the port each time it is called.
So my calling function is:
Private Sub Functionkey10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Functionkey10.Click
command = &H15
Terminal()
End Sub
and the terminal out put is:
Public Sub Terminal()
SerialPort1.ReadTimeout = -1 'No timeout to start
SerialPort1.RtsEnable = False
SerialPort1.Write(Chr(command)) 'Send message
SerialPort1.RtsEnable = True
End Sub
The above is just a quick test so I will need to do quite a bit of work yet but now the RTS pin state sticks untill specifically changed.....and of course for someone else getting into the same problem remember to OPEN THE PORT AND KEEP IT OPEN whilst you need to use the RTS (or DTR??) pin
Wednesday, October 18, 2006 8:17 AM
Make sure that you use Hardware Flow control!!
In some serial port controls, the RTS goes false after a short while, so you should make a loop to hold on Request to send signal.
I think you can test this by measuring the voltage level on the RTS pin.
As i know that the RS485 is a half duplix protocol, you should also make sure that the hardware you work with or if you have any repeater that would carry the RTS voltage level to the target hardware.
Hope this can help!
Best Regards,
Amr Ouf
If you see this POST is the answer to your question, please mark as an Answer.
Thursday, October 19, 2006 6:31 AM
Congratulations!
But you should care of removable serial port devices such as USB/SERIAL converters that if the user may have a fault in the motherboard and replaced the serial port with USB/Serial (OR USE ON LAPTOP) this would have a special handling,
You should handle exceptions when you use write method, if an exception occured... simply close and reopen the port.
If there's an exception then exit transfer PORT DOESN'T EXIST
if not retry again to send.
So, if you need to handle this case ... I think you would make a Send Function to do it for you and call from anywhere in your application.
Interfacing Hardware is really an exciting work, Have some fun!!!
Good Luck!
Best Regards,
Amr Ouf
Now, Let's close this session
You can mark your POST as an Answer.
Thursday, October 19, 2006 6:59 AM
Thanks for the advice, I need to do a bit more work. Of course the other issue that now arises is how long it takes for RTS to change state after the data is send, especially on an older, slow machine. The equipment I'm working with at present waits about 100uS after receiving the command to send data out. Looks like this is not long enough as it seems to take longer for the PC to change the RTS line
and I'm losing some characters or miss some bits and the response is garbled...but this can be another thread I guess, see if I can get some timing.
Thursday, October 19, 2006 8:05 AM
Do you use RTS to make the Device enters an inturrupt ISR?
is so, does the device responds by CTS?
I suggest that you add a handler to the Rx event and place the public string buffer that is will be concatinated when the you get data.
Then you make a wait loop after send that validates the RX buffer for a certain minimum length or a certain terminator/checksum if there's according to your protocol.
This will be more efficient then you clear the buffer afterwards.
Note: The time frame is important.
Good Luck,
Best Regards,
Amr Ouf
If you see this POST is the answer to your question, please mark as an Answer.
Thursday, October 19, 2006 10:50 PM
Sorry, I had this reply last nigh but my ISP died on me, fortunately I was able to save the text.
The 'device' (RS232 to RS485 converter) is simply a MAX232 and a MAX485 chip (or similar). The RTS is wired to the CTS so it gives instantnuos response. This signal is level converted and feeds the direction control of the MAX485, RTS=False data flows from PC to RS485 link, RTS=True data flows from RS485 link tp PC, the problem being that from the time that the data is send out, the command is given to change RTS and when RTS actually changes state takes longer than 100uS, could be even mS don't know yet, but the euipment on the other side od the RS485 link has received the message and responds before the direction is acually changed due to the latency of the RTS pin. As I have written the firmware for the microcontroller (which by the way works in the field with another microntroller driving it), I will try and slow down the response time untill Windows catches up. Then I will run my program on an old 233MHz machine and see how long it needs to respond and adjust the timing accordingly. I have seen 2mS response delays in some programs and now I know why. However this is just for internal workshop use for now so that I can simulate another piece of equiment.
Friday, October 20, 2006 11:38 AM
So, you have designed the circuit your selft!
If so, if there's ability to use CTR in the circuit to acknowlege that the device is ready to begin transfer?
This would solve the problem.
A calibration for the time frame may work, but i'm afraid there might be a heavy workload on the machine that would make the latency value incorrect.
A good practice in the RS485 is to send a series of dummy bytes (characters of 0x0) on the start of your packet to start the transfer - Leading even the Sync/Start Byte - then you should ignore all of these bytes at the other side.In this case you wouldn't have to count or take care about these byte that cvan be used to init. the transfer.
Otherwise if you see that the delay is according to the machine, i advice you to write an Unmanaged code on Visual Basic 6 / VC++6 DLL/OCX and use the MSCOMM32.OCX to communicate to the serial port then add a reference to your code.
This would be much faster.
Hope this can help!
Best Regards,
Amr Ouf
If you see this POST is the answer to your Question, please mark as an Answer.
Friday, October 20, 2006 8:37 PM
| Amr Ouf wrote: | |
|
That's what I have been doing for a living for about 40 years
|
As you point out this is necessary when talking to a machine that is encoumbered by an operating system and a program that is very bloated, all my boards usually talk among themselves, there is no operating system, their program is written in assembler and can repond in microseconds as they have nothing else better to do. The modules I have just designed for a company run on a 20 pin device with 2K of flash, one of them has 2 bytes free but in the real world they are communicating to another microcontroller module (designed by others) which has no problem with changing the direction of the RTS pin on time. The 'protocol' consists of 1 byte command 1 byte response in one module and 6 bytes response in another. I can use the direction control of the module to change the comms direction of the interface and just use a normal terminal program to do my testing, but this is a little messy as I have to open up the interface module and wire it up. I thought I could just make up a small program with some buttons to send the various commands (this bit works) and then have a box where I could diasplay the responses and the whole testing bit could be a bit more elegant. I could put together an intelligent interface that could buffer the responses and somehow then relay them to the pc as a small processor inside the unit could wait untill it sees RTS before sending. I believe this is the approach taken by some colleagues that have given up on what I'm trying to do. I may have a quick shot at doing it in Delphi see how it goes.
Saturday, October 21, 2006 8:34 AM
Yes, i have experienced this before I've used ATMEL AT89C52 to make a communication on both 232/422/485, being the 485 is a half duplex it caused me great problems.
I've worked in a Telphony appliction written on Borland Delphi 6 and i have found data losses, specially the first leading bytes in our protocol, but the next bytes usually arrives without problems.
So, I made a work around is to start the transfer with 10 characters 0x00 while the microcontroller enters Serial ISR and it will not buffer the stream untill a non zero has been received then it start to buffer data, once the terminator is validated and seems to be correct, it waits for the sync byte or leading zeroes again.
But here's a good thing to mention, the MSCOMM didn't the task in VB 6 and i used delphi 6 component TCOMM becuase it has a nice flow control mode which is TOGGLE , that can do the task for you it toggles the RTS automatically which doesn't exist.
After the project is complete I decided not to use the RS485 again because of its complications and the owner of the company should buy another type of cables with 4 wires and use the RS422 instead if he need to go for large distances.
The trick of RTS then send leading zeros to init transfer then send data afterwards has solved the problem in our project.
Good luck,
Best Regards,
Amr Ouf
Tuesday, April 24, 2007 7:44 PM
I'm working in a similar project, and the problem that i have found is that the serialport.RTSenable=false shutdowns the RTS before all the data have been sent.
I put a delay of 2 miliseconds and it works. I'm trying to find the way to know when all the bytes have been sent because the serialport.bytestowrite doesn't work because it doesn't returns the real value of out buffer.
Code Snippet
//baffer[cantidad];
serialPort1.RtsEnable = true;
for (i = 0; i < cantidad ; i++)
{
serialPort1.Write(buffer, 0, cantidad );
}
System.Threading.Thread.Sleep(2);
serialPort1.RtsEnable = false;