MUX Shield library

I was looking at the MUX shield from Mayhew Labs, Mux Shield | Mayhew Labs, and was thinking how great it would be if there was a library to access the pins with functions similar to digitalRead(), digitalWrite() and analogRead(). I have put together some functions in a sketch, as yet untested and was wondering if anyone could see any problems or suggest improvements for them. At the moment they only work for the first chip but if they are about right they could be expanded to run all 3 :slight_smile:

const byte control0 = 5; //S3
const byte control1 = 4; //S2
const byte control2 = 3; //S1
const byte control3 = 2; //S0

void setup(){
  pinMode(control0, OUTPUT);
  pinMode(control1, OUTPUT);
  pinMode(control2, OUTPUT);
  pinMode(control3, OUTPUT);
}

void muxDigitalWrite(int pin, int value){
  pinMode(14,OUTPUT);
  digitalWrite(control0, (pin&15)>>3); //S3
  digitalWrite(control1, (pin&7)>>2);  //S2
  digitalWrite(control2, (pin&3)>>1);  //S1
  digitalWrite(control3, (pin&1));     //S0
  digitalWrite(14, value);
}

int muxDigitalRead(int pin){
  pinMode(14,INPUT);
  digitalWrite(control0, (pin&15)>>3); //S3
  digitalWrite(control1, (pin&7)>>2);  //S2
  digitalWrite(control2, (pin&3)>>1);  //S1
  digitalWrite(control3, (pin&1));     //S0
  return digitalRead(14);
}

int muxAnalogRead(int pin){
  pinMode(A0,INPUT);
  digitalWrite(control0, (pin&15)>>3); //S3
  digitalWrite(control1, (pin&7)>>2);  //S2
  digitalWrite(control2, (pin&3)>>1);  //S1
  digitalWrite(control3, (pin&1));     //S0
  return analogRead(A0); 
}

I am definitely missing informative comments in your code

From the code I can conclude these are pinnumbers.

const byte control0 = 5; //S3
const byte control1 = 4; //S2
const byte control2 = 3; //S1
const byte control3 = 2; //S0

I'm not sure If these are user definable of fixed for the shield. If these are fixed you might use #define

#define CONTROL_0 5
etc

on the other hard it screams for an array

byte controls[4] = { 5,4,3,2} ;

void setup()
{
  for (byte i =0; i< 4; i++) pinMode(control[i], OUTPUT);
}

// avoid the repeating code
void muxSetPin(byte pin)
{
  for (byte i =0; i< 4; i++) digitalWrite(control[i], bitRead(pin, 3-i);  //something like that, 
 // NOTE reversing the pins in the control array could make it 
 // digitalWrite(control[i], bitRead(pin, i);
 // a better name for control could be addresPin ??
}

void muxDigitalWrite(int pin, int value)
{
  pinMode(14,OUTPUT);
  muxSetPin(pin);
  digitalWrite(14, value);
}

int muxDigitalRead(int pin)
{
  pinMode(14, INPUT);
  muxSetPin(pin);
  return digitalRead(14);
}

int muxAnalogRead(int pin)
{
  pinMode(A0, INPUT);
  muxSetPin(pin);
  return analogRead(A0); 
}

and next step is putting it in some Class.

Furthermore I was wondering how to control 48 IO lines with just 4 address lines ?

my 2 cents,

Here is the new variation on the code. Thanks for pointing out the problems. The address pins are user definable but are set for the shield. I have made them definable so that people can use this with any combination of the CD74HC4067 multiplexer chips. I have used const rather than #define because it is better according to the reference pages but does the same thing.

//Address pins S0, S1, S2, S3
//User definable but use 2, 3, 4, 5 for mux shield
const byte address[4]= {  2,3,4,5};
//Defines the number of CD74HC4067 chips being used
//Set to 3 for mux shield
const byte chips = 3;
//Mux is used later but needs to be a global variable
int mux;

void setup(){
  //Set address pins as output
  for(byte i = 0; i<4; i++){
    pinMode(address[i], OUTPUT);
  }
}

void muxSetPin(byte pin){
  mux = pin/16;
  pin = pin-(mux*16);
  for (byte i=0; i<4; i++){
    digitalWrite(address[i], bitRead(pin, i));
  }
}

void muxDigitalWrite(int pin, int value){
  //This section sets which of th MUX chips to send the data to
  for(byte i=0; i<chips; i++){
    if(i==mux){
      pinMode(14 + i,OUTPUT);
    }
    else{
      pinMode(14 + i,INPUT);
    }
  }
  muxSetPin(pin);
  //Writes a value to the appropriate chip
  digitalWrite(14 + mux, value);
}

int muxDigitalRead(int pin){
  //This section selects which chip to read from
  for(byte i=0; i<chips; i++){
    if(i==mux){
      pinMode(14 + i,INPUT);
    }
    else{
      pinMode(14 + i,OUTPUT);
    }
  }
  muxSetPin(pin);
  return digitalRead(14);
}

int muxAnalogRead(int pin){
  //This section sets which chip to read from
  for(byte i=0; i<chips; i++){
    if(i==mux){
      pinMode(A0 + i,INPUT);
    }
    else{
      pinMode(A0 + i,OUTPUT);
    }
  }
  muxSetPin(pin);
  return analogRead(A0); 
}

To address all 48 inputs/outputs the code has to find which mux chip that pin is on, resulting in the mux variable, then uses the 4 address lines to select which of the 16 pins on that chip it is. Hope this makes a bit more sense than the last one :slight_smile: