I have a potentiometer hooked connected from 5V to ground with the wiper connected to an ADC pin on an Arduino UNO. I am getting some chatter (slight changes) in the readings which I would like to smooth. The problem is these changes are triggering if statements (looking for a change in value of the ADC reading) in the code when they shouldn't be. Could I place a cap to ground on the wiper to steady the input voltage or am I stuck averaging the last X number of readings?
Even if you leave the pot untouched the value will change - it's a real world device. Change your thinking to take this into account. And no a cap will not help. And an average won't really help.
Mark
It shouldn't jump more than one value.
You could try a 100n cap from analogue-in to ground.
Are you using USB supply, or varying loads like blinking LEDs.
What is the pot value.
Is the wiring short (hum pickup).
Reading twice, and using the second reading could help.
Leo..
The present pot value is 10k (I think, it is whatever I had on hand). The plan is to use 50K to minimize power consumption. I was not going to average 2 values but 5 or 10 ADC readings.
How much is it changing? How much (unwanted) change does your software allow?
If you are on the "hairy edge", a tiny-tiny analog change can cause the digital value to jump up or down by a count of one. There is no way of getting around that with a true analog input into an ADC.
Noise & variation on the power supply, a high-resistance pot (maybe 100K or more), or a long distance between the pot and Arduino can make noise pick-up worse.
The problem is these changes are triggering if statements (looking for a change in value of the ADC reading)
Suggestions -
-
Look for a bigger change.
-
I assume you are doing this already, but look for greater-than, less-than, or a value between two values. Don't require the analog reading to exactly equal something.
-
Use some [u]hysteresis[/u]. The most common example of hysteresis is a thermostat... Say it's set for the heat to come-on below 70 degrees F... It doesn't come on 'till it gets down to 69, then it stays on 'till it hits 71.
-
You need to allow for the fact that you are dealing with analog.
And no a cap will not help. And an average won't really help.
Those things CAN sometimes help to remove the noise and average-out the variations. Sometimes those things are mandatory!
Here is the section of pertinent code.
off_sp_reading = ((adcReading * 5.0 / 1024.0) * SP_Sens + SP_Offset;
off_sp_reading=round(off_sp_reading *100.0) /100.0;
if ((off_sp_reading>off_temp_sp+0.05) or (off_sp_reading<off_temp_sp-0.05))
{
off_temp_sp=round(off_sp_reading *10.0) /10.0;
new_sp_detected = true;
new_sp_time = current_time;
}
Where SP_Sens is the setpoint range over the voltage range, in this case the setpoint range is 50 and the voltage range is 5. The SP_Offset is the minimum value, in this case 40.
I see you're measuring low digital values (40-50).
A mechanical pot could be unreliable at the extremes.
I assume you are going to replace the pot for a temp sensor.
If possible, use the internal 1.1volt Aref.
I am sometimes using this averaging.
analogRead(A1); // one unused reading
for (int x = 0; x < 100; x++){ // 100 readings
total = total + analogRead(A1); // add each value
}
Then use "total" in the maths.
Leo..
Wawa:
I see you're measuring low digital values (40-50).
A mechanical pot could be unreliable at the extremes.
I assume you are going to replace the pot for a temp sensor.
If possible, use the internal 1.1volt Aref.
I do not understand what you are talking about.
The pots are not being replaced, they are supplying the EGU setpoints for the system. The voltage range in use is 0 through 5V which will correspond to 40 through 90 EGU.
Sorry, did not read it properly.
So the pot is just there to change a preset.
Why not use a rotary encoder.
Leo..
Wawa:
Sorry, did not read it properly.
So the pot is just there to change a preset.
Why not use a rotary encoder.
Leo..
Not enough pins, selecting 1 of 500 points would require a 9 bit encoder and two of them. I don't have 18 digital inputs available.
Two pins.
With this encoder, the knob position has nothing to do with the value.
I don't know if you have any other feedback (LCD, LED brightness).
Leo..
Wawa:
Two pins.
http://www.hobbytronics.co.uk/arduino-tutorial6-rotary-encoderWith this encoder, the knob position has nothing to do with the value.
I don't know if you have any other feedback (LCD, LED brightness).
Leo..
Thanks for the info. But as you said, the knob position has nothing to do with the value. So it won't work. As you mentioned, the design element for the pot is to hold the position and value.
I suppose you have already tried a simple code that reads the pot and prints the A/D value to the serial monitor.
And you know, when you put the pot in the middle, how much that reading is varying.
If it's stable within one digit, you have to improve your code.
51 values is ~20 digital steps per value. That should not be a problem, even without averaging.
Leo..
edit.
Does it compile with the missing closing bracket in the first line of your code.
Hi,
This bit of code;
off_sp_reading = ((adcReading * 5.0 / 1024.0) * SP_Sens + SP_Offset;
off_sp_reading=round(off_sp_reading *100.0) /100.0;
if ((off_sp_reading>off_temp_sp+0.05) or (off_sp_reading<off_temp_sp-0.05))
{
off_temp_sp=round(off_sp_reading *10.0) /10.0;
new_sp_detected = true;
new_sp_time = current_time;
}
The first line you calc a value o_s_p, I'm not going to write it out completely.
The second line you "round" it off. So it is basically an integer.
The third line you compare rounded o_s_p with I gather another rounded o_t_s + 0.05 or -0.05.
Unless o_s_p = o_t_s, it will jitter o_t_s up and down.
o_s_p will never be less than+ or - 0.05 of o_t_s because you have "rounded' it off.
The analog input will always have some noise, although I'd like to see a picture of your project.
If you want the pot to have a range of 40 to 90.
val=map(analog, 0, 1023 ,40, 90);
Then do your if statement.
This will help minimize your noise because you are scaling down.
Might I suggest next to the pot you have a set press button, you automatically read the pot when you start the program and if you hold the set button ON.
Tom......
TomGeorge:
Hi,
This bit of code;off_sp_reading = ((adcReading * 5.0 / 1024.0) * SP_Sens + SP_Offset;
off_sp_reading=round(off_sp_reading *100.0) /100.0;
if ((off_sp_reading>off_temp_sp+0.05) or (off_sp_reading<off_temp_sp-0.05))
{
off_temp_sp=round(off_sp_reading *10.0) /10.0;
new_sp_detected = true;
new_sp_time = current_time;
}
The first line you calc a value o_s_p, I'm not going to write it out completely. The second line you "round" it off. So it is basically an integer. The third line you compare rounded o_s_p with I gather another rounded o_t_s + 0.05 or -0.05. Unless o_s_p = o_t_s, it will jitter o_t_s up and down. o_s_p will never be less than+ or - 0.05 of o_t_s because you have "rounded' it off. The analog input will always have some noise, although I'd like to see a picture of your project. If you want the pot to have a range of 40 to 90. val=map(analog, 0, 1023 ,40, 90); Then do your if statement. This will help minimize your noise because you are scaling down. Might I suggest next to the pot you have a set press button, you automatically read the pot when you start the program and if you hold the set button ON. Tom...... :)
off_sp_reading is a float. off_sp_reading (xxx.xxx) is multiplied by 100 (xxxxx.x), then rounded which results in nothing but the whole part (xxxxx) but is then divided by 100 to return it to a float (xxx.xx). So the map instruction doesn't work as the program is working with a number that is a float rounded to 2 decimal places.
The parenthesis is fixed, no worries.
Hi,
No worries, what is the application that needs 0.05 in 50 resolution, 1/1000?
5V, 5/1000=5mV.
5/1023bits= 4.8mV. (10bits)
One AtoD count resolution.
Tom....
TomGeorge:
Hi,
No worries, what is the application that needs 0.05 in 50 resolution, 1/1000?
5V, 5/1000=5mV.
5/1023bits= 4.8mV. (10bits)
One AtoD count resolution.Tom....
The actual resolution required is 0.1 EGU, but to add hysteresis and segregate the steps there must be something finer so 0.05 EGU.
Hi,
EGU ? ? ? What is the application?
Tom...
TomGeorge:
Hi,
EGU ? ? ? What is the application?Tom...
EnGineering Units. ie., it is the scaled adc value. Normally map() would work except it only does integers. I suppose I could use val=map(analog, 0, 1023, 4000, 9000) and just work with the scaled value *100 and then divide by 10 for the final display.
My understanding of the ADC is a value of 1024 (never reached) would equal AREF, with val=map(analog, 0, 1024, 4000, 9000).