0.1.5 AD5144A

This commit is contained in:
rob tillaart 2022-03-15 11:36:35 +01:00
parent 087fd4488a
commit 5c94b97699
6 changed files with 211 additions and 99 deletions

View File

@ -1,32 +1,24 @@
//
// FILE: AD5144A.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.4
// VERSION: 0.1.5
// PURPOSE: I2C digital potentiometer AD5144A
// DATE: 2021-04-30
// URL: https://github.com/RobTillaart/AD5144A
//
// HISTORY
// 0.1.0 2021-04-30 initial version
// 0.1.1 2021-05-12 add topScale() and bottomScale()
// 0.1.2 2021-05-12 add increment() and decrement() functions
// 0.1.3 2021-10-17 update build-ci, improve readme.md
// 0.1.4 2021-12-10 remove experimental from version string.
// add headers to library.json,
// minor edits readme, license,
// add check for maxValue in code.
// Datasheet: REV-C 7/2019
#include "AD5144A.h"
// Commands page 29 datasheet
// Commands page 29 datasheet
//
// not implemented (yet)
// 0 NOP
// 4 5 linear RDAC in/decrement
// 6 7 6dB RDAC in/decrement
// 12 13 top scale bottom scale ???
// not implemented (yet)
// 0 NOP
// 4 5 linear RDAC in/decrement
// 6 7 6dB RDAC in/decrement
// 12 13 top scale bottom scale ???
AD51XX::AD51XX(const uint8_t address, TwoWire *wire)
@ -37,7 +29,7 @@ AD51XX::AD51XX(const uint8_t address, TwoWire *wire)
#if defined (ESP8266) || defined(ESP32)
bool AD51XX::begin(uint8_t dataPin, uint8_t clockPin)
bool AD51XX::begin(uint8_t dataPin, uint8_t clockPin, bool doReset)
{
_wire = &Wire;
if ((dataPin < 255) && (clockPin < 255))
@ -47,17 +39,17 @@ bool AD51XX::begin(uint8_t dataPin, uint8_t clockPin)
_wire->begin();
}
if (! isConnected()) return false;
reset();
if (doReset) reset(); // See page 28 datasheet
return true;
}
#endif
bool AD51XX::begin()
bool AD51XX::begin(bool doReset)
{
_wire->begin();
if (! isConnected()) return false;
midScaleAll(); // is this what we want?
if (doReset) reset(); // See page 28 datasheet
return true;
}
@ -128,11 +120,12 @@ uint8_t AD51XX::storeEEPROM(const uint8_t rdac, const uint8_t value)
return send(cmd, value);
}
///////////////////////////////////////////////////////////
uint8_t AD51XX::setTopScale(const uint8_t rdac)
{
// COMMAND 12
// COMMAND 12
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
uint8_t cmd = 0x90 | rdac;
return send(cmd, 0x81);
@ -141,7 +134,7 @@ uint8_t AD51XX::setTopScale(const uint8_t rdac)
uint8_t AD51XX::clrTopScale(const uint8_t rdac)
{
// COMMAND 12
// COMMAND 12
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
uint8_t cmd = 0x90 | rdac;
return send(cmd, 0x80);
@ -150,7 +143,7 @@ uint8_t AD51XX::clrTopScale(const uint8_t rdac)
uint8_t AD51XX::setTopScaleAll()
{
// COMMAND 12
// COMMAND 12
uint8_t cmd = 0x98;
return send(cmd, 0x81);
}
@ -197,7 +190,8 @@ uint8_t AD51XX::clrBottomScaleAll()
return send(cmd, 0x00);
}
///////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
uint8_t AD51XX::setLinearMode(const uint8_t rdac)
{
@ -294,7 +288,7 @@ uint8_t AD51XX::decrement6dBAll()
}
///////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
uint8_t AD51XX::preload(const uint8_t rdac, const uint8_t value)
{
@ -349,7 +343,7 @@ uint8_t AD51XX::writeControlRegister(uint8_t mask)
}
//////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// PRIVATE
//
@ -385,15 +379,14 @@ uint8_t AD51XX::readBack(const uint8_t rdac, const uint8_t mask)
a = _wire->endTransmission();
// Serial.print(" TX: ");
// Serial.println(a);
a = _wire->requestFrom(_address, (uint8_t)1);
Serial.print(" RF: ");
Serial.println(a);
// Serial.print(" RF: ");
// Serial.println(a);
return _wire->read();
}
//////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES
//
@ -459,4 +452,6 @@ AD5141::AD5141(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
_maxValue = 255;
}
// -- END OF FILE --

View File

@ -2,17 +2,18 @@
//
// FILE: AD5144A.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.4
// VERSION: 0.1.5
// PURPOSE: I2C digital PotentioMeter AD5144A
// DATE: 2021-04-30
// URL: https://github.com/RobTillaart/AD5144A
//
// Datasheet: REV-C 7/2019
#include "Arduino.h"
#include "Wire.h"
#define AD51XXA_VERSION (F("0.1.4"))
#define AD51XXA_VERSION (F("0.1.5"))
#define AD51XXA_OK 0
@ -26,29 +27,31 @@ class AD51XX
public:
explicit AD51XX(const uint8_t address, TwoWire *wire = &Wire);
// default the reset function will be called in begin(),
// by setting doReset to false one can skip this explicitly.
#if defined (ESP8266) || defined(ESP32)
bool begin(uint8_t sda, uint8_t scl);
bool begin(uint8_t sda, uint8_t scl, bool doReset = true);
#endif
bool begin();
bool begin(bool doReset = true);
bool isConnected();
uint8_t reset();
// BASE functions
// rdac = 0..3 - zero based indexing...
// BASE functions
// rdac = 0..3 - zero based indexing...
uint8_t write(const uint8_t rdac, const uint8_t value);
// fast read from cache
// fast read from cache
uint8_t read(const uint8_t rdac) { return _lastValue[rdac]; };
// EEPROM functions
// defines power up value; copies between RDAC and EEPROM
// EEPROM functions
// defines power up value; copies between RDAC and EEPROM
uint8_t storeEEPROM(const uint8_t rdac);
uint8_t storeEEPROM(const uint8_t rdac, const uint8_t value);
uint8_t recallEEPROM(const uint8_t rdac);
// ASYNC functions
// ASYNC functions
uint8_t writeAll(const uint8_t value); // set all channels to same value
uint8_t zeroAll() { return writeAll(0); };
uint8_t midScaleAll() { return writeAll((_maxValue + 1)/2); };
@ -59,7 +62,7 @@ public:
uint8_t maxValue(const uint8_t rdac) { return write(rdac, _maxValue); };
// page 27
// page 27
uint8_t setTopScale(const uint8_t rdac);
uint8_t clrTopScale(const uint8_t rdac);
uint8_t setTopScaleAll();
@ -70,10 +73,10 @@ public:
uint8_t clrBottomScaleAll();
// page 27-28
// page 27-28
uint8_t setLinearMode(const uint8_t rdac);
uint8_t setPotentiometerMode(const uint8_t rdac);
// 0 = potentiometer, 1 = linear
// 0 = potentiometer, 1 = linear
uint8_t getOperationalMode(const uint8_t rdac);
uint8_t incrementLinear(const uint8_t rdac);
@ -86,45 +89,47 @@ public:
uint8_t decrement6dBAll();
// SYNC functions
// preload registers to change all channels synchronous
// SYNC functions
// preload registers to change all channels synchronous
uint8_t preload(const uint8_t rdac, const uint8_t value);
uint8_t preloadAll(const uint8_t value);
// copy the preloads to the channels. The bit mask indicates which channels
// b00001101 would indicate channel 0, 2 and 3;
// copy the preloads to the channels. The bit mask indicates which channels
// b00001101 would indicate channel 0, 2 and 3;
uint8_t sync(const uint8_t mask);
// MISC
// MISC
uint8_t pmCount() { return _potCount; };
uint8_t maxValue() { return _maxValue; };
uint8_t shutDown();
// returns the value from internal registers.
// returns the value from internal registers.
uint8_t readBackINPUT(const uint8_t rdac) { return readBack(rdac, 0x00); };
uint8_t readBackEEPROM(const uint8_t rdac) { return readBack(rdac, 0x01); };
uint8_t readBackCONTROL(const uint8_t rdac) { return readBack(rdac, 0x02); };
uint8_t readBackRDAC(const uint8_t rdac) { return readBack(rdac, 0x03); };
// USE WITH CARE - READ DATASHEET
// write to control register
// USE WITH CARE - READ DATASHEET
// write to control register
//
// value : 0 1
// bit 0 : FREEZE RDAC's normal operation
// bit 1 : EEPROM DISABLED normal operation
// bit 2 : normal operation LINEAR GAIN MODE
// bit 3 : normal operation BURST MODE
// value : 0 1
// bit 0 : FREEZE RDAC's normal operation
// bit 1 : EEPROM DISABLED normal operation
// bit 2 : normal operation LINEAR GAIN MODE
// bit 3 : normal operation BURST MODE
//
uint8_t writeControlRegister(uint8_t mask);
// TODO separate get set functions ?
// TODO separate get set functions ?
// uint8_t writeControlRegisterBit(uint8_t mask);
protected:
uint8_t _potCount = 4; // unknown, default max
uint8_t _maxValue = 255; // unknown, default max
private:
uint8_t send(const uint8_t cmd, const uint8_t value);
uint8_t readBack(const uint8_t rdac, const uint8_t mask);
@ -146,48 +151,56 @@ public:
AD5123(const uint8_t address, TwoWire *wire = &Wire);
};
class AD5124 : public AD51XX
{
public:
AD5124(const uint8_t address, TwoWire *wire = &Wire);
};
class AD5143 : public AD51XX
{
public:
AD5143(const uint8_t address, TwoWire *wire = &Wire);
};
class AD5144 : public AD51XX
{
public:
AD5144(const uint8_t address, TwoWire *wire = &Wire);
};
class AD5144A : public AD51XX
{
public:
AD5144A(const uint8_t address, TwoWire *wire = &Wire);
};
class AD5122A : public AD51XX
{
public:
AD5122A(const uint8_t address, TwoWire *wire = &Wire);
};
class AD5142A : public AD51XX
{
public:
AD5142A(const uint8_t address, TwoWire *wire = &Wire);
};
class AD5121 : public AD51XX
{
public:
AD5121(const uint8_t address, TwoWire *wire = &Wire);
};
class AD5141 : public AD51XX
{
public:

View File

@ -0,0 +1,77 @@
# Change Log
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.5] - 2022-03-14
### Added
- CHANGELOG.md: moved history from AD5144A.cpp to this file.
- fix #12 always call reset in begin().
- add flag to **begin(bool doReset = true)** to explcitly disable the reset
call. The default is true ==> backwards compatibility / normal use.
### Changed
- updated readme.md
### Fixed
## [0.1.4] - 2021-12-10
### Added
- add check for maxValue in code.
### Changed
- remove experimental from version string.
- add headers to library.json,
- minor edits readme, license,
### Fixed
## [0.1.3] - 2021-10-17
### Added
### Changed
- update build-ci
- improve readme.md
### Fixed
## [0.1.2] - 2021-05-12
### Added
- add increment()
- add decrement()
### Changed
### Fixed
## [0.1.1] - 2021-05-12
### Added
- add topScale()
- add bottomScale()
### Changed
### Fixed
## [0.1.0] - 2021-04-30
### Added
- initial version
### Changed
### Fixed

View File

@ -10,6 +10,7 @@
Arduino library for **I2C AD5144A** 4 channel digital potentiometer.
LIbrary has also classes for AD5123, AD5124, AD5143, AD5144, AD5144A, AD5122A, AD5142A, AD5121, AD5141
## Description
@ -27,6 +28,31 @@ It does not work for the **SPI** versions of these devices.
See Future below.
### Types supported
| device | #potmeters | # rheostats | range | tested |
|:--------|:-----------:|:-----------:|:------:|:-------:|
| AD5123 | 2 | 2 | 0..127 | no |
| AD5124 | 4 | 0 | 0..127 | no |
| AD5143 | 2 | 2 | 0..255 | no |
| AD5144 | 4 | 0 | 0..255 | partial |
| AD5144A | 4 | 0 | 0..255 | partial |
| AD5122A | 2 | 0 | 0..127 | no |
| AD5142A | 2 | 0 | 0..255 | no |
| AD5121 | 1 | 0 | 0..127 | no |
| AD5141 | 1 | 0 | 0..255 | no |
### Type AD51xy decomposition
- x = 2 => range = 0..127
- x = 4 => range = 0..255
- y = 1 => 1 potmeter
- y = 2 => 2 potmeters
- y = 4 => 4 potmeters
- y = 3 => 2 potmeters + 2 rheostats
## I2C
For the selection of the address, see table 12 / 13 datasheet.
@ -41,25 +67,14 @@ The library has a number of functions which are all quite straightforward.
As the library is experimental, function signatures might change in the future.
### Constructors
### Constructor
- **AD51XX(uint8_t address, TwoWire \*wire = &Wire)** base class, to set the I2C address and optional the Wire bus used.
This class does not distinguish between the derived classes.
The developer is responsible for handling this correctly when using the base class.
The developer is responsible for handling these differences correctly when using the base class.
| device | #potmeters | # rheostats | range | tested |
|:--------|:-----------:|:-----------:|:------:|:-------:|
| AD5123 | 2 | 2 | 0..127 | no |
| AD5124 | 4 | 0 | 0..127 | no |
| AD5143 | 2 | 2 | 0..255 | no |
| AD5144 | 4 | 0 | 0..255 | partial |
| AD5144A | 4 | 0 | 0..255 | partial |
| AD5122A | 2 | 0 | 0..127 | no |
| AD5142A | 2 | 0 | 0..255 | no |
| AD5121 | 1 | 0 | 0..127 | no |
| AD5141 | 1 | 0 | 0..255 | no |
Derived classes:
#### Derived classes
- **AD5123(uint8_t address, TwoWire \*wire = &Wire)**
- **AD5124(uint8_t address, TwoWire \*wire = &Wire)**
@ -72,20 +87,28 @@ Derived classes:
- **AD5141(uint8_t address, TwoWire \*wire = &Wire)**
### I2C / device initialization
- **bool begin(uint8_t sda, uint8_t scl)** ESP32 a.o initializing of Wire.
Returns true if the address of the device can be found on the I2C bus.
- **bool begin()** for UNO, returns true if the address of the device can be found on the I2C bus.
- **bool isConnected()** returns true if the address of the device can be found on the I2C bus.
- **uint8_t reset()** calls the built in RESET command, check datasheet for details,
- **bool begin(uint8_t sda, uint8_t scl, bool doReset = true)** ESP32 a.o initializing of the I2C data and clock pins.
If these pins are set to 255 the default pins will be used.
If **doReset** == true (default) **reset()** is called, to load last values stored in EEPROM.
Returns true if the address of the device can be found on the I2C bus. If the device cannot be found, **reset()** won't be called, even if **doReset** == true.
- **bool begin()** for UNO, if **doReset** == true (default) **reset()** is called, to load last values stored in EEPROM.
Returns true if the address of the device can be found on the I2C bus. If the device cannot be found, **reset()** won't be called, even if **doReset** == true.
- **bool isConnected()** returns true if the address of the device can be found on the I2C bus, false otherwise.
- **uint8_t reset()** calls the built in RESET command.
This loads the last values stored in EEPROM in the RDAC's.
Factory default is **midScale()** check datasheet for details.
### Basic IO
Used to set one channel at the time.
- **uint8_t write(uint8_t rdac, uint8_t value)** set channel rdac 0..3 to value 0..255 (depending on type less channels and lower max value should be used)
- **uint8_t write(uint8_t rdac, uint8_t value)** set channel rdac 0..3 to value 0..255
(depending on type less channels and lower max value should be used)
The value is also written into a cache of last set values for fast retrieval later.
If value > maxValue an error **AD51XXA_INVALID_VALUE** is returned.
- **uint8_t read(uint8_t rdac)** read back set value from the **cache**, not from the device.
@ -93,7 +116,7 @@ If value > maxValue an error **AD51XXA_INVALID_VALUE** is returned.
### EEPROM
The value stored in the EEPROM is the value the 4 potmeters will start at boot time.
The value stored in the EEPROM is the value the 4 potentiometers will start at boot time.
This allows to start at predefined values and makes it possibly easier to continue after
a reboot.
@ -102,34 +125,37 @@ a reboot.
If value > maxValue an error **AD51XXA_INVALID_VALUE** is returned.
- **uint8_t recallEEPROM(uint8_t rdac)** get the value from EEPROM and set the channel.
Note: **reset()** resets all 4 channels from the last values stored in EEPROM.
(Page 28 datasheet REV-C)
### Async
### Asynchronous
Sets values in sequence, not at exact same time
- **uint8_t writeAll(uint8_t value)** write the same value to all channels.
If value > maxValue an error **AD51XXA_INVALID_VALUE** is returned.
- **uint8_t zeroAll()** sets all channels to 0
- **uint8_t midScaleAll()** sets all channels to their midpoint 128 / 64
- **uint8_t maxAll()** sets all channels to the max 255 / 127
- **uint8_t zero(uint8_t rdac)** sets one channel to 0
- **uint8_t midScale(uint8_t rdac)** sets one channel to its midpoint = 128 / 64
- **uint8_t maxValue(uint8_t rdac)** sets one channel to the max 255 / 127
- **uint8_t zeroAll()** sets all channels to 0.
- **uint8_t midScaleAll()** sets all channels to their midpoint 128 / 64.
- **uint8_t maxAll()** sets all channels to the max 255 / 127.
- **uint8_t zero(uint8_t rdac)** sets one channel to 0.
- **uint8_t midScale(uint8_t rdac)** sets one channel to its midpoint = 128 / 64.
- **uint8_t maxValue(uint8_t rdac)** sets one channel to the max 255 / 127.
### Sync
### Synchronous
- **uint8_t preload(uint8_t rdac, uint8_t value)** prepare a single rdac for a new value but only use it after **sync()** is called.
If value > maxValue an error **AD51XXA_INVALID_VALUE** is returned.
- **uint8_t preloadAll(uint8_t value)** prepare all rdacs with the same value, and wait for **sync()**.
If value > maxValue an error **AD51XXA_INVALID_VALUE** is returned.
- **uint8_t sync(uint8_t mask)** will transfer the preloaded values to the (4) rdacs at the very same moment.
The 4-bit mask is used to select which rdacs to sync.
The 4-bit mask is used to select which rdacs to synchronize.
### TopScale BottomScale
See page 27 datasheet
See page 27 datasheet REV-C
- **uint8_t setTopScale(uint8_t rdac)**
- **uint8_t clrTopScale(uint8_t rdac)**
@ -143,7 +169,7 @@ See page 27 datasheet
### Operational modes
See page 27-28 datasheet
See page 27-28 datasheet REV-C
- **uint8_t setLinearMode(uint8_t rdac)**
- **uint8_t setPotentiometerMode(uint8_t rdac)**
@ -165,7 +191,8 @@ These function read back from the internal registers of the actual device.
- **uint8_t readBackINPUT(uint8_t rdac)** reads back the "preload value" in the INPUT register.
- **uint8_t readBackEEPROM(uint8_t rdac)** reads the **boot value** for the selected rdac from EEPROM.
- **uint8_t readBackCONTROL(uint8_t rdac)** read back the control register. Read the datasheet for the details of the individual bits.
- **uint8_t readBackCONTROL(uint8_t rdac)** read back the control register.
Read the datasheet for the details of the individual bits.
- **uint8_t readBackRDAC(uint8_t rdac)** reads the value of the rdac from the device.
@ -180,7 +207,7 @@ Read the datasheet for the details of the individual bits.
- **uint8_t pmCount()** returns the number of potentiometers / channels the device has.
Useful when writing your own loops over all channels.
- **uint8_t maxValue()** return maxValue (127 / 255) of the potentiometer.
- **uint8_t maxValue()** return maxValue of the potentiometer. Values expected are 127 or 255.
- **uint8_t shutDown()** check datasheet, not tested yet, use at own risk.
@ -195,7 +222,7 @@ The examples show the basic working of the functions.
- update documentation
- some functions can be performance optimized
- writing a value is not needed if last value is the same?
**could**
- improve unit testing CI
- more testing with hw

View File

@ -1,6 +1,6 @@
{
"name": "AD5144A",
"keywords": "I2C,digital,PotentioMeter, AD5144A",
"keywords": "I2C,digital,PotentioMeter,AD5144A",
"description": "Library to control 4 channel digital potentiometer AD5144A et al.",
"authors":
[
@ -13,9 +13,9 @@
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/AD5144A"
"url": "https://github.com/RobTillaart/AD5144A.git"
},
"version": "0.1.4",
"version": "0.1.5",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,11 +1,11 @@
name=AD5144A
version=0.1.4
version=0.1.5
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino Library for AD5144A
paragraph=4 Channel digital potentiometer
sentence=Arduino Library for AD5144A 4 Channel digital potentiometer
paragraph=Also for AD5123, AD5124, AD5143, AD5144, AD5144A, AD5122A, AD5142A, AD5121, AD5141
category=Signal Input/Output
url=https://github.com/RobTillaart/AD5144A
url=https://github.com/RobTillaart/AD5144A.git
architectures=*
includes=AD5144A.h
depends=