100 Digital/Analog Outputs

A current project I've been working on is building an array of 100 electromagnets. Does anyone have any suggestions or experience with expanding my digital/analog outputs beyond my Arduino Uno? Any input is appreciated.

dailyinvention:
A current project I've been working on is building an array of 100 electromagnets. Does anyone have any suggestions or experience with expanding my digital/analog outputs beyond my Arduino Uno? Any input is appreciated.

You could use a series of latching SIPO shift registers (daisy chained); clock the data out, then latch the data over to the outputs (which would drive the transistors for the magnets). Do this in a looping fashion for a form of PWM, if needed. You could clock the data out using SPI, or bit-bang it using digital I/O pins (IIRC, the former is faster). Another possibility would be to hang SPI/I2C versions of such shift registers on the bus (it's all basically the same). Look into how large-scale 2D LED matrices are driven; basically its the same idea, although you would need to use more shift registers, and you don't have to worry about driving multiple rows - unless your electromagnets are arranged in a grid, then one of those matrix driver circuits might be the ticket (sub transistors for the LEDs, more or less)...

Sure, there's a Centipede shield that will give you more IO, up to 64 I believe.

Can use that same concept to make your board.
How much current is needed per electromagnet?
Maybe you could get by with a bank of 13 shift registers that can do >5v and higher currents, such as TPIC6B595.

String them in one long line, serial out to next serial in.
Connect SPI signals MOSI to the first serial in, SCK to all SRCK pins, and SS to all RCK pins.
Then do a bunch of serial transfers to control them:
digitalWrite (SS, LOW);
SPI.transfer(mag0-7data);
SPI.transfer(mag8-15data);
:
SPI.transfer(mag96-103data);
digitalWrite (SS, HIGH); // all outputs update at the same time with this clock edge

Can also break into smaller groups, give each its own SS line.

As an example here's 4 on a board to drive 12V LED strips that will be arranged as large 7-segment displays.

If you need even higher voltage & current, then use similar shift register concept and have their outputs drive beefier transistors (power N-channel MOSFET) to sink the electromagnet current. Or relays even if transistors won't cut it.

You could use latching multiplex chips. The below is for using a parallel port to control a lot of christmas lights, but a similar hardware setup using an arduino should be fairly easy.

http://computerchristmas.com/index.phtml?link=how_to&HowToId=4

Ok, thats just archaic zoomkat. Look at page 3: 46 chips to do that. That's just poor design and high power comsumption.

From that link

This is the place to be if you are looking for information about controlling Christmas light displays with a computer.

I assume that was written in the 80s and never updated :slight_smile:


Rob

I'm always up for a link to a modern how-to-do-it for controlling a lot of things individully. :slight_smile: I've tinkered with the 74HC259 chips in the past. One might control ~128 devices using 18 74HC259 chips and 10 I/O pins, or 16 74HC259 chips and two serial 8 bit shift register chips. That might be ~$10 investment in chips, plus the other hardware. What are the other suggestions?

What's wrong with a dozen Serial-in/parallel-out shift registers, and 3 IO pins? SCK, MOSI, and SS. Blast out a dozen bytes via SPI.transfer, be really fast. 96 control lines, updated very fast. Keep the state of the IO you want an array, simple loop to read/write that you hit every mS or something, spend the rest of the time reading other IO lines and updating the array for the next read/write cycle.
Shift register used depends on what you want to control, and loop callout on how often you want to update it.

CrossRoads:
What's wrong with a dozen Serial-in/parallel-out shift registers, and 3 IO pins? SCK, MOSI, and SS. Blast out a dozen bytes via SPI.transfer, be really fast. 96 control lines, updated very fast. Keep the state of the IO you want an array, simple loop to read/write that you hit every mS or something, spend the rest of the time reading other IO lines and updating the array for the next read/write cycle.
Shift register used depends on what you want to control, and loop callout on how often you want to update it.

I would think the the control programming might be more involved using all shift registers (build the control string for all devices for every change to a single device). I haven't used shift registers so I don't know if special pins on the arduino would be required. I can't see much different in power consumption between the serial chips and the 259 chips. I don't have links to the serial DIY page so maybe you can provide that for the OP. I to would like to see that methodology. I assume it is similar to the control of LED betabrite signs.

The 74HC259 lets you latch 1 bit of data at a time. Need 5 IO lines to do it.
Want to update 8 pins? Need 8 writes to the part.
Shift register: 2 IO lines. Want to update 1 bit? Use 1 SPI.transfer.
Want to update 4 bits? Use 1 SPI.transfer.
Want to update 8 bits? USe 1 SPI.transter.

Want to update 96 IO?
Shift register: 12 SPI.transfers.

74HC259: 96 writes, plus hardware to select from 1 of 8 chips, plus setting up address to downselect to 1 of the 8 chips, plus setting up the address for 1 of the 8 outputs.
Do able for sure.
Lot cleaner & faster to just update 12 bytes in array and then blast out 12 SPI.transfers.

"(build the control string for all devices for every change to a single device"

void loop(){
// check IO pins, update array [0-11] as needed
// set a flag if something was changed

// see if 10 mS (or whatever) elapsed, and if the array was updated, if so update the output:
// or just the flag & update when something changed.
currentMillis = millis();
if ( (currentMillis>=previousMillis) && arrayUpdateFlag == 1){
previousMillis = previousMillis + interval; // reset for next pass
arrayUpdateFlag ==0;  // reset for next pass
digitalWrite (SS, LOW);
for (x =0; x<12; x=x+1){
SPI.transfer( array[x] );
} // end 12-byte loop
digitalWrite (SS, HIGH); // all outputs udpated at once here.
} // end time check
// back to top for array update checking, time update
} // end loop

Done.

Interesting function. I assume by the below that the SPI pin would not be available for use with other devices requiring the SPI pin? Can the same be done just using the other available I/O pins on the arduino?

edit: also from the below, there appears to be some overhead of developing the required arrays. I assume one would start with 12 "all off" arrays and then modify each array as needed prior to submitting them the function.

SPI.transfer( array[x] );

SCK, MOSI, MISO go in parallel to ALL devices that need SPI. Each device then gets its own SS pin. SS can be any of the pins.

The array is just 12 bytes; your other code would read IO, interact with whatever, and set/clear bits/bytes as needed.
The same data would be developed for the 74HC295, becomes a matter of great convenience putting it in the array to send to the outputs.
Its just 1 array:
array[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; // set it up fill with zeros

array location 0 (array[0]) might be 8 bits with an LED for each one. Use BIT math manipulation to set & clear the bits:
if (digitalRead (switch0) == 1){
array[0] = array[0] | B00000001;} // set the bit high, leave the rest unchanged
else {
array[0] = array[0] & B11111110;} // clear the bit, leave the rest unchanged

Lots of ways exist to manipulat that byte.

array location 1 (array[1]) might be 8 bits that might sink a lot of current thru a coil, or electromagnet
:
:
arrray location 11 (array[11]) mightbe 8 bits doing who knows what.

there appears to be some overhead of developing the required arrays.

That would apply regardless of the hardware I would think.

This seems like a done deal, there is no high-speed requirement and only 100 outputs, use one of the '595 shift register variants, the 74HC595 or the TPIC6B595 if you need high current.

If you need really high current then a 74HC595 and some FETs.

However the subject is "100 Digital/Analog Outputs", I assume we really aren't talking about analog?


Rob

This seems like a done deal, there is no high-speed requirement and only 100 outputs, use one of the '595 shift register variants, the 74HC595 or the TPIC6B595 if you need high current.

Well, maybe. probably depends on what the OP has in mind. Is this serial control using SPI going to interfere with the operation of an ethernet shield if one wants to control 100 devices via a web page?

Is this serial control using SPI going to interfere with the operation of an ethernet shield

Yep, good point, we need to know more.


Rob

How would it interfere? Only have a single process architecture - so what's better, less time to drive the shift register and more time to deal with ethernet data,
or more time writing tons of inividual bits and less time for ethernet?

What happened to the OP? There was no mention of ethernet needed.

Thank you for your comments on this. I'm going to be ordering some components and doing some more experimentation. I'm rather new to this and I really appreciate everyone's help.

How would it interfere? Only have a single process architecture - so what's better, less time to drive the shift register and more time to deal with ethernet data, or more time writing tons of inividual bits and less time for ethernet?

Is that question supposed to be the answer for the below question?

Is this serial control using SPI going to interfere with the operation of an ethernet shield if one wants to control 100 devices via a web page?

Yes. I don't see multiple uses of the SPI port causing interfence problems.
The 3 pins go in parallel to all SPI devices, the indivual Slave Select lines ensure only 1 part does something with data going, or driving data back to the processor.