Compacting Code

Hi, I have some IR sensors that I want to put through a single analog pin via a multiplexer 4051. I will eventually be wanting 20+ sensors so hence why I'm going down the multiplexer route.

I have some basic code to take readings through each multiplexed input but as I'm fairly new to programming I was wondering if this can be compacted down using for loops etc? I'm not sure if you can loop through different variables like the binary required to control the 4051?

int MuxPin0 = 14;
int MuxPin1 = 15;
int MuxPin2 = 16;
int TestPin = 17;

void setup() {
  pinMode(MuxPin0, OUTPUT);
  pinMode(MuxPin1, OUTPUT);
  pinMode(MuxPin2, OUTPUT);
  pinMode(TestPin, INPUT);

  int ReadAnalogueSensor();

}

void loop() {
  if (TestPin = HIGH)
  {
    ReadAnalogueSensor(5);
  }
}

void ReadAnalogueSensor(int aPin) {
  bool MUX01[] {LOW, LOW, LOW};   //0
  bool MUX01ON;
  bool MUX02[] {HIGH, LOW, LOW};  //1
  bool MUX02ON;
  bool MUX03[] {LOW, HIGH, LOW};  //2
  bool MUX03ON;
  bool MUX04[] {HIGH, HIGH, LOW}; //3
  bool MUX04ON;
  bool MUX05[] {LOW, LOW, HIGH};  //4
  bool MUX05ON;
  bool MUX06[] {HIGH, LOW, HIGH}; //5
  bool MUX06ON;
  bool MUX07[] {LOW, HIGH, HIGH}; //6
  bool MUX07ON;
  bool MUX08[] {HIGH, HIGH, HIGH}; //7
  bool MUX08ON;
  int AOut;
  int Threshold = 500;

  digitalWrite(MuxPin0, MUX01[0]);
  digitalWrite(MuxPin1, MUX01[1]);
  digitalWrite(MuxPin2, MUX01[2]);
  AOut = analogRead(aPin);
  if (AOut > Threshold)
  {
    MUX01ON = true;
    return MUX01ON;
  }
  digitalWrite(MuxPin0, MUX02[0]);
  digitalWrite(MuxPin1, MUX02[1]);
  digitalWrite(MuxPin2, MUX02[2]);
  AOut = analogRead(aPin);
  if (AOut > Threshold)
  {
    MUX02ON = true;
    return true;
  }
  digitalWrite(MuxPin0, MUX03[0]);
  digitalWrite(MuxPin1, MUX03[1]);
  digitalWrite(MuxPin2, MUX03[2]);
  AOut = analogRead(aPin);
  if (AOut > Threshold)
  {
    MUX03ON = true;
    return true;
  }
  digitalWrite(MuxPin0, MUX04[0]);
  digitalWrite(MuxPin1, MUX04[1]);
  digitalWrite(MuxPin2, MUX04[2]);
  AOut = analogRead(aPin);
  if (AOut > Threshold)
  {
    MUX04ON = true;
    return true;
  }
  digitalWrite(MuxPin0, MUX05[0]);
  digitalWrite(MuxPin1, MUX05[1]);
  digitalWrite(MuxPin2, MUX05[2]);
  AOut = analogRead(aPin);
  if (AOut > Threshold)
  {
    MUX05ON = true;
    return true;
  }
  digitalWrite(MuxPin0, MUX06[0]);
  digitalWrite(MuxPin1, MUX06[1]);
  digitalWrite(MuxPin2, MUX06[2]);
  AOut = analogRead(aPin);
  if (AOut > Threshold)
  {
    MUX06ON = true;
    return true;
  }
  digitalWrite(MuxPin0, MUX07[0]);
  digitalWrite(MuxPin1, MUX07[1]);
  digitalWrite(MuxPin2, MUX07[2]);
  AOut = analogRead(aPin);
  if (AOut > Threshold)
  {
    MUX07ON = true;
    return true;
  }
  digitalWrite(MuxPin0, MUX08[0]);
  digitalWrite(MuxPin1, MUX08[1]);
  digitalWrite(MuxPin2, MUX08[2]);
  AOut = analogRead(aPin);
  if (AOut > Threshold)
  {
    MUX08ON = true;
    return true;
  }
}

Thanks

for (byte i=0; i<8; i++) {
  digitalWrite(MuxPin0, i&1);
  digitalWrite(MuxPin1, i&2);
  digitalWrite(MuxPin2, i&4);
   // Now ready to read input i
}

int MuxPin0 = 14;
int MuxPin1 = 15;
int MuxPin2 = 16;

The pins are sequentially numbered - perhaps

int MuxPinx = 14

then MuxPinx++ to advance the loops.

Not sure if it saves much , but will make it less readable / debug.

Thanks guys for the quick replies.
This will help a lot.

Thanks.

I will also need to individually identify each sensor. What is the best way for this?
Maybe send the 'i' byte back on the return along with what analog pin? I'm just thinking that it might become confusing when I have a lot of multiplexers running at once. Is there a better way of doing this?

Identify the sensors by their address? You select a sensor by the multiplexer address and the analog input pin that the multiplexer output is connected to. Combine those numbers int an address and each sensor will have a unique identity. It’s not clear from your code what you are trying to do. You compare the input to a threshold and mark some inputs as “on” but it is not clear what you do with that data, if anything.

const byte MuxAddressPin0 = 14;
const byte MuxAddressPin1 = 15;
const byte MuxAddressPin2 = 16;


int TestPin = 17;


const byte InputsPerMultiplexer = 8;
const byte NumberOfInputs = 22;  // 20+
const byte NumberOfMultiplexers = (NumberOfInputs + InputsPerMultiplexer - 1) / InputsPerMultiplexer;


void setup() {
  pinMode(MuxAddressPin0, OUTPUT);
  pinMode(MuxAddressPin1, OUTPUT);
  pinMode(MuxAddressPin2, OUTPUT);


  pinMode(TestPin, INPUT_PULLUP);
}


void loop() {
  unsigned values[NumberOfInputs];


  for (byte i = 0; i < NumberOfInputs; i++) {
    values[i] = ReadAnalogueSensor(i);  // You don't need to store them in an array if you only need one at a time.
  }
  // Now that all the values have been read, do whatever you want with them.
}


unsigned ReadAnalogueSensor(int address) {
  // One analog input pin per multiplexer. First one on A0, second on A1...

  byte inputPin = A0 + (address / InputsPerMultiplexer);


  // Set the address bits of all of the multiplexers
  digitalWrite(MuxAddressPin0, address & 1);
  digitalWrite(MuxAddressPin1, address & 2);
  digitalWrite(MuxAddressPin2, address & 4);


  return analogRead(inputPin);
}

I will be using IR emitters and receivers to detect trains on a model set. I will have different blocks tell other trains to not go into those blocks.
So essentially when an IR receiver has an ON then Off signal that block is taken until the next sensor in the sequence is On then Off.

Below I have a SensorOn array that has the analog pin and the multiplexer address as well as its current state.
When programming the trains I guess I will use the information in SensorOn to store the On/Off state for each block in its own integer and have the train check the next block to see if it can proceed?

for (byte i = 0; i < 8; i++) {
    digitalWrite(MuxPin0, i & 1);
    digitalWrite(MuxPin1, i & 2);
    digitalWrite(MuxPin2, i & 4);

    AOut = analogRead(aPin);
    if (AOut > Threshold)
    {
      SensorOn[0] = aPin;
      SensorOn[1] = i;
      SensorOn[2] = 1;
      return SensorOn;
    }
    else {
      SensorOn[2] = 0;
    }
  }

So what you want to keep track of is which blocks are in use by a train (and which train) so you can keep two trains from sharing a block. Do you have sensors at each end of each block? You may want the train to 'reserve' a block if the block is not currently in use. That way you won't have two trains entering the block from opposite ends at the same time.