4051 Tutorial. Edits Welcome

After googling “arduino 4051” and finding little I decided to try to make a “tutorial” to help get folks going faster. Let me know if you see any problems with the fritzing file, my code or it’s comments, really anything.

Running out of analog inputs? Try using a 4051 Multiplexer.

This project will show you how to connect an arduino (UNO R3) to a 4051, read all the pins, then print the data on the serial bus.

In my fritzing file I tried to color code the wires the best I could.
Red=Power
Black=Ground
Brown= 4051 Inputs
Blue=Digital
Yellow=Analog
Orange=AREF

I also wired/coded a TMP36 to input 0 of the 4051 to show one input being used for reference on where to put your code.

#define aref_voltage 3.3

void setup()    {      //4051 digital control pins      
pinMode(8, OUTPUT);    // s0      
pinMode(9, OUTPUT);    // s1      
pinMode(10, OUTPUT);    // s2      

Serial.begin(9600);
analogReference(EXTERNAL);
}    


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      

   float voltage = readInZero * aref_voltage;
   voltage /= 1024.0;
 
  // now print out the temperature
  float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                               //to degrees ((voltage - 500mV) times 100)
 
  // now convert to Fahrenheit
  float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
  Serial.print(temperatureF); 
  Serial.println(" degrees F");
  
  delay(10);


//repeat to read other pins (in this case analog in 1)
digitalWrite(8, HIGH);      
digitalWrite(9, LOW);      
digitalWrite(10, LOW);

delay(10);
int readInOne = analogRead(0);
Serial.print("Sensor 2=");
Serial.println(readInOne);


//(analog in 2)
digitalWrite(8, LOW);      
digitalWrite(9, HIGH);      
digitalWrite(10, LOW);

delay(10);
int readInTwo = analogRead(0);
Serial.print("Sensor 3=");
Serial.println(readInTwo);

//(analog in 3)
digitalWrite(8, HIGH);      
digitalWrite(9, HIGH);      
digitalWrite(10, LOW);

delay(10);
int readInThree = analogRead(0);
Serial.print("Sensor 4=");
Serial.println(readInThree);


//(analog in 4)
digitalWrite(8, LOW);      
digitalWrite(9, LOW);      
digitalWrite(10, HIGH);

delay(10);
int readInFour = analogRead(0);
Serial.print("Sensor 5=");
Serial.println(readInFour);


//(analog in 5)
digitalWrite(8, HIGH);      
digitalWrite(9, LOW);      
digitalWrite(10, HIGH);

delay(10);
int readInFive = analogRead(0);
Serial.print("Sensor 6=");
Serial.println(readInFive);

//(analog in 6)
digitalWrite(8, HIGH);      
digitalWrite(9, LOW);      
digitalWrite(10, HIGH);

delay(10);
int readInSix = analogRead(0);
Serial.print("Sensor 7=");
Serial.println(readInSix);

//(analog in 7)
digitalWrite(8, HIGH);      
digitalWrite(9, HIGH);      
digitalWrite(10, HIGH);

delay(10);
int readInSeven = analogRead(0);
Serial.print("Sensor 8=");
Serial.println(readInSeven);

delay(3000);  //wait three seconds
}

Hopefully this code and fritzing file can help someone get their project up and running a little faster!

4051.fzz (10.6 KB)

I would suggest that you take a more modular approach to it, so your code can be easily reconfigured and reused by others.

I would do something like this:

#define CD4051_S0  8 //cd4051 S0 on pin 8
#define CD4051_S1  10 //cd4051 S1 on pin10
...
#define CD4051_CH0 0x00 //cd4051 channel 0
...
#define CD4051_CH7 0x07 //ch4051 channel 7

#define CD4051_INH 12 //inhibit pin on cd4051

#define CD4051_ADCPIN A0 //cd4051 adc pin

//reset the pins
void cd4051Init(void) {
  pinMode(CD4051_S0, OUTPUT); //S0 as output
  pinMode(CD4051_S1, OUTPUT); //S1 as output
  ...
}

//select an input
void cd4051Select(unsigned char ch) {
  switch (ch) {
    case CD4051_CH0: digitalWrite(CD4051_S0, LOW); digitalWrite(CD4051_S1, LOW); digitalWrite(CD4051_S2, LOW); break; //select ch0
    case CD4051_CH1: digitalWrite(CD4051_S0, LOW); digitalWrite(CD4051_S1, LOW); digitalWrite(CD4051_S2, HIGH); break; //select ch1
    ...
    default: continue; //do nothing
  }
}

//read from cd4051
unsigned short cd4051Read(unsigned char ch) {
  cd4051Select(ch); //select the channel
  //now adc pin connected to the selected channel
  return analogRead(CD4051_ADCPIN); //read the adc
}

Once that’s done, all you need to do in your code is to call cd4051Read():

#define TEMP_CH CD4051_CH5 //temperature sensor on ch5 of cd4051

  temp_adc=cd4051Read(TEMP_CH); //read from the temperature sensor

All of this is to put a logical framework around the device and “box” its access to a few well defined modules so you don’t have to write code for it in the future.

If there is a picture attached, it is not working.

No picture attached, just a fritzing file. I’ll post a screenshot for you.

Some thoughts from the past.

Funny! I just had someone over and was explaining how I could cascade the chips out for even more inputs... then you post that.

andyfisk: Funny! I just had someone over and was explaining how I could cascade the chips out for even more inputs... then you post that.

You may want to search the forum for 4051 for previous discussions and thoughts.

The code for setting the multiplexer data select lines is VERY turgid.
Simplify it by reading this:-
http://www.thebox.myzen.co.uk/Tutorial/Arrays.html

Thanks for the link.

I knew there had to be an easier way. I'll take a look at my code and post a revision.

Thanks again for the help!