working with analog expander 4051, the potentiometer is not consistant! help !

Hello,
I am working with the 4051 analog expander IC. I made all my connections but i got one problem. Each time i move the circuits on the table or turn off the circuit then on, the value of the potentiometer at 0 angle is different. The value is never 0 there is always a number. So remap it with map() to get 0-255 range but each time it changes i have to remap it again manually.
for example I plug the arduino in my laptop and check the start value let's say it is 150, then I unplug the arduino then plug and the value is 200. but when I plug and turn the pot everything works fine and i get a value on the display.
So what I am looking for is to let this be done automatically in the sketch by defining the value at 0 pot angle at the start to be the minimum value and the max reached to be the maximum value. It is to note that i am not turning the potentiometer all the way because it is my application that i should not turn it all the way. So I need your help make this work please.

In my sketch below, I tried a method, but seems not working and I thought also of making an array in which I add the values from the pot to it then should the minimum and maximum

It is to note that values of analog pin is never 0 with the 4051, I changed many and all worked this way thinking that i have a defected IC.

I am using a potentiometer like this

here is is my sketch :

// Define the 4051 analog expander pins
//-------------------------------------------------
int totalChannels = 8;
int addressA = A2;
int addressB = A3;
int addressC = A4;
int AnalogIn_z = A1;

int A = 0;      //Address pin A
int B = 0;      //Address pin B
int C = 0;      //Address pin C

const int numReadings = 10;
int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;  

int clutchValue = 0;
int clutchAverage;
int clutch_min;
int clutch_max;
int clutch_current_min;
int clutch_current_max;
int clutch_previous_min = clutch_min;
int clutch_previous_max = clutch_max;

void setup() {
  Serial.begin(9600);
  // define arduino pins used to connect to the 4051 analog expander
  pinMode(addressA, OUTPUT);
  pinMode(addressB, OUTPUT);
  pinMode(addressC, OUTPUT);
  pinMode(AnalogIn_z, INPUT);

}

void loop() {
    //Select each pin and read value
  for(int i=0; i<totalChannels; i++){
    A = bitRead(i,0); //Take first bit from binary value of i channel.
    B = bitRead(i,1); //Take second bit from binary value of i channel.
    C = bitRead(i,2); //Take third bit from value of i channel.

    //Write address to mux
    digitalWrite(addressA, A);
    digitalWrite(addressB, B);
    digitalWrite(addressC, C);

    //Read and print value
    if(i == 4) {
      clutchAverage = smooth(AnalogIn_z);
      clutch_current_min = clutchAverage;
      
      if(clutch_min < clutchAverage){
        if(clutch_min < clutch_previous_min){
          clutch_previous_min = clutch_min;
          clutch_min = clutchAverage;
        }
        if(clutch_max < clutchAverage){
          clutch_previous_max = clutch_max;
          clutch_max = clutchAverage;
        }
      } else if(clutch_min > clutchAverage){
        clutch_previous_min = clutch_min;
        clutch_min = clutchAverage;
      } else if(clutch_previous_min > clutch_min && clutch_min > clutchAverage){
        clutch_previous_min = clutch_min;
        clutch_min = clutchAverage;
        if(clutch_previous_max > clutch_max && clutch_max > clutchAverage){
          clutch_previous_max = clutch_max;
          clutch_max = clutchAverage;
        }
      }

      Serial.print("Clutch Value: ");
      Serial.println(clutchAverage);
      Serial.print("Clutch min: ");
      Serial.println(clutch_min);
      Serial.print("Clutch max: ");
      Serial.println(clutch_max);
      Serial.print("Clutch previous min: ");
      Serial.println(clutch_previous_min);
      Serial.print("Clutch previous max: ");
      Serial.println(clutch_previous_max);
      clutchAverage =  map(clutchAverage, clutch_min, clutch_max, 0, 255);
      Serial.print("Clutch remaped: ");
      Serial.println(clutchAverage);
      delay(500);
      //Serial.println(clutchAverage);
    }
  }

}

// Smoothing analog input function
int smooth(int potPin){

  total= total - readings[index];        
  // read from the sensor:  
  readings[index] = analogRead(potPin);
  // add the reading to the total:
  total= total + readings[index];      
  // advance to the next position in the array:  
  index = index + 1;                    

  // if we're at the end of the array...
  if (index >= numReadings)              
    // ...wrap around to the beginning:
    index = 0;                          

  // calculate the average:
  average = total / numReadings; 

  return average;
}

I have a couple of thoughts...

  1. You didn't mention the values you are seeing only that they are not stable. It would help to know the actual data.

  2. You should test your arduino with the A/D input that is going to the 4051 by shorting it to ground. The nearest ground on the board. See if it is stable.

  3. Its been a long time since I worked with the A/D inputs, however I don't thing it will ever reach 0. I may be wrong here.

  4. When you are dealing with analog signals it usually helps to have a resistor - capacitor filter right at the arduino. Perhaps a 5k in series and a 0.1µf to ground.

  5. How is your circuit physically wired? Are there other things going on? Grounding is important here. By grounding I mean which grounds are hooked where.

Is that a walking average ? It is common to fill it with a start value.

void setup()
{
  ...
  for( int i=0; i<numReadings; i++)
  {
    readings[i] = analogRead( AnalogIn_z);
  }
  ...
}

Which Arduino board do you use ?
Can you show a photo and/or schematic ?
Perhaps the potmeter is not connected properly, or perhaps you use a breadboard ?

An auto-zero is overthinking it, there is a problem somewhere that needs to be fixed.

A potmeter is never zero. A normal way is to use a margin for the maximum and minimum.
Suppose you have an Arduino Uno and the analogRead() returns 0...1023. Then you can reserve 5% on both sides, that is a value of about 50.

0...50 -> 0
51...972 -> 0 ... 255
973...1023 -> 255

When I have to guess, then I think that you have a breadboard with bad contacts.

firashelou:
Hello,
I am working with the 4051 analog expander IC.

Which "4051"
You should be using the 74HC4051, not the older CD/HEF4051 family.
Leo..

Seems you meet some issues about it...

JohnRob:
I have a couple of thoughts...

  1. You didn't mention the values you are seeing only that they are not stable. It would help to know the actual data.

  2. You should test your arduino with the A/D input that is going to the 4051 by shorting it to ground. The nearest ground on the board. See if it is stable.

  3. Its been a long time since I worked with the A/D inputs, however I don't thing it will ever reach 0. I may be wrong here.

  4. When you are dealing with analog signals it usually helps to have a resistor - capacitor filter right at the arduino. Perhaps a 5k in series and a 0.1µf to ground.

  5. How is your circuit physically wired? Are there other things going on? Grounding is important here. By grounding I mean which grounds are hooked where.

1- values I am getting when I turn the arduino on without touching the pot are: 447 or 441 it keeps changing between these 2 values up and down
And about my application the picture attached in the original post shows the handle how it is and the pot is not at 0 angle, it has some angle to it. And when I click the handle, the pot turns to reach a value between 560 and 570
but if i turn the arduino off and turn on again the value at start becomes 432 and that keeps changing if i turn off then on each time.
well, I unplugged the arduino from usb and plugged it and kept doing it for many times and here is the results at the start without touching the pot handle:
1st time: 417
2nd time: 427
3rd time: 421
4th time: 425
5th time: 431
6th time: 439
7th time: 441
8th time: 443

4- what do you mean having a resistor at arduino?

5- I attached a picture which shows my circuit in fritzing

Koepel:
Is that a walking average ? It is common to fill it with a start value.

void setup()

{
 ...
 for( int i=0; i<numReadings; i++)
 {
   readings[i] = analogRead( AnalogIn_z);
 }
 ...
}




Which Arduino board do you use ?
Can you show a photo and/or schematic ?
Perhaps the potmeter is not connected properly, or perhaps you use a breadboard ?

An auto-zero is overthinking it, there is a problem somewhere that needs to be fixed. 

A potmeter is never zero. A normal way is to use a margin for the maximum and minimum.
Suppose you have an Arduino Uno and the analogRead() returns 0...1023. Then you can reserve 5% on both sides, that is a value of about 50.

0...50 -> 0
51...972 -> 0 ... 255
973...1023 -> 255

When I have to guess, then I think that you have a breadboard with bad contacts.

1- what do you mean a walking average ? and you mean the array should have a start values like 0?

2- arduino Nano, I posted a fritzing picture showing my circuit

3- I use a breadboard yes for now, it is a testing circuit

4- well, I unplugged the arduino from usb and plugged it and kept doing it for many times and here is the results at the start without touching the pot handle:
1st time: 417
2nd time: 427
3rd time: 421
4th time: 425
5th time: 431
6th time: 439
7th time: 441
8th time: 443
how is that margin done you mean ?

5- I dont think the breadboard mind be the problem because it is a new breadboard and there is a signal always, don't you think ?

Wawa:
Which "4051"
You should be using the 74HC4051, not the older CD/HEF4051 family.
Leo..

yes the 74HC4051

Using the average of a few samples does not need an array.
This is how to reduce the high frequency electronic noise:

unsigned long total = 0;
for( int i=0; i<10; i++)  // 10 samples
{
  total += analogRead(A0);
}
unsigned int result = total / 10;  // average of 10 samples

The "walking average" or "running average" uses a fixed sample rate and for example the average of the last 10 samples. Filling the array in setup() means that the result does not need to start at zero and climb to the real value, but starts directly with the real value.

A Nano with analogRead() has a value of 0...1023, and your potmeter turned to the lowest value has 425 ? Then your potmeter is wrong or broken or the contacts are bad or the wiring is wrong. Something is not okay.

Every year there is an increasing amount of problems with breadboards (bad contacts) and jumper wires (broken) on this forum :frowning:

When the hardware is okay, then a margin for the potmeter is just code. Arduino has the map() and contrain() functions, but a few lines of normal 'C' code can do that as well.

Do you have a multimeter ? Can you buy one ? Check the resistance of the potmeter, and then check the voltages when the potmeter is in the circuit.

Koepel:
Using the average of a few samples does not need an array.
This is how to reduce the high frequency electronic noise:

unsigned long total = 0;

for( int i=0; i<10; i++)  // 10 samples
{
 total += analogRead(A0);
}
unsigned int result = total / 10;  // average of 10 samples




The "walking average" or "running average" uses a fixed sample rate and for example the average of the last 10 samples. Filling the array in setup() means that the result does not need to start at zero and climb to the real value, but starts directly with the real value.

A Nano with analogRead() has a value of 0...1023, and your potmeter turned to the lowest value has 425 ? Then your potmeter is wrong or broken or the contacts are bad or the wiring is wrong. Something is not okay.

Every year there is an increasing amount of problems with breadboards (bad contacts) and jumper wires (broken) on this forum :(

When the hardware is okay, then a margin for the potmeter is just code. Arduino has the map() and contrain() functions, but a few lines of normal 'C' code can do that as well.

Do you have a multimeter ? Can you buy one ? Check the resistance of the potmeter, and then check the voltages when the potmeter is in the circuit.

thanks again for your help, well let me explain
having a value of 425 is not a problem at start because as i said, the potentiometer is not at 0 angle in my application, it is turned a little so that value is logical. It is the way the handle was designed to have not a 0 value on purpose.

for your solution of samples I think i did that in smooth don't you think ? I took samples and made a smoothing pot but the problem still happens which is each time i turn the arduino off then on a new starting value come up so that is why I am looking to make the starting value dynamic to be able to set the min and max of the map() function

You don't have to quote my whole post, what I wrote is already there :wink:

I'm slowly getting it. I thought that the potmeter was at angle 0.
The potmeter is in a mechanical clutch foot pedal ?
When you start the Arduino, then the clutch is in the begin posistion and the potmeter is almost halfway ?
You need to get the offset in setup().

The running average is here: https://www.arduino.cc/en/Tutorial/BuiltInExamples/Smoothing and in the Arduino IDE menu: File / Examples / 03. Analog / Smoothing

That can benefit when pre-filling the array in setup().
If you don't pre-fill the array, then you can call the smooth() function a number of times.

The next code should result in a percentage from 0...100 for the potmeter. I suggest to make an other sketch to test it.

int potMin = 0;
int potMax = 1023;

void setup()
{
  // prefill the array or call smooth a number of times
  ...
  
  // find the value at the begin position and use it later as a offset
  int potMin = smooth( AnalogIn_z);
}

void loop()
{
  ...
  int pot = smooth( AnalogIn_z);
  pot = contrain( pot, potMin, potMax);
  int percentage = map( pot, potMin, potMax, 0, 100);
  ...
}

That might not work together with the code in the loop(). I don't understand what code with the 'clutch_current_min', 'clutchAverage', 'clutch_min' and so is doing. Is that some kind of automatic way to find the minimum and maximum value ?

Suppose you press and release the clutch with force, then the begin value of the potmeter changes. So you still need those margins.

  int pot = smooth( AnalogIn_z);
  int margin = (potMax - potMin) / 20;  // divide by 20 for 5% margin
  int l = potMin + margin;   // new lower boundery, with margin
  int h = potMax - margin;   // new high boundery, with margin
  pot = constrain( pot, l, h);
  int percentage = map( pot, l, h, 0, 100);

I even think that I prefer a fixed value in the sketch. For example everything below 450 is zero. You could add a button to calibrate it once in a while.

Koepel:
I'm slowly getting it. I thought that the potmeter was at angle 0.
The potmeter is in a mechanical clutch foot pedal ?

the clutch is a paddle that you click with your finger not your foot

Koepel:
When you start the Arduino, then the clutch is in the begin posistion and the potmeter is almost halfway ?
You need to get the offset in setup().

the offset in setup gives a wrong value, not the one settled up after, there must be a way to find the minimum that settles in after

Koepel:
The running average is here: https://www.arduino.cc/en/Tutorial/BuiltInExamples/Smoothing and in the Arduino IDE menu: File / Examples / 03. Analog / Smoothing

exactly this is the smoothing that i am using

Koepel:
The next code should result in a percentage from 0...100 for the potmeter. I suggest to make an other sketch to test it.

So i test it with my main sketch which contains all the project and it seems to work well now, the values are settled in and doesn't change everytime I unplug and plug :smiley:

Koepel:
I don't understand what code with the 'clutch_current_min', 'clutchAverage', 'clutch_min' and so is doing. Is that some kind of automatic way to find the minimum and maximum value ?

I was just sharing what i was trying to do and failed

The picture below shows the values settled in, you see that the Clutch Value is 82, this value should be the min and not the 15, 15 was at the start in the setup

Edit:
Seems after posting this reply, after unplugging the arduino for a while then plugging in, the value has changed from 82 to 220 ! what the heck ! :frowning:

Hi,
A proper schematic will be better.

If you take the pot out of circuit.
Connect the 4051 input that was going to the wiper to gnd, what value do you get?
Connect the 4051 input that was going to the wiper to +5v, what value do you get?

If you take two 4K7 or similar paired values and replace the pot with.
One 4K7 between gnd and the 4051 input.
On 4k7 between 5V and the 4052 input.
This should put 2.5V on the 4051 input.
What reading do you get?

Please measure it with a DMM as well.

Thanks.. Tom... :slight_smile:

TomGeorge:
Hi,
A proper schematic will be better.

If you take the pot out of circuit.
Connect the 4051 input that was going to the wiper to gnd, what value do you get?
Connect the 4051 input that was going to the wiper to +5v, what value do you get?

If you take two 4K7 or similar paired values and replace the pot with.
One 4K7 between gnd and the 4051 input.
On 4k7 between 5V and the 4052 input.
This should put 2.5V on the 4051 input.
What reading do you get?

Please measure it with a DMM as well.

Thanks.. Tom... :slight_smile:

thanks for your help I connected the pin number 4 of the 4051 that was connected to my pot to GND and it gave me a value of 193 ! is that normal ?

Pin 1 of the 4051 is Y4, not pin 4....

MarkT:
Pin 1 of the 4051 is Y4, not pin 4....

Proves we need to see a real circuit diagram, reverse engineered from the project.
Can you post a real picture of your project please?
Thanks.. Tom... :slight_smile:

MarkT:
Pin 1 of the 4051 is Y4, not pin 4....

yes the y4 i know that is what i am plugging my pot in

You've checked the selector pins are getting the correct voltages?

MarkT:
You've checked the selector pins are getting the correct voltages?

yes they are getting signal because i can see values of other pots also when i run my main sketch not the one used here in original post, but for the development and solution finding i run the sketch that is here in the original post
the problem is how to record the value of the pot at the start as min value when i am not touching the pot handle

Hi,
Have you actually measured the voltage at the pot wiper and at the output of the 4051 going to the controller analog input?

This would mean writing some simple code to select the Y4 input continuously.
You possibly have some hardware problem, lets write some code to check it out.

Did you write some code when developing this project to check that you have the addressing and reading correct?
That is to verify your hardware.

Have you measured voltages with a DMM?

Tom... :slight_smile: