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

So (as some of you who have been a lot of help to me already have probably figured out...) I am working on this massive sensor array thingy.

I have my PCB's etched, my smd components soldered, all I am waiting for is for some more multiplexers before the whole thing is done. (for some reason customs or sparkfun or somebody does not want me to finish this. Its been in the mail for almost 3 weeks :-(...)

Anyway, I do have one multiplexers which I put into the circuit, and I should be able to test 16 sensors at a time. It does not work as expected.

About half of the sensors give me the readings I expect. The other half give readings which look reasonable: i.e. the arduino usually outputs ~1024 and when exposed to ambient light, the values drop more or less as one would intuitivly assume they should.

In truth however, there appears to be some sort of leakage. For example: Sensor 2 will just stay at around 1024. Even if I should get readings of 100 or less, it stays at 1024. But if Sensor1 is activated (i.e. Sensor1 value sinks to under 100), then sensor2 to will also respond, sink to about 200, even if it should not.)

Ok, here is a sketch of the circuit, so you know what I am talking about:

(the multiplexer circuit is just copied off of the sparkfun brakout board: http://www.sparkfun.com/datasheets/BreakoutBoards/Analog-Mux-Breakout-v10.pdf)

Possible reasons that I can think of:

a) There is a problem with my logic, and this circuit is wrong.
b) There is a problem with my PCB, I have some connections which should not be there. (dont think thats the case. I checked this extensivly. Everything seems as it should be)
c) I am pulling more power than the arduino can handle (in retrospect, maybe I should have used stronger resistors for the voltage dividers?).
d) I fried some sensors when soldering (sort of doubt that).
e) I fried the multiplexer when soldering it (How fragile are they? I have no experience how a semi-fried multiplexer could behave...)
f) The code is whack. (pretty sure that is not the case. I used a modified version of this code: Search Results for “mux” – bildr.org)

Ok, about the power options. The sensor I am using is actually an IC with a led and a photodiode. The led is controlled by a separate circuit with its own power, that’s why Its not in the sketch I posted above. However, because of this, the datasheet confuses me, cause I never know which values refer to the sensor and which to the emitter. The datasheet can be found here: http://www.fairchildsemi.com/ds/QR/QRE1113.GR.pdf

These are the values which I think are relevant, but I am not realy sure:

Collector Emitter Voltage 30V
Emitter Collector Voltage 5V
Collector Current 20ma

I am running all of the sensors in parallel, so its 320ma, so I should be fine for now, right? The arduino can supply that current with the 5v pin, correct? I just double-checked the specs of the arduino mega and did not actually find any information on that. But then there are those 10k resistors which I don’t really know how to factor in :-/

Ok, I guess this already is quite a large "help me" post. If someone could take a look at this and help me eliminate the possible problems, or even point out new ones, that would be great. I am waiting until I get the other multiplexers tomorrow, before I do more trouble shooting, but any suggestions which will help me solve this are appreciated.

Thanks

P.

How fast are you going thru the analog readings? I didn't look at the code. It is often suggested here to read the same input twice, throw away the first one, give the selected input a chance to drive the A/D circuit in the ATMega correctly.
You have the grounds from your various supplies all connected to each other?

yep. all grounds connected.

I am reading them as fast as possible - I am not doing any intentional timing - just cycling through my sketch. Do you mean something like this:

(assuming I have a function, readMux(int) which sets the control pins to read the desired sensor)

trash = readMux(1);
sensor1 = readMux(1);
trash = readMux(2);
sensor2 = readMux(2);
trash = readMux3);
.... etc

Yes, exactly.
Don't have to give it a new name if you don't want to, I wasn't being literal 8)
sensor1 = readMux(1);
sensor1 = readMux(1);

Are you using the USB port to power this up?

It is always a good idea to use a standalone power supply when working outside of the Arduino. The 10K resistors make the currents going through them small enough for this not to be a problem for the USB port, but you never know. And I have no idea what other hardware you may have installed.

Try disconnecting most of the 16 sensors and get the mux out of the equation and test. Them put the same sensors, through the mux and test. See the differences. Then get all sixteen of them and see the differences. That's the only way you can see which part of the circuit is holding you.

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...