how to get more arduino analog inputs

I needed extra analog inputs for an arduino project and it seems a multiplexer was the way to go.. It took a little while to sift through a heap of information on using a multiplexer with the arduino, and in the end I grabbed some 4051 ICs from Jaycar..

The 4051 allows you to choose between 8 analog inputs, reading them from just on arduino analog pin. (It can also be used in reverse, adding 8 analog outputs, but I am only interested in extra inputs for the moment)

** To hook it up to the arduio make the following connections: (the arduino pins are relatively arbitrary, though they are the ones used in the example code)

pin 3 : an arduino analog pin –  eg:  ANALOG IN PIN 0
pin 6,7 & 8 : all go to the arduino’s ground (Gnd)
pin 9 (s0): to arduino digital pin 10
pin 10 (s1): to arduino digital pin 9
pin 11 (s2): to arduino digital pin 8
pin 16 : to arduino +5V

** The rest of the pins on the 4051 (8 of them) are for the anolog inputs, as follows:

pin 1 : anolog input 4
pin 2 : anolog input 6
pin 4 : anolog input 7
pin 5 : anolog input 5
pin 12 : anolog input 3
pin 13 : anolog input 0
pin 14 : anolog input 1
pin 15 : anolog input 2

.


.

** Now in the arduino code you select which of the 8 analog inputs to read through arduino pin 1 but setting s0 , s1 and s2 to either low or high.

** S0 = 1 , S1 = 2 and s2 = 4

** so to read from analog input 0 (4051 pin 13) you would set s0,s1&s2 to low (0 + 0 + 0)

** to read from analog input 1 (4051 pin 14) you would set s0 to high and s1&s2 to low (1+0+0)

**and so on…
input 2 (pin 15):  L,H,L  (0+2+0)
input 3 (pin 12):  H,H,L (1+2+0)
input 4 (pin 1):  L,L,H (0+0+4)
input 5(pin 5):  H,L,H (1+0+4)
input 6 (pin 2):  L,H,H (0+2+4)
input 7 (pin 4): H,H,H (1+2+4)

** so while there is some fancy code around to read all of the inputs one after another in a for loop (see http://www.arduino.cc/playground/Learning/4051 it was this code that I found most confusing in understanding how the 4051 worked)

** all you really need to do is set the three arduino digital outputs to the correct setting for the analog input you want to read, then do an analogRead of pin 0

for example:

void setup()

{

  //4051 digital control pins

  pinMode(8, OUTPUT);    // s0

  pinMode(9, OUTPUT);    // s1

  pinMode(10, OUTPUT);    // s2

  Serial.begin(9600);

}

void loop()

{

  //Read Value of 4051 analog-in 0 by setting the values of s0,s1 and s2

  digitalWrite(8, LOW);

  digitalWrite(9, LOW);

  digitalWrite(10, LOW);

  delay(10); //not sure if this delay is strictly necessary

  int readInZero = analogRead(0);  // read the input pin

  Serial.print(readInZero); //use the result

   //repeat to read other pins (in this case analog in 2)

   digitalWrite(8, LOW);

   digitalWrite(9, HIGH);

   digitalWrite(10, LOW);

   delay(10);

   int readInTwo= analogRead(0);

   Serial.print(readInTwo);

   //etc. for the other 6 4051 analog inputs

}
Categories: tutorials & resources

9 Responses to “how to get more arduino analog inputs”

  1. Caesar P

    I have a question . With the multiplexed code above can I read any and all of the eight inputs. Let stay I have piezo sensors (8 on each multiplexer) would the code bet able to accept input from any of the piezos i hit. Or do I have manually select the pin I want to read? I see the code has some can of loop function is this scan all the pins and ready to read and of the inputs active? I and new to the arduino world and appreciate any advice you can offer.
    Thank you in advance

  2. andrew

    Hi,

    The loop function “void loop()” is where the guts of any arduino code goes. It simply loops through its instructions continually while the arduino is powered up.

    So what you need to do is hook up all 8 piezos using the input pins of the multiplexer, then in the loop function read each of these pins in turn. (by setting s0, s1 & s2 to high or low according to what pin you are up to reading)

    You cannot, in reality, read all of the 8 pins at once, you need to run through them in turn, but you do it fast enough that it makes no real difference to the user.

    basically what you will be doing to the code above is adding 6 more code segments like the following but changing the LOW and HIGHS and also changing the variable name for each to make it unique (ie: readInTwo). This will switch through the inputs reading them in turn. If it seems laggy i would try removing or shortening the delay

    digitalWrite(8, LOW);

    digitalWrite(9, HIGH);

    digitalWrite(10, LOW);

    delay(10);

    int readInTwo= analogRead(0); //change this variable name to be unique for each pin

    //do some stuff with the value you just got

    hope this helps
    andrew

  3. C#Bb

    Took me all night but here’s my understanding; special thanks to Andrew Burrell
    Edited cy Caesar Passee
    MUx A edited by pitchoilcan at geemail dot com
    void setup()  
    {
    //4051 digital control pins
      pinMode
    (8, OUTPUT); // s0
      pinMode
    (9, OUTPUT); // s1
      pinMode
    (10, OUTPUT); // s2
        Serial.
    begin(9600);
    }
    void loop()
    {
    //Read Value of 4051 analog-in 0 by setting the values of s0,s1 and s2
      digitalWrite
    (8, LOW);
      digitalWrite
    (9, LOW);
      digitalWrite
    (10, LOW);
      delay
    (10); //not sure if this delay is strictly necessary
    int readInZero = analogRead(0); // read the input pin
      Serial.print(readInZero); //use the result
    //
      digitalWrite
    (8, LOW);
      digitalWrite
    (9, HIGH);
      digitalWrite
    (10, LOW);
      delay
    (10);
    int readInTwo= analogRead(0);
      Serial.print(readInTwo);  
    //
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, HIGH);
    delay(10);
    int readInFour= analogRead(0);
    Serial.print(readInFour);
    digitalWrite(8, High);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    delay(10);
    int readInSix= analogRead(0); 
    Serial.print(readInSix);
    //
    digitalWrite(8, HiGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, HiGH);
    delay(10);
    int readInSeven= analogRead(0); 
    Serial.print(readInSeven);
    //
    digitalWrite(8, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, LOW);
    delay(10);
    int readInFive= analogRead(0); 
    Serial.print(readInFive);
    //
    digitalWrite(8, LOW);
    digitalWrite(9, HIGH);
    digitalWrite(10, HIGH);
    delay(10);
    int readInThree= analogRead(0);
    Serial.print(readInThree);
    //
    digitalWrite(8, HIGH);
    digitalWrite(9, Low;
    digitalWrite(10, HIGH);
    delay(10);
    int readInOne= analogRead(0);
    Serial.print(readInOne);

  4. andrew

    hi..

    There were some syntax errors in your code, but the following, assuming your hardware is wired up correctly, should work for you to read all 8 analog inputs of the 4051 from analog pin 0 on the arduino. If you wanted to read from 3 4051s then you just need to repeat the process in the loop, but using two other analog pins on the arduino..


    void setup()

    {
    //4051 digital control pins

    pinMode(8, OUTPUT); // s0
    pinMode(9, OUTPUT); // s1
    pinMode(10, OUTPUT); // s2

    Serial.begin(9600);
    }

    void loop()

    {

    //Read Value of 4051 analog-in 0 by setting the values of s0,s1 and s2
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    delay(10); //not sure if this delay is strictly necessary
    int readInZero = analogRead(0); // read the arduino input pin the 4051 is using
    Serial.println(readInZero); //use the result

    //Read Value of 4051 analog-in 1 by setting the values of s0,s1 and s2
    digitalWrite(8, HIGH);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    delay(10); //not sure if this delay is strictly necessary
    int readInOne = analogRead(0); // read the arduino analog input pin
    Serial.println(readInOne); //use the result

    //Read Value of 4051 analog-in 2 by setting the values of s0,s1 and s2
    digitalWrite(8, LOW);
    digitalWrite(9, HIGH);
    digitalWrite(10, LOW);
    delay(10);
    int readInTwo= analogRead(0);
    Serial.println(readInTwo); //use the result

    //Read Value of 4051 analog-in 3 by setting the values of s0,s1 and s2
    digitalWrite(8, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, LOW);
    delay(10);
    int readInThree= analogRead(0);
    Serial.println(readInThree); //use the result

    //Read Value of 4051 analog-in 4 by setting the values of s0,s1 and s2
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, HIGH);
    delay(10);
    int readInFour= analogRead(0);
    Serial.println(readInFour); //use the result

    //Read Value of 4051 analog-in 5 by setting the values of s0,s1 and s2
    digitalWrite(8, HIGH);
    digitalWrite(9, LOW);
    digitalWrite(10, HIGH);
    delay(10);
    int readInFive= analogRead(0);
    Serial.println(readInFive); //use the result

    //Read Value of 4051 analog-in 6 by setting the values of s0,s1 and s2
    digitalWrite(8, LOW);
    digitalWrite(9, HIGH);
    digitalWrite(10, HIGH);
    delay(10);
    int readInSix= analogRead(0);
    Serial.println(readInSix); //use the result

    //Read Value of 4051 analog-in 7 by setting the values of s0,s1 and s2
    digitalWrite(8, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, HIGH);
    delay(10);
    int readInSeven= analogRead(0);
    Serial.println(readInSeven); //use the result

    }

  5. Constantine

    Hi,
    I was wondering if this setup means that it would not be possible for arduino to read the input of 2 analog pins on the multiplexer at the same time.
    For example, if I connect 2 potentiometers to 2 pins of the multiplexer and turn them at the same time,would arduino successfully read both or that is not possible?
    Thanks in advance,
    Constantine.

  6. andrew

    It is not literally possible to read more than one of the multiplexer’s pins at once, but the loop happens so fast that you can turn the two (or more) pots at once and it will read them in turn but fast enough to act like they are all being read at once. (if it is still not quite fast enough look at removing or shortening the delay(10) in each of the ‘read’ code blocks in the sketch.)

    hope this helps, a

  7. David Early

    I have a requirement for 10 analog input for photocells. Any ideas on this?

    What additionalo IC to use for this?

    Thanks,

    Dave

  8. andrew

    Hi Dave,

    Sorry I missed your question back on September. For more than 8 analogue inputs, there are two solutions I can think of. One would be to use two multiplexer ICs on 2 separate arduino pins, or more simply if you really only need 10 inputs, run 8 through the multiplexer and the last two through 2 standard arduino analogue inputs.

    a

  9. Trent

    Hi Andrew, I build a controller with 32 pots connected to 4 multiplexers. I was wondering if you know how to properly transform these signals into a MIDI message. At the moment I can see all the pot values on the serial monitor, so I know they are properly connected. When I try to connect my controller through a midi device and into a DAW such as ableton or renoise, it responds as if I am turning every single knob at once without having touched them.

    If you could give me some advice that would be amazing. Thanks!

    const int Apin = 2;
    const int Bpin = 3;
    const int Cpin = 4;
    const int trigPin = 5;
    const int echoPin = 6;
    byte potVal;
    byte lastVal[32]; // store the latest value here if it’s different
    byte MIDIBuf[3];
    unsigned long duration;
    int controllerNumber = 0;
    #define CONTROLLER_CHANGE_STATUS 0xB0

    void sendMIDI(int ctlNum, int value);

    void setup(void)
    {
    digitalWrite(trigPin, LOW);

    pinMode(Apin, OUTPUT);
    pinMode(Bpin, OUTPUT);
    pinMode(Cpin, OUTPUT);
    pinMode(echoPin, INPUT);
    pinMode(trigPin, OUTPUT);

    Serial.begin(9600); // MIDI
    }

    void loop()
    {
    controllerNumber = 0;

    digitalWrite(trigPin, HIGH); // start trig pulse
    delay(1);//for (int i = 0; i < 20; ++i);
    digitalWrite(trigPin, LOW); // end trig pulse
    duration = pulseIn(echoPin, HIGH); // read width of echo pulse

    MIDIBuf[0] = CONTROLLER_CHANGE_STATUS;
    MIDIBuf[1] = controllerNumber;
    MIDIBuf[2] = duration;
    Serial.write(MIDIBuf, 3);

    for (int i = 0 ; i < 8; ++i)
    {
    digitalWrite(Apin, (i & 1));
    digitalWrite(Bpin, (i & 2));
    digitalWrite(Cpin, (i & 4));

    for (int analogPin = 0; analogPin >3)&0x7F; // force 7-bit
    controllerNumber++;
    if (lastVal[controllerNumber] != potVal)
    Serial.println(analogRead(0));
    delay(100);
    { // only send if changed
    lastVal[controllerNumber] = potVal;
    MIDIBuf[0] = CONTROLLER_CHANGE_STATUS;
    MIDIBuf[1] = controllerNumber;
    MIDIBuf[2] = potVal;
    Serial.write(MIDIBuf, 3);
    }
    }
    }
    }

×

Comments are closed.