I am having trouble interfacing a precision potentiometer with my arduino, I am monitoring the output with this sketch:
/* Map an analog value to 8 bits (0 to 255) */
void setup() {
Serial.begin(9600);
}
void loop()
{
int mapval = 0;
int val = analogRead(3);
mapval = map(val, 0, 1023, 0, 1023);
// analogWrite(9, val);
Serial.println(mapval);
}
/*
Parameters
value: the number to map
fromLow: the lower bound of the value's current range
fromHigh: the upper bound of the value's current range
toLow: the lower bound of the value's target range
toHigh: the upper bound of the value's target range
*/
This is the potentiometer i'm using:
It is a 100k potentiometer, and I checked the datasheet to make sure the wiring was correct. Is the fact that it is 100k instead of 10k? I used the 3.3v pinout on the arduino...I noticed that the 5v was sometimes pulling too much power, I was using the USB cable for the power source
marco_c:
Are you wired with Pot pin 1 and 3 to the power supply and pin 2 (the wiper) to the analog input?
Yes I was, the serial.Println showed a constant high number output, and the value only dropped at the very end/beginning of the potentiometer rotation.
Test the potentiometer with a multimeter if its not marked - my 10-turn pot has the connections clearly marked. The wiper connection will probably be at the rear-end of the housing as it goes to the spindle.
In general in electronics it pays to check everything before applying power - don't assume what you can actually check (with the datasheet or a multimeter)
K, got the right output from it now, I soldered some leads to the potentiometer instead of using alligator clips and that seemed to help. It reads pretty smoothly, except when it gets to the end of the turn, when the Serial.print output is high, it jumps from the 200's up to the 600's very rapidly. should I add a resistor to it to prevent this number jump at the end of the turns? I reversed the polarity and it does the same number jump as well.
The 10-turn potentiometer is B100k. I tested the sketch with a standard single-turn B100k potentiometer, and the number output didn't jump at the end like how the 10 turn does, and had a very smooth and consistent output that didn't jump around at all. here's an example of the serial output from the 10-turn potentiometer to show what I mean...
I am using the 5v on-board power source with an 18k resistor between 5v and pin 3.
Well, I was not sure what all the jitter was with the output from the 10-turn potentiometer, but I have solved the problem by utilizing smoothing, calibration, and mapping the incoming signal. here is the code i've used:
// Define the number of samples to keep track of. The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input. Using a constant rather than a normal variable lets
// use this value to determine the size of the readings array.
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; // the average
int inputPin = A3;
int outputValue = 0; // value output to the PWM (analog out)
const int analogOutPin = 9; // Analog output pin that the LED is attached to
void setup()
{
// initialize serial communication with computer:
Serial.begin(9600);
// initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0;
}
void loop() {
// subtract the last reading:
total= total - readings[index];
// read from the sensor:
readings[index] = analogRead(inputPin);
// 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;
// send it to the computer as ASCII digits
// limits range of sensor values to between 0 and 500
average = constrain(average, 0, 500);
// map it to the range of the analog out:
outputValue = map(average, 0, 500, 0, 255);
// change the analog out value:
analogWrite(analogOutPin, outputValue);
Serial.print("outputValue =");
Serial.print(outputValue);
Serial.print("\t average =");
Serial.println(average);
delay(2); // delay in between reads for stability
}
Given the relatively high impedance of the pot you could electrically smooth the output with say a 10n or 100nF cap between wiper and ground - any noise from poor contact of the wiper on the track should be reduced, and the noise-immunity of the signal improved too. For best results place the cap near the Arduino analog input rather than at the pot's wiper.
MarkT:
Given the relatively high impedance of the pot you could electrically smooth the output with say a 10n or 100nF cap between wiper and ground - any noise from poor contact of the wiper on the track should be reduced, and the noise-immunity of the signal improved too. For best results place the cap near the Arduino analog input rather than at the pot's wiper.
I am curious about "Mapping" 10000 (100,000 ohms /10 turns) discrete values into 10 bits of available resolution, one turn would have 10 discrete values. If you look at the portion of a "Turn" that can be reported successfully. It would appear that you have large sections of the Pot that are questionable given the granularity of the available precision at 10 bits of resolution and as far as I can see worthless at 8 bits of data.
I would think that a 10000 ohm 10 turn pot would be more appropriate if still not overkill or just more data that available resolution... Given the restrictions imposed by floating point variables and the available resolution of the A/D converter.
10 bits of available resolution, one turn would have 10 discrete values
???
10 bits resulution is 0 .. 1023 --> 1 of 10 turns would cover about 100 values or ideally a different value every 4 degrees.
Mapping that down to 8 bit ( 0 .. 255 ) means a different value every 15 degrees.
Sure, 100 k is a bit high for 5 V , a total current of 50 µA is not too robust against external noise.
The operation of the AD converter already affects it. That 100nF cap would nicely feed the ADC with some more stable voltage.
10000 ohm 10 turn pot would be more appropriate
Yes.
restrictions imposed by floating point variables
Who needs floating point variables when there's a nice integer range 0 .. 1000 coming from an ADC ???
Drc3p0:
The 10-turn potentiometer is B100k. ....
I am using the 5v on-board power source with an 18k resistor between 5v and pin 3.
Either I don't understand or this 18k resistor is nonsense, making your 100k pot very non-linear ...
A simple scheme,please, Drc3p0 ? ...
No, Possibly I misspoke from ignorance of the value returned by analog in and the issues involved in conversion and based on that mistake spouted that nonsense involved in the amount of data returned per degree of rotation/turn that I was trying to get to... I should Never sit here and read the mail before my first cup of Coffee. I do Apologize. And the 10 K pot would be the best way to go.
michael_x:
Either I don't understand or this 18k resistor is nonsense, making your 100k pot very non-linear ...
A simple scheme,please, Drc3p0 ? ...
It's probably nonsense...I was just playing around with it when I was trying to restrict the value from jumping at the end of the wiper path...it's not necessary.
That measured "Jump" at the end is the beginning of the eleventh turn old school knobs for them were Vernier counters and stops at exactly ten turns so the pot never goes there, It''s gear limited to that number of turns. real Old school now with digital pots... Much more predictable. easier to change quickly. They can be used for linear distance measurement but the gearing must never be allowed to exceed Ten Turns. Work Well too.
You know, I really intended for this to be uploaded to an ATTINY85v. I didn't even think about how the majority of the functions in the sketch aren't even supported by AVR. oh well, bulky ATmega's it is.