Troubles with CD4051 odd results and noise.

Hi, Fantastic community here.

I am new to Arduino and electronic, I don't have a great knowledge of coding however the Arduino reference has helped a lot and advice I have found on the forum.

I'm a little confused as to what is occurring when I try to use the multiplexer.
I want to read 8 18650 batteries using the CD4051 rather then use multiple Analog pins.

When I power the CD4051 directly off 5v, an with my multimeter (Fluke 1587) Connected to Com-Out everything works, when I test reading 1 battery on each PIN of the multiplexer the reported values to Serial are correct with some small noise.

example:
874,26,28,26,20,17,11,7,0
869,5,10,20,26,20,18,27,27
873,0,0,0,01,10,24,28

However, If I remove my multimeter from the circuit or switch it off, the reported results in the Serial are no longer correct, battery voltage is correct for the pin its connected, all other results are similar to the batteries reading as if it was connected to all pins.

I found code on the forum from user CrossRoads in regards to reading from 2 multiplexer chips and made adaptions to his code, however I'm failing to see the mistakes I may be making, I would like to read 3 multiplexers in my finished product but I'm struggling to start with 1.

Maybe I'm biting off more then I can chew here, but I thought it may be possible to power the CD4051 from a digital pin so I can turn it on and off when required however this gave me really bad results with 1.8-3.3v coming out the com-out with no battery connected to any gate of the multiplexer, I found when 1 controlPin is HIGH voltage out was 1.8v, then with 2 HIGH 2.8v, when all 3 HIGH 3.3v, this doesn't happen if I power off 5v rail.

//#define mux0 2
#define mux_A 22
#define mux_B 23
#define mux_C 24

byte controlPins[8] = {  // PORTA Pins 28-22 AD7-AD0 | 000, 001, 010, 011, 100, 101, 110, 111
  B00000111, B00000001, B00000010, B00000011, B00000100, B00000101, B00000110, B00000000};

int muxArray[8];
byte x;

void setup() {
  //pinMode (mux0, OUTPUT);
  pinMode (mux_A, OUTPUT);
  pinMode (mux_B, OUTPUT);
  pinMode (mux_C, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  for (x = 0; x < 8; x = x + 1) {
    PORTA = controlPins[x];
    //digitalWrite (mux0, HIGH);
    delay(100);
    muxArray[x] = analogRead(A0);
    muxArray[x] = analogRead(A0); // 2 reads to ensure voltage has time to settle thru analog mux
    //digitalWrite (mux0, LOW);
  }
  Serial.println ("values 0 to 7: ");
  for (x = 0; x < 8; x = x + 1) {
    Serial.println (muxArray[x]);
  }
  delay(2000); // dumb pause to keep from bombarding the PC too quick
}

Code commented out is what I was trying to use to power multiplexer from digital pin.

I hope someone can give me some tips and points in the right directions.

Thanks, all the best.

Kfo:
Maybe I'm biting off more then I can chew here, but I thought it may be possible to power the CD4051 from a digital pin so I can turn it on and off when required however this gave me really bad results with 1.8-3.3v coming out the com-out with no battery connected to any gate of the multiplexer, I found when 1 controlPin is HIGH voltage out was 1.8v, then with 2 HIGH 2.8v, when all 3 HIGH 3.3v, this doesn't happen if I power off 5v rail.

If I Write the digital pin HIGH outside the for loop, I get the same results as powering direct from 5v after testing now, same issue with having multimeter connected however.

You are working with high impedance circuits, this means the voltage do not necessary change when you remove the battery or switch to another channel. The multimeter is similar to a 10Mohm resistors and was pulling the input down.
Try connecting a 1Mohm resistor from analog input to gnd.

Please post a schematic. We need to see how you are writing things up to understand your code. Hand drawn is ok. If you use Fritzing, please use the schematic view, not the breadboard view.

Why are you accessing AVR ports directly? Its not the Arduino way, is not necessary for performance reasons in your application, and it's not something beginners should be attempting because of the side-effects it can cause.

How are pins 6, 7, 8 (DIP package) wired?
Do you have a 0.1uF cap from pin 16 to Gnd?

HKJ-lygte:
You are working with high impedance circuits, this means the voltage do not necessary change when you remove the battery or switch to another channel. The multimeter is similar to a 10Mohm resistors and was pulling the input down.
Try connecting a 1Mohm resistor from analog input to gnd.

Hi, thanks for your suggestion. This solved the problem, results are correct with/without multimeter. Thank you.

PaulRB:
Please post a schematic. We need to see how you are writing things up to understand your code. Hand drawn is ok. If you use Fritzing, please use the schematic view, not the breadboard view.

Why are you accessing AVR ports directly? Its not the Arduino way, is not necessary for performance reasons in your application, and it's not something beginners should be attempting because of the side-effects it can cause.

I would have to draw something, however the circuit is very simple at the moment. 1 CD405 1 Arduino 2560, Control lines A,B,C - 22,23,24, PINS 6,7,8 - GND, VDD - D2, Com-Out - A0.

I access the AVR directly because I found it the easiest way for me to understand how to change the control lines to follow the truth table for the multiplexer.

CrossRoads:
How are pins 6, 7, 8 (DIP package) wired?
Do you have a 0.1uF cap from pin 16 to Gnd?

http://www.ti.com/lit/ds/symlink/cd4051b.pdf

As per my code 22,23,24 so I could use PORTA.
I have now connected the 1M resistor as recommended.

I may have things sorted, now I will try to add a extra 4051

#define mux0 2
#define mux_A 22
#define mux_B 23
#define mux_C 24

byte controlPins[8] = {  // PORTA Pins 28-22 AD7-AD0 | 000, 001, 010, 011, 100, 101, 110, 111
  B00000000, B00000001, B00000010, B00000011, B00000100, B00000101, B00000110, B00000111};

int muxArray[8];
byte x;

void setup() {
  pinMode (mux0, OUTPUT);
  pinMode (mux_A, OUTPUT);
  pinMode (mux_B, OUTPUT);
  pinMode (mux_C, OUTPUT);
  Serial.begin(9600);
  digitalWrite (mux0, LOW);
}

void loop() {
  for (x = 0; x < 8; x = x + 1) {
    PORTA = controlPins[x];
    digitalWrite (mux0, HIGH);
    delay(100);
    muxArray[x] = analogRead(A0);
    muxArray[x] = analogRead(A0); // 2 reads to ensure voltage has time to settle thru analog mux
    digitalWrite (mux0, LOW);
  }
  Serial.println ("values 0 to 7: ");
  for (x = 0; x < 8; x = x + 1) {
    Serial.println (muxArray[x]);
  }
  delay(2000); // dumb pause to keep from bombarding the PC too quick
}

Ok, so I got things sorted an working how I want.

As a test I decided to read the multiplexer while I have its VDD LOW an I get bad results again, I was hoping for 0, or a little noise... is this due to the high impedance?

void loop() {
  for (x = 0; x < 8; x = x + 1) {
    PORTA = controlPins[x];
    digitalWrite (mux0, LOW);
    delay(100);
    muxArray[x] = analogRead(A0);
    muxArray[x] = analogRead(A0);

17:43:11.176 -> values 0 to 7:
17:43:11.176 -> 695
17:43:11.211 -> 734
17:43:11.211 -> 734
17:43:11.211 -> 769
17:43:11.211 -> 732
17:43:11.211 -> 769
17:43:11.211 -> 770
17:43:11.211 -> 795
17:43:13.963 -> values 0 to 7:
17:43:13.998 -> 691
17:43:13.998 -> 736
17:43:13.998 -> 732
17:43:13.998 -> 771
17:43:13.998 -> 740
17:43:14.033 -> 769
17:43:14.033 -> 767
17:43:14.033 -> 794
17:43:16.780 -> values 0 to 7:
17:43:16.780 -> 695
17:43:16.815 -> 737
17:43:16.815 -> 732
17:43:16.815 -> 769
17:43:16.815 -> 734
17:43:16.815 -> 770
17:43:16.815 -> 766
17:43:16.815 -> 795

I forgot to mention I have 1x 18650 connected to Pin 0 of the 4051 through the tests in my above post.

Vdd on a 4051 is the power supply pin, you cannot have that low, it means the chip is unpowered!

Yes I understand it would be unpowered, I thought this would be a way to switch to another 4051 sharing the same analog and controlpins to archive something like this for instance.

void loop() {
  for (x = 0; x < 8; x = x + 1) {
    PORTA = controlPins[x];
    digitalWrite (mux0, HIGH);
    muxArray[x] = analogRead(A0);
    muxArray[x] = analogRead(A0);
    digitalWrite (mux0, LOW);
    digitalWrite (mux1, HIGH);
    muxArray[x + 8] = analogRead(A0); 
    muxArray[x + 8] = analogRead(A0); 
    digitalWrite (mux1, LOW);
  }

Is what I'm trying to archive not possible, or am I just not going the right way to switch.

Kfo:
Yes I understand it would be unpowered, I thought this would be a way to switch to another 4051 sharing the same analog and controlpins to archive something like this for instance.

You use the Enable (E) pin for that, it is a bad idea to remove power from a chip that has signals on other pins.

HKJ-lygte:
You use the Enable (E) pin for that, it is a bad idea to remove power from a chip that has signals on other pins.

Aha, makes sense. I’m not with the project any longer, but I now know I need to hookup the inhibit pin to digital 2 so I can switch mux.

Thank you so much for the help.

I access the AVR directly because I found it the easiest way for me to understand how to change the control lines to follow the truth table for the multiplexer.

Your "truth table", if you look closely, is just an array containing the numbers 0 to 7. It is literally a waste of space (ram memory) because controlPins[0] == 0, controlPins[1] == 1 and so on up to controlPins[7] == 7. This should give you a strong clue that you don't need it, and a simpler way is possible.

PaulRB:
Your "truth table", if you look closely, is just an array containing the numbers 0 to 7. It is literally a waste of space (ram memory) because controlPins[0] == 0, controlPins[1] == 1 and so on up to controlPins[7] == 7. This should give you a strong clue that you don't need it, and a simpler way is possible.

Thanks for the tip, so I have made changes, hopefully I understood you correctly.

byte controlPins[8] = {0, 1, 2, 3, 4, 5, 6, 7};

hopefully I understood you correctly.

No, try again.