Non-linear resistance in a digital potentiometer

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.

Thanks.

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.

jack

I would like to comment that -103 in the part name means that it is a 0-10K rheostat... not 0-5K.

At least that's what 103 means to me... 10 + 3 zeros = 10,000 Ohms

Pete

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);
}

If you are using the device as a rheostat, the error appears to be much larger than when used as a potentiometer...

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

jack

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.

Um, dumb question for newbs like me... What's the difference between a potentiometer and a rheostat?

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.

jack

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?

Lefty

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.

Daanii can you please supply a sketch of your hook-up so that we can better understand your application.

Here is a webpage that shows the wiring diagram for the motor controller I want to control electronically:

http://www.alltraxinc.com/files/Doc100-047-A_DWG-AXE-PermMag-wire-dia.pdf

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:

http://www.alltraxinc.com/files/Doc100-049-A_DWG-AXE-Taylor-Dunn-wire-dia.pdf

(NOTE: This wiring diagram shows the +6.0V to +10.5V speed signal option. I will probably use the 0V to +5V option instead.)

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.

Lefty

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.

Thanks for the help on this, Lefty and others.

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!

For more info... Potentiometer - Wikipedia

I need to source at least 50 mA, which is more than the Arduino PWM pins put out.

It's also more than the digital POT is supposed to be able to source...