I'm using the Arduino to set the resistance in a digital potentiometer. The digital pot is an MCP4162-103E/P that goes from 0 to 5k Ohms.
After setting the resistance, I measure the voltage on the wiper using an Arduino analog input. I noticed that the voltage is quite non-linear.
At low resistances, the voltage changes in smaller jumps than it should as the resistance increases. As the resistance gets toward the top of the scale, the voltage changes in bigger jumps than it should.
Does that seem right? Or could there be a problem in my code or in my circuit? I'm pretty new to using SPI, and more of a programmer than an engineer. So I may be missing something obvious to those more skilled.
It sounds like you are "loading" the device with some other component or your coding is non-linear. Can you provide a diagram of exactly how you have the device connected and a copy of your coding - no-one can critique either your circuit or code unless you supply a copy of them.
As already mentioned, the part number you mention is a 10k device, not a 5k.
Microchip offers an app note that talks about the non-linerarity and even has a section on improving accuracy.
While I have never worked with Digital Potentiometers, I do know that in projects I've worked on these devices were the subject of much calibration. The fact that Microchip has an entire app note on "Understanding Digital Resistor Variations" suggests what you are seeing is probably normal.
Thanks for the responses. I did indeed order a 0 to 10k pot thinking it was 0 to 5k. That I will correct.
Thanks also for the notes on calibration. That will be a bother in my application, but I can deal with it.
It does seem like the non-linearity is something I will just have to deal with as well.
But the Microchip materials made me think the non-linearity would be on the order of less than 1%. So I was surprised to find the fairly significant non-linearity shown in the following printout:
Pot Level: 0000 Pot Value: 0986
Pot Level: 0001 Pot Value: 0973
Pot Level: 0002 Pot Value: 0958
Pot Level: 0003 Pot Value: 0945
Pot Level: 0004 Pot Value: 0932
Pot Level: 0005 Pot Value: 0920
Pot Level: 0006 Pot Value: 0907
Pot Level: 0007 Pot Value: 0894
Pot Level: 0008 Pot Value: 0884
Pot Level: 0009 Pot Value: 0873
Pot Level: 0010 Pot Value: 0862
Pot Level: 0011 Pot Value: 0851
Pot Level: 0012 Pot Value: 0840
Pot Level: 0013 Pot Value: 0830
Pot Level: 0014 Pot Value: 0820
Pot Level: 0015 Pot Value: 0810
Pot Level: 0016 Pot Value: 0800
Pot Level: 0017 Pot Value: 0790
Pot Level: 0018 Pot Value: 0781
Pot Level: 0019 Pot Value: 0773
Pot Level: 0020 Pot Value: 0764
Pot Level: 0021 Pot Value: 0754
Pot Level: 0022 Pot Value: 0746
Pot Level: 0023 Pot Value: 0738
Pot Level: 0024 Pot Value: 0730
Pot Level: 0025 Pot Value: 0721
Pot Level: 0026 Pot Value: 0713
Pot Level: 0027 Pot Value: 0706
Pot Level: 0028 Pot Value: 0699
Pot Level: 0029 Pot Value: 0691
Pot Level: 0030 Pot Value: 0685
Pot Level: 0031 Pot Value: 0677
Pot Level: 0032 Pot Value: 0672
Pot Level: 0033 Pot Value: 0665
Pot Level: 0034 Pot Value: 0659
Pot Level: 0035 Pot Value: 0652
Pot Level: 0036 Pot Value: 0646
Pot Level: 0037 Pot Value: 0640
Pot Level: 0038 Pot Value: 0635
Pot Level: 0039 Pot Value: 0629
Pot Level: 0040 Pot Value: 0623
Pot Level: 0041 Pot Value: 0618
Pot Level: 0042 Pot Value: 0612
Pot Level: 0043 Pot Value: 0607
Pot Level: 0044 Pot Value: 0601
Pot Level: 0045 Pot Value: 0596
Pot Level: 0046 Pot Value: 0591
Pot Level: 0047 Pot Value: 0586
Pot Level: 0048 Pot Value: 0581
Pot Level: 0049 Pot Value: 0576
Pot Level: 0050 Pot Value: 0571
Pot Level: 0051 Pot Value: 0567
Pot Level: 0052 Pot Value: 0562
Pot Level: 0053 Pot Value: 0558
Pot Level: 0054 Pot Value: 0552
Pot Level: 0055 Pot Value: 0548
Pot Level: 0056 Pot Value: 0545
Pot Level: 0057 Pot Value: 0540
Pot Level: 0058 Pot Value: 0536
Pot Level: 0059 Pot Value: 0531
Pot Level: 0060 Pot Value: 0527
Pot Level: 0061 Pot Value: 0523
Pot Level: 0062 Pot Value: 0519
Pot Level: 0063 Pot Value: 0515
Pot Level: 0064 Pot Value: 0511
Pot Level: 0065 Pot Value: 0508
Pot Level: 0066 Pot Value: 0504
Pot Level: 0067 Pot Value: 0500
Pot Level: 0068 Pot Value: 0496
Pot Level: 0069 Pot Value: 0493
Pot Level: 0070 Pot Value: 0490
Pot Level: 0071 Pot Value: 0486
Pot Level: 0072 Pot Value: 0483
Pot Level: 0073 Pot Value: 0479
Pot Level: 0074 Pot Value: 0476
Pot Level: 0075 Pot Value: 0473
Pot Level: 0076 Pot Value: 0469
Pot Level: 0077 Pot Value: 0466
Pot Level: 0078 Pot Value: 0463
Pot Level: 0079 Pot Value: 0459
Pot Level: 0080 Pot Value: 0456
Pot Level: 0081 Pot Value: 0453
Pot Level: 0082 Pot Value: 0450
Pot Level: 0083 Pot Value: 0448
Pot Level: 0084 Pot Value: 0445
Pot Level: 0085 Pot Value: 0442
Pot Level: 0086 Pot Value: 0439
Pot Level: 0087 Pot Value: 0435
Pot Level: 0088 Pot Value: 0433
Pot Level: 0089 Pot Value: 0431
Pot Level: 0090 Pot Value: 0428
Pot Level: 0091 Pot Value: 0425
Pot Level: 0092 Pot Value: 0422
Pot Level: 0093 Pot Value: 0420
Pot Level: 0094 Pot Value: 0418
Pot Level: 0095 Pot Value: 0414
Pot Level: 0096 Pot Value: 0412
Pot Level: 0097 Pot Value: 0409
Pot Level: 0098 Pot Value: 0407
Pot Level: 0099 Pot Value: 0404
Pot Level: 0100 Pot Value: 0402
Pot Level: 0101 Pot Value: 0400
Pot Level: 0102 Pot Value: 0397
Pot Level: 0103 Pot Value: 0395
Pot Level: 0104 Pot Value: 0393
Pot Level: 0105 Pot Value: 0390
Pot Level: 0106 Pot Value: 0388
Pot Level: 0107 Pot Value: 0386
Pot Level: 0108 Pot Value: 0384
Pot Level: 0109 Pot Value: 0382
Pot Level: 0110 Pot Value: 0380
Pot Level: 0111 Pot Value: 0377
Pot Level: 0112 Pot Value: 0375
Pot Level: 0113 Pot Value: 0373
Pot Level: 0114 Pot Value: 0371
Pot Level: 0115 Pot Value: 0369
Pot Level: 0116 Pot Value: 0367
Pot Level: 0117 Pot Value: 0365
Pot Level: 0118 Pot Value: 0363
Pot Level: 0119 Pot Value: 0361
Pot Level: 0120 Pot Value: 0359
Pot Level: 0121 Pot Value: 0357
Pot Level: 0122 Pot Value: 0355
Pot Level: 0123 Pot Value: 0353
Pot Level: 0124 Pot Value: 0352
Pot Level: 0125 Pot Value: 0350
Pot Level: 0126 Pot Value: 0348
Pot Level: 0127 Pot Value: 0346
Pot Level: 0128 Pot Value: 0345
Pot Level: 0129 Pot Value: 0343
Pot Level: 0130 Pot Value: 0341
Pot Level: 0131 Pot Value: 0339
Pot Level: 0132 Pot Value: 0338
Pot Level: 0133 Pot Value: 0336
Pot Level: 0134 Pot Value: 0334
Pot Level: 0135 Pot Value: 0332
Pot Level: 0136 Pot Value: 0331
Pot Level: 0137 Pot Value: 0329
Pot Level: 0138 Pot Value: 0327
Pot Level: 0139 Pot Value: 0326
Pot Level: 0140 Pot Value: 0325
Pot Level: 0141 Pot Value: 0323
Pot Level: 0142 Pot Value: 0321
Pot Level: 0143 Pot Value: 0320
Pot Level: 0144 Pot Value: 0318
Pot Level: 0145 Pot Value: 0317
Pot Level: 0146 Pot Value: 0315
Pot Level: 0147 Pot Value: 0314
Pot Level: 0148 Pot Value: 0313
Pot Level: 0149 Pot Value: 0311
Pot Level: 0150 Pot Value: 0310
Pot Level: 0151 Pot Value: 0308
Pot Level: 0152 Pot Value: 0307
Pot Level: 0153 Pot Value: 0306
Pot Level: 0154 Pot Value: 0304
Pot Level: 0155 Pot Value: 0303
Pot Level: 0156 Pot Value: 0302
Pot Level: 0157 Pot Value: 0300
Pot Level: 0158 Pot Value: 0299
Pot Level: 0159 Pot Value: 0298
Pot Level: 0160 Pot Value: 0296
Pot Level: 0161 Pot Value: 0295
Pot Level: 0162 Pot Value: 0293
Pot Level: 0163 Pot Value: 0292
Pot Level: 0164 Pot Value: 0291
Pot Level: 0165 Pot Value: 0290
Pot Level: 0166 Pot Value: 0288
Pot Level: 0167 Pot Value: 0287
Pot Level: 0168 Pot Value: 0286
Pot Level: 0169 Pot Value: 0285
Pot Level: 0170 Pot Value: 0284
Pot Level: 0171 Pot Value: 0282
Pot Level: 0172 Pot Value: 0281
Pot Level: 0173 Pot Value: 0281
Pot Level: 0174 Pot Value: 0279
Pot Level: 0175 Pot Value: 0278
Pot Level: 0176 Pot Value: 0277
Pot Level: 0177 Pot Value: 0276
Pot Level: 0178 Pot Value: 0275
Pot Level: 0179 Pot Value: 0273
Pot Level: 0180 Pot Value: 0272
Pot Level: 0181 Pot Value: 0271
Pot Level: 0182 Pot Value: 0271
Pot Level: 0183 Pot Value: 0269
Pot Level: 0184 Pot Value: 0268
Pot Level: 0185 Pot Value: 0267
Pot Level: 0186 Pot Value: 0266
Pot Level: 0187 Pot Value: 0265
Pot Level: 0188 Pot Value: 0264
Pot Level: 0189 Pot Value: 0263
Pot Level: 0190 Pot Value: 0261
Pot Level: 0191 Pot Value: 0260
Pot Level: 0192 Pot Value: 0259
Pot Level: 0193 Pot Value: 0258
Pot Level: 0194 Pot Value: 0258
Pot Level: 0195 Pot Value: 0257
Pot Level: 0196 Pot Value: 0256
Pot Level: 0197 Pot Value: 0255
Pot Level: 0198 Pot Value: 0254
Pot Level: 0199 Pot Value: 0253
Pot Level: 0200 Pot Value: 0251
Pot Level: 0201 Pot Value: 0250
Pot Level: 0202 Pot Value: 0249
Pot Level: 0203 Pot Value: 0249
Pot Level: 0204 Pot Value: 0248
Pot Level: 0205 Pot Value: 0247
Pot Level: 0206 Pot Value: 0246
Pot Level: 0207 Pot Value: 0245
Pot Level: 0208 Pot Value: 0245
Pot Level: 0209 Pot Value: 0243
Pot Level: 0210 Pot Value: 0243
Pot Level: 0211 Pot Value: 0241
Pot Level: 0212 Pot Value: 0241
Pot Level: 0213 Pot Value: 0240
Pot Level: 0214 Pot Value: 0239
Pot Level: 0215 Pot Value: 0238
Pot Level: 0216 Pot Value: 0238
Pot Level: 0217 Pot Value: 0236
Pot Level: 0218 Pot Value: 0235
Pot Level: 0219 Pot Value: 0235
Pot Level: 0220 Pot Value: 0234
Pot Level: 0221 Pot Value: 0233
Pot Level: 0222 Pot Value: 0233
Pot Level: 0223 Pot Value: 0232
Pot Level: 0224 Pot Value: 0231
Pot Level: 0225 Pot Value: 0230
Pot Level: 0226 Pot Value: 0230
Pot Level: 0227 Pot Value: 0228
Pot Level: 0228 Pot Value: 0228
Pot Level: 0229 Pot Value: 0227
Pot Level: 0230 Pot Value: 0226
Pot Level: 0231 Pot Value: 0225
Pot Level: 0232 Pot Value: 0225
Pot Level: 0233 Pot Value: 0224
Pot Level: 0234 Pot Value: 0223
Pot Level: 0235 Pot Value: 0222
Pot Level: 0236 Pot Value: 0222
Pot Level: 0237 Pot Value: 0221
Pot Level: 0238 Pot Value: 0220
Pot Level: 0239 Pot Value: 0220
Pot Level: 0240 Pot Value: 0219
Pot Level: 0241 Pot Value: 0218
Pot Level: 0242 Pot Value: 0218
Pot Level: 0243 Pot Value: 0217
Pot Level: 0244 Pot Value: 0216
Pot Level: 0245 Pot Value: 0215
Pot Level: 0246 Pot Value: 0215
Pot Level: 0247 Pot Value: 0214
Pot Level: 0248 Pot Value: 0213
Pot Level: 0249 Pot Value: 0213
Pot Level: 0250 Pot Value: 0212
Pot Level: 0251 Pot Value: 0211
Pot Level: 0252 Pot Value: 0211
Pot Level: 0253 Pot Value: 0210
Pot Level: 0254 Pot Value: 0210
I'm out of space here, so I'll put my Arduino code and a description of my circuit in another reply.
In my circuit, I have the SPI control signal, clock and data output pins from the Arduino hooked up to the corresponding pins on the digital potentiometer.
The pot terminal is hooked up to the +5 V pin on the Arduino. The wiper terminal goes through a 2.5k Ohm resistor to ground. Then I also take the signal off the wiper terminal to the analog input pin 0 on the Arduino.
My code is this:
// include the SPI library:
#include <SPI.h>
#define potInputPin 0
// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;
int potValue;
void setup() {
// start serial port at 9600 bits per second
Serial.begin(9600);
// clear the serial port buffer
Serial.flush();
// set the slaveSelectPin as an output:
pinMode (slaveSelectPin, OUTPUT);
// initialize SPI:
SPI.begin();
}
void loop() {
// change the resistance from min to max:
for (int level = 0; level < 255; level = level + 1) {
digitalPotWrite(0, level);
Serial.print("Pot Level: ");
printNum(level);
Serial.print("\t");
delay(100);
potValue = analogRead(potInputPin);
Serial.print("Pot Value: ");
printNum(potValue);
Serial.print("\n");
}
// wait a second at the top:
Serial.print("\n");
delay(100);
// change the resistance from max to min:
for (int level = 0; level < 255; level = level + 1) {
digitalPotWrite(0, 255 - level);
Serial.print("Pot Level: ");
printNum(255 - level);
Serial.print("\t");
delay(100);
potValue = analogRead(potInputPin);
Serial.print("Pot Value: ");
printNum(potValue);
Serial.print("\n");
}
delay(30000);
}
int digitalPotWrite(int command, int value) {
// take the SS pin low to select the chip:
digitalWrite(slaveSelectPin,LOW);
// send in the value via SPI:
SPI.transfer(command);
SPI.transfer(value);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin,HIGH);
}
void printNum(int Value) {
int Thous = char(Value/1000);
Serial.write(Thous+48);
Value = Value - Thous * 1000;
int Huns = char(Value/100);
Serial.write(Huns+48);
Value = Value - Huns * 100;
int Tens = char(Value/10);
Serial.write(Tens+48);
Value = Value - Tens * 10;
int Ones = char(Value);
Serial.write(Ones+48);
}
The 2.5k to ground is your problem. It loads the potentiometer (think of 2 resistors in parallel) such that non-linear output occurs. When you have the pot set at 100% (10k) the output will be 5 volts since the load resistor is across the whole pot and has no effect. When the pot is set at 50% (5k) the 2.5k in parallel creates a parallel pair which measures 1.66k. This is in series with the remaining 5k and the series voltage divider is now 5k +1.66k so the output will be 1.25volts rather than the 2.5volts expected. The problem occurs at all settings of the pot, other than 0% and 100% and is extreme at higher percentages but has less effect the nearer you get to 0%
To minimise the effect the load resistor should be at least 10 times the value of the pot, say 100k
To minimise the effect the load resistor should be at least 10 times the value of the pot, say 100k
Thanks, that makes sense. I'll need to pick up some 100k Ohm resistors. I tried a 1M Ohm, but it did not work well.
Do I even need the resistor to ground?
I noted on the datasheet for the digital potentiometer that the maximum current going through the pot was 2.5 mA, so I put in the 2.5k Ohm resistor.
I'm not sure what the current would be if I had the wiper terminal connected just to the Arduino analog input pin, and not through the resistor to ground. Something tells me, though, that it is best not to try it. So I have not.
You may be trying to measure something that doesn't really matter in the greater scheme of things, and/or something (like error) that must be evaluated IN CONTEXT (i.e. in the complete circuit, not as an abstract measurement).
That's true. My goal with this circuit was just to test out a 0 to 5k Ohm digital potentiometer. That would help me design the circuit for the ultimate application.
I did learn a few things. As you note, I actually have a digital rheostat, not a digital potentiometer. As others have noted, I actually have a 0 to 10k Ohm device, not 0 to 5k.
More importantly, as you note, and as Jack explained, the linearity problem is probably an artifact of my test circuit, more than of the actual resistance of the rheostat. So I should probably move on to the ultimate application.
The ultimate application is to build an electronic throttle. I have an Alltrax AXE 4834 motor controller that I want to control electronically using the Arduino instead of a mechanical twist-grip Hall sensor throttle based on a 0 to 5k potentiometer.
A rheostat is basically a 2-terminal variable resistor. A potentiometer is a 3 terminal device composed of a length of resistance material with a pick-up (wiper) that can be slid along it.
A rheostat can be made from a potentiometer by simply using one of the resistance ends and the wiper terminal. For completeness the unused resistor terminal should also be connected to the wiper terminal. This means that, should the wiper fail or disconnect from the resistance element, there will always be the total resistance left in circuit, rather than an open connection.
Daanii can you please supply a sketch of your hook-up so that we can better understand your application.
Seen on the product description for your motor controller the speed input signal can be one of several:
?Throttle Input:
[ch9702]ITS (inductive)
[ch9702]Resistive 0-5K ohm (+/-10%)
[ch9702]5K-0 ohm (+/-10%)
[ch9702]0-5Volt
[ch9702]6-10Volt
It would seem to me the easiest, simplest, and possibly most reliable one to use with an Arduino is the 0-5vdc option. Than you could just utilize the Arduino PWM analogWrite() command. Electrically you would just need to low pass filter the pwm output with a simple single resistor/cap filter, possibly followed with a unity gain voltage follower opamp if the input impedance of the motor controller is too low for using just the filtered output. I would think this should be explored before adding the cost and complexity and learning curve of a digital pot for this application?
Daanii can you please supply a sketch of your hook-up so that we can better understand your application.
Yes, I'll do that.
It would seem to me the easiest, simplest, and possibly most reliable one to use with an Arduino is the 0-5vdc option.
You are right. That simple approach may indeed work.
But the people at Alltrax have given me conflicting information about the "black box" circuit I will be hooking into. At one point, they told me that if I will be using the 0 to +5V option, I need to source at least 50 mA, which is more than the Arduino PWM pins put out.
So I am preparing two circuits. One circuit will use the Arduino PWM output pin, with a low-pass filter as you so rightly suggest. (I had not thought about the op amp voltage follower, but that may indeed be needed.) The other circuit will use a digital potentiometer (or rheostat).
Not knowing which circuit will work best for this project, having both available will be best. I've got some time before the motors and controllers will be set up and ready to hook my circuit up to.
The throttle shown in the upper left corner is the one I want to create the circuit for. Now people use a mechanical potentiometer -- either an accelerator pedal or a twist-grip throttle. I want to use a digital potentiometer circuit instead.
An alternative wiring diagram shows the voltage (instead of resistance) speed input signal retrolefty suggests using:
So I am preparing two circuits. One circuit will use the Arduino PWM output pin, with a low-pass filter as you so rightly suggest. (I had not thought about the op amp voltage follower, but that may indeed be needed.) The other circuit will use a digital potentiometer (or rheostat).
If their speed input signal pin indeed needs up to 50ma of driving impedenace then a digital pot is not going to work either, as if you look at digital pot datasheets you most likey will find that they can handle near that kind of load.
If you use my suggestion you will need a unity gain voltage follower opamp following the r/c filter, however you will have to look carefully at opamp specs for current drive capacity. Most won't do 50ma, but I'm certain that there are some avalible that can.
If their speed input signal pin indeed needs up to 50ma of driving impedenace then a digital pot is not going to work either, as if you look at digital pot datasheets you most likey will find that they can handle near that kind of load.
Looks like I'll need to lean on Alltrax for more information about their controller. Then I won't be shooting in the dark with circuits that might not handle the current.
There are basically 2 types of POT one is LOG or logarithmic, the other is LIN or linear.
The efect that you have described, suggests that you have a LOG or logarithmic pot, where the resistance change slowly at one of the scale and gradually increases in speed, before rapidly changing towards the other end of the scale. With a LIN or linear pot, the resistance change will gradually change evenly across the WHOLE range.
The main difference between a rheostat and a potentiohmeter is the current handling capacity of the rheostat, a lot of 'stats' have the same 3 terminal configeration as a 'pot' and effectively do the same job...vary resistance!