[Solved, Thanks] Buggy Circuit - Please help me identify possible causes

trash = readMux(1);
sensor1 = readMux(1);

aka

(void) readMux(1);
sensor1 = readMux(1);

AWOL:

trash = readMux(1);

sensor1 = readMux(1);




aka



(void) readMux(1);
sensor1 = readMux(1);

Is there any difference in terms of speed by using the second form?

Is there any difference in terms of speed by using the second form?

No, the whole point is that you don't want it to be faster as you are giving the sample and hold capacitor on the A/D chance to settle down to the correct voltage.
It doesn't use a memory location though and it looks like you mean it when reading the code where as:-
sensor1 = readMux(1);
sensor1 = readMux(1);
looks like you might not mean it without any comments.

As to the OPs problem you need to do more measurements with a scope to see exactly what is going wrong, on the face of it there should be no problem.

Grumpy_Mike:

Is there any difference in terms of speed by using the second form?

No, the whole point is that you don't want it to be faster as you are giving the sample and hold capacitor on the A/D chance to settle down to the correct voltage.
It doesn't use a memory location tough and it looks like you mean it when reading the code where as:-
sensor1 = readMux(1);
sensor1 = readMux(1);
looks like you might not mean it without any comments.

As to the OPs problem you need to do more measurements with a scope to see exactly what is going wrong, on the face of it there should be no problem.

I know why it is read twice. I had never seen that form of using a function that we do not care about and therefor asked if there was a difference in speed, as it looks like it will take the same memory as the above form does.

Yay! I got it to work.

Turns out there where two independent things going on

a) I simply did not do a very good job soldering the multiplexer to the circuit. Thats why Sensor2 gave out the same reading as Sensor1, because Sensor2 was simply not physically connected to the multiplexer

b)The power supply I was using for the external power for the LEDs was bad. As in the output apparently fluctuated in voltage, and the LEDs would therefore pulse. This was not visible to eye (or to my IR camera) but produced a whole lot of noise. From now on I will not use old/second hand power sources for my project, as the first two power sources I used, which all had the correct ratings, and where in working condition had voltage (or amperage? or both?) fluctuations. As soon as I had a clean power source, everything worked like a charm.

About the double readings: My code works fine and I am only reading once. However, I read 4 multiplexers all together, which may have the same effect.
Just for completeness, here is my code:

/****************************************/
/*  Code For Reading 4 Multiplexers     */
/*   and sending the values to serial   */
/*                                      */
/*     Code by paul strohmeier          */
/*   http://fkeel.blogspot.com          */
/*                                      */
/* Feel free to use and destribute      */
/* Give me credit if you feel like it :-)
/*****************************************/

// I use this multiplexer:
// http://www.sparkfun.com/products/299

//This code is based on this tutorial:
//http://bildr.org/2011/02/cd74hc4067-arduino/

//Control pins for all multiplexers
int s0 = 2;
int s1 = 3;
int s2 = 4;
int s3 = 5;


//Signal pin for each individual multiplexer
int mux1 = 3;
int mux2 = 2;
int mux3 = 1;
int mux4 = 0;

void setup(){

//set control pins to output
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT); 

//not sure if this is actually necesary
  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);

//initate serial
  Serial.begin(9600);
}

void loop(){


//read the multiplexers & display the values

/* Attention:
I only use 8 pins of multiplexer 4, thats why 
I have two different conditions for i < 8 and i < 15
Depending on how many sensors you are reading, you will 
probably want to change this.
*/


  for(int i = 0; i < 16; i ++){
    if (i < 8) {
     // read all 4 multiplexers
     setMux(i);
      Serial.print(analogRead(mux1));
      Serial.print(",");
      Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
      Serial.print(",");
      Serial.print(analogRead(mux4));
      Serial.print(",");
    }
       else  if (i < 15) {
         //read multiplexer 1,2 & 3 only
     setMux(i);
      Serial.print(analogRead(mux1));
      Serial.print(",");
      Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
      Serial.print(",");
    }
     else {
       //read multiplexer 1,2 & 3 and then start new line
         setMux(i);
      Serial.print(analogRead(mux1));
      Serial.print(",");
      Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
      Serial.println(" ");
    }
  }
}


//function for setting control pins
void setMux(int input){
  int controlPin[] = {s0, s1, s2, s3};

/* Attention:
I made my own brakeout boards for my multiplexers. 
If you are using the sparkfun multiplexer brakout boards 
You will need to change the order. The correct order for
the Sparkfun brakeout are noted in the comment
*/

  int muxInput[16][4]={
    {0,0,0,0}, //SparkFun Input # 0
    {0,0,1,0}, //SparkFun Input # 4
    {0,0,0,1}, //SparkFun Input # 8
    {0,0,1,1}, //SparkFun Input # 12
    {1,0,0,0}, //SparkFun Input # 1
    {1,0,1,0}, //SparkFun Input # 5
    {1,0,0,1}, //SparkFun Input # 9
    {1,0,1,1}, //SparkFun Input # 13
    {0,1,0,0}, //SparkFun Input # 2
    {0,1,1,0}, //SparkFun Input # 6
    {0,1,0,1}, //SparkFun Input # 10
    {0,1,1,1}, //SparkFun Input # 14
    {1,1,0,0}, //SparkFun Input # 3
    {1,1,1,0}, //SparkFun Input # 7
    {1,1,0,1}, //SparkFun Input # 11
    {1,1,1,1}  //SparkFun Input # 15
  };

  //loop through the 4 sig
  for(int i = 0; i < 4; i ++){
    digitalWrite(controlPin[i], muxInput[input][i]);
  }
}

Thanks for all the input, everyone.

(and AWOL, sorry for the snappy replies in the pm about that other thread - you just sort of hit a sore spot... :-/...)

fkeel:
However, I read 4 multiplexers all together

Are you sure?

um. yes?

edit: what makes you think I might not be sure?

The Arduino has 1 Analog to Digital converter. Which means that you cannot read 4 analog signals at the same time. I may be picky about this, but it isn't right to say you read them at the same time.

In the setMux(int input) function you define your array every time you call it. This is going to take gob loads of time and is best done once only in the setup().

The code is a bit pedestrian and you would be better using loops rather than plodding through the same thing each time.

Finally look at bit maths to eliminate the need for that two dimensional matrix altogether.

@bubulindo - ok, point taken. what I meant to say is that I am recieving signals from all together 4 multiplexers. I am very aware of the fact that its not simultanious (its actually really slow right now... )

@grumpy mike - as said. the code is slow, I will try improving what you suggested and post it again - if you could give me some more feedback then, that would be super cool.

I am not sure how bit maths can help me - I have never used bitwise operations, but I'll look into it. Probably a valuable learning experience as well.

One thing that would make a big difference is getting rid of the matrix for a for loop. If you look at the data in the array you'll notice that the binary value (reading from left to right: 1 , 2, 4, 8) of the mux select pins is equal to the pin it selects:

{1,0,0,0}, //SparkFun Input # 1  = 0001
{1,0,1,0}, //SparkFun Input # 5 = 0101
{1,0,0,1}, //SparkFun Input # 9 = 1001
{1,0,1,1}, //SparkFun Input # 13 = 1101
{0,1,0,0}, //SparkFun Input # 2 = 0100

Using that knowledge, appropriate wiring and a for loop (along with some bitwise operations and direct port access) would free up quite a bit of memory (relative to the available memory that is...) and seriously speed things up.. There's plenty of posts on the subjects on the forums, but feel free to ask away after trying some things out.

OK, so I think I improved my code (in theory... it just doesn’t work yet. is giving back semi-random values... might have a wrong port selected or something) and since I will let this rest until tomorrow, I thought I would check to see whether someone can tell me if I am on the right path or not.

I need the array of binary values, because of the wiring of my sensors. Using the array allows me to call the pins in the order I want to read them, rather than in sequential order. This saves me a step of re-ordering them later. (Do you think this is silly? as in, am I wasting processing power on the arduino, as I could just do this on my computer?)

I am using DDRB to set pins 4,5,6,7 of register B of the arduino mega high (corresponding to pins 10,11,12,13)

I then use PORTB to write the binary values stored in muxInput[] to the digital outputs.

Is this correct so far?

Quick question to see if I got this right PORTB = B01000010 will set pin 1 & 6 of Port B high. Correct?

I am using this data sheet for selecting ports. Does anyone know any more extensive documentation on this? (for the arduino mega?)

Anyway, here is the code:

Quick question to see if I got this right PORTB = B01000010 will set pin 1 & 6 of Port B high. Correct?

I am using this data sheet for selecting ports. Does anyone know any more extensive documentation on this? (for the arduino mega?)

Anyway, here is the code:

  int muxInput[16]={ B00000000, B01000000, B10000000, B11000000, B00010000, B01010000, B10010000,
  B11010000, B00100000, B01100000, B10100000, B11100000, B00110000, B01110000, B10110000, B11110000};

  
//Signal pin for each individual multiplexer
int mux1 = 3;
int mux2 = 2;
int mux3 = 1;
int mux4 = 0;

void setup(){
  
  DDRB = B11110000;

//initate serial
  Serial.begin(9600);
}

void loop(){


//read the multiplexers & display the values

/* 
I only use 8 pins of multiplexer 4, thats why 
I have two different conditions for i < 8 and i < 15
Depending on how many sensors you are reading, you will 
probably want to change this.
*/


  for(int i = 0; i < 16; i ++){
    if (i < 8) {
     // read all 4 multiplexers
     setMux(i);
      Serial.print(analogRead(mux1));
      Serial.print(",");
      Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
      Serial.print(",");
      Serial.print(analogRead(mux4));
     Serial.print(",");
    }
       else  if (i < 15) {
         //read multiplexer 1,2 & 3 only
     setMux(i);
      Serial.print(analogRead(mux1));
      Serial.print(",");
     Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
    Serial.print(",");
    }
     else {
       //read multiplexer 1,2 & 3 and then start new line
         setMux(i);
      Serial.print(analogRead(mux1));
     Serial.print(",");
      Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
      Serial.println(" ");
    }
  }
}


//function for setting control pins
void setMux(int input){
  PORTB = muxInput[input];
  }

fkeel:
I need the array of binary values, because of the wiring of my sensors. Using the array allows me to call the pins in the order I want to read them, rather than in sequential order. This saves me a step of re-ordering them later. (Do you think this is silly? as in, am I wasting processing power on the arduino, as I could just do this on my computer?)

I haven't read the whole post, but I will comment on this... It seems logical to me to wire up the sensors you want to read in the order you want to read them... that way there's no guessing involved. Read mux #13 and you are reading sensor #13. This would let you essentially write the integer value (in binary) to the port select pins (hook them up appropriately to the same PORTx). It would free up the need to use the matrix as well as make things much much more efficient. You are writing a whole PORTx in less time than it takes to do a single digitalWrite (experts: please correct me if I'm wrong on any of this)

Edit: after reading, my point recommendation still stands.. Keep in mind that your current matrix has the 'binary' value in reverse.

my application is very small. i simply dont have the space to change the cabling. (I am making my own flexible pcb's and adding another layer would make it too bulky)

if you look at the code, I dont use a matrix anymore, but a simple 1d array.

am I using DDRB and the PORTB command correctly? (assuming, that I have identified the correct port...)

Ah... If you're stuck with the cabling as is, then yeah, using the byte array will work just fine.. Just make sure the values are correct (they are currently reversed see below). You should also use a byte instead of an int, as you only need values from 0-15.

byte muxInput[16]={ // byte because we only need values from 0 to 15
	B00000000, // 0
	B01000000, // 64
	B10000000, // 128
	B11000000, // 192
	B00010000, // 16
	B01010000, // 80
	B10010000, // 144
	B11010000, // 208
	B00100000, // 32
	B01100000, // 96
	B10100000, // 160
	B11100000, // 224
	B00110000, // 48
	B01110000, // 112
	B10110000, // 176
	B11110000  // 240
};

I can't speak to the mega as I have never dealt with it, but the answer will be in the datasheet for the atmega chip :slight_smile:

Edit: As for the wiring, you also need to be sure to wire up the mux select pins to the low end of the port (PortXpin0-3), mux S0 -> PortPin0, mux S1 -> PortPin 1, etc...

You should also use a byte instead of an int, as you only need values from 0-15.
Code:

byte muxInput[16]={ // byte because we only need values from 0 to 15
B00000000, // 0
B01000000, // 64
B10000000, // 128
B11000000, // 192

Zero to fifteen?

well. i got the code working...

//array which I will send to port A

 byte muxInput[16]={
  B00000000, B00100000, B00010000, B00110000,
  B10000000, B10100000, B10010000, B10110000,
  B01000000, B01100000, B01010000, B01110000,
  B11000000, B11100000, B11010000, B11110000

};
  
//Signal pin for each individual multiplexer
int mux1 = 3;
int mux2 = 2;
int mux3 = 1;
int mux4 = 0;

void setup(){

//set the pins I use as output
  DDRA = B11110000;

//initate serial
  Serial.begin(9600);
}

void loop(){


//read the multiplexers & display the values

/* 
I only use 8 pins of multiplexer 4, thats why 
I have two different conditions for i < 8 and i < 15
Depending on how many sensors you are reading, you will 
probably want to change this.
*/


  for(int i = 0; i < 16; i ++){
   if (i < 8)    {
     // read all 4 multiplexers
     setMux(i);
      Serial.print(analogRead(mux1));
      Serial.print(",");
      Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
      Serial.print(",");
      Serial.print(analogRead(mux4));
     Serial.print(",");
    }
       else  if (i < 15) {
         //read multiplexer 1,2 & 3 only
     setMux(i);
      Serial.print(analogRead(mux1));
      Serial.print(",");
     Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
    Serial.print(",");
    }
     else {
       //read multiplexer 1,2 & 3 and then start new line
         setMux(i);
      Serial.print(analogRead(mux1));
     Serial.print(",");
      Serial.print(analogRead(mux2));
      Serial.print(",");
      Serial.print(analogRead(mux3));
      Serial.println(" ");
    }
  } 
}


//function for setting control pins
void setMux(int input){
  PORTA = muxInput[input];
  }

This is still quite slow. Not sure if it inproved anything over my original code. I assume my limiting factor is that I am running 56 sensors over on analog to digital converter.

As far as the code goes, is there anything obvious I could improve to speed things up?

p.

I would say that the main speed killer is the use of Serial.print(). You should get a massive boost in performance if you avoid sending data over the serial link every loop.

If you must use Serial.print() then bumping the baud rate up to 115200 will give you some performance improvement.

Serial.begin(115200);

Another speed improvement you could make is to interleave printing with analogue reads.
This means breaking up the "analogRead" function into its three basic functions, namely:

  1. input mux setup and conversion start
  2. wait for conversion complete (busy wait)
  3. read result.

However, this only takes about the same time as it takes to transmit a single bit at 9600, so the saving isn't that big.