0.1.9 AD5144A

This commit is contained in:
rob tillaart 2022-12-07 16:52:55 +01:00
parent 48611e8905
commit 5b2bc91a61
16 changed files with 211 additions and 128 deletions

View File

@ -1,7 +1,7 @@
//
// FILE: AD5144A.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.8
// VERSION: 0.1.9
// PURPOSE: I2C digital potentiometer AD5144A
// DATE: 2021-04-30
// URL: https://github.com/RobTillaart/AD5144A
@ -65,6 +65,32 @@ uint8_t AD51XX::reset()
{
// COMMAND 14 - page 29
return send(0xB0, 0x00); // to be tested
// read the cache from EEPROM.
for (uint8_t rdac = 0; rdac < _potCount; rdac++)
{
_lastValue[rdac] = readBackEEPROM(rdac);;
}
}
/////////////////////////////////////////////////////////////////////////////
//
// READ / WRITE
//
uint8_t AD51XX::read(const uint8_t rdac)
{
return _lastValue[rdac];
};
uint8_t AD51XX::write(const uint8_t rdac, const uint8_t value)
{
// COMMAND 1 - page 29
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
if (value > _maxValue) return AD51XXA_INVALID_VALUE;
_lastValue[rdac] = value;
uint8_t cmd = 0x10 | rdac;
return send(cmd, _lastValue[rdac]);
}
@ -81,17 +107,46 @@ uint8_t AD51XX::writeAll(const uint8_t value)
}
uint8_t AD51XX::write(const uint8_t rdac, const uint8_t value)
uint8_t AD51XX::zeroAll()
{
// COMMAND 1 - page 29
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
if (value > _maxValue) return AD51XXA_INVALID_VALUE;
_lastValue[rdac] = value;
uint8_t cmd = 0x10 | rdac;
return send(cmd, _lastValue[rdac]);
}
return writeAll(0);
};
uint8_t AD51XX::midScaleAll()
{
return writeAll((_maxValue + 1)/2);
};
uint8_t AD51XX::maxAll()
{
return writeAll(_maxValue);
};
uint8_t AD51XX::zero(const uint8_t rdac)
{
return write(rdac, 0);
};
uint8_t AD51XX::midScale(const uint8_t rdac)
{
return write(rdac, (_maxValue + 1)/2);
};
uint8_t AD51XX::maxValue(const uint8_t rdac)
{
return write(rdac, _maxValue);
};
/////////////////////////////////////////////////////////////////////////////
//
// EEPROM
//
uint8_t AD51XX::storeEEPROM(const uint8_t rdac)
{
// COMMAND 9 - page 29
@ -121,8 +176,10 @@ uint8_t AD51XX::storeEEPROM(const uint8_t rdac, const uint8_t value)
}
///////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// SCALE
//
uint8_t AD51XX::setTopScale(const uint8_t rdac)
{
// COMMAND 12
@ -167,7 +224,7 @@ uint8_t AD51XX::setBottomScale(const uint8_t rdac)
uint8_t AD51XX::clrBottomScale(const uint8_t rdac)
{
{
// COMMAND 13
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
uint8_t cmd = 0x90 | rdac;
@ -192,7 +249,9 @@ uint8_t AD51XX::clrBottomScaleAll()
/////////////////////////////////////////////////////////////////////////////
//
// MODE
//
uint8_t AD51XX::setLinearMode(const uint8_t rdac)
{
// COMMAND 3
@ -220,6 +279,10 @@ uint8_t AD51XX::getOperationalMode(const uint8_t rdac)
}
/////////////////////////////////////////////////////////////////////////////
//
// INCREMENT / DECREMENT
//
uint8_t AD51XX::incrementLinear(const uint8_t rdac)
{
// COMMAND 4
@ -289,7 +352,9 @@ uint8_t AD51XX::decrement6dBAll()
/////////////////////////////////////////////////////////////////////////////
//
// PRELOAD / SYNC
//
uint8_t AD51XX::preload(const uint8_t rdac, const uint8_t value)
{
// COMMAND 2 - page 29
@ -327,6 +392,10 @@ uint8_t AD51XX::sync(const uint8_t mask)
}
/////////////////////////////////////////////////////////////////////////////
//
// MISC
//
uint8_t AD51XX::shutDown()
{
// COMMAND 15 - table 29
@ -345,8 +414,7 @@ uint8_t AD51XX::writeControlRegister(uint8_t mask)
/////////////////////////////////////////////////////////////////////////////
//
// PRIVATE
//
// PROTECTED
//
// _wire->endTransmission
// returns description
@ -355,7 +423,7 @@ uint8_t AD51XX::writeControlRegister(uint8_t mask)
// 2: received NACK on transmit of address
// 3: received NACK on transmit of data
// 4: other error
//
//
uint8_t AD51XX::send(const uint8_t cmd, const uint8_t value)
{
// COMMAND 1 - page 20
@ -459,5 +527,5 @@ AD5141::AD5141(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -2,18 +2,19 @@
//
// FILE: AD5144A.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.8
// VERSION: 0.1.9
// 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.8"))
#define AD51XXA_VERSION (F("0.1.9"))
#define AD51XXA_OK 0
@ -27,7 +28,7 @@ class AD51XX
public:
explicit AD51XX(const uint8_t address, TwoWire *wire = &Wire);
// default the reset function will be called in begin(),
// 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(int dataPin, int clockPin, bool doReset = true);
@ -41,7 +42,18 @@ public:
// rdac = 0..3 - zero based indexing...
uint8_t write(const uint8_t rdac, const uint8_t value);
// fast read from cache
uint8_t read(const uint8_t rdac) { return _lastValue[rdac]; };
uint8_t read(const uint8_t rdac);
// additional write functions
uint8_t writeAll(const uint8_t value); // set all channels to same value
uint8_t zeroAll();
uint8_t midScaleAll(); // _maxValue + 1)/2
uint8_t maxAll();
uint8_t zero(const uint8_t rdac);
uint8_t midScale(const uint8_t rdac); // _maxValue + 1)/2
uint8_t maxValue(const uint8_t rdac);
uint8_t mid(const uint8_t rdac) { return midScale(rdac); }; // will be obsolete 0.2.0
// EEPROM functions
@ -51,17 +63,6 @@ public:
uint8_t recallEEPROM(const uint8_t rdac);
// 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); };
uint8_t maxAll() { return writeAll(_maxValue); };
uint8_t zero(const uint8_t rdac) { return write(rdac, 0); };
uint8_t midScale(const uint8_t rdac) { return write(rdac, (_maxValue + 1)/2); };
uint8_t mid(const uint8_t rdac) { return midScale(rdac); }; // will be obsolete
uint8_t maxValue(const uint8_t rdac) { return write(rdac, _maxValue); };
// page 27
uint8_t setTopScale(const uint8_t rdac);
uint8_t clrTopScale(const uint8_t rdac);
@ -95,7 +96,7 @@ public:
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;
// sync should not have a default mask as one doesn't know which preloads
// sync can not have a default mask as one doesn't know which preloads
// are set and which not.
uint8_t sync(const uint8_t mask);
@ -128,11 +129,9 @@ public:
protected:
uint8_t _potCount = 4; // unknown, default max
uint8_t _maxValue = 255; // unknown, default max
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);
@ -210,4 +209,4 @@ public:
};
// -- END OF FILE --
// -- END OF FILE --

View File

@ -5,21 +5,27 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.9] - 2022-12-02
- fix #21
- update readme.md + comments
- add read back cache in reset()
- move part of code to .cpp file (prep 0.2.0)
- update keywords.txt
- minor refactor
## [0.1.8] - 2022-10-25
- add rp2040 to build
- redo comments
- clean up examples
## [0.1.7] - 2022-06-21
- fix ESP32 Wire.begin datatype
## [0.1.6] - 2022-04-25
- extra comments on **sync()**
- fixed issue #14, preloading values should not change cached values
## [0.1.5] - 2022-03-14
- CHANGELOG.md: moved history from AD5144A.cpp to this file.
- fix #12 always call reset in begin().
@ -27,29 +33,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
call. The default is true ==> backwards compatibility / normal use.
- updated readme.md
## [0.1.4] - 2021-12-10
- add check for maxValue in code.
- remove experimental from version string.
- add headers to library.json,
- minor edits readme, license,
## [0.1.3] - 2021-10-17
- update build-ci
- improve readme.md
## [0.1.2] - 2021-05-12
- add increment()
- add decrement()
## [0.1.1] - 2021-05-12
- add topScale()
- add bottomScale()
## [0.1.0] - 2021-04-30
- initial version

View File

@ -10,37 +10,36 @@
Arduino library for **I2C AD5144A** 4 channel digital potentiometer.
Library has also classes for AD5123, AD5124, AD5143, AD5144, AD5144A, AD5122A, AD5142A, AD5121, AD5141
Library also provides classes for AD5123, AD5124, AD5143, AD5144, AD5144A, AD5122A, AD5142A, AD5121, AD5141.
These are have different number of potmeters, rheostats and range but are functional compatible,
## Description
The library is an experimental library for the **I2C AD5144A** 4 channel digital potentiometer.
- it is not tested extensively, (AD5144A partly)
- so use at own risk, and
- please report problems and/or success.
The library is an experimental library for the **I2C AD5144A** 4 channel digital potentiometer and compatibles.
Tests have been done with the AD5144A only.
From the datasheet it is expected that the library will work for the family of related AD devices.
See table below. However these are not tested.
From the datasheet it is expected that the library will work more or less
for the family of related AD devices. However as said before this is not tested.
If there are problems, please file an issue.
If there are problems, please file an issue. Also interested in success stories :)
This library uses the **I2C** interface to communicate with the device.
It does not work for the **SPI** versions of these devices.
The library 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 |
| 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
@ -77,6 +76,8 @@ The developer is responsible for handling these differences correctly when using
#### Derived classes
Same as above.
- **AD5123(uint8_t address, TwoWire \*wire = &Wire)**
- **AD5124(uint8_t address, TwoWire \*wire = &Wire)**
- **AD5143(uint8_t address, TwoWire \*wire = &Wire)**
@ -101,7 +102,8 @@ 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.
This loads the last values stored in EEPROM in the RDAC's.
Furthermore it reads back the values from EEPROM in to the cache.
Factory default is **midScale()** check datasheet for details.
@ -110,7 +112,7 @@ Factory default is **midScale()** check datasheet for details.
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)
(depending on device 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.
@ -133,16 +135,16 @@ Note: **reset()** resets all 4 channels from the last values stored in EEPROM.
### Asynchronous
Sets values in sequence, not at exact same time
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 zero(uint8_t rdac)** sets the selected channel to 0.
- **uint8_t midScale(uint8_t rdac)** sets the selected channel to its midpoint = 128 / 64.
- **uint8_t maxValue(uint8_t rdac)** sets the selected channel to the max 255 / 127.
### Synchronous
@ -177,6 +179,12 @@ See page 27-28 datasheet REV-C
- **uint8_t setPotentiometerMode(uint8_t rdac)**
- **// 0 = potentiometer, 1 = linear
- **uint8_t getOperationalMode(uint8_t rdac)**
### Increment / decrement
See page 27-28 datasheet REV-C
- **uint8_t incrementLinear(uint8_t rdac)**
- **uint8_t incrementLinearAll()**
- **uint8_t decrementLineair(uint8_t rdac)**
@ -205,7 +213,7 @@ Read the datasheet for the details of the individual bits.
**Warning** use with care!
### Misc
### Miscellaneous
- **uint8_t pmCount()** returns the number of potentiometers / channels the device has.
Useful when writing your own loops over all channels.
@ -221,16 +229,19 @@ The examples show the basic working of the functions.
## Future
#### must
- update documentation
- some functions can be performance optimized
- writing a value is not needed if last value is the same?
#### should
- move code from .h to .cpp (0.2.0)
- more testing with hardware.
#### could
- some functions can be performance optimized
- writing a value is not needed if last value is the same?
- should be at least written once.
- flag cacheOn + cacheDirty or so?
- improve unit testing CI
- **stereo**, write one value to two channels.
- more testing with hardware.
- SPI based version of the library ?
- SPI based version of the library (if requested)

View File

@ -5,7 +5,8 @@
// URL: https://github.com/RobTillaart/AD5144A
// THIS IS A LOW LEVEL WRITE TEST FOR AD5144A
// IT DOES NOT USE THE LIBRARY
// IT DOES NOT USE THE LIBRARY
// IT USES Wire I2C bus
#include "Arduino.h"
@ -88,4 +89,4 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -25,21 +25,21 @@ void setup()
}
// values should be same after start
for (int ch = 0; ch < AD.pmCount(); ch++)
for (int potMeter = 0; potMeter < AD.pmCount(); potMeter++)
{
Serial.print(ch);
Serial.print(potMeter);
Serial.print('\t');
Serial.print(AD.recallEEPROM(ch));
Serial.print(AD.recallEEPROM(potMeter));
Serial.print('\t');
Serial.print(AD.readBackRDAC(ch));
Serial.print(AD.readBackRDAC(potMeter));
Serial.println();
}
// update values for after next (full) power up.
for (int ch = 0; ch < AD.pmCount(); ch++)
for (int potMeter = 0; potMeter < AD.pmCount(); potMeter++)
{
uint8_t val = AD.recallEEPROM(ch);
AD.storeEEPROM(ch, val + 1);
uint8_t value = AD.recallEEPROM(potMeter);
AD.storeEEPROM(potMeter, value + 1);
}
Serial.println("done...");
@ -51,4 +51,4 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -26,10 +26,10 @@ void setup()
Serial.println("check datasheet");
Serial.println("CH\tWP\tEE\tMODE\tBURST");
for (uint8_t ch = 0; ch < AD.pmCount(); ch++)
for (uint8_t potMeter = 0; potMeter < AD.pmCount(); potMeter++)
{
uint8_t mask = AD.readBackCONTROL(ch);
Serial.print(ch);
uint8_t mask = AD.readBackCONTROL(potMeter);
Serial.print(potMeter);
Serial.print('\t');
Serial.print(mask & 0x01);
Serial.print('\t');
@ -50,4 +50,4 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -39,5 +39,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -93,19 +93,19 @@ void test_midScaleAll()
Serial.println(stop - start);
Serial.println();
for (int i = 0; i < AD.pmCount(); i++)
for (int potMeter = 0; potMeter < AD.pmCount(); potMeter++)
{
if (AD.read(i) != AD.maxValue()/2)
if (AD.read(potMeter) != AD.maxValue()/2)
{
Serial.print("non-mid:\t");
Serial.println(i);
Serial.println(potMeter);
}
}
Serial.println();
}
void test_zeroAll() // todo test
void test_zeroAll()
{
Serial.println();
Serial.println(__FUNCTION__);
@ -117,16 +117,16 @@ void test_zeroAll() // todo test
Serial.println(stop - start);
Serial.println();
for (int i = 0; i < AD.pmCount(); i++)
for (int potMeter = 0; potMeter < AD.pmCount(); potMeter++)
{
if (AD.read(i) != 0)
if (AD.read(potMeter) != 0)
{
Serial.print("non-zero:\t");
Serial.println(i);
Serial.println(potMeter);
}
}
Serial.println();
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -47,11 +47,12 @@ void test_preload()
Serial.println();
Serial.println(__FUNCTION__);
for (int val = 0; val < 256; val += 17)
for (int value = 0; value < 256; value += 17)
{
for (uint8_t ch = 0; ch < AD.pmCount(); ch++) // all channels
// loop over all channels / potmeters
for (uint8_t potMeter = 0; potMeter < AD.pmCount(); potMeter++)
{
AD.preload(ch, val);
AD.preload(potMeter, value);
}
AD.sync(0x0F);
delay(100);
@ -65,9 +66,9 @@ void test_preloadAll()
Serial.println();
Serial.println(__FUNCTION__);
for (int val = 0; val < 256; val += 17)
for (int value = 0; value < 256; value += 17)
{
AD.preloadAll(val);
AD.preloadAll(value);
AD.sync(0x0F);
delay(100);
}

View File

@ -52,17 +52,17 @@ void test_i2C_clock(uint32_t clock)
return;
}
for (int p = 0; p < AD.pmCount(); p++)
for (int potMeter = 0; potMeter < AD.pmCount(); potMeter++)
{
for (int val = 0; val < 256; val++)
for (int value = 0; value < 256; value++)
{
AD.write(p, val);
if (AD.read(p) != val)
AD.write(potMeter, value);
if (AD.read(potMeter) != value)
{
Serial.print("error:\t");
Serial.print(p);
Serial.print(potMeter);
Serial.print("\t");
Serial.print(val);
Serial.print(value);
Serial.println();
}
}

View File

@ -26,19 +26,19 @@ void setup()
// will generate 20+ lines
// decrease step 50 to 1 to test all
for (int val = 0; val < 256; val+= 50)
for (int value = 0; value < 256; value += 50)
{
for (int p = 0; p < AD.pmCount(); p++)
for (int potMeter = 0; potMeter < AD.pmCount(); potMeter++)
{
Serial.print(val);
Serial.print(value);
Serial.print("\t");
Serial.print(AD.write(p, val));
Serial.print(AD.write(potMeter, value));
Serial.print("\t");
Serial.print(p);
Serial.print(potMeter);
Serial.print("\t");
Serial.print(AD.read(p));
Serial.print(AD.read(potMeter));
Serial.print("\t");
Serial.print(AD.readBackRDAC(p));
Serial.print(AD.readBackRDAC(potMeter));
Serial.println();
}
}

View File

@ -116,5 +116,5 @@ void test_maxAll()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -28,8 +28,8 @@ writeAll KEYWORD2
zeroAll KEYWORD2
midScaleAll KEYWORD2
maxAll KEYWORD2
zeroAll KEYWORD2
mid KEYWORD2
zero KEYWORD2
midScale KEYWORD2
maxValue KEYWORD2
preload KEYWORD2
@ -48,10 +48,12 @@ clrBottomScaleAll KEYWORD2
setLinearMode KEYWORD2
setPotentiometerMode KEYWORD2
getOperationalMode KEYWORD2
incrementLinear KEYWORD2
incrementLinearAll KEYWORD2
decrementLineair KEYWORD2
decrementLineairAll KEYWORD2
increment6dB KEYWORD2
increment6dBAll KEYWORD2
decrement6dB KEYWORD2

View File

@ -1,7 +1,7 @@
{
"name": "AD5144A",
"keywords": "I2C,digital,PotentioMeter,AD5144A",
"description": "Library to control 4 channel digital potentiometer AD5144A et al.",
"description": "Library to control 4 channel digital potentiometer AD5144A et al.\nAD5123, AD5124, AD5143, AD5144, AD5144A, AD5122A, AD5142A, AD5121, AD5141",
"authors":
[
{
@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/AD5144A.git"
},
"version": "0.1.8",
"version": "0.1.9",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,8 +1,8 @@
name=AD5144A
version=0.1.8
version=0.1.9
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino Library for AD5144A 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.git