1

I hope I can get some help on how to get this to work.

I have multiple Sensors (32 of these) which values I want to read. I am using a master multiplexer HC4051 connected to 4 slave multiplexers, this is my wiring: [here][1]

I tested it using one single multiplexer and it works as intended, but when adding the slave I cannot getting it to work, I am not sure how to code for it.

When using this code:

// 74XX4051 ADDRESS PINS :
#define  M_S0 2
#define  M_S1 3
#define  M_S2 4

#define  S_S0 7
#define  S_S1 6
#define  S_S2 5

// 74XX4051 ANALOG PIN :
#define  Z 0

void setup() {
    // CONFIGURE ADDRESS PINS
    pinMode(M_S0, OUTPUT);
    pinMode(M_S1, OUTPUT);
    pinMode(M_S2, OUTPUT);

    pinMode(S_S0, OUTPUT);
    pinMode(S_S1, OUTPUT);
    pinMode(S_S2, OUTPUT);

    // CONFIGURE SERIAL
    Serial.begin(57600);
}

void loop() {
    int value;

    // LOOP THROUGH ALL THE ADDRESSES OF THE MASTER 
    for ( byte count = 0; count < 4 ; count++ ) {
         // SET THE ADDRESS
         digitalWrite(M_S0, bitRead(count, 0) );   
         digitalWrite(M_S1, bitRead(count, 1) );
         digitalWrite(M_S2, bitRead(count, 2) );

         // LOOP THROUGH ALL THE ADDRESSES OF THE SLAVES
         for ( byte count_1 = 0; count_1 < 32 ; count_1++ ) {
             digitalWrite(S_S0, bitRead(count_1, 0) );
             digitalWrite(S_S1, bitRead(count_1, 1) );
             digitalWrite(S_S2, bitRead(count_1, 2) );

             // READ THE ANALOG VALUE
             value = (bitRead(count_1, 2), bitRead(count_1, 1), bitRead(count_1, 0));
         }

         // READ THE ANALOG FOR THE MASTER ADRESSE
         value = analogRead(Z);

         // SERIAL OUTPUT
         // print : ### value
         Serial.print(bitRead(count, 2));
         Serial.print(bitRead(count, 1));
         Serial.print(bitRead(count, 0));
         Serial.print(' ');
         Serial.println(value);

         delay(100);
     }
}

I am only getting random readings really (the reading LED for the moisture sensor does not switch on when the reading is done).

What I am doing wrong? Any help is appreciated.

UPDATE:

i updated my code as follows :

// Master moisture sensor pins
#define  M_S0 7
#define  M_S1 8
#define  M_S2 9
// Slave moisture sensor pins
#define  S_S0 4
#define  S_S1 5
#define  S_S2 6

// PIN from the transistor to power the sensors only when doing a reading
int sensorVCC = 13;

//  ANALOG PIN :
#define  Z 0

void setup() {
    Serial.begin(9600);
    // CONFIGURE ADDRESS PINS
    pinMode(M_S0, OUTPUT);
    pinMode(M_S1, OUTPUT);
    pinMode(M_S2, OUTPUT);

    pinMode(S_S0, OUTPUT);
    pinMode(S_S1, OUTPUT);
    pinMode(S_S2, OUTPUT);
    pinMode(sensorVCC, OUTPUT); 

    digitalWrite(sensorVCC, LOW);
}

void loop() {

    // LOOP THROUGH ALL THE ADDRESSES OF THE MASTER 
    for (int i = 0; i < 32; i++) {
    digitalWrite(sensorVCC, HIGH);
    delay(100); //make sure the sensor is powere

    digitalWrite(M_S2, i & 0b100000);
    digitalWrite(M_S1, i & 0b010000);
    digitalWrite(M_S0, i & 0b001000);        
    digitalWrite(S_S2, i & 0b000100);
    digitalWrite(S_S1, i & 0b000010);
    digitalWrite(S_S0, i & 0b000001);



    delay(1);


    int humidityRaw = analogRead(Z); // 1023 to 0 ===> 0 to 100%
    int humidityReal = map(humidityRaw, 975, 523, 0, 100);
    digitalWrite(sensorVCC, LOW);  

    Serial.print("Input ");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(humidityReal);
    Serial.println(" % ");
    delay(1000); 
}
}

and this is my output :

    Input 0: 100 % 
    Input 1: 0 % 
    Input 2: 100 % 
    Input 3: 0 % 
    .
    .
    .
    Input 0: 0 % 
    Input 1: 100 % 
    Input 2: 0 % 
    Input 3: 0 % 
    .
    .
    .
    Input 0: 100 % 
    Input 1: 0 % 
    Input 2: 0 % 
    Input 3: 0 % 
    .
    .
    .

ONLY channel 0 is hooked !! .... it seems that it reads with different delays. changing the delay gives me different sequence. what is wrong ?

0

2 Answers 2

0

It becomes much easier if you start thinking in binary.

If you have an 8 bit multiplexer connected to four 8 bit multiplexers that gives you 32 inputs. Four of the inputs on the "master" multiplexer are unused and can be ignored.

You have 32 inputs. That's inputs numbered 0 to 31. In binary that equates to, in full,

0 = 000000   8 = 001000  16 = 010000  24 = 011000
1 = 000001   9 = 001001  17 = 010001  25 = 011001
2 = 000010  10 = 001010  18 = 010010  26 = 011010
3 = 000011  11 = 001011  19 = 010011  27 = 011011
4 = 000100  12 = 001100  20 = 010100  28 = 011100
5 = 000101  13 = 001101  21 = 010101  29 = 011101
6 = 000110  14 = 001110  22 = 010110  30 = 011110
7 = 000111  15 = 001111  23 = 010111  31 = 011111

I have laid it out like that especially so that you see a pattern occurring. Four columns with 8 rows. Four slave multiplexers with 8 inputs. A perfect match. Each column has bits that are distinct to that column. Each row has bits that are unique to that row. So you could split those bits up and know that the left-hand three bits indicate the column, and the right-hand three bits indicate the row. Between the two it's a unique location in the table.

The same applies to the multiplexers. The left-hand three bits indicate which slave multiplexer to use, the right-hand three bits which input to use on the selected multiplexer.

So you can loop through each of the 32 inputs with a single loop and examine the individual bits of the input number and apply those bits directly to the select outputs to control the multiplexers - the left-hand bits to the master to select which slave to use, and the right-hand bits to the slaves to select which input to use.

So you have:

for (int i = 0; i < 32; i++) {
    digitalWrite(M_S2, i & 0b100000);
    digitalWrite(M_S1, i & 0b010000);
    digitalWrite(M_S0, i & 0b001000);
    digitalWrite(S_S2, i & 0b000100);
    digitalWrite(S_S1, i & 0b000010);
    digitalWrite(S_S0, i & 0b000001);

    delay(1);

    int reading = analogRead(Z);
    Serial.print("Input ");
    Serial.print(i);
    Serial.print(": ");
    Serial.println(reading);
}

The i & 0b000001 etc performs the same function as bitRead() but is more explicit using a mask that is far more visual as to what it achieves.

I also include a tiny delay after setting the multiplexers up so as to ensure they have settled into their new settings properly before reading. It shouldn't be needed, but it doesn't hurt.

1
  • Thanks for the answer .. i updated my code. it kind of works but as i wrote. i am getting different readings ... ONLY channel 0 is hooked !! .... it seems that it reads with different delays. changing the delay gives me different sequence. what is wrong
    – mounim
    Sep 5, 2016 at 21:41
0

I think that you have confused your address encoding in your code. Your complete address space is only a total of 5 bits, decimal 0 to 31. Your two loops (for ( byte count = 0; count < 4 ; count++ ) and for ( byte count_1 = 0; count_1 < 32 ; count_1++ )) are actually counting through a 7 bit address space, just with the 3 MSBs of the inner loop being ignored.

For your 32-input example, I'm going to assume that the master 4051 only has inputs A-D (y0 to y3) connected to downstream muxes and that the analog mux decodes based on the binary value of the input select. Then your digital outputs should correspond to, for byte address as your counter:

  • S_S0 -> bitRead(address, 0) (LSB)
  • S_S1 -> bitRead(address, 1)
  • S_S2 -> bitRead(address, 2)
  • M_S0 -> bitRead(address, 3)
  • M_S1 -> bitRead(address, 4)
  • M_S2 -> constant 0 (MSB)

Thus, your test should only use a for ( byte address = 0; address < 32 ; address++ ) to acquire data from all 32 possible inputs. Remember to have a long enough delay from selecting a different multiplexer input to starting your ADC conversion to avoid errors due to signal settling.

Additionally, you should be calling only one analog read location corresponding to the pin connected to the AnalogInPin in the schematic. You will have to record what the current multiplexer selection to determine which of the 32 inputs is actually being recorded by that conversion. Basically, there's only one 'master" analog input.

Your use of value = (bitRead(count_1, 2),bitRead(count_1, 1),bitRead(count_1, 0)); is confusing and seems incorrect. After you digitalWrite() the new address for your multiplexers, you shouldn't need to read-back the digital pins to know what address you have selected.

2
  • Thanks .. i just updated my code. is that what you meant ?
    – mounim
    Aug 7, 2016 at 20:26
  • That looks better, but you've also now removed the code you originally asked about. Try reverting to the previous version and then adding the loop() implementation as a new section? That structure indeed what I was thinking. If that implementation works for you, please mark this answer as 'accepted'. Also, if you are delay()ing for 100ms, that may be inconveniently long, but choosing the delay is application and system dependent.
    – user2943160
    Aug 7, 2016 at 21:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.