How to properly read values from analog sensors trough multiplexer

analogarduinomultiplexer

I need to read several analog sensors on a Arduino Mega ADK. I want to use a multiplexer for this (CD74HC4067E), see the schematics.

The output however from the multiplexer channels is not consistent with the output which i read directly from on the analog input:

Through the Mux x: 333   y: 276  z: 323      Direct analog readings x: 328 | y: 334 | z: 285
Through the Mux x: 333   y: 276  z: 321      Direct analog readings x: 328 | y: 335 | z: 277
Through the Mux x: 334   y: 276  z: 322      Direct analog readings x: 329 | y: 335 | z: 277
Through the Mux x: 333   y: 276  z: 324      Direct analog readings x: 328 | y: 334 | z: 283
Through the Mux x: 333   y: 276  z: 299      Direct analog readings x: 329 | y: 335 | z: 282

ALthough it might seem that there is a wiring problem (simply switch X and Z), my setup is correct (triple checked!).

When i turn the sensor 90 degrees clockwise so that Y is up, i get the following:

Through the Mux x: 334   y: 344  z: 270      Direct analog readings x: 266 | y: 334 | z: 344
Through the Mux x: 334   y: 345  z: 269      Direct analog readings x: 265 | y: 334 | z: 344
Through the Mux x: 333   y: 343  z: 271      Direct analog readings x: 264 | y: 333 | z: 343
Through the Mux x: 335   y: 344  z: 270      Direct analog readings x: 265 | y: 334 | z: 344

so it seems that the X and Z pins should be switched.

I can i improve this?

And my arduino code:

//to hold direct read from the analog output of the ADXL335
int xAnaRead;
int yAnaRead;
int zAnaRead;

//to hold readings from the mux:
int xMuxRead;
int yMuxRead;
int zMuxRead;

//mux pins
int s0 = 8;
int s1 = 9;
int s2 = 10;
int s3 = 11;

//The pin on which the Mux outputs
int SIG_pin = A0;

//Analog read pins
const int xPin = A8;
const int yPin = A9;
const int zPin = A10;

void setup(){
  Serial.begin(9600);
}

void loop(){

  //read value on channel 0 of Mux
  xMuxRead = readMux(0);  
  //read analog value
  int xAnaRead = analogRead(xPin);
  delay(100); //to let the capacitator discharge

  //read value on channel 1 of Mux
  yMuxRead = readMux(1);  
  //read analog value
  int yAnaRead = analogRead(yPin);
  delay(100); //to let the capacitator discharge

  //read value on channel 2 of Mux
  zMuxRead = readMux(2);  
  //read analog value
  int zAnaRead = analogRead(zPin);
  delay(100); //to let the capacitator discharge


  //Output the readings
  Serial.print("Through the Mux x: ");
  Serial.print(xMuxRead);  
  Serial.print("\t y: ");
  Serial.print(yMuxRead);  
  Serial.print("\t z: ");
  Serial.print(zMuxRead);  

  Serial.print("\t\t Direct analog readings x: ");
  Serial.print(xAnaRead);
  Serial.print(" | y: ");
  Serial.print(yAnaRead);
  Serial.print(" | z: ");
  Serial.print(zAnaRead);
  Serial.println("");
  delay(100);//just here to slow down the serial output - Easier to read
}


//this is verbose but it works, and is more readable (i need that :)
int readMux(int channel){

  int controlPin[] = {
    s0, s1, s2, s3        };
  int muxChannel[16][4]={
    {
      0,0,0,0    }
    , //channel 0
    {
      1,0,0,0                }
    , //channel 1
    {
      0,1,0,0                }
    , //channel 2
    {
      1,1,0,0                }
    , //channel 3
    {
      0,0,1,0                }
    , //channel 4
    {
      1,0,1,0                }
    , //channel 5
    {
      0,1,1,0                }
    , //channel 6
    {
      1,1,1,0                }
    , //channel 7
    {
      0,0,0,1                }
    , //channel 8
    {
      1,0,0,1                }
    , //channel 9
    {
      0,1,0,1                }
    , //channel 10
    {
      1,1,0,1                }
    , //channel 11
    {
      0,0,1,1                }
    , //channel 12
    {
      1,0,1,1                }
    , //channel 13
    {
      0,1,1,1                }
    , //channel 14
    {
      1,1,1,1                }  //channel 15
  };

  //loop through the 4 sig
  for(int i = 0; i < 4; i ++){
    digitalWrite(controlPin[i], muxChannel[channel][i]);
  }
  //read the value at the SIG pin
  int val = analogRead(SIG_pin);

  //return the value
  return val;
}

Best Answer

You simply have switched Y and Z on the multiplexer.