-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added differential amplifier api as a library
- Loading branch information
Showing
8 changed files
with
365 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,83 @@ | ||
# Differential Amplifier | ||
|
||
<img src="ADC Control Reg C.png" alt="Boards Manager" /> | ||
<img src="ADC Multiplexer.png" alt="Boards Manager" /> | ||
<img src="ADC Register List.png" alt="Boards Manager" /> | ||
<img src="Diagram.png" alt="Boards Manager" /> | ||
<img src="Differential Amplifier.png" alt="Boards Manager" /> | ||
## Usage: | ||
|
||
- See examples/differential_amplifier | ||
|
||
``` | ||
int output = analogDiffRead(A0, A1, GAIN_8); | ||
// output = (A1 - A0) * 8 | ||
int invalid_output = analogDiffRead(A0, A5, GAIN_8); | ||
// invalid_output = -1 | ||
``` | ||
|
||
- Available pin combinations | ||
|
||
| -\+ | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | | ||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ||
| A0 | | ✓ | | | | | | | | | | ||
| A1 | ✓ | | | | | | | | | | | ||
| A2 | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ||
| A3 | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ||
| A4 | ✓ | ✓ | | | | | | | | | | ||
| A5 | ✓ | ✓ | | | | | | | | | | ||
| A6 | ✓ | ✓ | | | | | | | | | | ||
| A7 | ✓ | ✓ | | | | | | | | | | ||
| A8 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | | ||
| A9 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | | ||
|
||
Also see the examples in the DAO library provided by this core. | ||
|
||
## How does it work? | ||
|
||
### Basics | ||
|
||
The differential amplifier (DAP) has 2 inputs (`inverting`/minus and `non-inverting`/plus), a `gain` value and 1 `output`. | ||
|
||
``` | ||
output = gain * (non-inverting - inverting) | ||
``` | ||
|
||
And the output can be read through the ADC (like a normal analog read). | ||
|
||
All information was extracted from this translation of the datasheet: [(English) LGT8FX8P_databook_V1.04](../LGT8FX8P_databook_v1.0.4.en.pdf) (thanks to [metallurge](https://github.com/metallurge) for the translated doc [here](https://github.com/RalphBacon/LGT8F328P-Arduino-Clone-Chip-ATMega328P/issues/2#issuecomment-517952757)) | ||
|
||
<img src="Diagram.png" alt="ADC Structure chart. Page 232" /> | ||
|
||
### Algorithm: | ||
|
||
1. Setup the inputs and gain and turn DAO on through the DAPRC (Differential amplifier control register): | ||
|
||
`DAPCR = DAPEN | gain | inverting | noninverting;` | ||
|
||
- Enable: DAPEN | ||
- Gain: GA[1:0] | ||
- Inverting input: DNS[2:0] | ||
- Non inverting input: DPS[1:0] | ||
Important: Only one input can use the multiplexer. This means that not all combinations of pins can be compared (See table in the library source) | ||
- <img src="Differential Amplifier.png" alt="DAPRC. Page 243" /> | ||
|
||
2. Configure the ADC input to use the Differential amplifier instead of reading directly from the analog pins | ||
|
||
`ADCSRC |= DIFS_DIFFAMP;` | ||
|
||
- ADC input switch: DIFS | ||
<img src="ADC Control Reg C.png" alt="ADCSRC. Page 243 " /> | ||
|
||
3. Setup the multiplexer if necessary and make the reading | ||
|
||
`int res = analogRead(inverting == INVERTING_MXER ? pin1 : pin2);` | ||
|
||
- For this, I'm just reusing the standard `analogRead(pin)` function which also configures the multiplexer. | ||
- Note: for some pin combinations it is not necessary to use the multiplexer, but for the sake of simplicity I still use the normal `analogRead(pin)` function. In this case it doesn't matter which pin is passed to the function, as the DAO won't use the output of the multiplexer. | ||
- <img src="ADC Multiplexer.png" alt="DAPRC. Page 243" /> | ||
|
||
4. Cleanup: | ||
|
||
- Turn DAO off: | ||
|
||
`DAPCR &= ~DAPEN;` | ||
|
||
- Undo step (3) (reconnect ADC to multiplexer for future normal analogRead calls) | ||
|
||
`ADCSRC &= ~DIFS_DIFFAMP;` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
lgt8f/libraries/differential_amplifier/differential_amplifier.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
DAP.cpp - Differential Amplifier library | ||
Copyright (c) 2019 David Buezas. All right reserved. | ||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
This library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
|
||
#include "differential_amplifier.h" | ||
#include "wiring_analog.c" | ||
/** DAPCR Differential Ampliifier Control Register **/ | ||
// enable DAP | gain | inverting | non-inverting | ||
// DAPEN | GA1 GA0 | DNS2 DNS1 DNS0 | DPS1 DPS0 | ||
|
||
#define DAPEN 0b1 << 7 | ||
|
||
#define INVERTING_ADC2 0b000 << 2 | ||
#define INVERTING_ADC3 0b001 << 2 | ||
#if defined(__LGT8FX8P48__) | ||
#define INVERTING_ADC8 0b010 << 2 | ||
#define INVERTING_ADC9 0b011 << 2 | ||
#endif | ||
#define INVERTING_APN4 0b100 << 2 // PE0/APN4/SCWD, not normally exposed | ||
#define INVERTING_MXER 0b101 << 2 | ||
#define INVERTING_GRND 0b110 << 2 | ||
#define INVERTING_CLOSE 0b111 << 2 | ||
|
||
#define NONINVERTING_MXER 0b00 << 0 | ||
#define NONINVERTING_ADC0 0b01 << 0 | ||
#define NONINVERTING_ADC1 0b10 << 0 | ||
#define NONINVERTING_GRND 0b11 << 0 | ||
|
||
/** ADCSRC ADC Control Status Register C **/ | ||
/* | ||
| offset compensation | n/a | calibration | auto monitoring | | ||
| OFEN | x | SPN | AMEN | | ||
... | ||
| x | SPD | DIFS | ADTM | | ||
| n/a | fast | 0=MXER 1=DIFF-AMP | test mode | | ||
*/ | ||
|
||
#define ADTM 0b1 << 0 | ||
#define DIFS_MXER 0b0 << 1 | ||
#define DIFS_DIFFAMP 0b1 << 1 | ||
#define SPD_FAST 0b1 << 2 | ||
#define AMEN 0b1 << 4 | ||
#define SPN 0b1 << 5 | ||
#define OFEN 0b1 << 7 | ||
|
||
int analogDiffRead(uint8_t negativePin, uint8_t positivePin, uint8_t gain) { | ||
uint8_t inverting; | ||
uint8_t muxedPin = A0; | ||
switch (negativePin) { | ||
case A2: | ||
inverting = INVERTING_ADC2; | ||
break; | ||
case A3: | ||
inverting = INVERTING_ADC3; | ||
break; | ||
#if defined(__LGT8FX8P48__) | ||
case A8: | ||
inverting = INVERTING_ADC8; | ||
break; | ||
case A9: | ||
inverting = INVERTING_ADC9; | ||
break; | ||
#endif | ||
default: | ||
inverting = INVERTING_MXER; | ||
muxedPin = negativePin; | ||
} | ||
uint8_t noninverting; | ||
switch (positivePin) { | ||
case A0: | ||
noninverting = NONINVERTING_ADC0; | ||
break; | ||
case A1: | ||
noninverting = NONINVERTING_ADC1; | ||
break; | ||
default: | ||
noninverting = NONINVERTING_MXER; | ||
muxedPin = positivePin; | ||
} | ||
if (negativePin == positivePin || | ||
inverting == INVERTING_MXER && noninverting == NONINVERTING_MXER) { | ||
// combination not allowed | ||
return -1; | ||
} | ||
// enable | gain | inverting | non-inverting | ||
// DAPEN | GA1 GA0 | DNS2 DNS1 DNS0 | DPS1 DPS0 | ||
DAPCR = DAPEN | gain | inverting | noninverting; // get right side | ||
ADCSRC |= DIFS_DIFFAMP; // set Diff. Amp. as source for the ADC | ||
// Note: analogRead() will configure the muxer even if the multiplexer is not | ||
// used by neither the inverting nor the noninverting pin, but that's fine | ||
// because the ADC won't read it | ||
int res = analogRead(muxedPin); | ||
DAPCR &= ~DAPEN; // disable Diff. Amp. | ||
ADCSRC &= ~DIFS_DIFFAMP; // set back the Muxer as source for the ADC | ||
return res; | ||
} |
50 changes: 50 additions & 0 deletions
50
lgt8f/libraries/differential_amplifier/differential_amplifier.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
DAP.h - Differential Amplifier library | ||
Copyright (c) 2019 David Buezas. All right reserved. | ||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
This library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
|
||
#include <inttypes.h> | ||
|
||
#define GAIN_1 0b00 << 5 | ||
#define GAIN_8 0b01 << 5 | ||
#define GAIN_16 0b10 << 5 | ||
#define GAIN_32 0b11 << 5 | ||
|
||
/* | ||
Reads the amplified difference between two pins. | ||
\param negativePin The pin (A0-A9) with the lowest voltage. | ||
\param positiveePin The pin (A0-A9) with the highest voltage. | ||
\param gain The gain. Use constants GAIN_1, GAIN_8, GAIN_16, GAIN_32 | ||
\returns int: (positivePin - negativePin) * gain if combination is available | ||
\returns -1 if combination is NOT available | ||
Available combinations: | ||
| -\+ | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | | ||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ||
| A0 | | ✓ | | | | | | | | | | ||
| A1 | ✓ | | | | | | | | | | | ||
| A2 | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ||
| A3 | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ||
| A4 | ✓ | ✓ | | | | | | | | | | ||
| A5 | ✓ | ✓ | | | | | | | | | | ||
| A6 | ✓ | ✓ | | | | | | | | | | ||
| A7 | ✓ | ✓ | | | | | | | | | | ||
| A8 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | | ||
| A9 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | | ||
*/ | ||
int analogDiffRead(uint8_t negativePin, uint8_t positivePin, uint8_t gain); |
48 changes: 48 additions & 0 deletions
48
lgt8f/libraries/differential_amplifier/examples/all_vs_all/all_vs_all.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
//============================================ | ||
// Differential Amplifier demo for LGT8F328x | ||
// by dbuezas | ||
// Using new differential_amplifier library. | ||
// Differential read from all analog pin combinations | ||
//============================================ | ||
#include "differential_amplifier.h" | ||
|
||
#define GAIN GAIN_1 | ||
// #define GAIN GAIN_8 | ||
// #define GAIN GAIN_16 | ||
// #define GAIN GAIN_32 | ||
|
||
void setup() { | ||
Serial.begin(230400); | ||
Serial.println("start"); | ||
// analogReference(DEFAULT); // 5v | ||
} | ||
void loop() { | ||
static byte list[] = {A0, A1, A2, A3, A4, A5, A6, A7}; | ||
static const byte list_length(sizeof(list) / sizeof(list[0])); | ||
Serial.print("-\\+\t"); | ||
for (int pos = 0; pos < list_length; pos++) { | ||
Serial.print("A"); | ||
Serial.print(pos); | ||
Serial.print("\t"); | ||
} | ||
Serial.println(); | ||
for (int neg = 0; neg < list_length; neg++) { | ||
Serial.print("A"); | ||
Serial.print(neg); | ||
Serial.print("\t"); | ||
for (int pos = 0; pos < list_length; pos++) { | ||
int value = analogDiffRead(list[neg], list[pos], GAIN); | ||
if (neg == pos) { | ||
Serial.print("x"); | ||
} else if (value == -1) { | ||
Serial.print("."); // -1 means pin combination not available | ||
} else { | ||
Serial.print(value); | ||
} | ||
Serial.print("\t"); | ||
} | ||
Serial.println(); | ||
} | ||
Serial.println("--------"); | ||
delay(100); | ||
} |
43 changes: 43 additions & 0 deletions
43
lgt8f/libraries/differential_amplifier/examples/voltage_follower/voltage_follower.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
//============================================ | ||
// Differential Amplifier demo for LGT8F328x | ||
// by dbuezas | ||
// Using new differential_amplifier library. | ||
// Connect A1 to the voltage source (0..5v) and D4 to A0 with a jumper wire | ||
// Open the Serial Plotter and you'll see how the DAC in D4 will follow the | ||
// voltage read by A1 | ||
//============================================ | ||
#include "differential_amplifier.h" | ||
|
||
#define INPUT_VOLTAGE_PIN A1 | ||
#define DAC_PIN DAC0 // D4 in the silk screen | ||
#define DAC_READER_PIN A0 | ||
|
||
void setup() { | ||
Serial.begin(230400); | ||
Serial.println("start"); | ||
analogReference(DEFAULT); // 5v. If not set, the DAC only gets to 1v | ||
pinMode(DAC0, ANALOG); // DAC0 = D4 | ||
} | ||
|
||
float dac_value = 0; | ||
void loop() { | ||
if (dac_value < 0) dac_value = 0; | ||
if (dac_value > 255) dac_value = 255; | ||
analogWrite(DAC_PIN, (int)dac_value); | ||
|
||
int minus = analogDiffRead(INPUT_VOLTAGE_PIN, DAC_READER_PIN, GAIN_1); | ||
int plus = analogDiffRead(DAC_READER_PIN, INPUT_VOLTAGE_PIN, GAIN_1); | ||
|
||
float error = minus > plus ? minus : -plus; | ||
int actual = analogRead(INPUT_VOLTAGE_PIN); | ||
int followed = analogRead(DAC_READER_PIN); | ||
Serial.print("\tactual: "); | ||
Serial.print(actual); | ||
Serial.print("\tfollowed: "); | ||
Serial.print(followed); | ||
Serial.println(); | ||
|
||
dac_value -= error / 1000; | ||
delay(10); | ||
return; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
####################################### | ||
# Syntax Coloring Map For Ultrasound | ||
####################################### | ||
|
||
####################################### | ||
# Datatypes (KEYWORD1) | ||
####################################### | ||
|
||
|
||
####################################### | ||
# Methods and Functions (KEYWORD2) | ||
####################################### | ||
|
||
####################################### | ||
# Constants (LITERAL1) | ||
####################################### | ||
GAIN_1 LITERAL1 | ||
GAIN_8 LITERAL1 | ||
GAIN_16 LITERAL1 | ||
GAIN_32 LITERAL1 | ||
|
Oops, something went wrong.