Item Description Supplier/Part No.
D1-D12 1N4001 Mouser 512-1N4001
JMPR1 0.1 SHUNT Mouser 517-950-00
Q1-Q12 2N3904 Mouser610-2N3904
Q13-Q24 TIP125 Mouser 512-TIP125
R1-R12 470 ohm Mouser 299-470-RC
R13-R24 1K ohm Mouser 299-1K-RC
R25 2.2K ohm Mouser 299-2.2K-RC
R26 10K ohm Mouser 299-10K-RC
RN1-RN2 8x10K, SIP Mouser 81-RGLD8X103J
SW1 6 mm NO Mouser 653-B3F-1022
TB1-TB13 0.2 Euro Mouser 571-2828362
X1-X8 0.1 M-STRT Mouser 517-6111TG*
PCB ExpressPCB
* The 517-6111TG is a 40-pin component; only two are
required for the project (split as needed).
◗ BILL OF MATERIALS
board receives the packet from an upstream device
(console or another unit) and uses the bytes intended for
this board while retransmitting all others. I believe this
design was intended to create a plug-and-play, auto-addressing scheme. You see, each controller is looking for
a specific two-byte sequence at the start of its data:
$7E $80 <dimmer data>
If we had two controllers in the system, we would see
something like this from the console:
$7E $80 <aaaaaaaa> $7E $81 <bbbbbbbb>
In the Renard system, the packet that follows $80 is
consumed locally and not retransmitted. When the second
address byte is ($81) received by the first controller, it is
decremented to $80 which enables the second packet for
the second controller. Downstream of the first controller,
the stream above becomes:
$7E $80 $7E $80 <bbbbbbbb>
As you can see, the first packet of dimmer values is
removed and the second address is decremented such
that it will be recognized by the second device in the
chain. The second device isn't bothered by the missing
packet data; the new SYNC byte that follows the address
byte resets everything internally.
With the large base of users, one can only assume
that the system has proven itself. My question became,
can I create a half-duplex (receive-only) device that would
work with the protocol? I think the answer is yes and I'm
going to show you what I did. From my view of the world,
the Renard protocol has three major states:
• Wait for sync byte ($7E)
To send the SYNC value as a dimmer level, it gets
encoded as two bytes: $7F, $30. What this means, then, is
that we need two-byte encoding for a $7F (ESC) dimmer
level — that would be $7F, $31. Finally, there is a "pad"
byte that may be sent by the console that is ignored by
the Renard device. To use the PAD value ($7D) in the
dimmer packet, it gets encoded as $7F, $2F.
Okay, then, let's give it a whirl. For most serial
applications, we can use the FullDuplexSerial object to do
the heavy lifting. Yes, we only need half duplex (reception)
for this project but FDS is still just fine. To set up FDS, we
will typically do something like this:
console.start(RX1, TX1, %0000, 115_200)
The serial object is called "console" and we're going to
receive at 115.2K baud on pin RX1 (the programming port
to make testing easy). The third parameter is the mode; in
this case, we're going with the standard true mode which
works with RS-485 devices, as well as USB-serial devices
like the Prop-Plug and the USB2SER.
And now for the fun! What I did is set up a simple
state handler to accommodate the rules defined for the
Renard protocol. Again, my code is just a "sniffer" (that is,
it doesn't retransmit anything) so it will be looking for an
address that could be something higher than $80 (which it
must be if there are standard Renard devices in use on the
same buss):
console.rxflush
state := W_SYNC
chan := 0
repeat
cmd := console.rx
case state
W_SYNC : if (cmd == SYNC)
state := W_ADDR
This is the basic setup and handling of the first state.
The receive buffer gets flushed after the serial object is
started just to make sure that there's no garbage in it. After
initializing the state and chan variables (which are local to
the method therefore must be manually initialized), we
drop into a repeat loop that will execute the state handler.
At the top of the loop, we receive a byte from the
console and drop into a case structure. The first task is to
look for the SYNC byte. When that happens, we can
advance the state to look for the address byte that
matches our board:
W_ADDR : if (cmd == PAD)
' ignore
elseif (cmd == SYNC)
' no change
elseif (cmd == ADDR)
state := W_LVL1
chan := 0
else
state := W_SYNC
In the W_ADDR state, the program is waiting for the
address byte, but other values could arrive and we need
to handle them. If a PAD ($7D) byte or another SYNC
byte arrives, there is no change in state. If the correct