RS485-RS232 through code

Hey there.

I'm currently working on a piece of measurement equipment (a ball-on-disc machine) where I am using an arduino to control the two servo motors. These are driven by their own motor controllers, that can be configured to track a quadrature encoder synchronously. The arduino is used to emulate the encoder signals, driving both motor controllers as slaves. This much I have managed myself, using only integrated timer functions leaving the main loop unused.

But configuring the motor controllers is done using a software communicating through RS485, a port my computer obviously does not have. I could and probably should order an adapter to RS232 or USB. But it would be nice if, instead, the arduino could act as a converter using only code. Especially since it is already integrated in the measurement rig.

Is it at all reasonable to forge a code capable of doing this reliably? Using any digital pins at the RS485 end and passing the messages on through the UART at some useful rate?

How about this for a solution:

When commanded to act as a RS485-RS232 converter, the main loop starts continuously:
-checking the state of the digital pins representing 485 Rx- and Rx+ (or just one of them, saving some clock cycles), and arduino pin 0 (232 Rx).
-Setting the digital pins representing 485 Tx- and Tx+ (placed on the same port and set directly, ensuring synchronous switching) according to the state of the 232 Rx pin
-setting 232 Tx according to 485 Rx pins.

In case that got confusing because of my poor description: I was thinking of using direct pin manipulation between the pins connected to the ATmega16U2 and some random pins chosen as an RS485 interface.

Due to my limited programming education, I have a hard time trying to determine how quickly the processor could perform these tasks. What sort of baud rate would this implementation support? Also, would the ATmega16U2 blindly accept these signals or is there more to it?
Finally, if this is possible: Do i need to deactivate the UART to prevent interference? Can this be/how is this done?

You can't.

RS485 is a differential, open-collector bus.

There are two signal wires, D+ and D-. A logical "1" is encoded when D+ is more positive than D-, and a logical "0" is encoded when D+ is more negative than D-. These two voltages are positive and negative, relative to a "common" voltage.

Additionally, when a device is not communicating via RS-485, it MUST tri-state both D+ and D-. You =can= tri-state a digital pin with an Arduino, by making it an "input" pin, but you cannot drive the RS-485 wires with the 0 and 5 volt signals.

The solution is to add a chip such as the Maxim MAX485. It's a =very= simple device and includes it's own circuitry to produce the required voltages.

right you are of course, I should have known but I've been confusing it with RS422 since this is also present on the motor controllers.

However: as i understand, rs485 needs very low voltage difference between the signals to tell 1 from 0. Thus I should be able to use a "common" voltage of 2.5 volts using a voltage divider, or maybe even the 3.3v pin, and perform the differential signaling with 0 and 5 volts respectively. Am i wrong? The tristating is more of an issue i suppose, knowing when to do it and if it can be done quickly enough.

Or is it still doomed to fail?

Or is it still doomed to fail?

Almost certainly. I suppose you could make it work but it needs at least 8 resistors and a lot of bit banging to get the push/pull signals.

As you have to add hardware anyway why not add an 8-pin 485 transceiver or two and be done with it.


Rob

Because with all the bureaucracy at this place ordering anything is two full days of work, and then you still have to wait for the delivery. If i can do it with with readily available components I could easily spend three full days on it and it would still be worth it. Also, lets not forget: This is not to be used for networking, only communicating with a device 1 meter away with nothing causing unusual amounts of interference. It needs not be robust in an industrial sense, only in that it under the right circumstances will relay the data.

As far as i can figure out from the manual, the device does only use +5V and GND for signaling. It can also use rather low baud rates should speed be an issue. So hardware should not be a problem.

Interestingly, I can find nothing that sounds like a reference pin. The pins in the connector are:
1 n.c.
2 GND_B
3 +5V_b
4 RS485-
5 Rs485+
6 24V_IN
7 +5V_B*
8 GND
9 +5V

For the simply connecting to a nearby computer they suggest bridging pins 3-9 and 2-8.

So how do i determine whether to send or receive data?

the device does only use +5V and GND for signalling.

Then it's not RS485, but certainly the pinout shows that it is.

In that case RS485+ = A and RS485+ = B I would say (A and B are the standard RS485 designators). IIRC if A > B by 200mV or more then you have a logic 1, A < B is logic 0.

So I'm wondering if you tie B to 3v3 and use a 0-5v signal on A it might work.


Rob

Given that it has no voltage reference, would it not suffice to send A=0V and B=5V to send a logic 0 and A=5V B=0V to send a logic 1? The difference would sum up to -5V and 5V respectively, more than enough.

To determine direction, I would switch to output on the RS485 side when receiving a start bit on RS232 and back to input when receiving a stop bit. What say you?

The reference is one or both of the GNDs (I don't know what the _B means but if you can join them together then do so).

What you suggest may work as well (although I think the logic is inverted) but it means bit banging two pins per connection.

My method (if it works) allows you to use the softwareserial library.

RS232

There is no RS232 here.

Normally with half-duplex 485 you enable the transmitter, send data, then disable it and wait for a response. You cannot have an output enabled and disable it when you see start bit because you will have contention between the two outputs.

EDIT: Neither scheme will work for reading data from the RS485, you have to amplify the signal somehow.


Rob

I realize I may have been unclear about the purpose of this code. My computer has a software that can configure the motor controllers through RS485, but the computer has no RS485 port. As an alternative, there was once a cable with an adapter that permitted connecting it to the RS232 port of the computer instead. I wish only to emulate this adapter, since it has gone missing.

I do not wish the microcontroller to say anything on it's own. That is why I am suggesting "bit banging" the communication straight to and from two arbitary pins connected to the RS485 of the motor controller, to the Rx and Tx pins on the arduino. Not because I want to talk to the arduino, but because the same pins are connected to the RS232-USB adapter (ATmega16U2).

The way I figure, the only tricky part is to know when to change data direction, since it does need two way communication in half duplex.

So the Arduino is an interpreter between the full-duplex RS232 and the half-duplex RS485?

The lost cable must have had some smarts, I don't think it could have been a simple cable unless a handshaking signal was used to control some hardware in the cable.

The Arduino cannot talk to RS232 without some extra hardware.

The communications is bi-directional.

If the above is true I cannot see any way to do this without hardware to convert both the 232 and the 485 levels. The best way to do this is with transceivers for both, the 232 can often be fudged with a few components and the 485 can partly be fudged as we've talked about.

It's possible that the A signal coming from the controller could be used directly into an Arduino pin, but it's far from guaranteed and it depends on the driver chip they are using and the value of the terminating resistor (if any).

All I can suggest is that you try it, run the A signal into a pin and use software serial to send a command then turn off the TX pin and listen on the Rx pin.

You then have to interface with the RS232 from the PC, at minimum this requires a diode (A to GND, K to signal with a small resistor (220R maybe) in series with the signal) because the -12v will kill the Arduino. If you are lucky that should be all that is needed on this end.

RS232-USB adapter

Where does this come into it? If you can talk USB none of the RS232 stuff matters.


Rob

Just thinking some more, before you lost the cable you had this

PC --- USB<->232 --- 232<->485 --- controller

And now you want the Arduino to replace the lost 232<->485 part.

Correct?


Rob

Assuming that the physical interfaces are sorted you may be able to transfer bits from one pin to another which I think is what you were suggesting. Some nice tight code should be able to do this.

However, unless you reassemble the bytes the only way to detect the end of the PC's transmission is with a timer. If there has not been a falling edge on the signal for say 9 bit times then it's done and you turn off the Tx pin to the 485 and hope the controller isn't to fast to respond.


Rob

Actually, the PC has an RS232 port, so I had:
PC --- 232<->485 --- controller

What I want is, as far as the "DriveManager" (motor controller software) sees it, the exact same thing. I want it to use the virtual COM port emulated by the ATmega16U2, then I want the micro controller to blindly pass the bits to and from the RS485 port of the device. The only thing I see standing in my way is knowing when to switch from sending to receiving.

My idea is to switch to send mode when receiving a start bit from the virtual RS232 port (pin 0 on the arduino). Switching back to receive mode after a specified number of silent bits is a good idea, I'll probably try that.

Another problem that may surface is if the UART of the micro controller shows some activity, but I haven't started researching this.

Switching back after a specified number of silent bits

The only way to do it AFAIK. The actual time used depends on the data and if there is any inter-byte delay on the data coming from the PC.

If there is then the delay has to be long enough to allow for that, then you may have a problem if the DriveManager responds too fast because you will still be waiting for the timout.

With direct port manipulation you should be able to transfer the bits in a timely fashion.

virtual COM port emulated by the ATmega16U2

So there is no RS232? Note, RS232 != serial, the two terms are kind of related but mean different things.

Sorry but this is getting too confusing, if the 16U2 talks USB there is no RS232 and you cannot get access to the actual bits of the data. Or is the 16U2 spitting out 5v serial that you want an Arduino to pass to the DriveManager.

If that's the case I'd just use a (software)serial port to accumulate the bytes then when the entire packet is received retransmit it to the DriveManager, get the response and send it to the PC.

EDIT: "virtual RS232 port (pin 0 on the arduino)"
OK, all the talk of RS232 and ATmega16U2s got me confused. We have 5v serial data on pin 0 so none of the above RS232 stuff is of any relevance and the ATmega16U2 is not relevent.

As I said I would read all the bytes and retransmit, unless the PC requires an immediate response that has to be the easiest way.


Rob

I did begin suspecting that my terminology was incorrect. I suppose RS232 means specifically -12V is a logic one and +12V is a logic zero. If so you are correct, there is no RS232 present. Everything is done on TTL level. However, the USB conversion is just a "magic box", nothing we need to consider. In goes serial communication on TTL level from the micro controller, and out comes serial data through a virtual COM port in the computer. As far as the computer sees it, it is communication through RS232, but of course in reality that never happens.

The point is, for the purpose of this discussion, I think we can pretend that RS232=serial, knowing that in fact everything takes place on the same level.

So the 16U2 is spitting out 5v serial that I want to pass on to the motor controller, except differential. And the motor controller returns a differential signal that I want to translate to 5V serial and send through the 16U2 into what the computer thinks is an RS232 port.

Is this helping or confusing even more?

Yep I think we're on the same page now :slight_smile:

So the only issues are converting the voltage levels, transferring the bits/bytes and detecting when to turn off the TX pin, all of which have been covered I think although possibly lost in the noise.

To summarise...

Tx to the controller should work by tying B to 3v3 and transmitting 0-5v on A (or swap A and B if the logic is inverted).
Rx from the controller might be a problem because the voltage levels will vary depending on the chip they use, termination resistor etc.
The data can be transferred bit by bit and a timer used to detect the end of the PC transmission so the Tx pin can be turned off.
The data can also be transferred by receiving all the bytes then retransmitting them. In this case you either have to know the protocol or you can still use a timer.

All the above may fail for various reasons so I think it's time to write some code and see what works.


Rob

Thank you for your advice, I'll get back when I have results. This may take quite a while since there is a whole lot of other things to be done in the project, but I think it will work one way or another.

crap:
...
The way I figure, the only tricky part is to know when to change data direction, since it does need two way communication in half duplex.

I noticed that you mentioned the controller having RS-422, but I do not see the pins for it on the connector pinout you showed. Does it in fact have RS-422? The reason I ask is RS-422 is electrically very similar to RS-485, except it has separate transmit and receive, whereas RS-485 has them shared. With RS-422 you would not have to worry about switching between transmitting and receiving.

Here is another possibility, assuming the motor controller does indeed have RS-422: I have used a module(Micromint Domino) that had RS-422 and it would talk to an RS-232 port on a PC by tying the TX- pin of the module to the RX pin of the PC, the RX- pin of the module to the TX pin of the PC, and the ground pins together. I do not know if the module had any pull-up or pull-down resistors on any of the RX or TX pins. This setup does not give you true RS-232 signaling, but I used these modules with several computers and none of them had trouble talking to the modules.