(Newbie) Making a large 2x32 input- and 2x32 output- controller.

Hi,

Let me start of by saying that I'm an absolute beginner when it comes to Arduino, coding, logic and whatnot. I've tried to stay in my analog domain as long as possible, but now it looks like I have to surrender... :slight_smile:

I've been trying to come up with a solution for controlling a whole bunch of relays with a whole bunch of switches. This is the plan:

  • 32 switches each turning a relay on/off, switching audio between 2 destinations. These should act like a "solo" function, meaning only one will be active at any time.

  • 32 additional switches doing the same thing, although these should work independently of each other.

  • Each switch are momentary/non-latching and has a corresponding LED which should light up when the corresponding relay is on.

I've managed to do a version of this in very small scale with my Arduino Uno with 4 pushbuttons, a Darlington-array (ULN2003), 4 relays and 4 LEDs. So while I consider myself to have some basic knowledge of what's going on inside, scaling it up to 64 inputs and 64 outputs throws me off. Here's the code:

/* 4 switches selecting 1 output to be high, driving a ULN2003 with relay+LED
 */

int inPin1 = 2;         // the number of the input pin
int outPin1 = 8;       // the number of the output pin

int inPin2 = 3;         // the number of the input pin
int outPin2 = 9;       // the number of the output pin

int inPin3 = 4;         // the number of the input pin
int outPin3 = 10;       // the number of the output pin

int inPin4 = 5;         // the number of the input pin
int outPin4 = 11;       // the number of the output pin

int state1 = LOW;      // the current state of the output pin
int reading1;           // the current reading from the input pin
int previous1 = HIGH;    // the previous reading from the input pin

int state2 = LOW;      // the current state of the output pin
int reading2;           // the current reading from the input pin
int previous2 = HIGH;    // the previous reading from the input pin

int state3 = LOW;      // the current state of the output pin
int reading3;           // the current reading from the input pin
int previous3 = HIGH;    // the previous reading from the input pin

int state4 = LOW;      // the current state of the output pin
int reading4;           // the current reading from the input pin
int previous4 = HIGH;    // the previous reading from the input pin

long time = 0;
long debounce = 200;   // the debounce time, increase if the output flickers

void setup()
{
  pinMode(inPin1, INPUT);
  pinMode(outPin1, OUTPUT);
  pinMode(inPin2, INPUT);
  pinMode(outPin2, OUTPUT);
  pinMode(inPin3, INPUT);
  pinMode(outPin3, OUTPUT);
  pinMode(inPin4, INPUT);
  pinMode(outPin4, OUTPUT);
}

void loop()
{
{  reading1 = digitalRead(inPin1);

  if (reading1 == HIGH && previous1 == LOW && millis() - time > debounce) {
    if (state1 == HIGH)
      state1 = LOW;
    else
      state1 = HIGH;
      state2 = LOW;
      state3 = LOW;
      state4 = LOW;
      
    time = millis(); 
    
  }

  digitalWrite(outPin1, state1);

  previous1 = reading1;
}  
{  reading2 = digitalRead(inPin2);

  if (reading2 == HIGH && previous2 == LOW && millis() - time > debounce) {
    if (state2 == HIGH)
      state2 = LOW;
    else
      state2 = HIGH;
      state1 = LOW;
      state3 = LOW;
      state4 = LOW;
      
    time = millis();    
  }

  digitalWrite(outPin2, state2);

  previous2 = reading2;
}  
{  reading3 = digitalRead(inPin3);

  if (reading3 == HIGH && previous3 == LOW && millis() - time > debounce) {
    if (state3 == HIGH)
      state3 = LOW;
    else
      state3 = HIGH;
      state1 = LOW;
      state2 = LOW;
      state4 = LOW;
      
    time = millis();    
  }

  digitalWrite(outPin3, state3);

  previous3 = reading3;
}
{  reading4 = digitalRead(inPin4);

  if (reading4 == HIGH && previous4 == LOW && millis() - time > debounce) {
    if (state4 == HIGH)
      state4 = LOW;
    else
      state4 = HIGH;
      state1 = LOW;
      state2 = LOW;
      state3 = LOW;

    time = millis();    
  }

  digitalWrite(outPin4, state4);

  previous4 = reading4;
}
}

I've been trying to read up on shift registers and i2c port expanders, but it's unclear to me how to actually implement them in my code. Any tips or ideas on how to easily do that? I was hoping to be able to use an Arduino Mega from start, since the project started with just 16 ins/outs, but as everything doubled in size the pins on the Mega wasn't enough. That sucks, everything would have been very easy for me to look at and work with. I've looked around the forum but since I'm an idiot I'm having a hard time translating other peoples project into mine. So for a complete newbie, would you recommend going with shift registers or port expanders?

Thanks.

sounds like it would be possible to use two mega's and a few pins between them ?

Why relays? They are bulky, noisy, power-hungry and difficult to drive (most relays sold for Arduono use have a transistor driver built-in).

If you are switching audio signals, can you use analog switch ICs?

PaulRB:
Why relays? They are bulky, noisy, power-hungry and difficult to drive (most relays sold for Arduono use have a transistor driver built-in).

If you are switching audio signals, can you use analog switch ICs?

Well power won't be an issue here, I've made a pretty nice overspec'ed PSU for the whole thing. I want the most clean "true bypass"-like switching possible. I've designed a lot of audio gear before and I always end up with relays in quality-critical situations. Plus I kind of like the clicking :slight_smile:

a simple way to add digital IO to an arduino is to use IO expander sheilds based on I2C or SPI
there are also relay expanders, e.g.

https://shop.controleverything.com/products/16-channel-relay-controller-arduino-micro

horace:
a simple way to add digital IO to an arduino is to use IO expander sheilds based on I2C or SPI
there are also relay expanders, e.g.
https://www.seeedstudio.com/Relay-Shield-v3.0-p-2440.html
https://shop.controleverything.com/products/16-channel-relay-controller-arduino-micro

Yeah, I'm reading this ( How to Connect an MCP23017 I/O Port Expander to an Arduino ) now and actually starting to understand a bit how it works.

I looked at the relay expanders before but they are all pretty oversized for my needs. I will be using small signal miniature relays, don't need to switch high current devices such as lamps or motors.

What's the spec of these signal relays? Can you post a link to the data sheet?

You could maybe use tpic6c595 ICs to drive them in groups of 8. These are medium current shift registers and can be daisy-chained so that only 3 Arduino pins are needed.

You may also find a tpic chip useful for scanning your matrix of 64 buttons and LEDs. Post a link to the button/LEDs you plan to use.

Illuminated switches: http://www.mouser.com/ds/2/295/hbilluminated-7022.pdf
Relays: http://www.mouser.com/ds/2/212/KEM_R7001_EA2_EB2-1103823.pdf (EA2-5NU)

My plan is to use ULN2003 darlington array to drive the relays.

Looking at the datasheet for tpic6c595, it sure looks like it's capable of running all 8 outputs on with those relays and the LEDs in the switches simultaneously...

ondskan:
My plan is to use ULN2003 darlington array to drive the relays.

And what drives the ULNs? If the answer is 74hc595 or other I/o extenders, my suggestion of the tpic chips would half the number of chips.

PaulRB:
And what drives the ULNs? If the answer is 74hc595 or other I/o extenders, my suggestion of the tpic chips would half the number of chips.

Straight outta the Arduino right now, but I'm now looking at the MCP23017 as extender. The tpic sure looks interesting!

Driving the LEDs in parallel with the relay coils is a simple and obvious solution I hadn't even thought of! A lot of wiring, though.

I had imagined driving the LEDs and scanning the buttons as an 8x8 matrix, to keep the wiring simpler. I imagined another tpic chip to sink current from rows of 8 LEDs. Maybe use 8 Arduino output pins to drive the LEDs in each column and 8 Arduino input pins to detect the switch states in each column.

But there are other ways, such as using a max7219 to control the LEDs. But you would still need to scan the button matrix.