I ended up with an X9C103P digital potentiometer (like this: http://uk.farnell.com/intersil/x9c103pz/ic-digital-pot-10k-9c103-dip8/dp/1208129) , and didn't find an Arduino library for it, so I coded one myself. And figured, why not make my first attempt on sharing the library as well. So feel free to download and give it a spin: https://sites.google.com/site/tfagerscode/home/digipotx9cxxx.
The zip file includes a Fritzing (http://www.fritzing.org/) picture on how to connect the chip. It should work also for other chips of the same family (X9Cxxx, xxx=102,103,104,503 according to datasheet).
Had a quick look at the code and it looks nice , still some remarks.
- why not mapping the UP and DOWN as follows?
define DIGIPOT_UP HIGH (or 1)
define DIGIPOT_DOWN LOW (or 0)
would make change() a bit simpler
direction can be of type uint8_t, big enough to hold LOW/HIGH value.
pinnumbers in the constructor can be uint8_t (aka byte)
unsigned prevents negative numbers
and the range is big enough I guess
==> also the private vars to hold the pinnrs can be uint8_t
void increase(int amount);
as amount is a signed int it can accept negative numbers. Note that the for loop inside change() needs a positive amount.
Solution: Use an uint16_t for amount !
what is the max value of amount? you might consider using the constrain function ...
idem for decrease() and change() signatures..
* It might be interesting to hold the cumulative value of all changes since start in a signed long. MIght be indicative for its value.
Can the value be read from the digipot?
Still, well done for a first lib.
Thanks a lot, Rob, for your comments. It's good to see that there's feedback available for newbies.
I uploaded an updated version of the library with datatype, direction handling and constrain() changes you suggested.
The ability to read back the changes I left for future development. I've also been thinking adding some reset() call, to reset the pot into a known state (like zero), and after that the library could hold the actual state of the potentiometer, and also set it to an absolute value. But, later maybe :)
Your welcome, that is what a forum is all about!
Think reset() is a good idea, but a just a special case of an absolute setting.
The code now is sort of relative setting increase/decrease etc
You could do someting like
setAbs(uint16_t value); 0..maxvalue
setAbs(uint8_t percentage); // 0..100%
with both you can easily implement reset()..
Keep us updated of your progress!
The library was updated to be compatible with Arduino 1.0. Also the suggested set() was added to set absolute potentiometer values.
Thanks for posting this update,
v.4, updated on May 26, 2011: modified to be compatible with Arduino 1.0; added set() to set absolute potentiometer values.
typo on the website - hint it is the year
You might add a link in the header of the .cpp /.h file to this thread to discuss the functionality.
Did some refactoring to optimize the code as some checks were made double - just give it a look if you like it
also caught one bug in set() ==> if the _currentValue is unknown you may not do math with it I assume
change(DIGIPOT_DOWN, DIGIPOT_MAX_AMOUNT); //_currentValue should in fact be enough...?
void DigiPot::set(uint8_t value)
value = constrain(value, 0, DIGIPOT_MAX_AMOUNT);
if (_currentValue == DIGIPOT_UNKNOWN)
else if (_currentValue > value)
else if (_currentValue < value)
change(DIGIPOT_UP, value - _currentValue);
void DigiPot::increase(uint8_t amount)
void DigiPot::decrease(uint8_t amount)
Change() can be optimized by not allways doing amount steps automatically but check if _currentValue == 0 or max too. But it might make the code more complex.
I’ll think it over…
Is there somewhere a simple schematic on how to use x9c103p with arduino?
The datasheet should be helpful for that, did you check it?