Go Down

Topic: Arduino library for X9C103P digital potentiometer (Read 2 times) previous topic - next topic

tfager

Hi all,

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).

robtillaart


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..

Idea:
* 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.

Succes
Rob


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

tfager

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 :)

robtillaart

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

of

setAbs(uint8_t percentage);   // 0..100%

with both you can easily implement reset()..

Keep us updated of your progress!

regards,
Rob
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

tfager

Hello,

The library was updated to be compatible with Arduino 1.0. Also the suggested set() was added to set absolute potentiometer values.

https://sites.google.com/site/tfagerscode/home/digipotx9cxxx

robtillaart

Thanks for posting this update,

Quote
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

Code: [Select]

void DigiPot::reset()
{
  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) 
    change(DIGIPOT_DOWN, DIGIPOT_MAX_AMOUNT);

  else if (_currentValue > value)
    change(DIGIPOT_DOWN, _currentValue-value);

  else if (_currentValue < value)
    change(DIGIPOT_UP, value - _currentValue);
}

uint8_t DigiPot::get()
{
  return _currentValue;
}

void DigiPot::increase(uint8_t amount)
{
  change(DIGIPOT_UP, amount);
}

void DigiPot::decrease(uint8_t amount)
{
  change(DIGIPOT_DOWN, 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..
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up