0.1.9 MCP_ADC

This commit is contained in:
rob tillaart 2022-11-17 13:00:17 +01:00
parent a3e2c91f94
commit 531c273094
9 changed files with 221 additions and 75 deletions

View File

@ -1,3 +1,18 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040
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
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
@ -9,3 +24,4 @@ compile:
- esp32
# - esp8266
# - mega2560
- rpipico

View File

@ -0,0 +1,39 @@
# Change Log MCP_ADC
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.9] - 2022-11-16
- add RP2040 in build-CI
- add changelog.md
- minor edit readme.md
- clean up unit test
## [0.1.8] - 2021-12-21
- update library.json
- update license
- minor edits
----
## [0.1.7] - 2021-11-07
## [0.1.6] - 2021-08-01
## [0.1.5] - 2021-07-31
## [0.1.4] - 2021-03-31
## [0.1.3] - 2021-02-04
## [0.1.2] - 2021-01-01
## [0.1.1] - 2020-08-14
## [0.1.0] - 2019-10-24
- initial version.

View File

@ -1,7 +1,7 @@
//
// FILE: MCP_ADC.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.8
// VERSION: 0.1.9
// DATE: 2019-10-24
// PURPOSE: Arduino library for MCP3002, MCP3004, MCP3008, MCP3202, MCP3204, MCP3208
// URL: https://github.com/RobTillaart/MCP_ADC
@ -31,25 +31,25 @@ void MCP_ADC::begin(uint8_t select)
if (_hwSPI)
{
#if defined(ESP32)
if (_useHSPI) // HSPI
if (_useHSPI) // HSPI
{
mySPI = new SPIClass(HSPI);
mySPI->end();
mySPI->begin(14, 12, 13, select); // CLK=14 MISO=12 MOSI=13
mySPI->begin(14, 12, 13, select); // CLK=14 MISO=12 MOSI=13
}
else // VSPI
else // VSPI
{
mySPI = new SPIClass(VSPI);
mySPI->end();
mySPI->begin(18, 19, 23, select); // CLK=18 MISO=19 MOSI=23
mySPI->begin(18, 19, 23, select); // CLK=18 MISO=19 MOSI=23
}
#else // generic hardware SPI
#else // generic hardware SPI
mySPI = &SPI;
mySPI->end();
mySPI->begin();
#endif
}
else // software SPI
else // software SPI
{
pinMode(_dataIn, INPUT);
pinMode(_dataOut, OUTPUT);
@ -70,7 +70,7 @@ void MCP_ADC::setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t selec
pinMode(_select, OUTPUT);
digitalWrite(_select, HIGH);
mySPI->end(); // disable SPI
mySPI->end(); // disable SPI
mySPI->begin(clk, miso, mosi, select);
}
#endif
@ -103,8 +103,8 @@ int16_t MCP_ADC::deltaRead(uint8_t channel)
if (channel >= _channels) return 0;
int16_t val0 = differentialRead(channel & 0xFE);
// int16_t val1 = differentialRead(channel | 0x01);
// no need to read if val0 has a positive value
// int16_t val1 = differentialRead(channel | 0x01);
// no need to read if val0 has a positive value
int16_t val1 = (val0 > 0) ? 0 : differentialRead(channel | 0x01);
if (channel & 0x01) return val1 - val0;
@ -138,7 +138,7 @@ int16_t MCP_ADC::readADC(uint8_t channel, bool single)
}
mySPI->endTransaction();
}
else // Software SPI
else // Software SPI
{
for (uint8_t b = 0; b < bytes; b++)
{
@ -153,7 +153,7 @@ int16_t MCP_ADC::readADC(uint8_t channel, bool single)
}
// MSBFIRST
// MSBFIRST
uint8_t MCP_ADC::swSPI_transfer(uint8_t val)
{
uint8_t clk = _clock;
@ -175,7 +175,7 @@ uint8_t MCP_ADC::swSPI_transfer(uint8_t val)
/////////////////////////////////////////////////////////////////////////////
//
// MCP3002
// MCP3002
//
MCP3002::MCP3002(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP_ADC(dataIn, dataOut, clock)
@ -186,17 +186,17 @@ MCP3002::MCP3002(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
uint8_t MCP3002::buildRequest(uint8_t channel, bool single, uint8_t * data)
{
// P17 fig 6.1 MCP3002
data[0] = 0x44; // start bit + MSB first bit
if (single) data[0] |= 0x20; // single read | differential
if (channel) data[0] |= (channel << 4); // channel = 0 or 1;
// P17 fig 6.1 MCP3002
data[0] = 0x44; // start bit + MSB first bit
if (single) data[0] |= 0x20; // single read | differential
if (channel) data[0] |= (channel << 4); // channel = 0 or 1;
return 2;
}
/////////////////////////////////////////////////////////////////////////////
//
// MCP3004
// MCP3004
//
MCP3004::MCP3004(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP_ADC(dataIn, dataOut, clock)
@ -207,17 +207,17 @@ MCP3004::MCP3004(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
uint8_t MCP3004::buildRequest(uint8_t channel, bool single, uint8_t * data)
{
// P21 fig 6.1 MCP3004/3008
data[0] = 0x01; // start bit
if (single) data[1] = 0x80; // single read | differential
if (channel) data[1] |= (channel << 4); // channel
// P21 fig 6.1 MCP3004/3008
data[0] = 0x01; // start bit
if (single) data[1] = 0x80; // single read | differential
if (channel) data[1] |= (channel << 4); // channel
return 3;
}
/////////////////////////////////////////////////////////////////////////////
//
// MCP3008
// MCP3008
//
MCP3008::MCP3008(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP_ADC(dataIn, dataOut, clock)
@ -228,17 +228,17 @@ MCP3008::MCP3008(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
uint8_t MCP3008::buildRequest(uint8_t channel, bool single, uint8_t * data)
{
// P21 fig 6.1 MCP3004/3008
data[0] = 0x01; // start bit
if (single) data[1] = 0x80; // single read | differential
if (channel) data[1] |= (channel << 4); // channel
// P21 fig 6.1 MCP3004/3008
data[0] = 0x01; // start bit
if (single) data[1] = 0x80; // single read | differential
if (channel) data[1] |= (channel << 4); // channel
return 3;
}
/////////////////////////////////////////////////////////////////////////////
//
// MCP3202
// MCP3202
//
MCP3202::MCP3202(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP_ADC(dataIn, dataOut, clock)
@ -249,18 +249,18 @@ MCP3202::MCP3202(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
uint8_t MCP3202::buildRequest(uint8_t channel, bool single, uint8_t * data)
{
// P17 fig 6.2 MCP3202
data[0] = 0x01; // start bit
data[1] = 0x20; // MSB first bit
if (single) data[1] |= 0x80; // single read | differential
if (channel) data[1] |= (channel << 6); // channel = 0 or 1;
// P17 fig 6.2 MCP3202
data[0] = 0x01; // start bit
data[1] = 0x20; // MSB first bit
if (single) data[1] |= 0x80; // single read | differential
if (channel) data[1] |= (channel << 6); // channel = 0 or 1;
return 3;
}
/////////////////////////////////////////////////////////////////////////////
//
// MCP3204
// MCP3204
//
MCP3204::MCP3204(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP_ADC(dataIn, dataOut, clock)
@ -271,18 +271,18 @@ MCP3204::MCP3204(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
uint8_t MCP3204::buildRequest(uint8_t channel, bool single, uint8_t * data)
{
// P21 fig 6.1 MCP3204/3208
data[0] = 0x04; // start bit
if (single) data[0] |= 0x02; // single read | differential
if (channel > 3) data[0] |= 0x01; // msb channel (D2)
if (channel) data[1] |= (channel << 6); // other 2 bits (D1 D0)
// P21 fig 6.1 MCP3204/3208
data[0] = 0x04; // start bit
if (single) data[0] |= 0x02; // single read | differential
if (channel > 3) data[0] |= 0x01; // MSB channel (D2)
if (channel) data[1] |= (channel << 6); // other 2 bits (D1 D0)
return 3;
}
/////////////////////////////////////////////////////////////////////////////
//
// MCP3208
// MCP3208
//
MCP3208::MCP3208(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
:MCP_ADC(dataIn, dataOut, clock)
@ -293,11 +293,11 @@ MCP3208::MCP3208(uint8_t dataIn, uint8_t dataOut, uint8_t clock)
uint8_t MCP3208::buildRequest(uint8_t channel, bool single, uint8_t * data)
{
// P21 fig 6.1 MCP3204/3208
data[0] = 0x04; // start bit
if (single) data[0] |= 0x02; // single read | differential
if (channel > 3) data[0] |= 0x01; // msb channel (D2)
if (channel) data[1] |= (channel << 6); // other 2 bits (D1 D0)
// P21 fig 6.1 MCP3204/3208
data[0] = 0x04; // start bit
if (single) data[0] |= 0x02; // single read | differential
if (channel > 3) data[0] |= 0x01; // MSB channel (D2)
if (channel) data[1] |= (channel << 6); // other 2 bits (D1 D0)
return 3;
}

View File

@ -2,7 +2,7 @@
//
// FILE: MCP_ADC.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.8
// VERSION: 0.1.9
// DATE: 2019-10-24
// PURPOSE: Arduino library for MCP_ADC
// URL: https://github.com/RobTillaart/MCP_ADC
@ -13,7 +13,7 @@
#include "SPI.h"
#define MCP_ADC_LIB_VERSION (F("0.1.8"))
#define MCP_ADC_LIB_VERSION (F("0.1.9"))
class MCP_ADC
@ -32,17 +32,17 @@ public:
void setSPIspeed(uint32_t speed);
uint32_t getSPIspeed() { return _SPIspeed; };
// debugging
// debugging
bool usesHWSPI() { return _hwSPI; };
// ESP32 specific
// ESP32 specific
#if defined(ESP32)
void selectHSPI() { _useHSPI = true; };
void selectVSPI() { _useHSPI = false; };
bool usesHSPI() { return _useHSPI; };
bool usesVSPI() { return !_useHSPI; };
// to overrule ESP32 default hardware pins
// to overrule ESP32 default hardware pins
void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select);
#endif
@ -57,9 +57,9 @@ protected:
bool _hwSPI;
uint8_t _channels;
int16_t _maxValue;
uint32_t _SPIspeed = 1000000; // 1MHz is a safe value (datasheet); in a test 4 MHz worked.
uint32_t _SPIspeed = 1000000; // 1 MHz is a safe value (datasheet); in a test 4 MHz worked.
// derived classes must implement this one
// derived classes must implement buildRequest() function.
virtual uint8_t buildRequest(uint8_t channel, bool single, uint8_t * data) = 0;
int16_t readADC(uint8_t channel, bool single);
@ -75,9 +75,11 @@ protected:
uint32_t _count;
};
/////////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES
//
class MCP3002 : public MCP_ADC
{
public:
@ -85,6 +87,7 @@ public:
uint8_t buildRequest(uint8_t channel, bool single, uint8_t * data);
};
class MCP3004 : public MCP_ADC
{
public:
@ -92,6 +95,7 @@ public:
uint8_t buildRequest(uint8_t channel, bool single, uint8_t * data);
};
class MCP3008 : public MCP_ADC
{
public:

View File

@ -134,10 +134,22 @@ which indicates that the last 2 bits got lost due to signal deformation.
For hardware SPI the ESP32 uses the VSPI pins. (see ESP examples).
## Operations
See examples.
## Future
#### must
- documentation
- testing, a lot ...
#### should
#### could
- analogRead (mask, int array\[8\] ) read ports (set in mask) in an array in one call.
would this save time?
@ -146,9 +158,5 @@ For hardware SPI the ESP32 uses the VSPI pins. (see ESP examples).
- get / setF(float A, float B) => float readF(channel) output = A\*value + B;
it actually does float mapping. As it implies the same mapping for all it might
not be that useful => multmap
not be that useful => multimap
## Operations
See examples.

View File

@ -13,7 +13,7 @@
MCP3002 mcp2;
MCP3004 mcp4;
MCP3008 mcp8(11,12,13); // software spi
MCP3008 mcp8(11, 12, 13); // software spi
// MCP3008 mcp8; // hardware spi
MCP3202 mcp22;
MCP3204 mcp24;
@ -81,6 +81,24 @@ void setup()
test_3();
}
// on UNO there is no difference above 8MHz (half CPU clock)
Serial.println("***************************************\n");
for (int s = 1; s <= 16; s *= 2)
{
Serial.println(s * 1000000UL);
mcp22.setSPIspeed(s * 1000000UL);
test_4();
}
// on UNO there is no difference above 8MHz (half CPU clock)
Serial.println("***************************************\n");
for (int s = 1; s <= 16; s *= 2)
{
Serial.println(s * 1000000UL);
mcp24.setSPIspeed(s * 1000000UL);
test_5();
}
// on UNO there is no difference above 8MHz (half CPU clock)
Serial.println("***************************************\n");
for (int s = 1; s <= 16; s *= 2)
@ -210,6 +228,80 @@ void test_3()
}
void test_4()
{
uint32_t val = 0;
start = micros();
for (int channel = 0; channel < mcp22.channels(); channel++)
{
val += mcp22.analogRead(channel);
}
stop = micros();
Serial.print("mcp22.analogRead()\t2x: \t");
Serial.println(stop - start);
delay(10);
start = micros();
for (int channel = 0; channel < mcp22.channels(); channel++)
{
val += mcp22.differentialRead(channel);
}
stop = micros();
Serial.print("mcp22.differentialRead() 2x: \t");
Serial.println(stop - start);
delay(10);
start = micros();
for (int channel = 0; channel < mcp22.channels(); channel++)
{
val += mcp22.deltaRead(channel);
}
stop = micros();
Serial.print("mcp22.deltaRead()\t2x: \t");
Serial.println(stop - start);
Serial.println();
delay(10);
}
void test_5()
{
uint32_t val = 0;
start = micros();
for (int channel = 0; channel < mcp24.channels(); channel++)
{
val += mcp24.analogRead(channel);
}
stop = micros();
Serial.print("mcp24.analogRead()\t4x: \t");
Serial.println(stop - start);
delay(10);
start = micros();
for (int channel = 0; channel < mcp24.channels(); channel++)
{
val += mcp24.differentialRead(channel);
}
stop = micros();
Serial.print("mcp24.differentialRead() 4x: \t");
Serial.println(stop - start);
delay(10);
start = micros();
for (int channel = 0; channel < mcp24.channels(); channel++)
{
val += mcp24.deltaRead(channel);
}
stop = micros();
Serial.print("mcp24.deltaRead()\t4x: \t");
Serial.println(stop - start);
Serial.println();
delay(10);
}
void test_6()
{
uint32_t val = 0;

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/MCP_ADC.git"
},
"version": "0.1.8",
"version": "0.1.9",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=MCP_ADC
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 MCP3002, MCP3004, MCP3008, MCP3202, MCP3204, MCP3208

View File

@ -47,19 +47,6 @@ unittest_teardown()
}
/*
unittest(test_new_operator)
{
assertEqualINF(exp(800));
assertEqualINF(0.0/0.0);
assertEqualINF(42);
assertEqualNAN(INFINITY - INFINITY);
assertEqualNAN(0.0/0.0);
assertEqualNAN(42);
}
*/
unittest(test_constructor)
{
MCP3002 ADC2;