Improve sampling speed while using a multiplexer

I currently connected 5 sensor via a multiplexer (I must connect them to a multiplexer because they are I2C devices but they cannot been allocate more then 2 addresses so I use a multiplexer to solve the addressing problem).

However the sample rate is a shame , it is about 6.5Hz . I wish I could improve the sample rate by using some tricks. In my loop() function, multiplexer will loop through channel 0-4 , and read each of these channel's sensor value and print it by using Serial.print()

Is there any tricks I could use to improve my sampling rate faster ? Thanks...

Here is my multiplexer class :

``````class MUX {
public:
//mux control pins:
int s0 = 22;
int s1 = 24;
int s2 = 26;
int s3 = 28;

//SIG pin (not necessary WHEN sig is connect to 5V)
//int SIG_pin = 0;

//array to store channel :: muxChannel[channel numbers ][4 digit channel representation]
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
};

void setupMux() {
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
pinMode(s3, OUTPUT);

digitalWrite(s0, LOW);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
Serial.println(F("Multiplexer initialized"));
}

void selectChannel(int channel) {
int controlPin[] = {s0, s1, s2, s3};
for (int i = 0; i < 4; i++) {
digitalWrite(controlPin[i], muxChannel[channel][i]);
}
}
``````
• What is the baud rate for the serial interface? Have you considered using `millis()` to time your code and see where most of the time is spent? May 9, 2015 at 15:07
• You may consider changing the i2c bus speed. Here is a forum post covering the steps forum.arduino.cc/index.php?topic=16793.0 May 11, 2015 at 12:42
• Thanks guys , I've speed up my baud rate and it really helps , I also use Robert's proposal , help as well :)
– Yank
May 12, 2015 at 0:26

It's hard to offer much more than speculation without knowing more about the sensors and your current code, but here is one possibility:

If the bulk of your loop time is the sum of the conversion times, is it possible to cycle through the sensors twice, once to start each conversion (so they will convert nearly simultaneously), wait one conversion-time (or for the first sensor to complete), then cycle through them again to read back each converted value?

``````for each sensor,
setup mux;
send start conversion command;
end

for each sensor,
setup mux;
while conversion not done,
;  // wait
end
``````

For 16 sensors and assuming the conversion time the majority of the time spent, that could speed your sample rate to ~100Hz. Expect maybe half of that, since mux-setup and communication times are probably not negligible.

The technique suggested by @JRobert (starting all the conversions in one loop, then running another loop to wait for completions and read results) looks reasonable.

Here are a couple of ways to shorten the code shown in the question:

First, instead of four `int` declarations to set the value of `s0 ... s3`, use an `enum`. An `enum` is used to declare integer constants.

``````enum { s0 = 22, s1 = 24, s2 = 26, s3 = 28};
``````

Second, don't bother with the lengthy, tedious, and unnecessary `muxChannel` array. Delete the declaration of `muxChannel` and replace `selectChannel` with the following:

``````void selectChannel(int channel) {
int controlPin[] = {s0, s1, s2, s3};
for (int i = 0; i < 4; i++) {
digitalWrite(controlPin[i], channel & 1);
channel /= 2;
}
}
``````

The expression `channel & 1` picks off the least-significant-bit of `channel`. The statement `channel /= 2;` divides `channel` by 2, which moves the next bit of `channel` into place for output. You could instead say `channel >>= 1;` or `channel = channel/2;`, etc. if you prefer.

You might also look closely at your sensor boards to see if there is any way to add jumpers to get another bit or two of I2C device addressing, allowing you to avoid multiplexing.