0

I am using a Mega to control some relay boards. I have a 16 relay board near the mega, and I want to put an 8 relay board about 40 ft. away. So I figured I could use a shift register - instead of running 9 wires (8 relays and gnd) I could just run 4 (gnd, latch, clock, and data). I had some cat5e cable so I ran that from the Mega to the shift register. (I have an external 5V power supply so that does not come from the mega).

Problem is that is works, but inconsistently. I wrote a test program to turn on the relays in sequence. Sometimes it goes in order as it should but other times it skips relays or goes out of order.

I think there might be 4 sources of the problem:

1 The cat5e cable is too thin. Would a bigger wire help? Will twisting one pair together and using it like it was one wire help?

2 The shift_out code timing is off. I tried inserting some delay statments and that seemed to help a little. But I'm not sure where to insert them.

 void shift_out() {
     DigitalWrite(latch_pin, LOW);
     for (i = 0; i < 8; i++)  {
         DigitalWrite(data_pin, !!(bits & (1 << i)));
         DigitalWrite(clock_pin, HIGH);
         DigitalWrite(clock_pin, LOW);
     }
     DigitalWrite(latch_pin, HIGH);
 }

DigitalWrite is my own function that manipulates the PORTn bits instead of using Arduino's digitalWrite().

3 The shift register is very close to some 110V wires. Maybe interference?

4 The 5V power supply isn't powerful enough to power the relay board and the shift register?

Any suggestions welcome.

Edit: here's a pic of what I've built. The Cat5 cable runs directly back to the Arduino. enter image description here

  • Since cant5 has 8 wires, use multiple wires for GND and 5V. Add a large capacitor to the shift register to prevent voltage fluctuations when currents go up or down. Slow down shiftOut so the signal has more time to stabilize. – Gerben Dec 21 '16 at 8:58
  • @Gerben I think I will try the capacitor. This image from the Arduino web site uses one. They use 1uf. Is that "large" enough? – Johnny Mopp Dec 21 '16 at 18:04
  • NO! Don't do that. That capacitor shouldn't be there. That one of the many things wrong on the Arduino website. Just add a capacitor between GND and VCC. The largest value you have. As those relays use quite a bit of current when they get energized. – Gerben Dec 21 '16 at 19:22
  • What its the output voltage of that power-adapter? How is that even connected? I was thinking you could use that to power the relays, instead of carrying the 5V over that 40ft cat5 cable. – Gerben Dec 21 '16 at 19:25
  • @Gerben Yes, I am using that to power the relays and the shift register as I was not getting enough power from the Arduino. However, I just added a capacitor and preliminary testing indicates it has fixed my problem. If you write that up as an answer, I will accept it. I added it before I saw your comment about the Arduino web site. I will move it from the latch pin to the VCC pin and see what happens. – Johnny Mopp Dec 21 '16 at 20:35
1

SPI is supposed to be used for things in close proximity to each other. See Wikipedia - Serial Peripheral Interface Bus.

The Serial Peripheral Interface (SPI) bus is a synchronous serial communication interface specification used for short distance communication, primarily in embedded systems.

(My emphasis).

At that distance, and at standard SPI speeds you are probably losing signal integrity. The default SPI speed is system clock divided by 4 (that is, 4 MHz). It's not surprising some bits go missing after 40 feet.

See my page about SPI - you can use SPI to transfer to a 595 register (as described here).

(I'm assuming you are talking about a 74HC595 shift register)

I suggest running at a somewhat lower speed - insert delays after toggling the clock pin (each way). Or use the SPI hardware at (say) SPI_CLOCK_DIV128.


The shift register is very close to some 110V wires. Maybe interference

You might also want to look at a balanced line driver (eg. RS485) - I have a page describing that.


The 5V power supply isn't powerful enough to power the relay board and the shift register?

The register won't take much power. I trust the relays are solid-state ones and not coils that you are directly driving from the 595 chip?


Also see How do you use SPI on an Arduino?

  • I'm not using SPI, just connecting some of the digital outputs to the shift register. I guess I didn't make it clear in my post. I just made a circuit board with a SN74HC595N soldered on it with leads going back to the Arduino and going to the relay board. Sorry if the question wasn't clear - I'm just a hobbyist. – Johnny Mopp Dec 21 '16 at 18:02
  • I understand what you are doing. As you can see from my page about the 595 chip you can drive it with SPI so it is effectively equivalent. All SPI is, is a clock and a data line (and another data line in the other direction if you want it). Plus a slave select (ie. the same thing as the latch pin). My suggestion about slowing down the transfer rate still stands. – Nick Gammon Dec 21 '16 at 21:04
0

If nothing else works, consider a RS485 link. Nick Gammons forum has a useful and in depth tutorial on the subject. There is a bit of a hardware penalty - an additional Arduino or some other avr and a couple of RS485 driver chips, which is why I council "if nothing else works" in this case.

  • Nick posted an answer 2 days ago (from today, fri 23 Dec) also describing this option. This answer seems posted 1 day ago. If you think the same as an answer posted earlier, you can upvote it and if you have anything to add to it (without it being another solution) you can comment and/or edit the question. The problem here is that it's a bit like "spam" if everyone starts posting the same answer. Also, this would mean that votes get spread over good answers and may cause the best answer not to come up on top. – Paul Dec 23 '16 at 11:17
0

A good debugging tool in this case is a logic analyzer. It could help understand the timing characteristics for your code (and wiring).

void shift_out() {
     DigitalWrite(latch_pin, LOW);
     for (i = 0; i < 8; i++)  {
         DigitalWrite(data_pin, !!(bits & (1 << i)));
         DigitalWrite(clock_pin, HIGH);
         DigitalWrite(clock_pin, LOW);
     }
     DigitalWrite(latch_pin, HIGH);
 }

For instance, how long is the clock pulse? Does the data signal raise/fall correctly before the clock signal? What is the clock pulse frequency? How is it affected by the RC factor of the wiring.

Given that the signals are within limits you can add micro-second delays to compensate for propagation.

void shift_out() {
     DigitalWrite(latch_pin, LOW);
     for (i = 0; i < 8; i++)  {
         DigitalWrite(data_pin, (bits & (1 << i)));
         delayMicroseconds(T1);
         DigitalWrite(clock_pin, HIGH);
         delayMicroseconds(T2);
         DigitalWrite(clock_pin, LOW);
     }
     DigitalWrite(latch_pin, HIGH);
 }

Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.