Remote buttons over Ethernet cable

Yet another easy, cheap and smart hack for a sort of remote, connected over Cat5 to a Pi or whatever with 2 GPIO.

Similar projects worth following
It's 4017 time !
I've always liked this decade counter that has so many uses... Here is one of them.
It synchronously scans a small keypad located tens (or hundreds ?) of meters away.
It is totally isolated for added safety.
It's connected to a Raspberry Pi but this could be any other programamble digital system.
The presented version can accomodate 9 buttons but more can be added when you cascade the 4017 (see the relevant datasheets).

The system has been installed in the Vallensbaek railway station for the YetiTV "a bouquet of pixels" art installation, that opened in january 2016. See it in action at

The circuit has been updated but here are the original design elements. Read the comments for more details :-)

So here is the old schematic:


Cheap. A CD4017 or 74HC4017 costs about 1$, add some "dust" (diodes, resistors) and a small PCB.

Simple and compact: yes too :-)

Low power: at most a few mA. (fail: the DC/DC draw much more, even unloaded)

Reliable: should be immune to EMI. Cat5 cable uses twisted pairs which should protect the signals over medium/long distances. A fluorescent lamp's ballast or other mains-conducted EMP could be picked up but should not disturb the system.

Easy to interface and program, with a robust algorithm that works even when the keypad is removed.

Wire-level Interface

The constraint is to read the buttons over existing Ethernel lines in a EMI-prone environment.

Many projects use a 74HC165 (for example this one ) but this method requires at least 2 control signals: PL (load data) then CP (clock pulse to shift data).

With the 4017, only one control signal is necessary: clock. This makes the system inherently more reliable (one point of failure less). Synchronisation is achieved by using one of the output signals, which will always be "on" (think about a serial link with a start bit that is on).

The 4 twisted pairs are used, one of the wire in each pair is tied to a common 0V/GND. The others are:

  1. 5V
  2. Clock
  3. Dout
  4. 5V

The original version is not isolated since there should be no electrical contact with anything else in the remote circuit. I added it anyway...

The 4017's clock input must be well filtered because any undesired pulse on this line would break the synchronisation. A RC filter + Schmitt trigger is used so far. This is less critical on the controller's side because the data is sampled just before changing the clock level, which happens at a pretty low frequency.

5V vs 3.3V

(moot: the optoisolators now remove this concern)

The Raspberry Pi is a 3.3V system but the 4017 is powered by 5V. Here is the trick:

  • The Ethernet cable has some inherent resistance that is proportional to its length. It should be about a few Ohms but it still counts.
  • The power supply of the remote board goes through a PN diode, which drops about 0.6 to 0.7V. A capacitor smoothes the voltage.
  • The 4017's pins have some inherent resistance too (resistance is futile but it's everywhere...)
  • The Dout signal goes through a diode, which drops another 0.7V.
  • At this point the voltage on a Dout signal can reach 5V-(2×0.6V)=3.6V. It is further reduced by a resistor network on the GPIO input: 1K Ohm in series and 5K of pull-down. The "on" signal is now around 3V.
The pull-down resistor value is chosen low to increase noise rejection. A current of 0.6mA flows when a button is pressed AND it is selected by the 4017, so this is the worst case power consumption(all buttons pressed at the same time). When no button is pressed, the "sync" signal will draw 0.06mA in average, and 0.12mA when one button is pressed.

A 100nF capacitor in parallel with the 5K pull-down will filter out some transients. As it is in series with the 1K resistor, the inrush current that charges it is limited.

For the 4017's clock input, the 5V supply wouldn't be usually compatible with the 3.3V GPIO signal. However, the margin is valid because of the diode drop: 5V-0.7V=4.3V, the Vih is usually 70% of Vcc, 4.3×0.7=3V, which is 10% lower than 3.3V.

Timing and algorithm

The keys are scanned at low speed, giving time to settle for all the electronics.

A polling routine is called at about 100Hz. This drives the clock output signal, so half the calls are just about changing the clock signal (there are 2 edges per cycle).

The other edge runs a software finite state machine, driving the synchronous bitstream, which works in either of two modes: scan or synchronisation.

  • Scan is the "normal" operating mode. The sync bit arrives at the expected moment (every 10 cycles) and the rest of the bits show which buttons are pressed.
  • If the remote is unplugged or being powered up (the filtering capacitor...
Read more »

  • 1 × CD4017 CMOS decade counter
  • 9 × push buttons or more
  • 2 × RJ45 connectors no magnetics inside
  • 1 × PCB one or two square inches
  • 1 × extension/prototype board for your MCU/Pi/controller

View all 8 components

  • Last notes

    Yann Guidon / YGDES02/13/2016 at 11:15 0 comments

      Before I forget, here are some more details.

      The system worked great, almost out of the box.

      For a better margin, I spied on the clock signal's waveform and the 'scope saw that the signal was too fast to go all the way to 0V so I slowed down the polling interval. The result was even better.

      The system is fully synchronous because the Finite State Machine is driven by a high-speed, high-priority event loop for real-time display. This adds quite some jitter to the clock signal. This is not important as long as the clock is delayed and not triggered earlier (hello POSIX !). Special care was taken in the code to preven "early switching" which would disrupt the communication pretty often.

      The rest of the code is a pretty standard Finite State Machine with 3 main states:

      1. init / desynchronised (waiting for the "1" marker)
      2. synchronising (waiting for a series of 9 "0"s)
      3. synchronised (running fine)

      Hysteresis has been added in the code to absorb any spurious signals.

      Oh, and there was even more fun tweaking the code to deal with multiple button presses!

  • Implementation

    Yann Guidon / YGDES01/21/2016 at 13:02 2 comments

    The system is coming together nicely :-)

    The two PCB have been soldered and tested, nothing special, except that I should have rotated the 4017 by 180°...

    Some SMD parts are needed, for example the LVC1G14:

    The cast aluminium box is solid and waterproof. A matching RJ45 plug completes the system:

    Who wouldn't want to press these lovely buttons ?

    Soon you'll enjoy them in Vallensbaek !

  • First signals

    Yann Guidon / YGDES01/17/2016 at 16:06 0 comments

    The pair of remotes seems to work at first power-up :-)

    I made a little script:

    echo 4  > /sys/class/gpio/export
    echo in > /sys/class/gpio/gpio4/direction
    echo 11 > /sys/class/gpio/export
    echo in > /sys/class/gpio/gpio11/direction
    echo 7 > /sys/class/gpio/export
    echo out > /sys/class/gpio/gpio7/direction
    while true
      # wrap around display so each round of 4017 is aligned
      for i in 1 2 3 4 5 6 7 8 9 10
        echo 1 > /sys/class/gpio/gpio7/value
        sleep 0.01
        echo 0 > /sys/class/gpio/gpio7/value
        sleep 0.01
        echo -n "   "$(</sys/class/gpio/gpio4/value)","$(</sys/class/gpio/gpio11/value)
    and the output is as expected !
    root@pi:/home/pi# ./ 
    (nothing connected)
    0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0  0,0
    (connecting one remote)
    0,0  0,0  0,0  0,0  1,0  0,0  0,0  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,0  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,0  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,0  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,0  0,0  0,0  0,0
    (connecting another remote)
    0,0  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    (pressing one button)
    0,1  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,1  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,1  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,1  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,1  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,1  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,1  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0
    0,0  0,0  0,0  0,0  1,0  0,0  0,1  0,0  0,0  0,0

    Now I have to write the sync algorithms and create FSMs in C...

  • Isolation

    Yann Guidon / YGDES12/01/2015 at 19:17 0 comments

    For extra safety, I'm wondering how to avoid damage to the host if "something" happened.

    Tiny isolated DC/DC converters exist. It would be too much a hassle to make mine again (been there, yada yada).

    Data isolation is another concern. It's a static design so no transformer is possible. An optoisolator is a good idea, or a more expensive isolator from ADi

    Safety first...

    I found the CNY17-2 in my archives but I still have to locate the DC/DC.

    The optoisolators change the signals that now work in current mode, so it's less sensitive to EMI. OTOH it increase the power consumption (but it's not critical).

View all 4 project logs

Enjoy this project?



Stuart Longland wrote 12/12/2015 at 03:00 point

Actually, if you sacrificed one button channel, you could convert this to be UART compatible.  If you made your SYNC a logic low, the last channel a logic HIGH and clocked it at 9.6kHz, you'd be able to read the stream straight off with a microcontroller UART.

You'd then be able to do away with the clock line.

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/12/2015 at 03:09 point

This is right. I have only 6 inputs to scan so it's possible. However:

* how do I create an accurate enough 9.6KHz (or less) clock ? RC won't do because of temperature sensitivity, and it needs to be CHEAP...

* I actually have 2 of these to manage with a RPi with only 1 serial input. Multiplexing serial ports is a tricky business...

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/12/2015 at 09:48 point

K.C. Lee : yes, i overlooked the CD4060 (which is silly considering my recent examination for the #Discrete YASEP). The chip is cheap and I got the 3.6864MHz crystals. I could get 900 or even 450 Bauds.

For more 2 sets of buttons, I meant that they are separate, in different wires, located far from each other. It would not be two sets if they were close : 3 chained 4017 would create a stream of two bytes very easily, with a hardwired marker for the first byte, MIDI style. No need of a MPU, I would save time by not programming anything ;-)

But the RPi has only one serial input and i see no "easy" way to safely switch from one input to another. At one moment or another, the controller has to use a control signal to say when to send data, to avoid a complex resynch routine.

  Are you sure? yes | no

K.C. Lee wrote 12/12/2015 at 05:32 point

It doesn't have to be 9600 as most UART these days have programmable baud rates and can go non-standard.  There are low frequency crystals starting from 20kHz and up.  I see 38.4kHz, 76.8kHz, 111kHz, 117kHz etc.  As for frequency, you can easily get away with 2% or so difference.

74HC4060 is a ripple counter with inverter oscillator front end that can be converted to a crystal oscillator to get you very stable low frequency.  But at some point,  a microcontroller might be a easier/cheaper way of doing this.  

BTW I use ADC to read my keys that are connected to a crude DAC using resistor dividers. They are usually good to 4-5 or so depending the ADC, resistor tolerance, noise etc.  So a remote switch could be as simple as a RG174 coax with a bunch of resistor networks on the far end. ESD/EMC get reduced to cap and may be diodes as we are talking about DC voltages.  :)

schematic: lower left corner on page 1.  Also saw that used on my old analog TV front panel switches. 2.1 Rel 0/Eagle PCB/Dual v12.pdf

  Are you sure? yes | no

Stuart Longland wrote 12/12/2015 at 05:42 point

Yeah, Yann made a valid point I hadn't considered: the desire for a low-cost oscillator that's accurate enough for serial.  Perhaps 9600 baud is a bit ambitious.  I just plucked it out of the air, being a commonly used signalling rate.

The standard rates go down to 300 baud, a 300Hz oscillator is probably far more doable cheaply.  I wasn't sure how accurate the oscillator needed to be, and of course, the faster you go, the harder that is to control.

As for two sets of buttons, if there's 7 or less on each, another hack could be done:

- Use the stop bit signal out of the decade counter to toggle a flip-flop.

- Feed the output of that flip-flop into a MUX: with the remaining bit in the data byte being fed by that same signal.

So then your host would receive:

Sbbbbbb0E Sbbbbbbb1E Sbbbbbbb0E … etc.

where S = start bit, E = end (stop) bit, b = button bit.  The 0 or 1 right at the end tells the host which set of switches has been read.

Alternative I just thought of: use a second 4017 clocked by the Q9 output of the first.  It basically provides a "column" output, and the first 4017 helps read the rows.

  Are you sure? yes | no

K.C. Lee wrote 12/12/2015 at 05:54 point

The lower frequency would work better for the passive optoisolators.  The frequency tolerance is usually around 2% or so. That gets a bit tricky as caps and RC oscillator aren't spec to that level without calibration.  There are usually calculation shown in the UART section of microcontroller datasheet.

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/08/2015 at 21:26 point

I have updated the schematics with a more accurate version. I hope it clears some misconceptions :-)

  Are you sure? yes | no

esot.eric wrote 12/05/2015 at 01:12 point

I haven't analyzed your circuit in detail, and this isn't exactly my area of expertise, but from what I understand "ground tied at both ends" == the very definition of a ground-loop... These things are great for coupling 60Hz right into low-(audio) frequency circuits, and elsewhere as well. 

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/05/2015 at 01:18 point

I might have used the wrong words then.

I meant the 0V of the circuit. The whole thing is isolated, there is no contact to local devices at the remote part. The 4 pairs are

* 0V-5V
* 0V-clk
* 0V-Dout
* 0V-5V

I now use optoisolators at the Pi side, and isolated DC/DC to provide the 5V. That circuit wastes 25mA already but... "it could be worse".

  Are you sure? yes | no

esot.eric wrote 12/05/2015 at 01:20 point

Actually, this looks quite a bit like MIDI... which of course is designed for similar circumstances. Only thing is, throw that clock optocoupler on the receiver-side, maybe?

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/05/2015 at 02:10 point

MIDI is unidirectional with one asynchronous serial stream.

This thing is bidirectional synchronous so it's not a lot like MIDI, but the comparison is interesting (and I use a lower frequency).

I *could* have used a serial asynchronous link but I need two of these in parallel, so it's better to poll during the idle times of my program...

I believe it's better to have all the optos at the same place. The voltage domains have a much clearer boundary. You wouldn't want to have the 0V of one device on one pair and the 0V of the other device on the other pair... MIDI does not power the devices, my thing is closer to the PS/2 interface (but much cruder and without the bidirectional gotchas, oh the memories...).

  Are you sure? yes | no

esot.eric wrote 12/06/2015 at 00:34 point

Righto! Actually, I've a CAT-5 cable-tester that uses a 4017 to cycle through each wire ;)

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/06/2015 at 15:14 point

Did I mention I like the 4017 ? ;-)

  Are you sure? yes | no

K.C. Lee wrote 12/05/2015 at 05:14 point

Don't worry too much about ground loops unless the area enclosed by the loop is large.  i.e. if the pairs runs all over the place separately, then that's where you pick up the noise.  Since they are in twisted pairs next to each other bundled under a PVC jacket into a cable, the amount to pick up is smaller.  

I am assuming that the keypad end is not grounded to some external earth ground.  Optos would break that external loop.

Also we are dealing with digital signals, so you'll get some noise margins between VIL(max) and VIH(min).

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/03/2015 at 23:21 point

Yay I found a pair of unused XP Power IE0505S from an old project :-) I'm doing the Pi board at this moment. I will implement full isolation, "juste because", with 2 remotes :-)

  Are you sure? yes | no

Chase Rayfield wrote 12/03/2015 at 18:35 point

Twisted pair is for balanced differential signals... it isn't buying you anything here if anything it could make it worse. A shielded cable might buy you some signal integrity but TP certain doesn't.

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/03/2015 at 18:56 point

Hi Chase,

I'm interested to know how it could be worse.

AFAIK twisted pair is not "bad" for unbalanced signals, it was already used in the 60s in the CDC6600 for example.

Twisted pairs increase EMF resiliance and it doesn't depend on the balance of the signal.

On top of that, this little project uses low frequency signals (a few KHz at most, with moderate edges) so reflection and EMI are an issue only at the 4017's clock input.

What do you believe are the failure modes of this system ?

  Are you sure? yes | no

K.C. Lee wrote 12/03/2015 at 19:53 point

If you have signal/gnd and signal/pwr pairs with decoupling caps at both ends of the connectors, that should provide good EMI as you are pairing the return current close to the signals.  Use series terminations at the drivers because the cable impedance is around 100 ohms.  

I do have some reservation on the driver/receiver types as you want hysteresis and definitely not a RC filter.

Things get bad if you have the signal/signal on a pair and power/gnd on the other pair.

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/03/2015 at 20:34 point

Hi K.C. :-)

As described in the project detail, each signal has its own GND in its pair so EMI resilience should be pretty good. There is also a pair of GND/VCC pairs for low impedence power supply. I usually decouple "a lot", I have reels of SMT ceramic capacitors to use :-) (is 22uF enough ?)

I intend to add a HC14 gate to add hysteresis at the 4017's clock input. The data output is sampled at low frequency and shouldn't create any problem. I'll check with the 'scope anyway.

Concerning the Ethernet wiring, it is already fixed and I can't change it. I'm fortunate it is done for me anyway and that I can pass any signal I need with a simple recabling in the patch bay :-)

  Are you sure? yes | no

K.C. Lee wrote 12/03/2015 at 21:19 point

My example is how to do it with the bare minimal pairs of wires.  The decoupling cap at either end of the connector "ties" the power and ground together via a low impedance, so that either one of them works well for providing a return path for your signals.

If you already have ground as the return pair, then that is very good.  Ground is where the logic thresholds are measured after all.

Decoupling usually means the small value caps (e.g. 0.1uF) for high frequency vs bulk for large values (e.g. 10u or 22u or 100uf etc) for big dips in the voltage.  Still worth while to use a lossy cap (e.g. electrolytic with some ESR) to damp out any spikes etc as you have the high Q MLCC without much loads (CMOS 4017) on that other end of a long cable.

  Are you sure? yes | no

esot.eric wrote 12/04/2015 at 22:56 point

For some reason this speaks to me of "ground-loop (antenna?)" but I'm not certain... 

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/05/2015 at 00:34 point


Each signal has its own pair with the ground tied at both ends, there are also 2 pairs with 5V and GND each.

Each pair has identical length, as well, and signals are slow. It shouldn't emit or receive much...

  Are you sure? yes | no

Yann Guidon / YGDES wrote 12/05/2015 at 00:39 point

My concern would be the clock signal that triggers a change on the data return signal, then inducing a signal on the clock line and triggering another clock pulse...

A RC network on the data out would reduce the risk, this moves the 1K resistor to the remote side and a little capacitor (some NF ?)

A low-pass on the clock input is still required, before a Schmitt trigger gate.

  Are you sure? yes | no

K.C. Lee wrote 12/05/2015 at 05:18 point

I guess with the Schmitt trigger, you wouldn't have to worry too much about the low rise/fall time, so you can probably get away with this.  The cable itself will have a lot of capacitance.
>Cat5 is 50 pF per meter

Your data line has its own twisted ground wire which is going to be carrying most of the return current.  Hopefully that would minimize the magnetic coupling to your clock/ground pair.  I don't usually deal with capacitive coupling as I like to keep my circuit impedance low.  That's probably where your external cap would help you.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates