mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-19 16:46:11 -04:00
0.1.7 MCP_DAC
This commit is contained in:
parent
8e0ab56977
commit
c7cc4b04fa
@ -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
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: MCP_DAC.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.6
|
||||
// VERSION: 0.1.7
|
||||
// DATE: 2021-02-03
|
||||
// PURPOSE: Arduino library for MCP_DAC
|
||||
// URL: https://github.com/RobTillaart/MCP_DAC
|
||||
@ -20,6 +20,9 @@
|
||||
// default parameter 0 for getPercentage()
|
||||
// extended unit tests
|
||||
// 0.1.6 2021-12-21 update library.json, license, minor edits
|
||||
// 0.1.7 2022-10-02 support for RP2040 pico (kudos to Intubin)
|
||||
// update documentation for RP2040 (kudos to Intubin)
|
||||
// update build-CI to support RP2040
|
||||
|
||||
|
||||
#include "MCP_DAC.h"
|
||||
@ -70,6 +73,19 @@ void MCP_DAC::begin(uint8_t select)
|
||||
mySPI->end();
|
||||
mySPI->begin(18, 19, 23, select); // CLK=18 MISO=19 MOSI=23
|
||||
}
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
|
||||
if (_useSPI1 == true) {
|
||||
mySPI = &SPI1;
|
||||
}else{
|
||||
mySPI = &SPI;
|
||||
}
|
||||
|
||||
mySPI->end();
|
||||
mySPI->begin();
|
||||
|
||||
|
||||
#else // generic hardware SPI
|
||||
mySPI = &SPI;
|
||||
mySPI->end();
|
||||
@ -86,7 +102,7 @@ void MCP_DAC::begin(uint8_t select)
|
||||
}
|
||||
|
||||
|
||||
#if defined(ESP32)
|
||||
#if defined(ESP32) or defined(ARDUINO_ARCH_RP2040)
|
||||
void MCP_DAC::setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)
|
||||
{
|
||||
_clock = clk;
|
||||
@ -96,7 +112,20 @@ void MCP_DAC::setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t selec
|
||||
digitalWrite(_select, HIGH);
|
||||
|
||||
mySPI->end(); // disable SPI
|
||||
|
||||
#if defined(ESP32)
|
||||
|
||||
mySPI->begin(clk, miso, mosi, select);
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
|
||||
mySPI->setCS(select);
|
||||
mySPI->setSCK(clk);
|
||||
mySPI->setTX(mosi);
|
||||
|
||||
mySPI->begin();
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: MCP_DAC.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.6
|
||||
// VERSION: 0.1.7
|
||||
// DATE: 2021-02-03
|
||||
// PURPOSE: Arduino library for MCP_DAC
|
||||
// URL: https://github.com/RobTillaart/MCP_DAC
|
||||
@ -13,7 +13,7 @@
|
||||
#include "SPI.h"
|
||||
|
||||
|
||||
#define MCP_DAC_LIB_VERSION (F("0.1.6"))
|
||||
#define MCP_DAC_LIB_VERSION (F("0.1.7"))
|
||||
|
||||
|
||||
|
||||
@ -74,47 +74,77 @@ public:
|
||||
void reset();
|
||||
bool usesHWSPI() { return _hwSPI; };
|
||||
|
||||
// ESP32 specific
|
||||
#if defined(ESP32)
|
||||
|
||||
#if defined(ESP32) // ESP32 specific
|
||||
|
||||
void selectHSPI() { _useHSPI = true; };
|
||||
void selectVSPI() { _useHSPI = false; };
|
||||
bool usesHSPI() { return _useHSPI; };
|
||||
bool usesVSPI() { return !_useHSPI; };
|
||||
|
||||
// to overrule ESP32 default hardware pins
|
||||
// to overrule the ESP32s default hardware pins
|
||||
void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select);
|
||||
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040) // RP2040 specific
|
||||
|
||||
// check which SPI-Bus (SPI or SPI1) is used
|
||||
void selectSPI() { _useSPI1 = false; };
|
||||
void selectSPI1() { _useSPI1 = true; };
|
||||
bool usesSPI() { return !_useSPI1; };
|
||||
bool usesSPI1() { return _useSPI1; };
|
||||
|
||||
// to overrule the RP2040s default hardware pins
|
||||
void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select);
|
||||
|
||||
#endif
|
||||
|
||||
protected:
|
||||
uint8_t _dataOut;
|
||||
uint8_t _clock;
|
||||
uint8_t _select;
|
||||
uint8_t _latchPin = 255;
|
||||
bool _hwSPI;
|
||||
uint32_t _SPIspeed = 16000000;
|
||||
|
||||
uint8_t _channels;
|
||||
uint16_t _maxValue;
|
||||
uint16_t _value[2];
|
||||
uint8_t _gain;
|
||||
bool _buffered = false;
|
||||
bool _active = true;
|
||||
protected:
|
||||
uint8_t _dataOut; // Data out Pin (MOSI)
|
||||
uint8_t _clock; // Clock Pin (SCK)
|
||||
uint8_t _select; // Chip Select Pin (CS)
|
||||
uint8_t _latchPin = 255; // Latch-DAC Pin (LDAC)
|
||||
bool _hwSPI; // Hardware SPI (true) or Software SPI (false)
|
||||
uint32_t _SPIspeed = 16000000; // SPI-Bus Frequency
|
||||
|
||||
uint8_t _channels; // Number of DAC-Channels of a given Chip
|
||||
uint16_t _maxValue; // Maximum value of a given Chip
|
||||
uint16_t _value[2]; // Current value (cache for performance)
|
||||
uint8_t _gain; // Programmable Gain Amplifier variable
|
||||
bool _buffered = false; // Buffer for the Reference Voltage of the MCP49XX Series Chips
|
||||
bool _active = true; // Indicates shutDown mode.
|
||||
|
||||
void transfer(uint16_t data);
|
||||
uint8_t swSPI_transfer(uint8_t d);
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
|
||||
SPIClassRP2040 * mySPI;
|
||||
|
||||
#else
|
||||
|
||||
SPIClass * mySPI;
|
||||
|
||||
#endif
|
||||
|
||||
SPISettings _spi_settings;
|
||||
|
||||
#if defined(ESP32)
|
||||
|
||||
bool _useHSPI = true;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
|
||||
bool _useSPI1 = false;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 4800 Series
|
||||
// MCP4800 Series
|
||||
//
|
||||
class MCP4801 : public MCP_DAC
|
||||
{
|
||||
@ -160,7 +190,7 @@ public:
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 4900 Series
|
||||
// MCP4900 Series
|
||||
//
|
||||
class MCP4901 : public MCP_DAC
|
||||
{
|
||||
|
@ -113,7 +113,9 @@ MCP49xxx series only, see page 20 ==> not functional for MCP48xx series.
|
||||
- **bool usesHWSPI()** returns true if HW SPI is used.
|
||||
|
||||
|
||||
### ESP32 specific
|
||||
## ESP32 specific
|
||||
|
||||
### SPI port selection
|
||||
|
||||
This functionality is new in 0.1.2 and it is expected that the interface will change
|
||||
in the future.
|
||||
@ -127,7 +129,7 @@ The **selectVSPI()** or the **selectHSPI()** needs to be called
|
||||
BEFORE the **begin()** function.
|
||||
|
||||
|
||||
#### experimental
|
||||
### 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.
|
||||
@ -145,7 +147,7 @@ This interface can change in the future as the **select** pin is known
|
||||
in the code.
|
||||
|
||||
|
||||
#### ESP32 connections to MCP4922 (example)
|
||||
### ESP32 connections to MCP4922 (example)
|
||||
|
||||
ESP32 has **four** SPI peripherals from which two can be used.
|
||||
|
||||
@ -159,15 +161,80 @@ SPI0 and SPI1 are used to access flash memory. SPI2 and SPI3 are "user" SPI cont
|
||||
| SDI | MOSI = 13 | MOSI = 23 |
|
||||
| not used | MISO = 12 | MISO = 19 |
|
||||
|
||||
By using different **SELECT** pins multiple DAC's can be controlled over
|
||||
one SPI bus.
|
||||
|
||||
## Future
|
||||
|
||||
- test test test and ....
|
||||
- refactor the API
|
||||
- improve documentation
|
||||
- ...
|
||||
## RP2040 specific
|
||||
|
||||
### SPI port selection
|
||||
|
||||
Select the SPI bus on which the device is on. Both need to be called before the **begin()** function. If the function is called after the **begin()** function, changes will only apply if the **end()** and then the **begin()** functions are called.
|
||||
|
||||
- **void selectSPI()** Select the SPI (SPI0) bus. This is the default and does not need to be called.
|
||||
- **void selectSPI1()** Select the (second) SPI1 bus.
|
||||
- **bool usesSPI()** returns true if SPI is used
|
||||
- **bool usesSPI1()** returns true if SPI1 is used
|
||||
|
||||
|
||||
### Experimental
|
||||
|
||||
- **void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)** overrule GPIO pins of RP2040 for different SPI pins. needs to be called
|
||||
AFTER the **begin()** function. Selcted pins must match the RP2040 pinout!
|
||||
|
||||
|
||||
```cpp
|
||||
void setup()
|
||||
{
|
||||
MCP.selectSPI(); //use for SPI / SPI0
|
||||
MCP.selectSPI1(); //use for SPI1
|
||||
MCP.begin(17);
|
||||
MCP.setGPIOpins(CLK, MISO, MOSI, SELECT); // SELECT should match the param of begin()
|
||||
}
|
||||
```
|
||||
|
||||
### Pico connections to MCP4922 (example)
|
||||
|
||||
The RP2040 has **two** SPI peripherals from which two can be used.
|
||||
|
||||
SPI (SPI0) and SPI1 can both be used to connect devices.
|
||||
|
||||
|
||||
| MCP4922 | SPI / SPI0 | SPI1 |
|
||||
|:--------:|:-------------:|:-------------:|
|
||||
| CS | SELECT = 17 | SELECT = 13 |
|
||||
| SCK | SCLK = 18 | SCLK = 14 |
|
||||
| SDI | MOSI = 19 | MOSI = 15 |
|
||||
| not used | MISO = 16 | MISO = 12 |
|
||||
|
||||
By using different **SELECT** pins multiple DAC's can be controlled over
|
||||
one SPI bus.
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples
|
||||
|
||||
|
||||
## Future
|
||||
|
||||
#### Must
|
||||
|
||||
- test test test and ....
|
||||
- improve documentation.
|
||||
|
||||
#### Should
|
||||
|
||||
- **useSPI1** and **useHSPI** are functional identical indicators.
|
||||
- how to refactor to a generic model? Should work for all libraries.
|
||||
- int8_t HWSPIport = 0, 1, 2, 3, 4, .... (-1 == SW SPI ?).
|
||||
- numbers are not self-documenting.
|
||||
- **selectSPIport(int)** ?
|
||||
- would reduce conditional code.
|
||||
|
||||
#### Could
|
||||
|
||||
- refactor the API (how).
|
||||
- minimize conditional in code if possible.
|
||||
|
||||
|
||||
|
@ -0,0 +1,27 @@
|
||||
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:
|
||||
# - uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
# - m4
|
||||
# - esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- rpipico
|
@ -0,0 +1,198 @@
|
||||
//
|
||||
// FILE: MCP4921_wave_generator_RP2040.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo function generators
|
||||
// DATE: 2021-02-03
|
||||
// URL: https://github.com/RobTillaart/FunctionGenerator
|
||||
//
|
||||
// depending on the platform, the range of "smooth" sinus is limited.
|
||||
// other signals are less difficult so have a slightly larger range.
|
||||
//
|
||||
// PLATFORM SINUS SQUARE SAWTOOTH TRIANGLE
|
||||
// UNO -100 Hz
|
||||
// ESP32 -200 Hz -1000 -250 -100
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
SPI Connections:
|
||||
|
||||
MOSI: GP 19
|
||||
SCK: GP 18
|
||||
CS: GP 17
|
||||
LDAC: GP 2
|
||||
|
||||
SPI1 Connections:
|
||||
|
||||
MOSI: GP 15
|
||||
SCK: GP 14
|
||||
CS: GP 13
|
||||
LDAC: GP 3
|
||||
|
||||
|
||||
(Experimental) The Pins can be changed at any time via the setGPIO() command, view the Pico Pinout for compatible Pins
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "MCP_DAC.h"
|
||||
|
||||
|
||||
uint16_t freq = 10;
|
||||
uint32_t period = 0;
|
||||
uint32_t halvePeriod = 0;
|
||||
|
||||
|
||||
// q = square
|
||||
// s = sinus
|
||||
// w = sawtooth
|
||||
// t = triangle
|
||||
// r = random
|
||||
char mode = 'q';
|
||||
|
||||
|
||||
MCP4921 MCP;
|
||||
uint16_t count;
|
||||
uint32_t lastTime = 0;
|
||||
|
||||
|
||||
// LOOKUP TABLE SINE
|
||||
uint16_t sine[361];
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
// fill table with sinus values for fast lookup
|
||||
for (int i = 0; i < 361; i++)
|
||||
{
|
||||
sine[i] = 2047 + round(2047 * sin(i * PI / 180));
|
||||
}
|
||||
|
||||
|
||||
MCP.selectSPI(); //select SPI
|
||||
//MCP.selectSPI1(); //select SPI1
|
||||
|
||||
MCP.begin(17); // select pin = 17, SPI
|
||||
//MCP.begin(13); // select pin = 13, SPI1
|
||||
|
||||
|
||||
MCP.fastWriteA(0);
|
||||
|
||||
period = 1e6 / freq;
|
||||
halvePeriod = period / 2;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Serial.println(analogRead(A0)); // read output back via A0.
|
||||
yield();
|
||||
uint32_t now = micros();
|
||||
|
||||
count++;
|
||||
|
||||
if (now - lastTime > 100000)
|
||||
{
|
||||
lastTime = now;
|
||||
// Serial.println(count); // show # updates per 0.1 second
|
||||
count = 0;
|
||||
if (Serial.available())
|
||||
{
|
||||
int c = Serial.read();
|
||||
switch (c)
|
||||
{
|
||||
case '+':
|
||||
freq++;
|
||||
break;
|
||||
case '-':
|
||||
freq--;
|
||||
break;
|
||||
case '*':
|
||||
freq *= 10;
|
||||
break;
|
||||
case '/':
|
||||
freq /= 10;
|
||||
break;
|
||||
case '0' ... '9':
|
||||
freq *= 10;
|
||||
freq += (c - '0');
|
||||
break;
|
||||
case 'c':
|
||||
freq = 0;
|
||||
break;
|
||||
case 'A':
|
||||
break;
|
||||
case 'a':
|
||||
break;
|
||||
case 'q':
|
||||
case 's':
|
||||
case 'w':
|
||||
case 't':
|
||||
case 'r':
|
||||
case 'z':
|
||||
case 'm':
|
||||
case 'h':
|
||||
mode = c;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
period = 1e6 / freq;
|
||||
halvePeriod = period / 2;
|
||||
Serial.print(freq);
|
||||
// Serial.print('\t');
|
||||
// Serial.print(period);
|
||||
// Serial.print('\t');
|
||||
// Serial.print(halvePeriod);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t t = now % period;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case 'q':
|
||||
if (t < halvePeriod ) MCP.fastWriteA(4095);
|
||||
else MCP.fastWriteA(0);
|
||||
break;
|
||||
case 'w':
|
||||
MCP.fastWriteA(t * 4095 / period );
|
||||
break;
|
||||
case 't':
|
||||
if (t < halvePeriod) MCP.fastWriteA(t * 4095 / halvePeriod);
|
||||
else MCP.fastWriteA( (period - t) * 4095 / halvePeriod );
|
||||
break;
|
||||
case 'r':
|
||||
MCP.fastWriteA(random(4096));
|
||||
break;
|
||||
case 'z': // zero
|
||||
MCP.fastWriteA(0);
|
||||
break;
|
||||
case 'h': // high
|
||||
MCP.fastWriteA(4095);
|
||||
break;
|
||||
case 'm': // mid
|
||||
MCP.fastWriteA(2047);
|
||||
break;
|
||||
default:
|
||||
case 's':
|
||||
// reference
|
||||
// float f = ((PI * 2) * t)/period;
|
||||
// MCP.setValue(2047 + 2047 * sin(f));
|
||||
//
|
||||
int idx = (360 * t) / period;
|
||||
MCP.fastWriteA(sine[idx]); // lookuptable
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -2,11 +2,13 @@
|
||||
|
||||
Note that some examples are ESP32 specific as they use e.g. VSPI()
|
||||
|
||||
| example | UNO | ESP32 |
|
||||
|:-----------------------|:-----:|:-----:|
|
||||
| MCP4911_test | Y | Y |
|
||||
| MCP4921_standalone | Y | Y |
|
||||
| MCP4921_test | Y | Y |
|
||||
| MCP4921_VSPI | N | Y |
|
||||
| MCP4921_wave_generator | N | Y |
|
||||
| example | UNO | ESP32 | RP2040 |
|
||||
|:-----------------------------:|:-----:|:-----:|:------:|
|
||||
| MCP4911_test | Y | Y | Y |
|
||||
| MCP4921_standalone | Y | Y | Y |
|
||||
| MCP4921_test | Y | Y | Y |
|
||||
| MCP4921_VSPI | N | Y | N |
|
||||
| MCP4921_wave_generator | Y | Y | Y |
|
||||
| MCP4921_wave_generator_ESP32 | N | Y | N |
|
||||
| MCP4921_wave_generator_RP2040 | N | N | Y |
|
||||
|
||||
|
@ -52,6 +52,11 @@ setGPIOpins KEYWORD2
|
||||
increment KEYWORD2
|
||||
decrement KEYWORD2
|
||||
|
||||
selectSPI KEYWORD2
|
||||
selectSPI1 KEYWORD2
|
||||
usesSPI KEYWORD2
|
||||
usesSPI1 KEYWORD2
|
||||
|
||||
# Instances (KEYWORD2)
|
||||
|
||||
# Constants (LITERAL1)
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/MCP_DAC"
|
||||
},
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.7",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,9 +1,9 @@
|
||||
name=MCP_DAC
|
||||
version=0.1.6
|
||||
version=0.1.7
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for Microchip SPI DAC, 8, 10, 12 bit; 1 or 2 channel.
|
||||
paragraph= MCP4801, MCP4802, MCP4811,MCP4812, MCP4821, MCP4822, MCP4901, MCP4902, MCP4911, MCP4912, MCP4921, MCP4922
|
||||
paragraph= MCP4801, MCP4802, MCP4811,MCP4812, MCP4821, MCP4822, MCP4901, MCP4902, MCP4911, MCP4912, MCP4921, MCP4922.
|
||||
category=Sensors
|
||||
url=https://github.com/RobTillaart/MCP_DAC
|
||||
architectures=*
|
||||
|
Loading…
Reference in New Issue
Block a user