0.1.1 MAX520

This commit is contained in:
Rob Tillaart 2024-03-07 13:18:08 +01:00
parent 009a981537
commit 1cc33356a6
16 changed files with 353 additions and 52 deletions

View File

@ -6,7 +6,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: arduino/arduino-lint-action@v1
with:
library-manager: update

View File

@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6

View File

@ -10,7 +10,7 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: json-syntax-check
uses: limitusus/json-syntax-check@v1
with:

View File

@ -6,5 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.1] - 2024-03-07
- improve documentation
- fix reset() value byte
- fix example addresses
- add examples
- update keywords.txt
- update unit_test
## [0.1.0] - 2024-03-06
- initial version

View File

@ -2,8 +2,8 @@
// FILE: MAX520.cpp
// AUTHOR: Rob Tillaart
// DATE: 2024-03-06
// VERSION: 0.1.0
// PURPOSE: Arduino library for MAX520/521 4/8 channel 8 bit DAC.
// VERSION: 0.1.1
// PURPOSE: Arduino library for MAX520 and MAX521 4/8 channel 8 bit DAC.
// URL: https://github.com/RobTillaart/MAX520
@ -30,10 +30,7 @@ MAX520::MAX520(const uint8_t deviceAddress, TwoWire *wire)
bool MAX520::begin()
{
if (! isConnected()) return false;
for (int i = 0; i < _channels; i++)
{
_values[i] = 0;
}
reset();
return true;
}
@ -82,7 +79,8 @@ int MAX520::write(uint8_t channel, uint8_t value)
}
// TODO optimize. page 11 figure 7
// Can be optimized with one I2C transaction.
// page 11 figure 7
int MAX520::write(uint8_t * values)
{
for (int i = 0; i < _channels; i++)
@ -115,8 +113,13 @@ int MAX520::read(uint8_t channel)
//
int MAX520::reset()
{
for (int i = 0; i < _channels; i++)
{
_values[i] = 0;
}
_wire->beginTransmission(_address);
_wire->write(MAX520_RESET);
_wire->write(0x00); // needs a value to ignore
return _wire->endTransmission();
}

View File

@ -3,8 +3,8 @@
// FILE: MAX520.h
// AUTHOR: Rob Tillaart
// DATE: 2024-03-06
// VERSION: 0.1.0
// PURPOSE: Arduino library for MAX520/521 4/8 channel 8 bit DAC.
// VERSION: 0.1.1
// PURPOSE: Arduino library for MAX520 and MAX521 4/8 channel 8 bit DAC.
// URL: https://github.com/RobTillaart/MAX520
@ -12,7 +12,7 @@
#include "Wire.h"
#define MAX520_LIB_VERSION (F("0.1.0"))
#define MAX520_LIB_VERSION (F("0.1.1"))
#define MAX520_OK 0x00
#define MAX520_CHANNEL_ERROR 0x81

View File

@ -11,30 +11,62 @@
# MAX520
Arduino library for MAX520/521 4/8 channel 8 bit DAC.
Arduino library for MAX520 and MAX521 4/8 channel 8 bit DAC.
## Description
**Experimental**
The MAX520 is a 4 channel 8 bit DAC. It has no output buffer amplifiers,
giving it very low supply current.
The MAX520 is a 4 channel 8 bit DAC. The 520 has no output buffer amplifiers,
giving it low supply current. See datasheet for details.
The output range of the MAX520 4 DACs depends on the 4 VREF inputs.
You can have e.g. one from 0.0-5.0V one from 0.0-3.3V and two from 0.0-2.5V.
The output range of the MAX520 4 DACs depends on the **FOUR** VREF inputs.
You can have e.g. one from 0.0-5.0V, one from 0.0-3.3V and two from 0.0-2.5V.
This provides a flexibility, many other DAC's do not have.
The MAX520 is a write only device, so the library provides a cache of the last
written values per DAC. These cached values are set to 0 when **begin()** is called.
At startup and after **reset()** the outputs of the 4 DAC's are 0V.
The MAX521 is an 8 channel 8 bit DAC. The 521 has output amplifiers to they can
provide more current. See datasheet for details.
The MAX521 is a 8 channel 8 bit DAC.
The output range of the MAX521 8 DACs depends on the **FIVE** VREF inputs.
OUT0..OUT3 use VREF0..VREF3 and OUT4..OUT7 all use VREF4.
After calling **begin()** the user has to write the values per DAC.
| Device | Output | VREF | buffered | time | Notes |
|:--------:|:---------:|:--------:|:----------:|:------:|:-------:|
| MAX520 | OUT_0 | VREF_0 | N | 2 |
| MAX520 | OUT_1 | VREF_1 | N | 2 |
| MAX520 | OUT_2 | VREF_2 | N | 2 |
| MAX520 | OUT_3 | VREF_3 | N | 2 |
| | | | | |
| MAX521 | OUT_0 | VREF_0 | Y | 6 |
| MAX521 | OUT_1 | VREF_1 | Y | 6 |
| MAX521 | OUT_2 | VREF_2 | Y | 6 |
| MAX521 | OUT_3 | VREF_3 | Y | 6 |
| MAX521 | OUT_4..7 | VREF_4 | Y | 6 | shared VREF4 |
_time = time to settle a value in microseconds_
The MAX52x comes in various types with different working ranges (e.g. temperature).
See datasheet for details.
As always feedback about the library or device behaviour is welcome.
After calling **begin()** the user has to write the values per DAC or call **reset()**
#### Related
TODO other DAC libraries.
- https://github.com/RobTillaart/MAX520
- https://github.com/RobTillaart/MCP_DAC
- https://github.com/RobTillaart/MCP4725
- https://github.com/RobTillaart/DAC8550
- https://github.com/RobTillaart/DAC8551
- https://github.com/RobTillaart/DAC8552
- https://github.com/RobTillaart/DAC8554
@ -42,15 +74,33 @@ TODO other DAC libraries.
#### I2C addresses
| device | address pins | addresses |
|:--------:|:--------------:|:--------------:|
| MAX520 | 3 | 0x20 .. 0x27 |
| MAX521 | 2 | 0x20 .. 0x23 |
| Device | Address pins | Address range |
|:--------:|:--------------:|:----------------:|
| MAX520 | 3 | 0x20..0x27 |
| MAX521 | 2 | 0x20..0x23 |
#### I2C Performance
up to 400 KHz.
The devices are rated up to 400 KHz. Given that setting a DAC takes 3 bytes
and some ACK bits a maximum update speed is theoretical in the order of
10 KHz for one channel (or 2.5 KHz for 4 channels).
As it is possible to **write(array)** multiple channels in one transaction
the actual numbers might be slightly higher.
The settling time of a new value the MAX520 is 2 us and the MAX521 uses up
to 6 us. This faster than I2C can provide new values.
TODO: No hardware test is done yet to measure performance.
| speed | write (us) | Notes |
|:--------:|:-------------:|:-------:|
| 50000 | |
| 100000 | |
| 200000 | |
| 300000 | |
| 400000 | | max datasheet
#### I2C multiplexing
@ -77,18 +127,18 @@ too if they are behind the multiplexer.
#include "MAX520.h"
```
**MAX520_INITIAL_VALUE** is a define 0xFF that can be set compile time or before
the include of "MAX520.h" to overrule the default value used with the **begin()** call.
#### Constructor
- **MAX520(uint8_t deviceAddress = 0x20, TwoWire \*wire = &Wire)** Constructor with optional address, default 0x20,
and the optional Wire interface as parameter.
- **bool begin(uint8_t value = MAX520_INITIAL_VALUE)** set the initial value (default 0xFF) for the DACS.
- **MAX521(uint8_t deviceAddress = 0x20, TwoWire \*wire = &Wire)** Constructor with optional address, default 0x20,
and the optional Wire interface as parameter.
- **bool begin()** initializes all DAC's to 0V by calling **reset()**.
Returns false if the device cannot be seen on the I2C bus.
- **bool isConnected()** checks if the address set in the constructor or by **setAddress()** is visible on the I2C bus.
- **bool setAddress(uint8_t deviceAddress)** sets the device address after construction.
Can be used to switch between MAX520 modules runtime. Note this corrupts internal buffered values,
Can be used to switch between MAX520 modules runtime. Note this corrupts internal cached last written values,
so one might need to call **write()** again. Returns true if address can be found on I2C bus.
- **uint8_t getAddress()** Returns the device address.
- **uint8_t getChannels()** Returns the number of channels (4 or 8).
@ -96,18 +146,22 @@ so one might need to call **write()** again. Returns true if address can be foun
#### Read and Write
- **int write(uint8_t channel, uint8_t value)** writes value to chosen DAC.
- **int write(uint8_t \* values)** writes to all DACs. user must take care that array is large enough (4/8).
- **int write(uint8_t channel, uint8_t value)** writes a value 0..255 to the chosen DAC.
- **int write(uint8_t \* values)** writes to all DACs.
The user must take care that the array is large enough to hold 4 or 8 values.
- **int read(uint8_t channel)** returns the last written value to chosen DAC. (from cache).
#### Reset and power down
- **int reset()** TODO what values?
- **int powerDown()**
- **int wakeUp()**
- **int reset()** resets the values to 0V. Also clears the cache.
- **int powerDown()** sets device in a low current mode.
- **int wakeUp()** wakes up the device.
TODO
TODO: investigate the actual behaviour of the devices in PD mode.
What effect does it have and are the cached values still actual / correct?
Feedback welcome.
#### Miscellaneous
@ -116,28 +170,33 @@ TODO
## Error codes
| name | value | description |
| Name | Value | Description |
|:-----------------------|:-------:|:--------------------------|
| MAX520_OK | 0x00 | no error |
| MAX520_CHANNEL_ERROR | 0x81 | channel nr out of range |
| MAX520_I2C_ERROR | 0x82 | I2C communication error |
## Future
#### Must
- improve documentation.
- test with hardware
- stabilize.
- verify behaviour of powerDown() / wakeup()
#### Should
- error handling
- measure actual performance (I2C)
#### Could
- add **wakeUp(values)** ?
- add **powerDown(values)** ?
- error handling
- add **writeAll(value)** ?
#### Wont

View File

@ -7,7 +7,10 @@
#include "MAX520.h"
MAX520 mx(0x38);
// adjust address if needed
// MAX520 0x20..0x27
// MAX521 0x20..0x23
MAX520 mx(0x20);
void setup()
@ -16,6 +19,7 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX520_LIB_VERSION:\t");
Serial.println(MAX520_LIB_VERSION);
Serial.println();
Wire.begin();

View File

@ -0,0 +1,54 @@
//
// FILE: MAX520_demo_read.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo MAX520
// URL: https://github.com/RobTillaart/MAX520
#include "MAX520.h"
// adjust address if needed
// MAX520 0x20..0x27
// MAX521 0x20..0x23
MAX520 mx(0x20);
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("MAX520_LIB_VERSION:\t");
Serial.println(MAX520_LIB_VERSION);
Serial.println();
Wire.begin();
mx.begin();
// all channels should read 0.
for (int ch = 0; ch < mx.getChannels(); ch++)
{
Serial.print(ch);
Serial.print("\t");
Serial.println(mx.read(ch));
}
}
void loop()
{
for (int value = 0; value < 256; value++)
{
for (int ch = 0; ch < mx.getChannels(); ch++)
{
mx.write(ch, value);
delay(250);
Serial.print(mx.read(ch));
Serial.print("\t");
}
Serial.println();
}
}
// -- END OF FILE --

View File

@ -0,0 +1,45 @@
//
// FILE: MAX520_demo_write.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo MAX520 write(array)
// URL: https://github.com/RobTillaart/MAX520
#include "MAX520.h"
// adjust address if needed
// MAX520 0x20..0x27
// MAX521 0x20..0x23
MAX520 mx(0x20);
uint8_t values[4] = { 0, 85, 170, 255 };
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("MAX520_LIB_VERSION:\t");
Serial.println(MAX520_LIB_VERSION);
Serial.println();
Wire.begin();
mx.begin();
mx.write(values);
for (int ch = 0; ch < mx.getChannels(); ch++)
{
Serial.print(mx.read(ch));
Serial.print("\t");
}
Serial.println();
}
void loop()
{
}
// -- END OF FILE --

View File

@ -7,7 +7,10 @@
#include "MAX520.h"
MAX521 mx(0x38);
// adjust address if needed
// MAX520 0x20..0x27
// MAX521 0x20..0x23
MAX521 mx; // uses default address
void setup()
@ -16,6 +19,7 @@ void setup()
Serial.println(__FILE__);
Serial.print("MAX520_LIB_VERSION:\t");
Serial.println(MAX520_LIB_VERSION);
Serial.println();
Wire.begin();

View File

@ -0,0 +1,81 @@
//
// FILE: MAX521_performance.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo MAX521
// URL: https://github.com/RobTillaart/MAX520
#include "MAX520.h"
// adjust address if needed
// MAX520 0x20..0x27
// MAX521 0x20..0x23
MAX521 mx(0x20);
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("MAX520_LIB_VERSION:\t");
Serial.println(MAX520_LIB_VERSION);
Serial.println();
Wire.begin();
mx.begin();
Serial.println("Clock\tTime (us)");
for (uint32_t speed = 50000; speed <= 500000; speed += 50000)
{
test_1(speed);
}
Wire.setClock(100000);
Serial.println("\done");
}
void loop()
{
}
void test_1(uint32_t speed)
{
// wait to flush Serial
delay(100);
Wire.setClock(speed);
uint32_t start = micros();
for (int value = 0; value < 256; value++)
{
mx.write(0, value);
}
uint32_t stop = micros();
Serial.print("Write(ch, value)");
Serial.print("\t");
Serial.print(speed);
Serial.print("\t");
Serial.print((stop - start) / 256.0, 2);
Serial.print("\n");
delay(100);
uint8_t values[8] = { 0, 42, 85, 127, 170, 212, 255 };
start = micros();
for (int value = 0; value < 10; value++)
{
mx.write(values);
}
stop = micros();
Serial.print("Write(values)");
Serial.print("\t");
Serial.print(speed);
Serial.print("\t");
Serial.print((stop - start) / 10.0, 2);
Serial.print("\n");
delay(100);
}
// -- END OF FILE --

View File

@ -16,6 +16,12 @@ getChannels KEYWORD2
write KEYWORD2
read KEYWORD2
reset KEYWORD2
powerDown KEYWORD2
wakeUp KEYWORD2
lastError KEYWORD2
# Constants ( LITERAL1)
MAX520_LIB_VERSION LITERAL1

View File

@ -1,7 +1,7 @@
{
"name": "MAX520",
"keywords": "I2C, MAX520, MAX521, DAC",
"description": "Arduino library for MAX520/521 4/8 channel 8 bit DAC.",
"description": "Arduino library for MAX520 and MAX521 4/8 channel 8 bit DAC.",
"authors":
[
{
@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/MAX520.git"
},
"version": "0.1.0",
"version": "0.1.1",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,8 +1,8 @@
name=MAX520
version=0.1.0
version=0.1.1
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for MAX520/521 4/8 channel 8 bit DAC.
sentence=Arduino library for MAX520 and MAX521 4/8 channel 8 bit DAC.
paragraph=
category=Signal Input/Output
url=https://github.com/RobTillaart/MAX520.git

View File

@ -51,18 +51,54 @@ unittest_teardown()
}
unittest(test_constructor)
{
MAX520 mx; // default address
MAX520 mx0(0X20);
MAX520 mx1(0X21);
MAX520 mx2(0X22);
MAX520 mx3(0X23);
Wire.begin();
mx.begin();
mx0.begin();
mx1.begin();
mx2.begin();
mx3.begin();
assertEqual(0x20, mx.getAddress());
assertEqual(0x20, mx0.getAddress());
assertEqual(0x21, mx1.getAddress());
assertEqual(0x22, mx2.getAddress());
assertEqual(0x23, mx3.getAddress());
MAX521 mx5;
mx5.begin();
assertEqual(0x20, mx5.getAddress());
}
unittest(test_begin)
{
MAX520 mx0(0x38);
MAX520 mx0;
Wire.begin();
mx0.begin();
assertEqual(4, mx0.getChannels());
for (int ch = 0; ch < mx0.getChannels(); ch++)
{
assertEqual(0, mx0.read(ch));
}
MAX521 mx1(0x38);
MAX521 mx1;
Wire.begin();
mx1.begin();
assertEqual(8, mx1.getChannels());
for (int ch = 0; ch < mx1.getChannels(); ch++)
{
assertEqual(0, mx1.read(ch));
}
}