# How can I control 128 (or more) solenoids?

I need to switch 128 solenoids either on or off individually, several times a second. I'd like to drive this from either a PC, or an embedded device.

How would you recommend I do this? Perhaps there is a way I can enable addressing of a group of (8 or 16) solenoids and send a turn on, or turn off command to them?

Considering what's out there, what is the easiest way to go about this? What is the best or most preferred way?

I am looking at these solenoid valves that run at about $50 each. Do share information if you know of any cheaper/better ones. The purpose is to control an indoor waterfall. It's low-pressure so all the water drips downwards. • Need to know how big the solenoids are - voltage/current. – mikeselectricstuff Dec 5 '10 at 0:35 • I'm looking at these that draw 6 to 8W. If you know of a better/cheaper one that will control the release of water "droplets" do share.$50/per unit is expensive ascovalve.com/Applications/ProductSearch/… – halfbit Dec 5 '10 at 1:45
• Would a sprinkler valve work? Do you need the solenoid to use a 120V coil, or could you use a lower voltage (e.g. 6V, 12V)? – W5VO Dec 5 '10 at 4:42
• I can use a lower voltage... but a purely mechanical (non computer controlled) sprinkler valve probably won't cut it. What would determine my required voltage? – halfbit Dec 5 '10 at 4:57
• Sprinkler valves are not that simple. They actually won't work without significant pressure, and they take a while to close as well. – Connor Wolf Dec 5 '10 at 6:29

FTDI USB chip + daisy-chained '595 shift register. Put a separate transistor on each relay.

More detail:

A chain of 74hc595 is described here: http://www.arduino.cc/en/Tutorial/ShiftOut (Only two are shown, but the concept can be expanded to any number of '595s.)

To drive a the chain, three signals are needed, data, latch, and clock.

You can use an FTDI part in "bitbang" mode to generate three signals from computer control. To use the FTDI in bitbang mode, use libftdi (You could also use FTDI's official drivers, but libftdi is less hassle in my experience). A FT232R has enough pins to do this. FTDI sells a DIP breakout, and Sparkfun sells some breakouts too.

Notice you will need 128 2N2222s and 128 330 ohm resistors. (you can get resistor arrays that might be easier to manage.)

I've drawn the circuit assuming a 12V supply for your relays and no less than 24 ohm coils. If this is not the case, you might need a sturdier transistor or logic-level MOSFETs. The 2222 is about as cheap a transistor as you will find, and when you're buying 128 pieces that makes a difference.

I didn't show bypass caps or the exact 232R hookup. Read the datasheet.

OK, I just saw the solenoid you are trying to control. 2N2222 won't work. You need to switch 120VAC to the solenoid. So you can either have a small relay (with 2N2222) to switch the 120V, or use a solid-state relay that can take logic inputs and connect it directly to the '595 output.

OK, here's code to drive this using libftdi. Pin assigments in the source code. apt-get install libftdi-dev, then compile like this: "gcc test_595.c -lftdi"

/* This program is distributed under the GPL, version 2 */

#include <stdio.h>
#include <ftdi.h>

#define HC595_CT (1) // number of '595 chips

int main(int argc, char **argv)
{
struct ftdi_context ftdic;
int f,i;

unsigned char buf[2*8*HC595_CT+1]; // latch pulse, 8*HC595_CT clock pulses

if ((f=ftdi_init(&ftdic)) < 0)
{
fprintf(stderr, "ftdi_init failed\n");
return f;
}

f = ftdi_usb_open(&ftdic, 0x0403, 0x6001);

if (f < 0 && f != -5)
{
fprintf(stderr, "unable to open ftdi device: %d (%s)\n", f, ftdi_get_error_string(&ftdic));
exit(-1);
}

printf("ftdi open succeeded: %d\n",f);

// FTDI cable assignments:
#define BIT_DATA (1<<0)  // 1: orange. TXD, "data"
// 2: yellow. RXD, unused
#define BIT_CLOCK (1<<2) // 4: green. RTS, "clock"
#define BIT_LATCH (1<<3) // 8: brown. CTS, "latch"

ftdi_enable_bitbang(&ftdic, BIT_DATA | BIT_CLOCK | BIT_LATCH);

// set zero
*buf=0;
f = ftdi_write_data(&ftdic, buf, 1);

unsigned char *b=buf;

unsigned char data;
unsigned char state;

if (argc == 2) {
data=atof(argv[1]);
} else {
data=0x5a;
}

printf("sending data %d\n",data);

for (i=0; i<8; i++) {
state=(data & (128L>>i))?BIT_DATA:0;
*b++=state;
state |= BIT_CLOCK;
*b++=state;
}
*b++=BIT_LATCH;

f = ftdi_write_data(&ftdic, buf, (b-buf));

ftdi_disable_bitbang(&ftdic);
ftdi_usb_close(&ftdic);
ftdi_deinit(&ftdic);
}


And here's a picture of my test setup:

(I used the TTL-232R-3V3 cable.)

• I'm a bit new to all of this, and I'm self-teaching almost everything. Can you tell me a little more? IE specific products, or other tips. I'm browsing all the FTDI products now looking for the right USB solution. – halfbit Dec 5 '10 at 2:21
• I'll sketch the circuit for you later. – markrages Dec 5 '10 at 2:25
• FT245 is probably better than FT232 – Connor Wolf Dec 5 '10 at 6:31
• What advantage does the 245 give over the 232R? – markrages Dec 5 '10 at 16:02
• That solenoid comes in a wide variety of coil voltages, from 6V to 240V. I would probably pick the 12V coil, such as the 8262G002 12/DC. However, the 120V coil was 6-8W, so something a bit bigger than a 2n2222 might be safer. – W5VO Dec 5 '10 at 22:03

Cleaned Schematic with niceties (bypass caps, pin numbers, etc...):

With the FT245 you could use multiple shorter shift-register chains, since you have more IO.

I didn't draw it like that, but there you are. Anyways, the schematic is done in Altium Designer. If you want the schematic files, I can send them to you, but you need the software to open it.

• This is an improved schematic for markrages' answer, correct? You should probably just put it as an edit there. – Kevin Vermeer Dec 6 '10 at 6:15
• my sample code takes 1+2*8*N FTDI periods for a full shift. So sixteen 595's would take 257 periods. The FT232R just uses the async baudrate for clocking in bitbang samples. So at 115200 baud, a register update is 2.24 msec. – markrages Dec 6 '10 at 7:05
• Ideally, yes, but the USB interface is the slow part. I have a project based around a FT245 in bit-bang mode, and I get ~10 updates per second. Now, I'm doing this in python, so there is almost definitely some interpreter overhead, but I have trouble imagining you's get better than 1000 updates per second, considering each update takes a full USB packet. Unless you're doing something different in C than calling the FT_Write command from the driver, I can't see it being much faster. – Connor Wolf Dec 6 '10 at 9:20
• You know you can write more than one byte at a time, right? – markrages Dec 6 '10 at 21:06
• In bit-bang mode? No I didn't realize. Well, nevermind, then. Crap. – Connor Wolf Dec 7 '10 at 0:29

Is there some reason a 7 to 128 decoder wouldn't be appropriate? Using a FTDI chip and serial shift register seems like overkill.

• Yeah. with a pure decoder you can only open 1 valve at a time. – Connor Wolf Dec 5 '10 at 6:32
• How expensive are latching relays? – krapht Dec 5 '10 at 6:57

Whichever solution you end up using I would recommend taking a look at the power supply for this beast. You have the potential for really drawing a lot of current by accident (shorting out a transistor due to transient, a clock glitch setting a '1' to many, many outputs, etc.) -- Individual PTCs on each coil protects an individual coil, and I would also suggest either a low-ohm (0.1?) shunt resistor or a hall-effect current sensor which will cut power to the entire driver section if an overload is detected. An op-amp that integrates the overload over time is probably a good hardware trip design, but you can do it in a micro if that's your thing, too.

I would put 16 of these or something similar in series could drive. Not sure how you want to determine on/off but a low-end 8 pin PIC (

Matrix drive.

Mutiplex both your sources and sinks.

Connect the solenoids in arrays. ( rows & columns)

a lot less electronics.

Circuits can be like what's depicted, but you can get by with a lot less if you matrix it.

• This would allow addressing any single solenoid. But the OP wants to control all the solenoids at the same time. – markrages Feb 21 '11 at 2:39
• @markrages would a solenoid notice the difference ? – Tim Williscroft Feb 21 '11 at 3:27
• Let's see, let's say you have a 9x8 multiplex and drive the solenoid 1/9th of the time. With a catch diode on the solenoid, current can flow for a while, keeping the solenoid closed. Assume zero losses, then we want to put the equivalent energy into the solenoid as the solenoid's DC rating. So drive it with rated voltage * 9. (to get rated current, di/dt = v/L). So 24V solenoids would need 216V drivers. If you stay below the voltage where the coil arcs over this might work. – markrages Feb 21 '11 at 20:12
• LEDs are easily multiplexed because they are open circuit when reverse-biased. For solenoids, each will need a series resistor for this reason. – markrages Feb 21 '11 at 20:13
• @markrages: If each solenoid had both a series diode to the supply and a reverse-parallel catch diode, multiplexing should be reasonable, though 9:1 seems a bit much. My inclination, if the application would allow it, would be to use a 4:1 wired multiplex with 12.5% duty cycle for most solenoids; any row which had solenoids that were being newly energized would receive 62.5% duty cycle briefly. This would require slightly staggering solenoid "grab" operations, but would allow a nice reduction in circuitry. – supercat Mar 22 '11 at 15:45

For an alternative, if you've got a little funds to burn you could always invest in a Fez Domino and expand the I2C bus to 320 IOs.

The Fez Domino is and embeded C# device, however the IO board mentioned in the PDF uses a standard I2C bus which is common on most uCs.