From fb8e834e43c317d98b9241f3f9b4ba7a486bbcbf Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Mon, 11 Sep 2023 20:03:59 +0200 Subject: [PATCH] 0.2.1 MCP_ADC --- libraries/MCP_ADC/CHANGELOG.md | 9 +++ libraries/MCP_ADC/MCP_ADC.cpp | 50 ++++++++++++++-- libraries/MCP_ADC/MCP_ADC.h | 14 ++++- libraries/MCP_ADC/README.md | 58 ++++++++++++++----- .../MCP3208_performance/performance_0.1.9.md | 16 ++--- .../readADC_vs_readADCMultiple.md | 4 +- libraries/MCP_ADC/keywords.txt | 1 + libraries/MCP_ADC/library.json | 4 +- libraries/MCP_ADC/library.properties | 4 +- 9 files changed, 125 insertions(+), 35 deletions(-) diff --git a/libraries/MCP_ADC/CHANGELOG.md b/libraries/MCP_ADC/CHANGELOG.md index 295db52ed..9648a048d 100644 --- a/libraries/MCP_ADC/CHANGELOG.md +++ b/libraries/MCP_ADC/CHANGELOG.md @@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.2.1] - 2023-09-08 +- fix #13 support **MCP3201** +- add **MCP3001** support +- fix startup pulse for **select** pin. +- update readme.md +- fix version number in .cpp +- update keywords.txt + + ## [0.2.0] - 2023-08-15 - add analogReadMultiple(channels\[], numChannels, readings\[]) - Kudo's to Alex Uta. diff --git a/libraries/MCP_ADC/MCP_ADC.cpp b/libraries/MCP_ADC/MCP_ADC.cpp index 506dc0d6a..76c914469 100644 --- a/libraries/MCP_ADC/MCP_ADC.cpp +++ b/libraries/MCP_ADC/MCP_ADC.cpp @@ -1,9 +1,9 @@ // // FILE: MCP_ADC.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.9 +// VERSION: 0.2.1 // DATE: 2019-10-24 -// PURPOSE: Arduino library for MCP3002, MCP3004, MCP3008, MCP3202, MCP3204, MCP3208 +// PURPOSE: Arduino library for MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204, MCP3208 // URL: https://github.com/RobTillaart/MCP_ADC @@ -25,6 +25,8 @@ void MCP_ADC::begin(uint8_t select) _select = select; pinMode(_select, OUTPUT); digitalWrite(_select, HIGH); + digitalWrite(_select, LOW); // force communication See datasheet) + digitalWrite(_select, HIGH); _spi_settings = SPISettings(_SPIspeed, MSBFIRST, SPI_MODE0); @@ -153,7 +155,16 @@ int16_t MCP_ADC::readADC(uint8_t channel, bool single) } digitalWrite(_select, HIGH); - if (bytes == 2) return ((256 * data[0] + data[1]) & _maxValue); + if (bytes == 2) + { + // combine bytes + int16_t raw = 256 * data[0] + data[1]; + // patch bit pattern MCP3001 + if ((_channels == 1) && (_maxValue == 1023)) raw >>= 3; + // patch bit pattern MCP3201 + if ((_channels == 1) && (_maxValue == 4095)) raw >>= 1; + return raw & _maxValue; + } // data[0]? return ((256 * data[1] + data[2]) & _maxValue); } @@ -185,7 +196,13 @@ void MCP_ADC::readADCMultiple(uint8_t channels[], uint8_t numChannels, int16_t r } if (bytes == 2) { - readings[i] = ((256 * data[0] + data[1]) & _maxValue); + // combine bytes + int16_t raw = 256 * data[0] + data[1]; + // patch bit pattern MCP3001 + if ((_channels == 1) && (_maxValue == 1023)) raw >>= 3; + // patch bit pattern MCP3201 + if ((_channels == 1) && (_maxValue == 4095)) raw >>= 1; + readings[i] = raw & _maxValue; } else { readings[i] = ((256 * data[1] + data[2]) & _maxValue); } @@ -219,6 +236,28 @@ uint8_t MCP_ADC::swSPI_transfer(uint8_t val) +///////////////////////////////////////////////////////////////////////////// +// +// MCP3001 +// +MCP3001::MCP3001(uint8_t dataIn, uint8_t dataOut, uint8_t clock) + :MCP_ADC(dataIn, dataOut, clock) +{ + _channels = 1; + _maxValue = 1023; +} + +uint8_t MCP3001::buildRequest(uint8_t channel, bool single, uint8_t * data) +{ + // P16 fig 6.1 MCP3001 + // no specific data needed + // keep build CI compiler (ESP32) happy next statement + data[0] = data[1] = 0; + if ((channel == 0) || (single == false)) return 2; + return 2; +} + + ///////////////////////////////////////////////////////////////////////////// // // MCP3002 @@ -297,7 +336,8 @@ uint8_t MCP3201::buildRequest(uint8_t channel, bool single, uint8_t * data) { // P21 fig 6.1 MCP3201 // no specific data needed - // keep build CI compiler (ESP32) happy next statement + // keep build CI compiler (ESP32) happy next statements + data[0] = data[1] = 0; if ((channel == 0) || (single == false)) return 2; return 2; } diff --git a/libraries/MCP_ADC/MCP_ADC.h b/libraries/MCP_ADC/MCP_ADC.h index 17cb385c4..722cc6a0d 100644 --- a/libraries/MCP_ADC/MCP_ADC.h +++ b/libraries/MCP_ADC/MCP_ADC.h @@ -2,9 +2,9 @@ // // FILE: MCP_ADC.h // AUTHOR: Rob Tillaart -// VERSION: 0.2.0 +// VERSION: 0.2.1 // DATE: 2019-10-24 -// PURPOSE: Arduino library for MCP_ADC +// PURPOSE: Arduino library for MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204, MCP3208 // URL: https://github.com/RobTillaart/MCP_ADC // @@ -13,7 +13,7 @@ #include "SPI.h" -#define MCP_ADC_LIB_VERSION (F("0.2.0")) +#define MCP_ADC_LIB_VERSION (F("0.2.1")) class MCP_ADC @@ -84,6 +84,14 @@ class MCP_ADC // // DERIVED CLASSES // +class MCP3001 : public MCP_ADC +{ +public: + MCP3001(uint8_t dataIn = 255, uint8_t dataOut = 255, uint8_t clock = 255); + uint8_t buildRequest(uint8_t channel, bool single, uint8_t * data); +}; + + class MCP3002 : public MCP_ADC { public: diff --git a/libraries/MCP_ADC/README.md b/libraries/MCP_ADC/README.md index 14408da63..566f78536 100644 --- a/libraries/MCP_ADC/README.md +++ b/libraries/MCP_ADC/README.md @@ -2,13 +2,16 @@ [![Arduino CI](https://github.com/RobTillaart/MCP_ADC/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) [![Arduino-lint](https://github.com/RobTillaart/MCP_ADC/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MCP_ADC/actions/workflows/arduino-lint.yml) [![JSON check](https://github.com/RobTillaart/MCP_ADC/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MCP_ADC/actions/workflows/jsoncheck.yml) +[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/MCP_ADC.svg)](https://github.com/RobTillaart/MCP_ADC/issues) + [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MCP_ADC/blob/master/LICENSE) [![GitHub release](https://img.shields.io/github/release/RobTillaart/MCP_ADC.svg?maxAge=3600)](https://github.com/RobTillaart/MCP_ADC/releases) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/MCP_ADC.svg)](https://registry.platformio.org/libraries/robtillaart/MCP_ADC) # MCP_ADC -Arduino library for MCP3002 MCP3004 MCP3008 MCP3201 MCP3202 MCP3204 MCP3208 and compatibles. +Arduino library for MCP3001 MCP3002 MCP3004 MCP3008 MCP3201 MCP3202 MCP3204 MCP3208 and compatibles. ## Description @@ -19,10 +22,11 @@ The chips are communicates with SPI and support both hardware SPI or optional so | type | bits | chan | notes | |:----------|:------:|:------:|:--------| +| MCP3001 | 10 | 1 | not tested yet. | MCP3002 | 10 | 2 | | MCP3004 | 10 | 4 | | MCP3008 | 10 | 8 | -| MCP3201 | 12 | 1 | not tested yet. +| MCP3201 | 12 | 1 | test, see #13 | MCP3202 | 12 | 2 | | MCP3204 | 12 | 4 | | MCP3208 | 12 | 8 | @@ -39,17 +43,29 @@ Build into the library is a delta mode which is a software enhanced differential This delta mode can return negative values too. +#### Related + +- https://gammon.com.au/adc tutorial about ADC's (UNO specific) +- https://github.com/RobTillaart/ADS1x15 (12 & 16 bit ADC, I2C, slow) +- https://github.com/RobTillaart/PCF8591 (8 bit ADC + 1 bit DAC) + + +- https://github.com/RobTillaart/MCP_DAC + + + ## Interface ```cpp #include "MCP_ADC.h" ``` -#### Base +#### Constructors If the pins are not set in the constructor, the class will automatically use the hardware SPI, otherwise it will use software SPI. +- **MCP3001(uint8_t dataIn, uint8_t dataOut, uint8_t clock)** constructor 10 bit ADC 1 channel. - **MCP3002(uint8_t dataIn, uint8_t dataOut, uint8_t clock)** constructor 10 bit ADC 2 channel. - **MCP3004(uint8_t dataIn, uint8_t dataOut, uint8_t clock)** constructor 10 bit ADC 4 channel. - **MCP3008(uint8_t dataIn, uint8_t dataOut, uint8_t clock)** constructor 10 bit ADC 8 channel. @@ -59,8 +75,12 @@ use the hardware SPI, otherwise it will use software SPI. - **MCP3208(uint8_t dataIn, uint8_t dataOut, uint8_t clock)** constructor 12 bit ADC 8 channel. - **void begin(uint8_t select)** set select pin. - **uint8_t channels()** returns the number of channels. -- **int16_t maxValue()** returns maxReading of adc, e.g. 1023. +- **int16_t maxValue()** returns maxReading of ADC, typical 1023 or 4095. This makes it easy to calculate relative measurements. + + +#### Base + - **int16_t analogRead(uint8_t channel)** reads the value of a single channel. - **void analogReadMultiple(uint8_t channels[], uint8_t numChannels, int16_t readings[])** reads multiple channels in one call. See section below. @@ -87,6 +107,8 @@ of the ADC first to get optimal speed. | 6 | 6 | 7 | 3x08 | | 7 | 7 | 6 | 3x08 | +Note: the MCP3x01 are not included in this table, not investigated yet. + ### Debug @@ -108,8 +130,10 @@ BEFORE the **begin()** function. #### setGPIOpins() experimental - **void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)** -overrule GPIO pins of ESP32 for hardware SPI. needs to be called AFTER the **begin()** function. +overrule GPIO pins of ESP32 for hardware SPI. +This function needs to be called AFTER the **begin()** function. +in code: ```cpp void setup() { @@ -165,16 +189,15 @@ Finally **analogReadMultiple()** can be used to read only one channel too by using numChannels = 1. -## MCP3201 experimental - -Since 0.2.0 code for the MCP3201 has been added however this 12 bit single -channel device has not been tested yet. +## MCP3001, MCP3201 experimental -As the SPI transfer looked quite a bit like the MCP3202 it is expected to work -but the proof is in the hardware test. +Since 0.2.0 code for the MCP3201 has been added. +The first tests are done (see #13) which showed that the 0.2.0 implementation +was not correct. +This has been fixed in the 0.2.1 version. -Note that not all function calls make sense for the MCP3201 as this device only -has one channel. So use the library carefully. +Note that not all function calls make sense for the MCP3201 and MCP3001 as these +devices only have one channel. So use the library carefully. Feedback is as always welcome. @@ -202,3 +225,12 @@ Feedback is as always welcome. it actually does float mapping. As it implies the same mapping for all it might not be that useful => check multiMap library. + +## 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, + diff --git a/libraries/MCP_ADC/examples/MCP3208_performance/performance_0.1.9.md b/libraries/MCP_ADC/examples/MCP3208_performance/performance_0.1.9.md index 5f3fcc54a..039428151 100644 --- a/libraries/MCP_ADC/examples/MCP3208_performance/performance_0.1.9.md +++ b/libraries/MCP_ADC/examples/MCP3208_performance/performance_0.1.9.md @@ -8,14 +8,14 @@ Max clock frequency tested 16 MHz, ESP32 WROVER Module ### Library version: 0.1.9 -| Action | HW 1 MHz | HW 2 MHz | HW 4 MHz | HW 8 MHz | HW 10 MHz | HW 12 MHz | HW 14 MHz | HW 16 MHz | notes | -|:------------------------------|---------:|---------:|---------:|---------:|:---------:|:---------:|:---------:|:---------:| -| mcp28.analogRead() | 397.0 | 243.0 | 188.0 | 158.00 | 153.0 | 209.0 | 208.0 | 147.0 | -| mcp28.analogReadMultiple() | 271.0 | 154.0 | 99.00 | 70.00 | 64.00 | 61.00 | 59.0 | 55.00 | -| single / multiple ratio | 1.0 | 1.0 | 1.0 | 2.0 | 2.0 | 3.0 | 3.0 | 2.0 | -| | | | | | | | | | -| mcp28.differentialRead() | 359.0 | 241.0 | 186.0 | 157.0 | 151.0 | 148.0 | 146.0 | 142.0 | -| mcp28.deltaRead() | 363.0 | 304.0 | 234.0 | 198.0 | 191.0 | 187.0 | 185.0 | 145.0 | +| Action | HW 1 MHz | HW 2 MHz | HW 4 MHz | HW 8 MHz | HW 10 MHz | HW 12 MHz | HW 14 MHz | HW 16 MHz | notes | +|:------------------------------|---------:|---------:|---------:|----------:|----------:|-----------:|----------:|----------:|:----------| +| mcp28.analogRead() | 397.0 | 243.0 | 188.0 | 158.00 | 153.0 | 209.0 | 208.0 | 147.0 | +| mcp28.analogReadMultiple() | 271.0 | 154.0 | 99.00 | 70.00 | 64.00 | 61.00 | 59.0 | 55.00 | +| single / multiple ratio | 1.0 | 1.0 | 1.0 | 2.0 | 2.0 | 3.0 | 3.0 | 2.0 | +| | | | | | | | | | +| mcp28.differentialRead() | 359.0 | 241.0 | 186.0 | 157.0 | 151.0 | 148.0 | 146.0 | 142.0 | +| mcp28.deltaRead() | 363.0 | 304.0 | 234.0 | 198.0 | 191.0 | 187.0 | 185.0 | 145.0 | ### Notes diff --git a/libraries/MCP_ADC/examples/MCP3208_performance/readADC_vs_readADCMultiple.md b/libraries/MCP_ADC/examples/MCP3208_performance/readADC_vs_readADCMultiple.md index 8749d63b9..90d52ab29 100644 --- a/libraries/MCP_ADC/examples/MCP3208_performance/readADC_vs_readADCMultiple.md +++ b/libraries/MCP_ADC/examples/MCP3208_performance/readADC_vs_readADCMultiple.md @@ -5,8 +5,8 @@ - source https://github.com/RobTillaart/MCP_ADC/pull/11#issuecomment-1676461195 - figures are indicative and platform dependent. -| function | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <- channels -|:--------------------:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:| +| function | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <- channels | +|:--------------------:|------:|------:|------:|------:|------:|------:|------:|------:|:-------------:| | analogRead | | 42 | 59 | 78 | 98 | 118 | 137 | 157 | (us) | analogReadMultiple | | 27 | 34 | 41 | 49 | 55 | 62 | 70 | (us) | ratio | | 1.56 | 1.73 | 1.90 | 2.00 | 2.15 | 2.21 | 2.24 | diff --git a/libraries/MCP_ADC/keywords.txt b/libraries/MCP_ADC/keywords.txt index d89f80343..db5b62aaf 100644 --- a/libraries/MCP_ADC/keywords.txt +++ b/libraries/MCP_ADC/keywords.txt @@ -1,6 +1,7 @@ # Syntax Colouring Map For MCP_ADC # Data types (KEYWORD1) +MCP3001 KEYWORD1 MCP3002 KEYWORD1 MCP3004 KEYWORD1 MCP3008 KEYWORD1 diff --git a/libraries/MCP_ADC/library.json b/libraries/MCP_ADC/library.json index a355248ce..935cefff5 100644 --- a/libraries/MCP_ADC/library.json +++ b/libraries/MCP_ADC/library.json @@ -1,6 +1,6 @@ { "name": "MCP_ADC", - "keywords": "MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204, MCP3208", + "keywords": "MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204, MCP3208", "description": "Arduino library for MCP_ADC, e.g. MCP3008 SPI 10 bit, 8 channel ADC", "authors": [ @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/MCP_ADC.git" }, - "version": "0.2.0", + "version": "0.2.1", "license": "MIT", "frameworks": "*", "platforms": "*", diff --git a/libraries/MCP_ADC/library.properties b/libraries/MCP_ADC/library.properties index 04f5d3c55..fb082d653 100644 --- a/libraries/MCP_ADC/library.properties +++ b/libraries/MCP_ADC/library.properties @@ -1,9 +1,9 @@ name=MCP_ADC -version=0.2.0 +version=0.2.1 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for MCP_ADC, e.g. MCP3008 SPI 10 bit, 8 channel ADC -paragraph=MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204, MCP3208 +paragraph=MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204, MCP3208 category=Sensors url=https://github.com/RobTillaart/MCP_ADC architectures=*