0.1.0 MCP4261

This commit is contained in:
Rob Tillaart 2024-07-09 12:25:32 +02:00
parent db9c7dda89
commit 4dfce7b8ef
19 changed files with 1343 additions and 0 deletions

View File

@ -0,0 +1,32 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040 # name:architecture:board
gcc:
features:
defines:
- ARDUINO_ARCH_RP2040
warnings:
flags:
packages:
rp2040:rp2040:
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
teensy:Teensy:
url: https://www.pjrc.com/teensy/package_teensy_index.json
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
# - due
# - zero
# - leonardo
- m4
- esp32
- esp8266
# - mega2560
- rpipico

4
libraries/MCP4261/.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: RobTillaart
custom: "https://www.paypal.me/robtillaart"

View File

@ -0,0 +1,13 @@
name: Arduino-lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: arduino/arduino-lint-action@v1
with:
library-manager: update
compliance: strict

View File

@ -0,0 +1,17 @@
name: Arduino CI
on: [push, pull_request]
jobs:
runTest:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- run: |
gem install arduino_ci
arduino_ci.rb

View File

@ -0,0 +1,18 @@
name: JSON check
on:
push:
paths:
- '**.json'
pull_request:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: json-syntax-check
uses: limitusus/json-syntax-check@v2
with:
pattern: "\\.json$"

View File

@ -0,0 +1,10 @@
# Change Log MCP4261
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.0] - 2024-02-21
- initial version

21
libraries/MCP4261/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024-2024 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,386 @@
//
// FILE: MCP4261.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2024-02-21
// PURPOSE: Arduino library for MCP4261 SPI based digital potentiometers.
// URL: https://github.com/RobTillaart/MCP4261
#include "MCP4261.h"
// see page 18 datasheet
#define MCP4261_IGNORE_CMD 0x00
#define MCP4261_WRITE_CMD 0x00
#define MCP4261_SHUTDOWN_CMD 0x20
#define MCP4261_NONE_CMD 0x30
// HARDWARE SPI
MCP4261::MCP4261(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI)
{
_pmCount = 2;
_maxValue = 255;
_select = select;
_shutdown = shutdown;
_dataIn = 255;
_dataOut = 255;
_clock = 255;
_hwSPI = true;
_mySPI = mySPI;
_spi_settings = SPISettings(_SPIspeed, MSBFIRST, SPI_MODE0);
}
// SOFTWARE SPI
MCP4261::MCP4261(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)
{
_pmCount = 2;
_maxValue = 255;
_select = select;
_shutdown = shutdown;
_dataIn = dataIn;
_dataOut = dataOut;
_clock = clock;
_hwSPI = false;
_mySPI = NULL;
}
void MCP4261::begin(uint16_t value)
{
pinMode(_select, OUTPUT);
digitalWrite(_select, HIGH);
pinMode(_shutdown, OUTPUT);
digitalWrite(_shutdown, HIGH);
setSPIspeed(1000000);
if(_hwSPI)
{
// _mySPI->end();
// _mySPI->begin();
// delay(1);
}
else
{
pinMode(_dataIn, INPUT);
pinMode(_dataOut, OUTPUT);
pinMode(_clock, OUTPUT);
digitalWrite(_dataOut, LOW);
digitalWrite(_clock, LOW);
}
reset(value);
}
void MCP4261::reset(uint16_t value)
{
digitalWrite(_shutdown, LOW);
digitalWrite(_shutdown, HIGH);
setValue(value); // set all to same value.
}
/////////////////////////////////////////////////////////////////////////////
//
// SET VOLATILE VALUE
//
bool MCP4261::setValue(uint16_t value)
{
setValue(0, value);
setValue(1, value);
return true;
}
bool MCP4261::setValue(uint8_t pm, uint16_t value)
{
if (pm >= _pmCount) return false;
if (value > _maxValue) return false;
_value[pm] = value;
uint8_t cmd = 0x00;
if (pm == 1) cmd = 0x10;
if (value > 0xFF) cmd |= (value >> 8); // high bits
writeDevice(2, cmd, value & 0xFF);
return true;
}
uint16_t MCP4261::getValue(uint8_t pm)
{
if (pm >= _pmCount) return 0;
return _value[pm];
}
bool MCP4261::incrValue(uint8_t pm)
{
if (pm >= _pmCount) return false;
if (_value[pm] >= _maxValue) return false;
_value[pm]++;
uint8_t cmd = 0x04;
if (pm == 1) cmd = 0x14;
writeDevice(1, cmd, cmd); // value2 = DUMMY
return true;
}
bool MCP4261::decrValue(uint8_t pm)
{
if (pm >= _pmCount) return false;
if (_value[pm] == 0) return false;
_value[pm]--;
uint8_t cmd = 0x08;
if (pm == 1) cmd = 0x18;
writeDevice(1, cmd, cmd); // value2 = DUMMY
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// SET NON-VOLATILE VALUE
//
bool MCP4261::setValueNV(uint8_t pm, uint16_t value)
{
if (pm >= _pmCount) return false;
if (value > _maxValue) return false;
uint8_t cmd = 0x20;
if (pm == 1) cmd = 0x30;
if (value > 0xFF) cmd |= (value >> 8); // high bits
writeDevice(2, cmd, value & 0xFF);
return true;
}
/////////////////////////////////////////////////////////////////////////////
//
// MISC
//
uint8_t MCP4261::pmCount()
{
return _pmCount;
}
void MCP4261::powerOn()
{
digitalWrite(_shutdown, HIGH);
}
void MCP4261::powerOff()
{
digitalWrite(_shutdown, LOW);
}
bool MCP4261::isPowerOn()
{
return digitalRead(_shutdown) == HIGH;
}
/////////////////////////////////////////////////////////////////////////////
//
// SPI
//
void MCP4261::setSPIspeed(uint32_t speed)
{
_SPIspeed = speed;
_spi_settings = SPISettings(_SPIspeed, MSBFIRST, SPI_MODE0);
}
uint32_t MCP4261::getSPIspeed()
{
return _SPIspeed;
}
bool MCP4261::usesHWSPI()
{
return _hwSPI;
}
/////////////////////////////////////////////////////////////////////////////
//
// PROTECTED
//
/*
TODO - see page 46
- need read8, read16
- bid8, bidi16
*/
//
// USES SPI MODE 0
//
void MCP4261::writeDevice(uint8_t count, uint8_t value1, uint8_t value2)
{
digitalWrite(_select, LOW);
if (_hwSPI)
{
_mySPI->beginTransaction(_spi_settings);
_mySPI->transfer(value1);
if (count == 2) _mySPI->transfer(value2);
_mySPI->endTransaction();
}
else // Software SPI
{
swSPI_write(value1);
if (count == 2) swSPI_write(value2);
}
digitalWrite(_select, HIGH);
}
// MSBFIRST
void MCP4261::swSPI_write(uint8_t value)
{
uint8_t clk = _clock;
uint8_t dao = _dataOut;
// MSBFIRST
for (uint8_t mask = 0x80; mask; mask >>= 1)
{
digitalWrite(dao,(value & mask));
digitalWrite(clk, HIGH);
digitalWrite(clk, LOW);
}
}
////////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES MCP41xx SERIES
//
MCP4141::MCP4141(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI)
:MCP4261(select, shutdown, mySPI)
{
_pmCount = 1;
_maxValue = MCP41XX_MAX_VALUE;
}
MCP4141::MCP4141(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP4261(select, shutdown, dataIn, dataOut, clock)
{
_pmCount = 1;
_maxValue = MCP41XX_MAX_VALUE;
}
//
MCP4142::MCP4142(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI)
:MCP4261(select, shutdown, mySPI)
{
_pmCount = 1;
_maxValue = MCP41XX_MAX_VALUE;
}
MCP4142::MCP4142(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP4261(select, shutdown, dataIn, dataOut, clock)
{
_pmCount = 1;
_maxValue = MCP41XX_MAX_VALUE;
}
//
MCP4161::MCP4161(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI)
:MCP4261(select, shutdown, mySPI)
{
_pmCount = 1;
_maxValue = MCP41XX_MAX_VALUE;
}
MCP4161::MCP4161(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP4261(select, shutdown, dataIn, dataOut, clock)
{
_pmCount = 1;
_maxValue = MCP41XX_MAX_VALUE;
}
//
MCP4162::MCP4162(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI)
:MCP4261(select, shutdown, mySPI)
{
_pmCount = 1;
_maxValue = MCP41XX_MAX_VALUE;
}
MCP4162::MCP4162(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP4261(select, shutdown, dataIn, dataOut, clock)
{
_pmCount = 1;
_maxValue = MCP41XX_MAX_VALUE;
}
////////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES MCP42xx SERIES
//
MCP4241::MCP4241(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI)
:MCP4261(select, shutdown, mySPI)
{
_pmCount = 2;
_maxValue = MCP42XX_MAX_VALUE;
}
MCP4241::MCP4241(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP4261(select, shutdown, dataIn, dataOut, clock)
{
_pmCount = 2;
_maxValue = MCP42XX_MAX_VALUE;
}
//
MCP4242::MCP4242(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI)
:MCP4261(select, shutdown, mySPI)
{
_pmCount = 2;
_maxValue = MCP42XX_MAX_VALUE;
}
MCP4242::MCP4242(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP4261(select, shutdown, dataIn, dataOut, clock)
{
_pmCount = 2;
_maxValue = MCP42XX_MAX_VALUE;
}
//
MCP4262::MCP4262(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI)
:MCP4261(select, shutdown, mySPI)
{
_pmCount = 2;
_maxValue = MCP42XX_MAX_VALUE;
}
MCP4262::MCP4262(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP4261(select, shutdown, dataIn, dataOut, clock)
{
_pmCount = 2;
_maxValue = MCP42XX_MAX_VALUE;
}
// -- END OF FILE --

174
libraries/MCP4261/MCP4261.h Normal file
View File

@ -0,0 +1,174 @@
#pragma once
//
// FILE: MCP4261.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2024-02-21
// PURPOSE: Arduino library for MCP4261 SPI based digital potentiometers.
// URL: https://github.com/RobTillaart/MCP4261
#include "Arduino.h"
#include "SPI.h"
#define MCP4261_LIB_VERSION (F("0.1.0"))
#ifndef MCP41XX_MIDDLE_VALUE
#define MCP41XX_MIDDLE_VALUE 64
#endif
#ifndef MCP41XX_MAX_VALUE
#define MCP41XX_MAX_VALUE 129
#endif
#ifndef MCP42XX_MIDDLE_VALUE
#define MCP42XX_MIDDLE_VALUE 129
#endif
#ifndef MCP42XX_MAX_VALUE
#define MCP42XX_MAX_VALUE 257
#endif
#ifndef __SPI_CLASS__
// MBED must be tested before RP2040
#if defined(ARDUINO_ARCH_MBED)
#define __SPI_CLASS__ SPIClass
#elif defined(ARDUINO_ARCH_RP2040)
#define __SPI_CLASS__ SPIClassRP2040
#else
#define __SPI_CLASS__ SPIClass
#endif
#endif
class MCP4261
{
public:
// HARDWARE SPI
MCP4261(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI = &SPI);
// SOFTWARE SPI
MCP4261(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock);
void begin(uint16_t value);
void reset(uint16_t value);
uint8_t pmCount();
// set both potmeters (just a wrapper)
bool setValue(uint16_t value);
// set single potmeter (0 or 1)
bool setValue(uint8_t pm, uint16_t value);
uint16_t getValue(uint8_t pm = 0);
bool incrValue(uint8_t pm);
bool decrValue(uint8_t pm);
// Set non volatile potmeter
// not tested
bool setValueNV(uint8_t pm, uint16_t value);
// speed in Hz
void setSPIspeed(uint32_t speed);
uint32_t getSPIspeed();
bool usesHWSPI(); // debugging
// MISC
void powerOn();
void powerOff();
bool isPowerOn();
protected:
uint8_t _dataIn;
uint8_t _dataOut;
uint8_t _clock;
uint8_t _select;
uint8_t _shutdown;
bool _hwSPI;
uint32_t _SPIspeed;
uint16_t _value[2] = { 0, 0 };
uint8_t _pmCount;
uint16_t _maxValue;
void writeDevice(uint8_t count, uint8_t value1, uint8_t value2);
void swSPI_write(uint8_t value);
__SPI_CLASS__ * _mySPI;
SPISettings _spi_settings;
};
////////////////////////////////////////////////////
//
// DERIVED CLASSES MCP41xx SERIES
//
class MCP4141 : public MCP4261
{
public:
MCP4141(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI = &SPI);
MCP4141(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock);
};
class MCP4142 : public MCP4261
{
public:
MCP4142(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI = &SPI);
MCP4142(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock);
};
class MCP4161 : public MCP4261
{
public:
MCP4161(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI = &SPI);
MCP4161(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock);
};
class MCP4162 : public MCP4261
{
public:
MCP4162(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI = &SPI);
MCP4162(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock);
};
/////////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES MCP42xx SERIES
//
class MCP4241 : public MCP4261
{
public:
MCP4241(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI = &SPI);
MCP4241(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock);
};
class MCP4242 : public MCP4261
{
public:
MCP4242(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI = &SPI);
MCP4242(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock);
};
class MCP4262 : public MCP4261
{
public:
MCP4262(uint8_t select, uint8_t shutdown, __SPI_CLASS__ * mySPI = &SPI);
MCP4262(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock);
};
// -- END OF FILE --

208
libraries/MCP4261/README.md Normal file
View File

@ -0,0 +1,208 @@
[![Arduino CI](https://github.com/RobTillaart/MCP4261/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/MCP4261/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MCP4261/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/MCP4261/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MCP4261/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/MCP4261.svg)](https://github.com/RobTillaart/MCP4261/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MCP4261/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/MCP4261.svg?maxAge=3600)](https://github.com/RobTillaart/MCP4261/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/MCP4261.svg)](https://registry.platformio.org/libraries/robtillaart/MCP4261)
[![Commits since latest](https://img.shields.io/github/commits-since/RobTillaart/MCP4261/latest)](https://github.com/RobTillaart/MCP4261/commits/master)
# MCP4261
Arduino library for MCP4261 SPI based digital potentiometers and compatibles.
## Description
**Experimental**
The MCP4261 library supports both hardware SPI and software SPI up to 10 MHz.
These series of potmeters (rheostats) come in values of 5, 10, 50 and 100 kΩ (±20%).
Where other potmeters uses a range of 0..127 or 0.255, these series potmeters
use a range 0..129 and 0..257. This implies some extra care to set the wiper
to end position.
The library supports setting the value of the potmeters and caches this setting.
This way it can be retrieved very fast.
Furthermore the library has two functions to increase and decrease
the value of a potmeter.
Feedback, issues and improvements are welcome,
Please open an issue on GitHub.
### Not implemented yet
The library is under development and not all functionality is implemented.
(as I only needed to set values).
- EEPROM, 10 addresses of 10 bits. (MCP4261 et al )
- Non volatile registers for power on setup.. (partially)
- read back from device
- read status
- TCON register
- High Voltage something?
### Compatibles
These are the devices that should work with this library.
Only the 4261 is tested.
| Number | Type | pots | POR | MaxValue | Notes |
|:--------:|:--------:|:------:|:--------:|:----------:|:--------|
| MCP4141 | Potmeter | 1 | NV-Wiper | 129 |
| MCP4142 | Rheostat | 1 | NV-Wiper | 129 |
| MCP4161 | Potmeter | 1 | NV-Wiper | 257 |
| MCP4162 | Rheostat | 1 | NV-Wiper | 257 |
| MCP4241 | Potmeter | 2 | NV-Wiper | 129 |
| MCP4242 | Rheostat | 2 | NV-Wiper | 129 |
| MCP4261 | Potmeter | 2 | NV-Wiper | 257 | base class
| MCP4262 | Rheostat | 2 | NV-Wiper | 257 |
To investigate:
MCP4131/32/51/52, MCP4231/32/51/52, these have no NV RAM so they
have a POR power on reset of middle value (= half max value.
MCP4151 Reichelt
MCP4262 Mouser
### Related
TODO: list of other digital pot meters / rheostats.
#### Related
| Address | Function | Memory Type |
|:---------:|:------------------------:|:--------------|
| 00h | Volatile Wiper 0 | RAM |
| 01h | Volatile Wiper 1 | RAM |
| 02h | Non-Volatile Wiper 0 | EEPROM |
| 03h | Non-Volatile Wiper 1 | EEPROM |
| 04h | Volatile TCON Register | RAM |
| 05h | Status Register | RAM |
| 06h | Data EEPROM | EEPROM |
| 07h | Data EEPROM | EEPROM |
| 08h | Data EEPROM | EEPROM |
| 09h | Data EEPROM | EEPROM |
| 0Ah | Data EEPROM | EEPROM |
| 0Bh | Data EEPROM | EEPROM |
| 0Ch | Data EEPROM | EEPROM |
| 0Dh | Data EEPROM | EEPROM |
| 0Eh | Data EEPROM | EEPROM |
| 0Fh | Data EEPROM | EEPROM |
## Interface
```cpp
#include "MCP4261.h"
```
### Constructor
- **MCP4261(uint8_t select, uint8_t shutdown, \__SPI_CLASS__ \* mySPI = &SPI)**
HW SPI constructor.
- **MCP4261(uint8_t select, uint8_t shutdown, uint8_t dataIn, uint8_t dataOut, uint8_t clock)**
SW SPI Constructor. The dataIn pin is not used yet.
- **void begin(uint8_t value)** user must explicit set initial value.
- **void reset(uint8_t value)** user must explicit set initial value.
- **uint8_t pmCount()** returns 1 or 2, depending on device type.
### Set Volatile Values
- **bool setValue(uint8_t value)** set all potmeters to the same value. (wrapper).
Returns true.
- **bool setValue(uint8_t pm, uint8_t value)** set single potmeter (0 or 1).
Returns false if pm > pmCount.
- **uint8_t getValue(uint8_t pm = 0)** returns value from cache.
- **bool incrValue(uint8_t pm)**
- **bool decrValue(uint8_t pm)**
### Set Volatile Values
**Experimental**
TODO: how does this fit in interface as reset() always sets a value.
- **bool setValueNV(uint8_t pm, uint16_t value)**
### EEPROM
Not implemented yet
### SPI
Note changing the SPI speed might affect other devices on the same SPI bus.
So use with care.
- **void setSPIspeed(uint32_t speed)** default 1MHz, typical 4 MHz.
- **uint32_t getSPIspeed()** idem.
- **bool usesHWSPI()** idem.
### Power
- **void powerOn()** idem.
- **void powerOff()** idem.
- **bool isPowerOn()** idem.
## Future
#### Must
- improve documentation
#### Should
- read registers.
- read values.
- status register
- TCON
#### Could
- EEPROM support
- 10 registers, 10 bit
- bool writeEEPROM(address, uint16_t value);
- uint16_t readEEPROM(address);
- write to non-volatile register 02/03 to set Power On Reset values
- read when reset?
- how to fit in use model.
- unit tests
- examples
- error handling
- improve return values
- investigate performance
- AVR SW SPI?
#### Won't
## Support
If you appreciate my libraries, you can support the development and maintenance.
Improve the quality of the libraries by providing issues and Pull Requests, or
donate through PayPal or GitHub sponsors.
Thank you,

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,147 @@
//
// FILE: MCP4261_demo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
// URL: https://github.com/RobTillaart/MCP4261
#include "MCP4261.h"
uint32_t start, stop;
// select, shutdown, dataIn, dataOut, clock == SOFTWARE SPI
// MCP4261 pot(10, 6, 7, 8, 9);
// select, shutdown, &SPI === HW SPI UNO clock = 13, dataOut = 11
MCP4261 pot(10, 6, &SPI);
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
SPI.begin();
pot.begin(0); // initial value
// test_extremes();
//test_sinus();
test_sawtooth();
test_incr_decr();
//test_timing();
Serial.println("\nDone...");
}
void loop()
{
test_incr_decr();
}
void test_extremes()
{
Serial.println(__FUNCTION__);
delay(10);
Serial.println("0");
pot.setValue(0, 0);
delay(2000);
Serial.println(MCP42XX_MIDDLE_VALUE);
pot.setValue(0, MCP42XX_MIDDLE_VALUE);
delay(2000);
Serial.println(MCP42XX_MAX_VALUE);
pot.setValue(0, MCP42XX_MAX_VALUE);
delay(2000);
}
// connect all A GND and B 5V
// every W will have a different signal (same freq).
void test_sinus()
{
Serial.println(__FUNCTION__);
delay(10);
start = millis();
uint32_t i = 0;
while (millis() - start < 10000)
{
int8_t value = 127 * sin(i * TWO_PI / 100);
pot.setValue(0, 128 + value);
pot.setValue(1, 128 + value / 2);
i++;
}
}
// straightforward sawtooth.
void test_sawtooth()
{
Serial.println(__FUNCTION__);
delay(10);
for (int i = 0; i < 255; i++)
{
pot.setValue(0, i); // auto wrap is fast...
pot.setValue(1, i++); // auto wrap is fast...
delay(100);
}
}
void test_incr_decr()
{
Serial.println(__FUNCTION__);
delay(10);
pot.setValue(0, 0);
for (int i = 0; i < 255; i++)
{
pot.incrValue(0);
pot.incrValue(1);
delay(100);
}
for (int i = 0; i < 255; i++)
{
pot.decrValue(0);
pot.decrValue(1);
delay(100);
}
}
void test_timing()
{
Serial.println(__FUNCTION__);
delay(10);
start = micros();
for (int i = 0; i < 1000; i++)
{
pot.setValue(0, i++); // auto wrap is fast...
}
stop = micros();
Serial.print("1000 x setValue():\t");
Serial.println(stop - start);
delay(10);
volatile int x = 0;
start = micros();
for (int i = 0; i < 500; i++)
{
x += pot.getValue(0);
x += pot.getValue(1);
}
stop = micros();
Serial.print("1000 x getValue():\t");
Serial.println(stop - start);
delay(10);
}
// -- END OF FILE --

View File

@ -0,0 +1,117 @@
//
// FILE: MCP4261_performance.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
// URL: https://github.com/RobTillaart/MCP4261
//
// under investigation.
#include "MCP4261.h"
uint32_t start, stop;
// select, shutdown, dataIn, dataOut, clock == SOFTWARE SPI
// MCP4261 pot(10, 6, 7, 8, 9);
// select, shutdown, &SPI === HW SPI UNO clock = 13, data = 11
MCP4261 pot(10, 6, &SPI);
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("MCP4261_LIB_VERSION: ");
Serial.println(MCP4261_LIB_VERSION);
Serial.println();
SPI.begin();
pot.begin(0); // initial value
pot.setSPIspeed(1000000);
test_timing();
pot.setSPIspeed(2000000);
test_timing();
pot.setSPIspeed(4000000);
test_timing();
pot.setSPIspeed(8000000);
test_timing();
Serial.println("\nDone...");
}
void loop()
{
}
void test_timing()
{
Serial.println();
Serial.println(__FUNCTION__);
Serial.print("SPI:\t");
Serial.println(pot.getSPIspeed());
delay(100);
start = micros();
for (int i = 0; i < 250; i++)
{
pot.setValue(0, 42);
pot.setValue(1, 43);
}
stop = micros();
Serial.print("500 x setValue():\t");
Serial.print(stop - start);
Serial.print("\t");
Serial.println((stop - start) / 500.0);
delay(100);
volatile int x = 0;
start = micros();
for (int i = 0; i < 250; i++)
{
x += pot.getValue(0);
x += pot.getValue(1);
}
stop = micros();
Serial.print("500 x getValue():\t");
Serial.print(stop - start);
Serial.print("\t");
Serial.println((stop - start) / 500.0);
delay(100);
pot.setValue(0);
start = micros();
for (int i = 0; i < 250; i++)
{
pot.incrValue(0);
pot.incrValue(1);
}
stop = micros();
Serial.print("500 x incrValue():\t");
Serial.print(stop - start);
Serial.print("\t");
Serial.println((stop - start) / 500.0);
delay(100);
pot.setValue(255);
start = micros();
for (int i = 0; i < 250; i++)
{
pot.decrValue(0);
pot.decrValue(1);
}
stop = micros();
Serial.print("500 x decrValue():\t");
Serial.print(stop - start);
Serial.print("\t");
Serial.println((stop - start) / 500.0);
delay(100);
}
// -- END OF FILE --

View File

@ -0,0 +1,48 @@
BOARD: Arduino UNO
IDE: 1.8.19
MCP4261_performance.ino
MCP4261_LIB_VERSION: 0.1.0
HW SPI
test_timing
SPI: 1000000
500 x setValue(): 15404 30.81
500 x getValue(): 380 0.76
500 x incrValue(): 10776 21.55
500 x decrValue(): 10660 21.32
test_timing
SPI: 2000000
500 x setValue(): 11380 22.76
500 x getValue(): 384 0.77
500 x incrValue(): 8768 17.54
500 x decrValue(): 8640 17.28
test_timing
SPI: 4000000
500 x setValue(): 9400 18.80
500 x getValue(): 380 0.76
500 x incrValue(): 7768 15.54
500 x decrValue(): 7644 15.29
test_timing
SPI: 8000000
500 x setValue(): 8400 16.80
500 x getValue(): 376 0.75
500 x incrValue(): 7268 14.54
500 x decrValue(): 7140 14.28
SW SPI
500 x setValue(): 107264 214.53
500 x getValue(): 380 0.76
500 x incrValue(): 56556 113.11
500 x decrValue(): 56432 112.86
Done...

View File

@ -0,0 +1,43 @@
# Syntax Colouring Map For MCP4261
# Data types (KEYWORD1)
MCP4141 KEYWORD1
MCP4142 KEYWORD1
MCP4161 KEYWORD1
MCP4162 KEYWORD1
MCP4241 KEYWORD1
MCP4242 KEYWORD1
MCP4261 KEYWORD1
MCP4262 KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
reset KEYWORD2
pmCount KEYWORD2
setValue KEYWORD2
getValue KEYWORD2
incrValue KEYWORD2
decrValue KEYWORD2
setValueNV KEYWORD2
setSPIspeed KEYWORD2
getSPIspeed KEYWORD2
powerOn KEYWORD2
powerOff KEYWORD2
isPowerOn KEYWORD2
usesHWSPI KEYWORD2
# Constants (LITERAL1)
MCP4261_LIB_VERSION LITERAL1
MCP41XX_MIDDLE_VALUE LITERAL1
MCP41XX_MAX_VALUE LITERAL1
MCP42XX_MIDDLE_VALUE LITERAL1
MCP42XX_MAX_VALUE LITERAL1

View File

@ -0,0 +1,23 @@
{
"name": "MCP4261",
"keywords": "MCP4141,MCP4142,MCP4161,MCP4162,MCP4241,MCP4242,MCP4261,MCP4262",
"description": "Arduino library for MCP4261 SPI based digital potentiometers.",
"authors":
[
{
"name": "Rob Tillaart",
"email": "Rob.Tillaart@gmail.com",
"maintainer": true
}
],
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/MCP4261.git"
},
"version": "0.1.0",
"license": "MIT",
"frameworks": "*",
"platforms": "*",
"headers": "MCP4261.h"
}

View File

@ -0,0 +1,11 @@
name=MCP4261
version=0.1.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for MCP4261 SPI based digital potentiometers.
paragraph=MCP4141,MCP4142,MCP4161,MCP4162,MCP4241,MCP4242,MCP4261,MCP4262
category=Signal Input/Output
url=https://github.com/RobTillaart/MCP4261
architectures=*
includes=MCP4261.h
depends=

View File

@ -0,0 +1,71 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// DATE: 2022-12-01
// PURPOSE: unit tests for the A1301 magnetic sensor
// URL: https://github.com/RobTillaart/A1301
// https://www.adafruit.com/product/2857
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
//
// supported assertions
// ----------------------------
// assertEqual(expected, actual)
// assertNotEqual(expected, actual)
// assertLess(expected, actual)
// assertMore(expected, actual)
// assertLessOrEqual(expected, actual)
// assertMoreOrEqual(expected, actual)
// assertTrue(actual)
// assertFalse(actual)
// assertNull(actual)
#include <ArduinoUnitTests.h>
#include "Arduino.h"
#include "MCP4261.h"
unittest_setup()
{
fprintf(stderr, "MCP4261_LIB_VERSION: %s\n", (char *) MCP4261_LIB_VERSION);
}
unittest_teardown()
{
}
unittest(test_constants)
{
assertEqual(64, MCP41XX_MIDDLE_VALUE);
assertEqual(129, MCP41XX_MAX_VALUE);
assertEqual(129, MCP42XX_MIDDLE_VALUE);
assertEqual(257, MCP42XX_MAX_VALUE);
}
unittest(test_constructor)
{
MCP4261 mcp(10, 6);
// before begin.
assertEqual(2, mcp.pmCount());
assertEqual(0, mcp.getValue());
}
/*
TODO
setValue false test
setValue, getValue
incrValue
decrValue
*/
unittest_main()
// -- END OF FILE --