4051 and pots

My schematics is exactly the same like this (left), except that I'm using only 4 "slave" 4051s connected to "master"

The readings from pots shoul be 0-127 however I'm getting 1-120, 0-123 etc and almost never the full spectre. Is there any reason for this?

kustom:
The readings from pots shoul be 0-127 however I'm getting 1-120, 0-123 etc and almost never the full spectre. Is there any reason for this?

Yes. The reason is resistance in the 4051's - they aren't perfect switches (it's literally the effect of the semi- in semiconductor).

Is there any hardware fix for this? To add some resistors/capacitors? Another/better mux?

If nothing I'll try to code rescaling function.

Hardware fix? Sure, drop the 2nd mux chip.
Instead feed the inputs into a multichannel ADC chip such as MCP3208
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010534
of MCP3008 if you only want 10 bit resolution.

Thanks for advice. Can you daisy chain them?

No, these use SPI interface - so you connect all control inputs in parallel (SCK, MOSI, MISO) and give each a unique Slave Select signal).
The Slave Select can be generated from a shift register as well, also driven by the SPI Interface - so with 4 pins (SCK, MISO, MOSI to everyone, SS to the shift register, which then create SS's for the 8 ADCs) you can control 9 devices reading 64 input signals with 12 bit resolution.

Very cool. Thanks, I'm going to order few of those.

Here's a loop I wrote to cycle thru & read one every 5mS & send it out the serial port.
What you do with it once you read it is up to you, the important thing is setting it up with the control bits

void loop(){

  // Elapsed time check for ADC and Switch reading
  if ( (millis() - previousMillis) >=5 ){

    previousMillis = previousMillis + 5; // set for next 5 mS interval

    // read ADC with 3 byte transfer
    // PORTB previously set to outputs with DDRB command
    PORTB = PORTB & B11111011;  // ADC_SS, LOW
    // ADCaddress = 0x0600, 640, 680, 6C0, 700, 740, 780, 7C0
    dummyADC = SPI.transfer (highByte(ADCaddress));  // 0x06, 0x07 out, read in dummy data
    highADC = SPI.transfer (lowByte(ADCaddress));    // 0x00, 0x40, 0x80, 0xC0, read in upper 4 bits
    lowADC = SPI.transfer (0);              // dummy 0 byte out , read in lower 8 bits
    PORTB = PORTB | B00000100; // ADC_SS, HIGH

    // send the data out

    Serial.write (ADCsyncbyte);      // syncbyte = B00110011, 0x33
    // bits 4-3-2 = 0 when switch pressed. Invert them.  Leave bits 1-0 alone. No bits 7-6. Bit 5 not used.
    Serial.write (PINC ^ B0011100);   // 3 switches on Port C, make them 1 if 0 (1 EXOR 1 = 0, 0 EXOR 1 = 1, 0 EXOR 0 = 0
    Serial.write (address_count);    // find way to put this in top nibble of next command?
    Serial.write (highADC & 0x0F);   // send it out
    Serial.write (lowADC);           // send it out
    
    // prep address_count for next pass. Used to create ADC select, DAC select
    address_count = address_count +1;  // 0 to 7, pass to Rx for DAC sync
    if (address_count == 8){ 
      address_count = 0;
    }  // reset if hit all 8
    // baseADCaddress = 0x600
    ADCaddress = baseADCaddress + (address_count * 0x40); // update for next ADC pass

  } // end 5mS test

From the CD4051 data sheet the device is NOT a GOOD analog measurement part for source/load resistances under 20K ohms Digital is fine but the gate (transmission gate) changes over a 2/1 (@~ 200 ohms) ratio for both applied (I/O) voltage and temperature @ 5V supply and control. This would require a pot of at least 20K for the change to be ~1%. This was the technique I have used in the past and it always worked well, every time I have used that part. I used a pair of 4051's and a pair of 4066's to make a really nice 8 channel stereo audio patch panel that was programmable (I used a Stamp and a Serial LCD from WireZ electronics...) That was 10 years ago and stamps were all I could find then. I used it for several years without issues.
Edit... The MCP3208 looks like a much better part for your application. The 4501 is... ok for audio and high impedance (low current) digital but is 'Iffy' for accurate 5V analog measurement. The part was really designed to work well with Bi-polar supplies @ 10 - 15 Vdc Vdd to Vee. (+/- 5 to 7.5V)

Doc

Sorry for bumping this thread but I've got some new info.

So I started to play around with 4051 again. Schematics is the same as in first post, readings are the same etc etc. However, I've switched every pot to external power supply (another USB cable) and readings are accurate this time! Full spectre, 0-127. When I switch them back to Arduino power, readings are the same as before (2-125, 3-123 etc). Any explanation for this?

You don't show power/gnd connections in the schematics, they don't expand as posted, so its hard to say.

There are:
6 4021 chips
5 4051 chips
4 74HC595 chips in my schematics

all sharing same ground/power.

Any project that size should have it's own power supply. Having said that ... You didn't mention whether you were using the USB power supply or an external 5V supply and your drawing doesn't show any bypassing either. I would expect issues like that If you are using the USB power and the bypassing inherent to the Uno? board although the power supplies are the same for both the Uno and Mega. Enough bypassing for the CPU board as it should be but totally ineffective at the end of a foot or so of wire on an an external PCB or worse a breadboard where there would be none at all. It is my experience that with a 150 mA load (an LCD back-light) there was a 100mV difference from the supply end of the board to the max load at the other end of the PCB, Not Good at all and the Back-light PWM "Noise" was intolerable. I replaced the power supply from the Arduino with a plug in breadboard supply and added a 100 nf cap/ic and a couple of 100 uF caps. It fixed all my issues and made analog temp measurements with an Analog devices TMP36 accurate again..

Bob

Accurate readings: USB from Arduino + another USB only to power up pots only
Inaccurate readings: USB from Arduino only

I will separate grounds for each chip (one ground for 4051 chips, one for 4021 chips etc). Are you suggesting that I power up Arduino with external power supply? Where do I need to add those capacitors?

It sounds like the extra voltage from the other source is compensating for the resistance in the multiplexer chips.

Why are you looking for a hardware solution when a software solution is the simple one line use of the map() function?

I will separate grounds for each chip

That will stop it from working.

Where do I need to add those capacitors?

Between power and ground, but that is not your problem.

Grumpy_Mike:
It sounds like the extra voltage from the other source is compensating for the resistance in the multiplexer chips.

Why are you looking for a hardware solution when a software solution is the simple one line use of the map() function?

Because I'm still beginner at this stuff and tutorials never warn you about voltage drops and noise. I'll investigate that function.

I don't really understand what that function does nor how could I use it in my case.

EDIT: Ok I've figured what it does. Still don't understand how to apply it in my project.

It will make the spread you get into the spread you want.
So suppose you only get the raw values 0 to 800 from the analogue read. Map will make them into 0 to 127.
So what spread do you actually get, the full range should be 0 to 1023

Grumpy_Mike:
It will make the spread you get into the spread you want.
So suppose you only get the raw values 0 to 800 from the analogue read. Map will make them into 0 to 127.
So what spread do you actually get, the full range should be 0 to 1023

I thought that will be your answer. However it isn't that simple: each time I turn arduino on, range is different. Sometimes 3-125, sometimes 2-123 etc.

Any analogue to digital is only ever at the absolute best plus and minus the least significant digit.

Sometimes 3-125, sometimes 2-123 etc.

How are you getting that number? It is too small to be a direct reading you must be doing something with it first, what is the raw range?