Because all Boys (and some girls) love Trains

RS-bus feedback Circuit


The decoders described at this site can communicate to a LENZ master station via the RS feedback bus. A piggy-back print (see picture below, left) for RS-bus slaves has therefore been designed that can easily be mounted on all decoder prints (the picture below at the right shows a switch decoder with an AVR32A processor and a RS-feedback print, as well as a switch decoder with an AVR8535 processor without feedback print).
These feedback prints are used for normal feed-back information (such as the position of switches or track occupancy), similar to prints from other manufacturers, but can also transmit the values of the decoders internal Configuration Variables (CVs) during CV programming.


RS-Bus basics
A detailed description of the RS-bus is provided by the der-moba website (in German); below is just a summary of that info.
Physical layer: The RS-bus is a master-slave bus. The master is implemented in the command station (like a Lenz LZ100) and the slaves are implemented in the decoders. The master is connected to the slaves via a bus consisting of two-wires, which are twisted to reduce possible interference. Data over the bus is transferred as current pulses, instead of voltage levels. The advantage of using current pulses instead of voltage levels, is the better protection against interference. The current sources are implemented in the slaves; a 20mA current source for sending and a 3 mA source for reception. Since the duty cycle of the pulses is roughly 50% (a complete pulse takes
200µs; thigh=93µs and tlow=107µs), the average load per slave is roughly 1,5 mA.
Access control: The RS-bus is one directional: data bytes can be send from a slave (decoder) to the master, but the master can not send data bytes to the slaves. A maximum of 128 slaves can be connected to the same master station. To determine which slave is allowed to send next (multiple access), the master sends sequences of 130 pulses. To allow slaves to detect the start of the pulse sequence, the master is silent for a period of 7ms. Each slave counts the number of pulses after the period of silence, and when this count corresponds to the RS-bus address of the slave, the slave starts sending a start bit followed by eight data bits (sending all bits takes 1,875 ms, which corresponds to 4800 baud). The master detects that the slave is sending, and transmission of the subsequent access control pulses is postponed till the slave is ready.
Data format: Although RS-bus slaves can send eight bits of user data, only four of these bits can be used for the actual feedback data. Such collection of four feedback bits is called a nibble. A track occupancy decoder that wants to send feedback information regarding eight tracks, should therefore send such information in two nibbles. The remaining four bits of each data byte are used for control purposes: the first bit determines the parity, the second and third bit determines the type of feedback decoder and the fourth bit determines whether the first or second nibble is being transmitted.
The fact that four feedback bits are included per data byte, may have unexpected side effects, particularly in case of switches. For details, see the page on RS-bus problems.

The software is  already included in the Switch decoder software, and can be downloaded from the switch decoder’s download section.

Note that this software uses the following AVR functions (8535, 16A, 32A, 164A, 324A, 644A and pin compatible AVRs):

  • PD2=INT0: used to receive RS-bus information from the command station
  • PD1=TXD/TXD0: used to send RS-bus information to the command station (UART / UART2)
  • 8-bit Timer/Counter2


The circuit is basically the same as the one described on the der-moba website (in German). To isolate the RS-bus from the rest of the decoder, two opto-couplers are being used.
The sender logic is isolated via a CNY17 (or equivalent) opto-coupler
, which drives a BC547 transistor. This combination acts as current source and takes 20 mA, as determined by the 33 Ohm resistor (since a 20 mA flow through the resistor creates a Basis-Emitter voltage of 660 mV). The current flow is switched on and off based on the value of RS_SEND.
The receiver logic acts as 3 mA current source. The description
on the der-moba website proposes a LM334 with an associated 22 Ohm resistor as current source (see also LM334 Version). It turns out, however, that the LM334 is quite susceptible to interference and therefore a better choice is to create a “standard” current source, using two transistors and resistors. The transistors are standard BC547 (or equivalents); the 220 Ohm determines the amount of current that flows (3 mA through 220 Ohm gives 660 mV). The second resistor is relatively uncritical and can be around 22 KOhm. As described on the der-moba website a zener diode of 5,6V is needed to “decouple” the receiver whenever the sender is active. The 1N4148 protects the circuitry against accidental interchanging the R and S signals. The opto-coupler at the receiver side is a PC817 or similar; note that it is also possible to use AC versions, such as the LTV814. The output of the opto-coupler (pin 3) is connected to an interrupt line of the micro-controller (RS_RECEIVE) and via a 1K5 resistor to GND.
DIL 28 socket is used to connect the RS-bus circuit to the decoder print.

A new version of the PCB is under construction and will be added later.

Receiver logic
Although the receiver logic seems relatively simple, certain aspects are still important. The Current Transfer Ratio (CTR) of the PC817 is specified between 50 and 600, depending on the exact model (PC817: 50-600 / PC817A: 80-160% / PC817B: 130-260% / PC817C: 200-400). If the CTR is low (thus 50), the
output current through the 1K5 resistor may not be sufficient to create a High (+5V) signal. In such cases the value of the output resistor could be increased. On the other hand, if the output resistor is increased, the response to fast changes gets worse.

The figure at the left below shows in white a resistor value of 1K5, versus a 1K value in purple. In the right figure the purple resistor value is 4K7.



LM334 circuit
The LM334 circuit is described on the der-moba website (in German).
The sender logic is isolated via a CNY17 (or equivalent) opto-coupler
, which drives a BC547 acting as 20 mA current source. The receiver logic acts as 3 mA current source, and uses a LM334 with an associated 22 Ohm resister to ensure that exactly 3 mA  flows through the LM334. Although usage of a LM334 as current source is quite common, it turned out that under certain circumstances  strange interferences occured (see below).

The PCB for the LM334 version has been designed in Eagle, and can be obtained from the download page. The figure below shows the component (left) and bottom side of the PCB (the PCB is two sided). The size is equal to a 28pin DIL socket.


Below a picture of the PCB, with all components mounted. The PC 817 is shown at the left, the LM334 and BC547 in the center and the CNY17 at the right. In addition, four resistors, one 5V6 zener diode, a 1N4148 normal diode and a 100nF capacitor are shown. Note that no SMD components are used, which means that building the board is quite simple.

LM334 interference

Although the LM334 version worked well on layouts where the decoder’s power supply was completely isolated from the DCC signal, massive interference occurred if an electrical connection existed between the decoder’s power supply and the DCC signal. Such connection is unavoidable  for feedback decoders, which use the DCC signal for power.
An example of such interference is shown below, as measured over the output resistor of the PC817 (thus the RS_RECEIVE signal that raises the AVR interrupts). The oscilloscope shows (part of the 130) RS-bus pulses generated by the master station; these pulses should be counted (raise AVR interrupts) by the decoders to determine when they are allowed to start sending. In principle all pulses should have the same length (width on the oscilloscope screen). As can be seen, some pulses are far too short and may fail to raise an interrupt. In the case of the white signal a LTV814 opto-coupler with 1K5 output resistor was used, the purple signal comes from an PC817 opto-coupler and 2K2 resistor. In both cases the RS-bus wiring represents a normal mid-size layout. Important is to note that the power source for the decoder, and thus the RS_VCC and RS_GND, comes from the DCC signal generated by the same master station that controls the RS-bus. Since opto-couplers are used to isolate the RS-bus from the remaining hardware, interference should not have taken place.

It turns out, however, that there is clear interference between the DCC power signal and the output of the receiving opto-coupler. This interference is not caused by crosstalk between DCC and RS-bus wires, but by the fact that the decoder is powered from the DCC signal. The problem is caused by the LM334, as can be seen in the figure below. In that figure for the white signal the LM334 is replaced by a traditional current source, consisting of two transistors plus resistors. For the purple signal the same reception hardware as above, thus a LM334, is used.


The software consist of two parts:

  • Layer 1, which is described in the file rs_bus_hardware.c.
  • Layer 2, which is described in the file rs_bus.c (or rs_bus_port.c, depending on the decoder).

Layer 1 takes care of all physical layer aspects, as well as the access control. Layer 2 takes care of initialization and formatting of the data bytes.

Overall operation

The interaction between both layers is illustrated in the figure below (note: although the figure shows some names specific for the Emergency-stop decoder, all decoders use a similar set-up).

Diagram to show interaction between both RS-bus layers

The top-part of the figure shows the variables and (function) calls specific for connecting the decoder to the RS-bus; the bottom-part shows the variables and calls specific for sending data bytes over the RS-bus.

To connect, three variables are used: RS_Layer_1_active, RS_Layer_2_connected and T_Feedback.

  • The RS_Layer_1_active flag is set whenever the hardware detects a valid signal (transition) on the RS-bus. If there is no signal (transition) for a period longer than 4 msec, the RS_Layer_1_active flag is cleared. This flag is checked by layer 2 before initialization / data transmission.
  • The RS_Layer_2_connected flag is set by layer 2 after it has established a “connection” to the master station. Connection establishment basically means that the RS-bus slave (the decoder) has transmitted the low and high order nibbles in two consecutive data bytes. The flag is cleared by layer 1 after 200 ms of silence on the RS-bus.
  • The T_Feedback timer is incremented by layer 1 every ms. It can be used by layer 2 for various purposes, for example to read the actual switch positions once every 30 ms.

Also for sending data three variables are used: RS_bus_address, RS_data2send_flag and RS_data2send.

  • The RS_bus_address variable is set by layer 2 and derived from the switch address / CV value. It is used by layer 1 while counting the number of access control pulses.
  • The RS_data2send_flag is set by layer 2 after to indicate that is has a data byte waiting in the RS_data2send variable.
  • The RS_data2send variable holds the data byte to be transmitted over the RS-bus. The byte holds a feedback nibble, and was formatted by layer 2.

Layer 1 operation

An interrupt (INT0) is raised at every transition of the RS-bus. If the master is polling, such interrupt occurs every 200 micro-seconds. One complete polling cycle consists of 130 interrupts. At each interrupt, the RS_address_polled variable gets incremented by the INT0-ISR. Once all feedback modules are polled, the master is idle for 7 ms. Such waiting period  allows all feedback modules to synchronize (which means, in our case, the RS_address_polled variable is reset to zero). To detect this idle timer, a timer of roughly 1 ms is running.  The ISR of this timer maintains a counter (T_RS_Idle), which is reset (by the INT0-ISR) every time a transition is detected at the RS-bus. If the counter exceeds 4, we know the   master station has been idle for more than 4 ms. The timer ISR sets, next to resetting the RS_address_polled variable, also theRS_Layer_1_active flag, to indicate a valid (or invalid) RS-bus signal is received. In addition, it increments the T_Feedback counter, which is used in rs_bus_port.c to determine the interval between successive feedback samples.

Feedback modules may send information back to the master once their address is called. The length of such information is 9 bits, and takes around 1,875 ms (4800 baud). During that period no RS-bus transitions will occur, which means that the T_RS_Idle counter  will not be resetted. Therefore the length of the timing interval to detect if the master is idle, should be between 1,875 ms and 7 ms. A value of 4 ms therefore seems save.

To send information back to the master, the process that uses these basic RS-bus routines initializes the RS_bus_address variable, assembles the data byte (RS_data2send) and,  once ready, sets the RS_data2send flag. Using a flag which the AVR can set within a single instruction, has as advantage that either all or none of the data will be send; it is not possible that the hardware starts sending data while the data byte is still being modified. The flag is tested, and the actual data transfer is performed, by the RS-bus ISR (INT0-ISR).  By initiating the actual data transfer from within this ISR, we ensure that: 1) data is send immediately after the feedback module gets its turn, and  2) it is not possible that more than one byte is send per cycle.

Layer 2 operation

After the decoder is switched on, the init_RS routine within the layer 2 software has to first initialize the RS-bus hardware. The init_RS routine therefore first reads the address of this decoder from its EEPROM, and checks whether this address does not exceed the maximum RS-bus address (the maximum decoder address is 256, the maximum RS-bus address is 128). Since feedback decoders should not send feedback information of multiple switches in a single nibble, the skip_even_addresses flag can be set if needed, as well as a variable telling how often feedback data should  be retransmitted (RS_tranmissions). Eventually the init_RS routine calls the layer 1 routines: init_rs_usart, init_rs_input_interrupt and init_timer2.

Every time the decoder’s main software loop calls the send_RS routine, the RS_Layer_2_connected flag is checked to determine if the decoder should first connect to the master station. If that is the case, the RS_connect routine is called, which establishes the connection by sending the low and high order nibble in 2 consecutive cycles.

If feedback data is available,
the send_RS routine calls the send_feedbacks routine, which fills in the four feedback bits (nibble). On its turn, the send_feedbacks routine calls the format_and_send_RS_data_nibble routine, to formats the data byte (RS_data2send) in accordance to the RS-bus specification (the parity, TT-bits, and nibble identifier).

Note that in case none of the feedback modules sends information, one complete polling cycle takes 33,1 ms.  On the other hand, if all feedback modules send information, one polling cyclus takes 33,1 + 128 * 1,875 = 273,1 ms. Since feedback modules can only send half of their data  (one nibble) during one polling cycle, roughly 550 ms are needed to send all changes.