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 ?
2 Answers 2
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.
-
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 wrongmounim– mounim09/05/2016 21:41:22Commented Sep 5, 2016 at 21:41
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
-> constant0
(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.
-
Thanks .. i just updated my code. is that what you meant ?mounim– mounim08/07/2016 20:26:05Commented 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 aredelay()
ing for 100ms, that may be inconveniently long, but choosing the delay is application and system dependent.user2943160– user294316008/07/2016 21:00:25Commented Aug 7, 2016 at 21:00