Cannot read voltages using a 74HC4067

Hi,

I am trying to read voltages (i.e. ADC input) using a 16 channel 74HC4067, which then should feed to an MCP3208.

It doesn't seem to pass the inputs through to the "Z" pin. Here's the code:

#include <MCP3208.h>
#include <SPI.h>tp
MCP3208 adc(15);


  float voltage = 0.0;            // calculated voltage
  float R1 = 330000;
  float R2 = 1000;
  float divider = 340  ; // 299.7012987;
  float  Vref = 4.095; // Using LM4040 reference voltage
  unsigned int total; // can hold max 64 readings

int s0 = 5;
int s1 = 4;
int s2 = 0;
int s3 = 2;


void setup() {
  adc.begin();
  Serial.begin(9600);
  Serial.println("Voltage monitor: MCP3208VoltMeter");
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);
  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
}

void loop() { 
  // MUX Connection
  for (int i = 0; i < 16; i ++) {

    //MCP3208 Code
    // take a number of analog samples and add them up
    for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
      total = total + adc.analogRead(0); // add each value to a total
    }
    voltage = (total / 64.0) * divider * Vref / 4095 ; // convert readings to volt

//   Serial.print("adc.analogRead(0) :");
//    Serial.println(adc.analogRead(0));


    Serial.print("Battery ");
    Serial.print(i);
    Serial.print(": ");
//    Serial.print(voltage);

 //   Serial.print(readMux(i));
    Serial.println("V");
    Serial.println();
      
  total = 0; // reset value
  delay(1000); // one second between measurements
  }

}




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
  };

  for (int i = 0; i < 4; i ++) {
    digitalWrite(controlPin[i], muxChannel[channel][i]);
  }

    for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
      total = total + adc.analogRead(0); // add each value to a total
    }
    voltage = (total / 64.0) * divider * Vref / 4095 ; // convert readings to volt

Serial.print("adc.analogRead(0) :");
Serial.println(adc.analogRead(0));
 Serial.print(voltage);
 Serial.println("V");

  // int val = adc.analogRead(0);
  int val = voltage;

  return val;
}

There's a 12V battery connected to Y0 (Battery 0), and this is the output:

Battery 15: adc.analogRead(0) :3200
2112.70V
2112V

Battery 0: adc.analogRead(0) :2798
2040.07V
2040V

Battery 1: adc.analogRead(0) :3015
1975.99V
1975V

Battery 2: adc.analogRead(0) :3016
2050.13V
2050V

What am I doing wrong?

RudiAhlers:
Hi,

I am trying to read voltages (i.e. ADC input) using a 16 channel 74HC4067, which then should feed to an MCP3208.

It doesn't seem to pass the inputs through to the "Z" pin. Here's the code:

There's a 12V battery connected to Y0 (Battery 0), and this is the output:

Your post make no sense!

WHAT is the "Z" pin?

"I am trying to read voltages (i.e. ADC input) using a 16 channel 74HC4067, which then should feed to an MCP3208"

WHY use a 74HC4067 and MCP3208... if its 16 channels you need why not just use 2 MCP3208 (8 ADC channels per chip)?

"There's a 12V battery connected to Y0 (Battery 0)"

Hope you are using a voltage divider! Maximum input to the MCP3208 is 5V assuming you are using a Vref of 5V

sherzaad:
Your post make no sense!

WHAT is the "Z" pin?

"I am trying to read voltages (i.e. ADC input) using a 16 channel 74HC4067, which then should feed to an MCP3208"

WHY use a 74HC4067 and MCP3208... if its 16 channels you need why not just use 2 MCP3208 (8 ADC channels per chip)?

"There's a 12V battery connected to Y0 (Battery 0)"

Hope you are using a voltage divider! Maximum input to the MCP3208 is 5V assuming you are using a Vref of 5V

This is the programming section, right? I wasn't aware of the fact that I need to explain the hardware associated as well....

I want to measure 16x 12V battery's voltages. So I need to split both the positive and negative rails. I have 2x 74HC4067, one feeding the negative rails, and another reading from the positive input.

Yes, there is a voltage divider in each circuit.

The 74HC4067 has 16x independent input or output pins, labeled Y0 to Y15, and a common input or output
labeled Z
See datasheet for more info: https://assets.nexperia.com/documents/data-sheet/74HC_HCT4067.pdf

RudiAhlers:
This is the programming section, right? I wasn't aware of the fact that I need to explain the hardware associated as well....

That's like saying you want a route from A to B without telling if you want to drive, sail, fligh etc... And if you read How to use the forum you would have known :wink:

But you can't use a 74HC4067 for that. Input voltage needs to be within 0 to Vcc. Aka, they don't give you isolation...

septillion:
That's like saying you want a route from A to B without telling if you want to drive, sail, fligh etc... And if you read How to use the forum you would have known :wink:

But you can't use a 74HC4067 for that. Input voltage needs to be within 0 to Vcc. Aka, they don't give you isolation...

Please explain?

How could I then use these 74HC4067 chips to measure the 16x batteries? The 16x 12V batteries are wired 4 batteries in series, for a 48V bank, and then 4x 48V banks in parallel. And I want to measure the 4 banks as well, though I don't have enough equipment for that right now.

Not. Not independent at least.

Connect pack GND to GND and connect all batteries via a (at least) 1:10 voltage divider. A downside is, you lose resolution because the full range becomes +-48V rather then +-12V.

septillion:
Not. Not independent at least.

Connect pack GND to GND and connect all batteries via a (at least) 1:10 voltage divider. A downside is, you lose resolution because the full range becomes +-48V rather then +-12V.

I don't want to do it that way, since if I take one battery out of the equation, it breaks the whole loop and I would have to either recode everything to work with say 3 batteries, or 8 if I decide to build a 96V string.

septillion:
Not. Not independent at least.

Connect pack GND to GND and connect all batteries via a (at least) 1:10 voltage divider. A downside is, you lose resolution because the full range becomes +-48V rather then +-12V.

or you could use the MCP3208 as a differential ADC to read across each battery (2 batteries per chip + voltage divider). check the datasheet to see how to use MCP3208 in differential mode

sherzaad:
or you could use the MCP3208 as a differential ADC to read across each battery (2 batteries per chip + voltage divider). check the datasheet to see how to use MCP3208 in differential mode

I had a look at that, but wasn't sure if it would still create a common ground?

I quickly looked at the MCP3208 and it's pseudo differential. The IN- must stay withing 100mV from Vss. Aka, not suitable to measure directly.

Nicest way, use a ADC per battery and isolate the digital side of things.

septillion:
I quickly looked at the MCP3208 and it's pseudo differential. The IN- must stay withing 100mV from Vss. Aka, not suitable to measure directly.

septillion:
So it can't measure a battery connected to IN+ and IN- ?

Nicest way, use a ADC per battery and isolate the digital side of things.

How? I see a lot of people say use opto-isolators, but I don't know which to use, that has a good linear scale. i.e. I want to see the difference between 12.50V and 12.52V on the battery

RudiAhlers:
Nicest way, use a ADC per battery and isolate the digital side of things.

How? I see a lot of people say use opto-isolators, but I don't know which to use, that has a good linear scale. i.e. I want to see the difference between 12.50V and 12.52V on the battery

you missed the important bit in septilion comment :"isolate the digital side of things" that means the ADC converted digital output