none
Full duplex pc to half duplex serial communication with SerialPort class in C++ (but any language will do)

    Question

  • Hello.  I am a bit new to the .NET environment, and though I feel I was able to get a good handle on most of the basics of .NET, I believe I've encountered a problem beyond the basics.  I am trying to talk with a device called a ColorPAL that uses asynchronous serial communication, but it is half-duplex instead of full-duplex.  I am able to send it the hex string commands that it wants just fine with the TX line.  However, I find myself unable to read because the RX isn't connected to anything.  Basically what I want to do is that I want to be able to swap the TX line to become a RX line so that I can then read line of the half-duplex.  I read that there is a PinChanged event, so it lead me to believe there is a way to change pins??   If the RX line is very high impedance I could connect it to the TX line, but I have no idea about that.

     

    How can I get a full duplex to read a half-duplex using the visual studio software?

     

    Here is the code I'm using, in case that helps.

    #include "stdafx.h"
    #include <Windows.h>
    
    using namespace System;
    using namespace System::IO::Ports;
    
    int main(array<System::String ^> ^args)
    {
    	String^ portName; //the com port
    	String^ ans;
    	String^ strRead;
    	array<unsigned char>^serialBytes={0x87,0x00,0x02,0x00};
    	unsigned short on = 1;
    	int baudRate=7200;
    	short loop=1;
    	for each (String^ s in SerialPort::GetPortNames())
        {
          Console::WriteLine("  {0}", s);
        }
      Console::WriteLine("Type in the port name of the maestro and hit ENTER"); //prompt the user
    	portName=Console::ReadLine();
    	SerialPort^ pal;
    	pal = gcnew SerialPort(portName, baudRate); //initialize the serial port class as maestro and open port
    	pal->ReadTimeout = 500;
    
    	pal->Open(); //open the serial port
    	Sleep(2000);
    
    	while(loop==1)
    	{
    		Console::WriteLine("Type in the command to send to the ColorPAL");
    		ans=Console::ReadLine();
    		if(String::Compare(ans, "multi")==0) //doesn't work yet
    		{
    			pal->WriteLine("= m !");
    			strRead=pal->ReadLine();
    			Console::WriteLine(strRead);
    		}
    		pal->WriteLine(ans);
    	}
    
      return 0;
    }
    

    Wednesday, September 29, 2010 9:33 PM

Answers

  • ahihmc

    First you need to find out how the hardware is connected. It is common that an RS-485 connection is a half-duplex, 2-wire (plus ground) line, but a standard RS-232 port cannot be connected as half duplex because this requires that it is possible to three-state the transmitter, that is, set it in high impedance mode, which it is not. If your device has an RS-232 port, it is almost guaranteed that it has a separate TX and RX line.

    It is likely that your device is specified as half duplex because it needs a question (poll) and then sends a reply, but that the hardware is actually full duplex.

    PS. Why do you want to program it all in C++? .Net has a SerialPort class, which is very easy to use unless you have special requirements such as Break detection or 9th bit communication. If you don't mind VB examples, you can read my tutorial, which describes everything in minor details - somebody thinks too minor details :-)


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.
    • Marked as answer by SamAgain Tuesday, October 5, 2010 7:58 AM
    Thursday, September 30, 2010 9:28 AM
  • The problem is still the hardware. An RS-232 port simply cannot be connected as half duplex because you cannot set the transmitter into high impedance mode. This means that if one transmitter tries to drive the line to logical 0, that is, a voltage of approximately 12 V, the other transmitter will still try to set the line to 1, that is, to -12V. This creates a short circuit where the most powerful transmitter wins and the result is completely unpredictable.

    I have looked at your device and it is quite obvious that it is NOT and RS-232 device, but a device with an open drain output. This is why it can be connected as half-duplex without any risk of short circuit. To be able to communicate with the device using an RS-232 port, you must of course apply a 5V to the board and then you need some hardware to convert the signal levels.

    In the user manual there is very little information about the interface and the one there is contradict itself. For example, it says that it is not necessary to apply a pull-up resistor as this is included, but the schematic does not show such a resistor - only a 330 ohm serial resistor! The pull-up resistor may be included in the ATTiny13A, but in that case, it is probably not very powerful and cannot drive very much. Because the interface is non-inverted, it has the opposite polarity of an RS-232 interface so you need to invert the signals.

    I wonder how you are able to send anything to the device when the signal levels are inverted! What level conversion do you use for the moment?

     


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.
    • Marked as answer by SamAgain Tuesday, October 5, 2010 7:58 AM
    Friday, October 1, 2010 7:41 AM
  • As far as I understand the datasheet for ColorPAL, the signals are non-inverted, that is, 1 = 5V and 0 = 0V. Therefore, you probably have to invert the signals from the PIC, but it would have been nice with a more precise specification in the data sheet than just "non-inverted". Besides, the PIC must be programmed to open drain output on the transmitter if this is possible. If not, add a schottky diode with the katode connected to TX from the PIC. In this way, both transmitters can only pull the line low. The pull-up internal in the ATTiny13A will then pull the line high if no transmitter is operating.

    When you connect the two transmitters and the two receivers to the same line, you will of course also receive your own transmission.


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.
    • Marked as answer by SamAgain Tuesday, October 5, 2010 7:57 AM
    Friday, October 1, 2010 8:32 PM

All replies

  • Is the device u r referring is

     

    http://www.pololu.com/catalog/product/1608

     

    ?

    Thursday, September 30, 2010 8:01 AM
  • ahihmc

    First you need to find out how the hardware is connected. It is common that an RS-485 connection is a half-duplex, 2-wire (plus ground) line, but a standard RS-232 port cannot be connected as half duplex because this requires that it is possible to three-state the transmitter, that is, set it in high impedance mode, which it is not. If your device has an RS-232 port, it is almost guaranteed that it has a separate TX and RX line.

    It is likely that your device is specified as half duplex because it needs a question (poll) and then sends a reply, but that the hardware is actually full duplex.

    PS. Why do you want to program it all in C++? .Net has a SerialPort class, which is very easy to use unless you have special requirements such as Break detection or 9th bit communication. If you don't mind VB examples, you can read my tutorial, which describes everything in minor details - somebody thinks too minor details :-)


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.
    • Marked as answer by SamAgain Tuesday, October 5, 2010 7:58 AM
    Thursday, September 30, 2010 9:28 AM
  • Hello all,

    Yes, that is a link to the device I am referring to.

    The receiving device is specified as a half duplex, one, because it needs a poll and to send a reply, but also, two, because it literally is only one line so that you literally can not transmit and receive simultaneously without buffer clashes.  I could make it so that on the sending device, the PC interfacing through a PIC, which appears to be a RS-232 port, the RX and TX physically connect.  However, if they are physically connected then everything sent out by TX will simply go into RX, and that doesn't really get me any closer to reading the 1-wire half-duplex (at least from my understanding).  Though there may be something about I can do about tricking the PC that can by connecting both lines.  I could try clearing the RX buffer before a read for example (though I already tried this and it clears too much, which must mean that either I cleared the information sent along with the previous TX storage or the info never made it in because the buffer was full, or maybe it just wasn't sent for some other reason that I do not understand).  I don't know, this is why I'm asking the experts :p.  Half-duplex serial comms are new to me, and I am having trouble finding out how to interface a full-duplex to a half-duplex.  

    If it's not possible to use a RS-232 full-duplex to a half-duplex then I'll just work on making a soft UART for a microcontroller that will do what I need.  I'd like to not have to open up that can of worms. :)

    I am using C++ because that's the language I know (unless there is a serial port for Matlab or Mathematica!). I can read java or basic just fine (kind of like if you know spanish and italian you can read french just fine) for the most part, so I don't mind reading in other languages, but I can't write in them. Oh yeah, and I read your tutorial, Carsten, it was really great and recapped most of what I've recently learned, though I did learn a few new things, but I didn't really find anything to help me out with this topic.

    Thursday, September 30, 2010 9:04 PM
  • The problem is still the hardware. An RS-232 port simply cannot be connected as half duplex because you cannot set the transmitter into high impedance mode. This means that if one transmitter tries to drive the line to logical 0, that is, a voltage of approximately 12 V, the other transmitter will still try to set the line to 1, that is, to -12V. This creates a short circuit where the most powerful transmitter wins and the result is completely unpredictable.

    I have looked at your device and it is quite obvious that it is NOT and RS-232 device, but a device with an open drain output. This is why it can be connected as half-duplex without any risk of short circuit. To be able to communicate with the device using an RS-232 port, you must of course apply a 5V to the board and then you need some hardware to convert the signal levels.

    In the user manual there is very little information about the interface and the one there is contradict itself. For example, it says that it is not necessary to apply a pull-up resistor as this is included, but the schematic does not show such a resistor - only a 330 ohm serial resistor! The pull-up resistor may be included in the ATTiny13A, but in that case, it is probably not very powerful and cannot drive very much. Because the interface is non-inverted, it has the opposite polarity of an RS-232 interface so you need to invert the signals.

    I wonder how you are able to send anything to the device when the signal levels are inverted! What level conversion do you use for the moment?

     


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.
    • Marked as answer by SamAgain Tuesday, October 5, 2010 7:58 AM
    Friday, October 1, 2010 7:41 AM
  • Hi Carsten, thanks for the help once again.  Yeah, my big problem is that the communication interface that's talked about in the data sheet has so little information.  

    The PC actually goes through a USB to a PIC (PIC18F14k50), which then passes on the data that the PC initially sends.  The PIC sets up a virtual COM port with the PC.  The logic levels of the virtual COM port are 0-5V TTL levels.  Right now my logic levels are ~5V (logic 0) and 0V (logic 1).  Could it be that the PIC is the strongest transmitter and so it can transmit fine to the ColorPAL, but when the ColorPAL tries to transmit, the PIC continues to force the line high?  I could always add some resistors if I need to increase the impedance.  The ATTiny13A does include pull-up resistors, I've worked with that micro before.  

    Friday, October 1, 2010 3:13 PM
  • As far as I understand the datasheet for ColorPAL, the signals are non-inverted, that is, 1 = 5V and 0 = 0V. Therefore, you probably have to invert the signals from the PIC, but it would have been nice with a more precise specification in the data sheet than just "non-inverted". Besides, the PIC must be programmed to open drain output on the transmitter if this is possible. If not, add a schottky diode with the katode connected to TX from the PIC. In this way, both transmitters can only pull the line low. The pull-up internal in the ATTiny13A will then pull the line high if no transmitter is operating.

    When you connect the two transmitters and the two receivers to the same line, you will of course also receive your own transmission.


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.
    • Marked as answer by SamAgain Tuesday, October 5, 2010 7:57 AM
    Friday, October 1, 2010 8:32 PM
  • Yep, the PIC TX line was a push-pull (sink and source), so I added the diode (generic, not a shottky) and it all worked, thanks for the help Carsten!
    Wednesday, October 6, 2010 9:32 PM