74HC4051 - Measuring 8 batteries

Good day,

For a project i need to measure the voltage of 8 batteries, since the Atmega1284 (which i am using for this) doesn't have enough analog inputs (it has 8 but i also need to connect other things to the analog input) i want to use a multiplexer to measure the 8 voltages.

I have bought the 74HC4051 multiplexer.

I have connected the multiplexer as this and connected 1 power supply as a test:

I use this code as a test:

/*
This code relies on the fact that PORTB on the ATMega328 chip has consecutive pins
which we can take advantage of to set the channel on the mux.
This code has been tested with Sparkfun's 16-ch mux (https://www.sparkfun.com/products/9056).
*/

#define MUX_CH_COUNT 8 // Reduce this number if you use less channels
#define PIN_D_MUX_S0 5  // bit 7 of PORTB  
#define PIN_D_MUX_S1 6  // bit 6 of PORTB
#define PIN_D_MUX_S2 7 // bit 5 of PORTB
#define PIN_A_MUX_SIG A0 // This pin will read the input from the mux. 

void setup() { 
  pinMode(PIN_D_MUX_S0,   OUTPUT);
  pinMode(PIN_D_MUX_S1,   OUTPUT);
  pinMode(PIN_D_MUX_S2,   OUTPUT);
  Serial.begin(9600);  
}  
  
void loop() {
  for (byte i=0; i<MUX_CH_COUNT; i++) {
    PORTB = (PORTB & B11110000) | i;
    short val = analogRead(PIN_A_MUX_SIG);
    // "val" holds the value for input "i", so you can insert your custom code here.
    
    // Print the values...
    Serial.print(i);    
    Serial.print(": ");
    Serial.print(val);
    Serial.print(" | ");    
  }
  
  Serial.println("");
  delay(1000);
}

The values which i am getting with the battery not connected is:

0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |

but somethimes i get something like this:

0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 178 | 1: 183 | 2: 185 | 3: 189 | 4: 187 | 5: 156 | 6: 161 | 7: 178 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 180 | 1: 168 | 2: 159 | 3: 161 | 4: 174 | 5: 176 | 6: 148 | 7: 143 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 1023 | 1: 1023 | 2: 1023 | 3: 1023 | 4: 1023 | 5: 1023 | 6: 1023 | 7: 1023 | 
0: 1023 | 1: 1023 | 2: 1023 | 3: 1023 | 4: 1023 | 5: 1023 | 6: 1023 | 7: 1023 | 
0: 1023 | 1: 1023 | 2: 1023 | 3: 1023 | 4: 1023 | 5: 1023 | 6: 1023 | 7: 1023 | 
0: 1023 | 1: 1023 | 2: 1023 | 3: 1023 | 4: 1023 | 5: 1023 | 6: 1023 | 7: 1023 | 
0: 1023 | 1: 1023 | 2: 1023 | 3: 1023 | 4: 1023 | 5: 1023 | 6: 1023 | 7: 1023 | 
0: 1023 | 1: 1023 | 2: 1023 | 3: 1023 | 4: 1023 | 5: 1023 | 6: 1023 | 7: 1023 | 
0: 1023 | 1: 1023 | 2: 1023 | 3: 1023 | 4: 1023 | 5: 1023 | 6: 1023 | 7: 1023 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 144 | 4: 173 | 5: 187 | 6: 181 | 7: 177 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |

When i connect the battery, i get values like this:

0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 132 | 1: 201 | 2: 160 | 3: 243 | 4: 288 | 5: 252 | 6: 278 | 7: 232 | 
0: 774 | 1: 756 | 2: 770 | 3: 785 | 4: 770 | 5: 746 | 6: 742 | 7: 764 | 
0: 140 | 1: 163 | 2: 126 | 3: 175 | 4: 238 | 5: 214 | 6: 263 | 7: 247 | 
0: 133 | 1: 147 | 2: 157 | 3: 144 | 4: 147 | 5: 134 | 6: 166 | 7: 194 | 
0: 782 | 1: 778 | 2: 771 | 3: 777 | 4: 773 | 5: 774 | 6: 783 | 7: 763 | 
0: 134 | 1: 152 | 2: 144 | 3: 132 | 4: 160 | 5: 156 | 6: 167 | 7: 224 | 
0: 764 | 1: 772 | 2: 785 | 3: 764 | 4: 779 | 5: 781 | 6: 752 | 7: 779 | 
0: 140 | 1: 137 | 2: 179 | 3: 149 | 4: 180 | 5: 153 | 6: 163 | 7: 210 | 
0: 794 | 1: 769 | 2: 763 | 3: 767 | 4: 782 | 5: 781 | 6: 776 | 7: 768 | 
0: 146 | 1: 156 | 2: 142 | 3: 149 | 4: 163 | 5: 145 | 6: 203 | 7: 228 | 
0: 154 | 1: 144 | 2: 160 | 3: 129 | 4: 764 | 5: 192 | 6: 748 | 7: 173 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |

What am i doing wrong? I expected to get the same values on 1 input (in this case 0 because i connected the battery to Y0.

Why do all the other numbers get values too, and why is the value for number 0 different every reading?

I only connected 1 battery to test, i am not sure if this causes the problem

Thanks for helping

Where do you select the port on the MUX? Can't see any place in the loop() function where you select it.

The only thing I see is

    PORTB = (PORTB & B11110000) | i;

but does that select the input pin on the MUX?

I used this example here: Arduino 16-Channel Analog Multiplexer Reading · GitHub

I don't know the function of that but i guessed it was to set a variable for somewhat

I guess it does. Have you tried controlling the MUX "manually" from the code (by using digitalWrite)?

You mean from this? Arduino Playground - 4051

I did but i am not really understanding what i am doing and what i should see,

if i print the results of r0, r1 and r2, i get these values:

r0: 1
r1: 0
r2: 0

r0: 0
r1: 1
r2: 0

r0: 1
r1: 1
r2: 0

r0: 0
r1: 0
r2: 1

r0: 1
r1: 0
r2: 1

r0: 0
r1: 1
r2: 1

r0: 1
r1: 1
r2: 1

r0: 0
r1: 0
...

Something like that.

I used a PCF8574 to control a 16 channel analog mux to read 16 different NTCs. The output of the analog mux was connected to one of the analog inputs on the Arduino.

#include "PCF8574.h"

#define MUX_I2C_ADDR    0x21
#define MUX_INPUT_PIN   A3


// Create objects for the I2C module controlling the MUX.
PCF8574 i2cMuxController = PCF8574(MUX_I2C_ADDR);

...

for (int port = 0; 16 > port; port++) {
  for (int i = 0; 4 > i; i++) {
    byte s = (port >> i) & 0b0001;
    i2cMuxController.digitalWrite(i, s);
    readValue = analogRead(MUX_INPUT_PIN);
    ...
  }
}

Modified version of you code. (Note: I have not tested the code - just edited your code in a text editor).

#define MUX_CH_COUNT 8 // Reduce this number if you use less channels
#define PIN_D_MUX_S0 5  // bit 7 of PORTB 
#define PIN_D_MUX_S1 6  // bit 6 of PORTB
#define PIN_D_MUX_S2 7 // bit 5 of PORTB
#define PIN_A_MUX_SIG A0 // This pin will read the input from the mux.

volatile uint8_t muxpins[] = {PIN_D_MUX_S0, PIN_D_MUX_S1, PIN_D_MUX_S2}

void setup() {
  pinMode(PIN_D_MUX_S0,   OUTPUT);
  pinMode(PIN_D_MUX_S1,   OUTPUT);
  pinMode(PIN_D_MUX_S2,   OUTPUT);
  Serial.begin(9600); 
} 
 
void loop() {
  for (byte i=0; i<MUX_CH_COUNT; i++) {
    for (byte j = 0; 3 > j; j++) {
      byte s = (i >> j) & 0b01;
      digitalWrite(muxpins[j], s);
    }
    short val = analogRead(PIN_A_MUX_SIG);
    // "val" holds the value for input "i", so you can insert your custom code here.
   
    // Print the values...
    Serial.print(i);   
    Serial.print(": ");
    Serial.print(val);
    Serial.print(" | ");   
  }
 
  Serial.println("");
  delay(1000);
}

Thanks for your help but the output i am getting with your example is:

0: 0 | 1: 0 | 2: 0 | 3: 30 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 33 | 4: 0 | 5: 0 | 6: 0 | 7: 29 | 
0: 0 | 1: 0 | 2: 0 | 3: 60 | 4: 0 | 5: 15 | 6: 154 | 7: 658 | 
0: 181 | 1: 245 | 2: 229 | 3: 270 | 4: 196 | 5: 214 | 6: 238 | 7: 677 | 
0: 10580 | 1: 0 | 2: 0 | 3: 54 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 909 | 1: 0 | 2: 0 | 3: 31 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 893 | 1: 0 | 2: 0 | 3: 33 | 4: 0 | 5: 0 | 6: 10 | 7: 51 | 
0: 0 | 1: 1 | 2: 0 | 3: 64 | 4: 0 | 5: 40 | 6: 166 | 7: 468 | 
0: 173 | 1: 250 | 2: 237 | 3: 265 | 4: 192 | 5: 214 | 6: 223 | 7: 531 | 
0: 0 | 1: 0 | 2: 0 | 3: 109 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 556 | 1: 0 | 2: 0 | 3: 38 | 4: 0 | 5: 0 | 6: 0 | 7: 2 | 
0: 0 | 1: 0 | 2: 0 | 3: 50 | 4: 0 | 5: 1 | 6: 21 | 7: 58 | 
0: 0 | 1: 8 | 2: 7 | 3: 73 | 4: 0 | 5: 111 | 6: 174 | 7: 408 | 
0: 166 | 1: 184 | 2: 240 | 3: 280 | 4: 242 | 5: 278 | 6: 300 | 7: 452 | 
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 14 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 
0: 0 | 1: 0 | 2: 0 | 3: 43 | 4: 0 | 5: 3 | 6: 19 | 7: 58 | 
0: 0 | 1: 8 | 2: 0 | 3: 71 | 4: 0 | 5: 177 | 6: 195 | 7: 143 |

no matter if i have a voltage on the pin or not, maybe my connection is not good?

bluebirdsoftware:
For a project i need to measure the voltage of 8 batteries...

I suppose you're not trying to measure eight voltages of a battery stack,
because that won't work with a 4051 muxer.
Leo..

No, i am trying to measure the voltage of 8 individual car batteries, i am using voltage dividers per battery.
I should be able to do that right?

bluebirdsoftware:
No, i am trying to measure the voltage of 8 individual car batteries, i am using voltage dividers per battery.
I should be able to do that right?

Yes. Individual, with common ground, is ok.
Just asking, because of previous posters not realising you can't simply measure cells in a battery stack.

You should divide to 2.56volt (not to 5volt), and use the (stable) internal 2.56volt Aref of the chip.
Leo..

bluebirdsoftware:
Thanks for your help but the output i am getting with your example is:

0: 0 | 1: 0 | 2: 0 | 3: 30 | 4: 0 | 5: 0 | 6: 0 | 7: 0 | 

0: 0 | 1: 0 | 2: 0 | 3: 33 | 4: 0 | 5: 0 | 6: 0 | 7: 29 |
0: 0 | 1: 0 | 2: 0 | 3: 60 | 4: 0 | 5: 15 | 6: 154 | 7: 658 |
0: 181 | 1: 245 | 2: 229 | 3: 270 | 4: 196 | 5: 214 | 6: 238 | 7: 677 |
0: 10580 | 1: 0 | 2: 0 | 3: 54 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |
0: 909 | 1: 0 | 2: 0 | 3: 31 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |
0: 893 | 1: 0 | 2: 0 | 3: 33 | 4: 0 | 5: 0 | 6: 10 | 7: 51 |
0: 0 | 1: 1 | 2: 0 | 3: 64 | 4: 0 | 5: 40 | 6: 166 | 7: 468 |
0: 173 | 1: 250 | 2: 237 | 3: 265 | 4: 192 | 5: 214 | 6: 223 | 7: 531 |
0: 0 | 1: 0 | 2: 0 | 3: 109 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |
0: 556 | 1: 0 | 2: 0 | 3: 38 | 4: 0 | 5: 0 | 6: 0 | 7: 2 |
0: 0 | 1: 0 | 2: 0 | 3: 50 | 4: 0 | 5: 1 | 6: 21 | 7: 58 |
0: 0 | 1: 8 | 2: 7 | 3: 73 | 4: 0 | 5: 111 | 6: 174 | 7: 408 |
0: 166 | 1: 184 | 2: 240 | 3: 280 | 4: 242 | 5: 278 | 6: 300 | 7: 452 |
0: 0 | 1: 0 | 2: 0 | 3: 0 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |
0: 0 | 1: 0 | 2: 0 | 3: 14 | 4: 0 | 5: 0 | 6: 0 | 7: 0 |
0: 0 | 1: 0 | 2: 0 | 3: 43 | 4: 0 | 5: 3 | 6: 19 | 7: 58 |
0: 0 | 1: 8 | 2: 0 | 3: 71 | 4: 0 | 5: 177 | 6: 195 | 7: 143 |




no matter if i have a voltage on the pin or not, maybe my connection is not good?

Have you tried to connect a multimeter to the output of the mux and manually measure the voltage?

About bad connections - do you use a solderless board and wires with pins? I have had some problems with bad connection when using solderless boards and wires.

0: 10580

How did that happen? digitalRead() returns maximum 1023.

I have no idea, i tried a lot of diffent examples but i keep getting random values.
Here is a picture of my project

I have nothing connected to the other input pins, only pin 1 has a voltage between 0v and 5v

Wawa:
You should divide to 2.56volt (not to 5volt), and use the (stable) internal 2.56volt Aref of the chip.
Leo..

What do you mean with this?

Maybe the connection wires are not okay, but if i push the wires into place or move them, i don't see any difference in the values

I am using this code now as a test:

const byte PIN_ADDR_A = 5; //S0
const byte PIN_ADDR_B = 6; //S1
const byte PIN_ADDR_C = 7; //S2
 
const byte PIN_SIG = A0;
 
void setup()
{
  
  // adress pins out and LOW
  pinMode(PIN_ADDR_A, OUTPUT);
  pinMode(PIN_ADDR_B, OUTPUT);
  pinMode(PIN_ADDR_C, OUTPUT);
  digitalWrite(PIN_ADDR_A, LOW);
  digitalWrite(PIN_ADDR_B, LOW);
  digitalWrite(PIN_ADDR_C, LOW);
 
  Serial.begin(9600);
}
 
void loop()
{
 
  for(byte i = 0; i < 8; i++)
  {
    Serial.print("Channel ");
    Serial.print(i);
    Serial.print(" : ");
    Serial.println(readAnalogMux(i));
  }
  Serial.println("-------------");
  
  delay(1000);
}
 
int readAnalogMux(byte channel)
{
  digitalWrite(PIN_ADDR_A, bitRead(channel, 0));
  digitalWrite(PIN_ADDR_B, bitRead(channel, 1));
  digitalWrite(PIN_ADDR_C, bitRead(channel, 2));
  return analogRead(PIN_SIG);
}

And this is my output

-------------
Channel 0 : 331
Channel 1 : 0
Channel 2 : 0
Channel 3 : 35
Channel 4 : 214
Channel 5 : 183
Channel 6 : 0
Channel 7 : 0
-------------
Channel 0 : 395
Channel 1 : 0
Channel 2 : 0
Channel 3 : 31
Channel 4 : 223
Channel 5 : 203
Channel 6 : 0
Channel 7 : 0
-------------
Channel 0 : 0
Channel 1 : 0
Channel 2 : 0
Channel 3 : 31
Channel 4 : 206
Channel 5 : 179
Channel 6 : 1
Channel 7 : 0
-------------
Channel 0 : 878
Channel 1 : 0
Channel 2 : 0
Channel 3 : 38
Channel 4 : 220
Channel 5 : 207
Channel 6 : 0
Channel 7 : 0
-------------
Channel 0 : 0
Channel 1 : 0
Channel 2 : 0
Channel 3 : 33
Channel 4 : 231
Channel 5 : 35
Channel 6 : 0
Channel 7 : 25
-------------

If i set voltage on the input pin i get values like this:

Channel 0 : 304
Channel 1 : 0
Channel 2 : 0
Channel 3 : 33
Channel 4 : 194
Channel 5 : 162
Channel 6 : 1
Channel 7 : 0
-------------
Channel 0 : 916
Channel 1 : 191
Channel 2 : 191
Channel 3 : 251
Channel 4 : 713
Channel 5 : 497
Channel 6 : 167
Channel 7 : 453
-------------
Channel 0 : 766
Channel 1 : 819
Channel 2 : 813
Channel 3 : 845
Channel 4 : 292
Channel 5 : 0
Channel 6 : 0
Channel 7 : 440
-------------
Channel 0 : 765
Channel 1 : 796
Channel 2 : 790
Channel 3 : 824
Channel 4 : 746
Channel 5 : 188
Channel 6 : 3
Channel 7 : 0
-------------
Channel 0 : 30
Channel 1 : 196
Channel 2 : 190
Channel 3 : 255
Channel 4 : 746
Channel 5 : 212
Channel 6 : 168
Channel 7 : 1
-------------
Channel 0 : 64
Channel 1 : 302
Channel 2 : 326
Channel 3 : 398
Channel 4 : 127
Channel 5 : 99
Channel 6 : 185
Channel 7 : 484
-------------

so at first it seems that it is measuring different data, but then it gets random again

Random data may indicate bad connection. I have had strange problems while testing sensors, LCDs and keypads due to bad connections in the type of wires as on the picture you posted.

You are using those cheap cables, and problems you will have. Test every single one before using, pull the pin, and if it staays, measure connectivity. They are total garbage.

Cheers,
kari

I agree about the Dupont style cables, they can be very unreliable.

Personally I use solid core wire, cut to length and laid flat on the breadboards, which I clip together. Takes longer to wire up, but, hey, how much time have you wasted already trying to get this circuit working? The wire is not wasted afterwards, pull them out in shape, keep them in a jar and re-use them on your next prototype (you will find you use certain lengths very frequently).

Here's one of mine as an example of what I'm describing. I'm quite "OCD" about keeping things neat and using wire colours consistently. This pays back in time saved debugging circuits.

I noticed, on your pictures, I can't see any bypass caps on either the atmega or the multiplexer chip. They may not fix the problem, but you should always have them, and never waste time looking for other problems until you have bypass caps fitted.

I think a bad connection is a possibility, do you think the rest of the scheme is okay? And is it okay to not connect all the other inputs? Because i want to measure maximum of 8 batteries but not always 8 at the same time

I will make the same connections as yours PaulRB, which cable do you use, regular cable or special cable for this?

Thanks for helping everyone

PaulRB:
I noticed, on your pictures, I can't see any bypass caps on either the atmega or the multiplexer chip. They may not fix the problem, but you should always have them, and never waste time looking for other problems until you have bypass caps fitted.

What exactly do you mean with this?

The wire I use is solid core hook-up wire, 22 or 24 AWG, 1/0.6mm. You will need a wire stripper and small pair of pliers to use it.

bluebirdsoftware:
What exactly do you mean with this?

I mean you should have bypass caps fitted. 0.1uF ceramic, one close to each Vcc pin of each chip. On my picture, you can see them on the power bus at the bottom right of the breadboard.