Introduction: MCP41HVX1 Digital Potentiometer for Arduino

The MCP41HVX1 family of digital potentiometers (aka DigiPots) are devices that mimic the function of an analog potentiometer and are controlled thru SPI. An example application would be replacing the volume knob on your stereo with a DigiPot that is controlled by an Arduino. This assumes that the volume control on your stereo is a potentiometer and not a rotary encoder.

MCP41HVX1 are a little different then other DigiPots in that they have a split rail design. This means that while the DigiPot itself can be controlled by the output voltage of an Arduino, the signal that is passed thru the resistor network works with a far greater range of voltage (up to 36 volts). Most DigiPots that can be controlled by 5 volts are limited to 5 volts across the resistor network which restricts their usage for retrofitting an existing circuit that operates on higher voltage such as what you would find in a car or boat.

The MCP41HVX1 family is made up of the following chips:

  • MCP41HV31-104E/ST - 100k ohm (7 bits)
  • MCP41HV31-503E/ST - 50k ohm (7 bits)
  • MCP41HV31-103E/ST - 10k ohm (7 bits)
  • MCP41HV31-502E/ST - 5k ohm (7 bits)
  • MCP41HV31-103E/MQ - 10k ohm (7 bits)
  • MCP41HV51-104E/ST - 100k ohm (8 bits)
  • MCP41HV51-503E/ST - 50k ohm (8 bits)
  • MCP41HV51T-503E/ST - 50k ohm (8 bits)
  • MCP41HV51-103E/ST - 10k ohm (8 bits)
  • MCP41HV51-502E/ST - 5k ohm (8 bits)

The 7 bit chips allow for 128 steps in the resistor network and 8 bit chips allow for 256 steps in the resistor network. This means that 8 bit chips allow for twice as many resistance values from the potentiometer.

Supplies

  • Choose the appropriate MCP41HVX1 chip from the list above. The chip you select is based on the resistance range required for your application. This Instructable is based on the TSSOP 14 package versions of the chip so to follow along with this guide pick any chip in the list except for the MCP41HV31-103E/MQ which is a QFN package. It is recommended to get a few extra chips as I did encounter a bad one and they are inexpensive. I ordered mine from Digi-Key.
  • Secondary DC power supply that is from 10 to 36 volts. In my example I use a 17 volt wall wart DC power supply from my box of old power supplies.
  • Soldering flux
  • Soldering iron
  • Solder
  • Tweezers and\or toothpick
  • TSSOP 14 pin breakout board - Amazon - QLOUNI 40pcs PCB Proto Boards SMD to DIP Adapter Plate Converter TQFP (32 44 48 64 84 100) SOP SSOP TSSOP 8 10 14 16 20 23 24 28 (Assortment of sizes. Plenty available for multiple projects)
  • Quantify of 2 - 7 pin headers - Amazon - DEPEPE 30 Pcs 40 Pin 2.54mm Male and Female Pin Headers for Arduino Prototype Shield - (Cut to size needed. Plenty in the package for multiple projects)
  • Arduino Uno - if you don't have one I would suggest getting an official board. I have had mixed luck with the unofficial versions. Digi-Key - Arduino Uno
  • Multi-meter which can measure resistance and also check for continuity
  • Jumper wires
  • Breadboard
  • Highly recommended but not absolutely required is a hands free magnifier as the TSSOP chips are very small. You will need both hands for soldering and testing with the multi-meter. I use a pair of Harbor Freight 3x Clip-On Magnifiers on top of my prescription glasses and a free standing\articulated magnifying glass. Other options are a pair of inexpensive readers from the discount or dollar store. You can even wear the readers over your prescription glasses or get two pairs of readers (one of top of the other) depending on how good (or bad) your vision is. If you are doubling up on glasses be careful as your range of vision will be very limited so make sure to take them off before doing anything else. Also be extra careful when soldering.
  • One other item that is not required but highly recommended is the Harbor Freight Helping Hands. They are alligator clips attached to a metal base. These are available from many other vendors on the internet as well under different brand names. These are very helpful when soldering the chip onto the breakout board.

Step 1: Soldering the TSSOP Chip to a Breakout Board

The TSSOP chip needs to be soldered to a breakout board so that you can use it with a breadboard or directly with DuPont jumpers. For prototyping work they are much too small to work with directly.

Due to their small size, soldering the TSSOP chip may be the most challenging part of this project but knowing the trick to doing this makes it a task that anyone can accomplish. There are several techniques, the one below is what I did.

The strategy is to flow the solder on to the traces of the breakout board first.

  • Do not put the chip on to the breakout board until instructed.
  • First thing to do is put a generous amount of flux onto the breakout board.
  • Next, using your soldering iron heat some solder and flow it on to the traces.
  • Put some more flux on top of the solder that you flowed out on the traces as well as the bottom of the legs of the chip.
  • Place the chip on top of the traces where you just placed solder and flux. Tweezers or a toothpick make for good tools for precisely setting the chip in place. Make sure to align the chip properly so the all pins are directly above the traces. Align pin one of the chip with the marking for pin one on the break out board.
  • Using your soldering iron heat one of the pins on the end of the chip (either pin 1, 7, 8, or 14) pressing it into the trace. The solder that you previously applied will melt and flow around the pin.

Watch the video in this step to see a demonstration of how to solder the chip to the breakout board. One suggestion that I have that is different from the video is that after you have soldered the first pin stop and recheck for alignment of the entire chip to make sure that all the pins are still on top of the traces. If you are off a bit it is easy to correct at this point. Once you are comfortable everything looks good, solder another pin at the opposite end of the chip and check alignment again. If that looks good go ahead and do the rest of the pins.

After you have soldered all the pins the video suggests using a magnifying glass to verify your connections. A better method is to use a multimeter to check continuity. You should place one probe on to the leg of the pin and the other probe onto the part of the board where you will solder the header (see the second picture in this step). You should also check the adjacent pins to make sure that they are not connected due to solder shorting several pins together. So for example if you are verifying pin 4, also check pin 3 and pin 5. Pin 4 should show continuity while pin 3 and pin 5 should show an open circuit. The only exception is the wiper P0W may show connectivity to P0A or P0B.

TIPS:

  • As mentioned in the materials list having some magnification available that leaves your hands free to work will be very helpful in this step.
  • Using the alligator clip helping hands to hold the breakout board makes soldering everything a bit easier.
  • Write the chip number on a piece of masking tape and stick to the bottom of the breakout board (see the third picture in this section). If in the future you need to identify the chip it will be much easier to read off the masking tape. My personal experience is that I got a little bit of flux on the chip and the number came off completely so all I have is the tape.

Step 2: Wiring

You will need to connect the Arduino and Digipot as shown in the wiring diagram. The pins that are being used are based on the layout of an Arduino Uno. If you are using a different Arduino see the last step.

Step 3: Getting the Arduino Library for Controlling the DigiPot

To simplify programing I have created a library that is available on Github. Go to github.com/gregsrabian/MCP41HVX1 to get the MCP41HVX1 library. You will want to select the "Clone" button and then select "Download Zip". Make sure to save the Zip file to a location that you know where it is at. The desktop or downloads folder are handy locations. Once you import it into the Arduino IDE you can delete it from the download location.

Step 4: Importing the New Library Into the Arduino IDE

Within the Arduino IDE go to "Sketch", then select "Include Library", then choose "Add ZIP Library..". A new dialog box will appear allowing you to select the .ZIP file that you downloaded from GitHub.

Step 5: Library Examples

After you have added the new library you will notice that if you go to "File", then select "Examples", and then choose "Examples from Custom Libraries" you will now see an entry for MCP41HVX1 in the list. If you hover over that entry you will see WLAT, Wiper Control, and SHDN which are example sketches. In this Instructable we will be using the Wiper Control example.

Step 6: Examining the Source Code

#include "MCP41HVX1.h"

// Define the pins used on the Arduino
#define WLAT_PIN 8 // If set to Low "transfer and use"
#define SHDN_PIN 9 // Set high to enable the resistor network
#define CS_PIN 10 // Set to low to select chip for SPI

// Define some values used for the test app
#define FORWARD true
#define REVERSE false
#define MAX_WIPER_VALUE 255 // Maximum wiper valued

MCP41HVX1 Digipot( CS_PIN, SHDN_PIN, WLAT_PIN);

void setup ()
{
Serial.begin( 9600);
Serial.print( "Starting Position = ");
Serial.println( Digipot.WiperGetPosition()); // Display initial value
Serial.print( "Set Wiper Position = ");
Serial.println( Digipot.WiperSetPosition( 0)); // Set wiper position to 0
}

void loop ()
{
static bool bDirection = FORWARD;
int nWiper = Digipot.WiperGetPosition(); // Get current wiper position
// Determine the direction.
if( MAX_WIPER_VALUE == nWiper)
{
bDirection = REVERSE;
}
else if( 0 == nWiper)
{
bDirection = FORWARD;
}
// Move the digipot wiper
if( FORWARD == bDirection)
{
nWiper = Digipot.WiperIncrement(); // The direction is forward
Serial.print( "Increment - ");
}
else
{
nWiper = Digipot.WiperDecrement(); // The direction is backward
Serial.print( "Decrement - ");
}

Serial.print( "Wiper Position = ");
Serial.println( nWiper);

delay( 100);
}

Step 7: Understanding the Source Code and Running the Sketch

This source code is available within the Arduino IDE by going to the Examples menu and locating MCP41HVX1 that you just installed (see previous step). Within MCP41HVX1 open up the "Wiper Control" example. It is best to use the code that is included with the library as if there are any bug fixes it will be updated.

The Wiper Control example demonstrates the following APIs from the MCP41HVX1 library:

  • Constructor MCP41HVX1( int nCSPin, int nSHDNPin, int nWLATPin)
  • WiperGetPosition()
  • WiperSetPosition( byte byWiper)
  • WiperIncrement()
  • WiperDecrement()

Within the sample source code make sure to set MAX_WIPER_VALUE to 127 if you are using a 7 bit chip. The default is 255 which is for 8 bit chips. If you make changes to the sample the Arduino IDE will force you to pick a new name for the project as it won't let you update the example code. This is expected behavior.

Each time thru the loop the wiper will increment by one step or decrement by one step depending on the direction it is going. If the direction is up and it gets to the MAX_WIPER_VALUE it will reverse direction. If it hits 0 it will reverse again.

As the sketch runs the serial monitor is updated with the current wiper position.

To see the resistance change you will need to use a multimeter set to read Ohms. Put the meter probes on P0B (pin 11) and P0W (pin 12) on the digipot to see the resistance change as the application is running. Note that the resistance value will not go all the way down to zero as there is some internal resistance within the chip but it will get close to 0 ohms. It will most likely not go to the max value either but will be close.

As you watch the video you can see the multimeter shows the resistance increasing until it reaches the max value and then starts to decrease. The chip being used in the video is the MCP41HV51-104E/ST which is an 8 bit chip with 100k ohm max value.

Step 8: Troubleshooting

If things are not working as expected here are a few things to look at.

  • Verify your wiring. Everything must be connected correctly. Make sure that you are using the full wiring diagram as stated in this Instructable. There are alternate wiring diagrams presented in the README, library source code, and down below in this Instructable but stick with what is documented above in the Wiring step above.
  • Make sure that every pin on your digitpot is soldered to the breakout board. Using visual inspection is not good enough. Make sure that you verify using the continuity function of your multimeter to verify that all of the pins on the digipot are electrically connected to the breakout board and there is no cross connection of pins from solder that may have bridged across traces.
  • If the serial monitor is showing that the wiper position is changing when you run the sketch but the resistance value is not changing that is an indicator that WLAT or SHDN is not making a proper connection to the breakout board or the jumper wipers for WLAT or SHDN are not connected properly to the Arduino.
  • Make sure that you are using a secondary power supply that is DC between 10 and 36 volts.
  • Ensure that the 10 to 36 volt power supply is working by measuring the voltage with your multimeter.
  • Try using the original sketch. If you made any changes you may have introduced an error.
  • If none of the troubleshooting steps have helped try another digipot chip. Hopefully you bought several and soldered them at the same time to a TSSOP breakout board so it should just be a matter of swapping out one for the other. I had a bad chip which caused me quite a bit of frustration and this was the fix.

Step 9: Internals & Additional Information

Further Information:

Further information can be found in the MCP41HVX1 data sheet.

Full documentation on the entire MCP41HVX1 library is available in the README.md file which is part of the library download. This file is written in mark down and be can be viewed with proper formatting within Github (look at the bottom of the page) or with a mark down viewer\editor.

Communications between Arduino and the DigiPot:

The Arduino communicates with the DigiPot using SPI. After the library sends a wiper position command such as WiperIncrement, WiperDecrement, or WiperSetPosition it then calls WiperGetPosition to get the wiper position from the chip. The value returned from these Wiper commands is the position of the wiper as the chip sees it and can be used to verify that the wiper has moved to the expected location.

Advanced Functionality (WLAT & SHDN)

These advanced functions are not demonstrated in the "Wiper Control" example. There are APIs available in the library for controlling WLAT & SHDN. There is also WLAT and SHDN example sketches (in the same location as the Wiper Control sketch) with the library.

SHDN (Shutdown)

SHDN is used to disable or enable the resistor network. Setting SHDN to low disables and high enables the resistor network. When the resistor network is disabled P0A (DigiPot pin 13) is disconnected and P0B (DigiPot pin 11) is connected to P0W (DigiPot pin 12). There will be a small amount of resistance between P0B and P0W so your meter will not read 0 ohms.

If your application has no need to control SHDN you can wire it directly to HIGH (see alternate wiring diagram). You will need to use the correct constructor or pass in MCP41HVX1_PIN_NOT_CONFIGURED to the constructor to indicate that SHDN is hard wired. It is important to note that if you are following along with the example you must use the full wiring diagram (see Wiring step above).

WLAT (Write Latch)

The internal architecture is two components on a single chip. One of the components is the SDI interface and the register to hold the wiper value. The other component is the resistor network itself. WLAT connects both internal components together.

When WLAT is set to LOW any set wiper position command information is passed directly to the resistor network and the wiper position is updated.

If WLAT is set to HIGH the wiper position information passed in through SPI is held in an internal register but is not passed to the resistor network and therefore the wiper position will not update. Once WLAT is set to LOW the value is transferred from the register to the resistor network.

WLAT is useful if you are using multiple digipots that you need to keep in sync. The strategy is to set WLAT to HIGH on all of the digipots and then set the wiper value on all the chips. Once the wiper value has been sent to all the digipots WLAT can be set to LOW on all devices simultaneously so that they all move the wipers at the same time.

If you are only controlling one DigiPot or have multiple but they don't need to be kept in sync you most likely won't need this functionality and can therefore wire WLAT directly to LOW (see alternate wiring diagram). You will need to use the correct constructor or pass in MCP41HVX1_PIN_NOT_CONFIGURED to the constructor to indicate that WLAT is hard wired. It is important to note that if you are following along with the example you must use the full wiring diagram (see Wiring step above).

Step 10: Alternate Wiring Diagram

Wiring

You have the option of connecting WLAT from the digpot directly to LOW\GND instead of connecting to a digital pin. If you do this then you will not be able to control WLAT. You also have the option of connecting SHDN directly to HIGH instead of a digital pin. If you do this you will not be able to control SHDN.

WLAT and SHDN are independent of each other so you can hard wire one and connect the other to a digital pin, hard wire both, or connect both to digital pins so that they can be controlled. Refer to the alternate wiring diagram for the ones that you want to hard wire and refer back to the main wiring diagram in step 2 for wiring to controllable digital pins.

Constructors

There are three constructors in the MCP41HVX class. We will be discussing two of them. They are all documented in the README.md file so if interested in the third constructor please refer to the documentation.

  • MCP41HVX1( int nCSPin) - use this constructor only if both WLAT and SHDN are hard wired.
  • MCP41HVX1( int nCSPin, int nSHDNPin, int nWLATPin) - Use this constructor if either WLAT or SHDN are hard wired. Pass in the constant MCP41HVX1_PIN_NOT_CONFIGURED if the pin is hard wired or the pin number if it is connected to a digital pin.

nCSPin must be connected to a digital pin. It is invalid to pass MCP41HVX1_PIN_NOT_CONFIGURED to the constructor for nCSPin.


What If Am Not Using An Arduino Uno?

The Arduino uses SPI to communicate to the digipot. The SPI pins are specific pins on the Arduino board. The SPI pins on the Uno are:

  • SCK - pin 13 on the Uno connected to pin 2 on the digipot
  • MOSI - pin 11 on the Uno connected to pin 4 on the digipot
  • MISO - pin 12 on the Uno connected to pin 5 on the digipot

If you are using an Arduino that is not an Uno you will need to figure out which pin is SCK, MOSI, and MISO and connect those to the digipot.

The other pins used in the sketch are regular digital pins so any digital pin will work. You will need to modify the sketch to specify the pins that you choose on the Arduino board that you are using. The regular digital pins are:

  • CS - pin 10 on the Uno connected to pin 3 on the digipot (update CS_PIN in the sketch with new value)
  • WLAT - pin 8 on the Uno connected to pin 6 on the digipot (update WLAT_PIN in the sketch with new value)
  • SHDN - pin 9 on the Uno connected to pin 7 on the digipot (update SHDN_PIN in the sketch with new value)