Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Offsetcals adc1 fix #22

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 36 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ void setStartPin(uint8_t pin)
Optional. Designate an Arduino pin to start ADC1.
If not used, a command will be sent instead.

void setDrdyPin(uint8_t pin)
-----------------------------
Optional. Designate an Arduino pin to watch for Data Ready.
If not used, calibrations will require a `waitTime` and dataReady() will always return true.

General Commands
================
Expand All @@ -122,29 +126,9 @@ void reset()
------------
Resets the chip.

void startADC1()
----------------
Starts conversion on ADC1.

void stopADC1()
---------------
Stops conversion on ADC1.

void startADC2()
void startADC1(uint8_t pos_pin, uint8_t neg_pin)
----------------
Starts conversion on ADC2.

void stopADC2()
---------------
Stops conversion on ADC2.


Analog Read Functions
=====================

int32_t readADC1(uint8_t pos_pin,uint8_t neg_pin)
-------------------------------------------------
Reads the 32 bit voltage between the two pins `pos_pin` and `neg_pin`.
Starts conversion on ADC1 between the two pins `pos_pin` and `neg_pin`.
These can be:

| Option | Description |
Expand All @@ -159,9 +143,13 @@ These can be:
| `ADS126X_TDAC` | TDAC test signal positive/negative |
| `ADS126X_FLOAT` | Float (open connection) |

int32_t readADC2(uint8_t pos_pin,uint8_t neg_pin)
-------------------------------------------------
Reads the 24 bit voltage between the two pins `pos_pin` and `neg_pin`.
void stopADC1()
---------------
Stops conversion on ADC1. Uses `start_pin` if it was set (via `setStartPin`), sends a command if it wasn't.

void startADC2(uint8_t pos_pin, uint8_t neg_pin)
----------------
Starts conversion on ADC2 between the two pins `pos_pin` and `neg_pin`.
These can be:

| Option | Description |
Expand All @@ -174,8 +162,26 @@ These can be:
| `ADS126X_ANALOG` | Analog power supply monitor positive/negative |
| `ADS126X_DIGITAL` | Digital power supply monitor positive/negative |
| `ADS126X_TDAC` | TDAC test signal positive/negative |
| `ADS126X_FLOAT` | Float (open connection) |
| `ADS126X_FLOAT` | Float (open connection) |

void stopADC2()
---------------
Stops conversion on ADC2.

Analog Read Functions
=====================

int32_t readADC1()
-------------------------------------------------
Reads the 32 bit voltage between the pins set in `startADC1`.

int32_t readADC2(uint8_t pos_pin,uint8_t neg_pin)
-------------------------------------------------
Reads the 24 bit voltage between the pins set in `startADC2`.

bool dataReady()
---------------
If `setDrdyPin` was used, returns true when the adc's `DRDY` (data ready indicator) pin is `LOW`. If not pin was set, this always returns true. Useful for getting continuous conversions as quickly as possible. Almost certainly faster than command polling (especially if you attach this pin to an interrupt routine).

Calibration Functions
=====================
Expand Down Expand Up @@ -553,6 +559,10 @@ Selects the PGA gain
| `ADS126X_GAIN_16` | 16 V/V |
| `ADS126X_GAIN_32` | 32 V/V |

void getGain()
--------------
Returns the value of the constant used in setGain (i.e. `ADS126X_GAIN_1` -> `0b000` which is int `0`). To get the corresponding actual voltage gain, do something like `uint8_t voltageGainValue = 1 << adc.getGain();` (`ADS126X_GAIN_1` would return `1`).

void setRate(uint8_t rate)
--------------------------
Selects the ADC data rate. In FIR filter mode, the available data
Expand Down
4 changes: 2 additions & 2 deletions examples/basics/basics.ino
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ void setup() {
Serial.begin(115200);

adc.begin(chip_select); // setup with chip select pin
adc.startADC1(); // start conversion on ADC1
adc.startADC1(pos_pin, neg_pin); // start conversion on ADC1

Serial.println("Reading Voltages:");
}

void loop() {
long voltage = adc.readADC1(pos_pin,neg_pin); // read the voltage
long voltage = adc.readADC1(); // read the voltage
Serial.println(voltage); // send voltage through serial
delay(1000); // wait 1 second
}
115 changes: 81 additions & 34 deletions src/ADS126X.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ void ADS126X::setStartPin(uint8_t pin) {
_ads126x_write_pin_low(start_pin);
}

void ADS126X::setDrdyPin(uint8_t pin) {
drdy_used = true;
drdy_pin = pin;
_ads126x_setup_input(drdy_pin);
}

/*!< Regular ADC Commands */

void ADS126X::noOperation() {
Expand All @@ -43,28 +49,56 @@ void ADS126X::reset() {
ADS126X::readRegisters(0,ADS126X_REG_NUM); // read all the registers
}

void ADS126X::startADC1() {
void ADS126X::startADC1(uint8_t pos_pin, uint8_t neg_pin) {
// NOTE: can take up to 50ms for VRef to settle after power on (and possibly after changing certain registers?)
// check if desired pins are different than old pins
if ((REGISTER.INPMUX.bit.MUXN != neg_pin) || (REGISTER.INPMUX.bit.MUXP != pos_pin)) {
REGISTER.INPMUX.bit.MUXN = neg_pin;
REGISTER.INPMUX.bit.MUXP = pos_pin;
ADS126X::writeRegister(ADS126X_INPMUX); // replace on ads126x
}
if(start_used) {
_ads126x_write_pin_low(start_pin);
_ads126x_delay(2);
_ads126x_delaymicro(2); // p.61 delay needs to be ~5.42534722e-7 seconds. so like 0.5us I think?
_ads126x_write_pin_high(start_pin);
_ads126x_delaymicro(2);
_ads126x_write_pin_low(start_pin);
_ads126x_delaymicro(2);
}
else ADS126X::sendCommand(ADS126X_START1);
}

void ADS126X::stopADC1() {
ADS126X::sendCommand(ADS126X_STOP1);
if (start_used) {
_ads126x_write_pin_low(start_pin);
}
else ADS126X::sendCommand(ADS126X_STOP1);
}

void ADS126X::startADC2() {
ADS126X::sendCommand(ADS126X_START2);
void ADS126X::startADC2(uint8_t pos_pin, uint8_t neg_pin) {
// check if desired pins are different than old pins
if ((REGISTER.ADC2MUX.bit.MUXN != neg_pin) || (REGISTER.ADC2MUX.bit.MUXP != pos_pin)) {
REGISTER.ADC2MUX.bit.MUXN = neg_pin;
REGISTER.ADC2MUX.bit.MUXP = pos_pin;
ADS126X::writeRegister(ADS126X_ADC2MUX); // replace on ads126x
}
else ADS126X::sendCommand(ADS126X_START2);
}

void ADS126X::stopADC2() {
ADS126X::sendCommand(ADS126X_STOP2);
}

int32_t ADS126X::readADC1(uint8_t pos_pin,uint8_t neg_pin) {
// NOTE: only drdy_pin version is implemented!
bool ADS126X::dataReady() {
if (drdy_used) {
return !_ads126x_read_pin(drdy_pin); // LOW == data ready.
} else {
return true; // TODO: enable status byte and read ADC and check appropriate status bit
}
}

int32_t ADS126X::readADC1() {
if(cs_used) _ads126x_write_pin_low(cs_pin);

// create buffer to hold transmission
Expand All @@ -81,13 +115,6 @@ int32_t ADS126X::readADC1(uint8_t pos_pin,uint8_t neg_pin) {
} ADC_BYTES;
ADC_BYTES.reg = 0; // clear the ram just in case

// check if desired pins are different than old pins
if((REGISTER.INPMUX.bit.MUXN != neg_pin) || (REGISTER.INPMUX.bit.MUXP != pos_pin)) {
REGISTER.INPMUX.bit.MUXN = neg_pin;
REGISTER.INPMUX.bit.MUXP = pos_pin;
ADS126X::writeRegister(ADS126X_INPMUX); // replace on ads126x
}

uint8_t i = 0; // current place in outgoing buffer
buff[i] = ADS126X_RDATA1; // the read adc1 command
i++;
Expand Down Expand Up @@ -124,7 +151,7 @@ int32_t ADS126X::readADC1(uint8_t pos_pin,uint8_t neg_pin) {
return ADC_BYTES.reg;
}

int32_t ADS126X::readADC2(uint8_t pos_pin,uint8_t neg_pin) {
int32_t ADS126X::readADC2() {
if(cs_used) _ads126x_write_pin_low(cs_pin);

// create buffer to hold transmission
Expand All @@ -141,13 +168,6 @@ int32_t ADS126X::readADC2(uint8_t pos_pin,uint8_t neg_pin) {
} ADC_BYTES;
ADC_BYTES.reg = 0; // clear so pad byte is 0

// check if desired pins are different than old pins
if((REGISTER.ADC2MUX.bit.MUXN != neg_pin) || (REGISTER.ADC2MUX.bit.MUXP != pos_pin)) {
REGISTER.ADC2MUX.bit.MUXN = neg_pin;
REGISTER.ADC2MUX.bit.MUXP = pos_pin;
ADS126X::writeRegister(ADS126X_ADC2MUX); // replace on ads126x
}

uint8_t i = 0; // current place in outgoing buffer
buff[i] = ADS126X_RDATA2; // the read adc2 command
i++;
Expand Down Expand Up @@ -185,14 +205,24 @@ int32_t ADS126X::readADC2(uint8_t pos_pin,uint8_t neg_pin) {
return ADC_BYTES.reg;
}

void ADS126X::calibrateSysOffsetADC1(uint8_t shorted1,uint8_t shorted2) {
// connect the pins internally
REGISTER.INPMUX.bit.MUXN = shorted1;
REGISTER.INPMUX.bit.MUXP = shorted2;
ADS126X::writeRegister(ADS126X_INPMUX);
_ads126x_delay(10); // let signal sort of settle
void ADS126X::calibrateSysOffsetADC1(uint8_t shorted1, uint8_t shorted2, uint16_t waitTime) {
const uint8_t previousRunMode = REGISTER.MODE0.bit.RUNMODE;
setContinuousMode();
startADC1(shorted1, shorted2);
_ads126x_delay(10); // let things settle?
ADS126X::sendCommand(ADS126X_SYOCAL1);
_ads126x_delay(50); // delay to allow time for reads
if (drdy_used) {
while (_ads126x_read_pin(drdy_pin)) {
// drdy_pin is pulled low when cal is complete
}
} else {
_ads126x_delay(waitTime);
}
// reset RUNMODE
if (previousRunMode != ADS126X_CONV_CONT) {
REGISTER.MODE0.bit.RUNMODE = previousRunMode;
ADS126X::writeRegister(ADS126X_MODE0);
}
}

void ADS126X::calibrateGainADC1(uint8_t vcc_pin,uint8_t gnd_pin) {
Expand All @@ -204,13 +234,26 @@ void ADS126X::calibrateGainADC1(uint8_t vcc_pin,uint8_t gnd_pin) {
_ads126x_delay(50); // delay to allow time for reads
}

void ADS126X::calibrateSelfOffsetADC1() {
REGISTER.INPMUX.bit.MUXN = ADS126X_FLOAT;
REGISTER.INPMUX.bit.MUXP = ADS126X_FLOAT;
ADS126X::writeRegister(ADS126X_INPMUX);
_ads126x_delay(10);
// assumes that you want to calibrate with the same GAIN and VREF that you are using
// if not using DRDY pin, see table 9-28 on pg 79 to find appropraite wait time
void ADS126X::calibrateSelfOffsetADC1(uint16_t waitTime) {
const uint8_t previousRunMode = REGISTER.MODE0.bit.RUNMODE;
setContinuousMode();
startADC1(ADS126X_FLOAT, ADS126X_FLOAT);
_ads126x_delay(10); // let things settle?
ADS126X::sendCommand(ADS126X_SFOCAL1);
_ads126x_delay(50);
if (drdy_used) {
while (_ads126x_read_pin(drdy_pin)) {
// drdy_pin is pulled low when cal is complete
}
} else {
_ads126x_delay(waitTime);
}
// reset RUNMODE
if (previousRunMode != ADS126X_CONV_CONT) {
REGISTER.MODE0.bit.RUNMODE = previousRunMode;
ADS126X::writeRegister(ADS126X_MODE0);
}
}

void ADS126X::calibrateSysOffsetADC2(uint8_t shorted1,uint8_t shorted2) {
Expand Down Expand Up @@ -428,6 +471,10 @@ void ADS126X::setGain(uint8_t gain) {
ADS126X::writeRegister(ADS126X_MODE2);
}

uint8_t ADS126X::getGain() {
return REGISTER.MODE2.bit.GAIN;
}

void ADS126X::setRate(uint8_t rate) {
REGISTER.MODE2.bit.DR = rate;
ADS126X::writeRegister(ADS126X_MODE2);
Expand Down
17 changes: 11 additions & 6 deletions src/ADS126X.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,24 @@ class ADS126X {
void begin(uint8_t chip_select);
void begin(void);
void setStartPin(uint8_t pin); // designate a pin connected to START
void setDrdyPin(uint8_t pin); // designate a pin connected to DRDY (Data Ready)

// All ADC Commands. Page 85
//General Commands
void noOperation(void);
void reset(void);
void startADC1(void);
void startADC1(uint8_t pos_pin, uint8_t neg_pin);
void stopADC1(void);
void startADC2(void);
void startADC2(uint8_t pos_pin, uint8_t neg_pin);
void stopADC2(void);
// Analog Read Functions
int32_t readADC1(uint8_t pos_pin,uint8_t neg_pin);
int32_t readADC2(uint8_t pos_pin,uint8_t neg_pin);
bool dataReady(void);
int32_t readADC1(void);
int32_t readADC2(void);
// Calibration Functions
void calibrateSysOffsetADC1(uint8_t shorted1,uint8_t shorted2);
void calibrateSysOffsetADC1(uint8_t shorted1,uint8_t shorted2, uint16_t waitTime);
void calibrateGainADC1(uint8_t vcc_pin,uint8_t gnd_pin);
void calibrateSelfOffsetADC1(void);
void calibrateSelfOffsetADC1(uint16_t waitTime);
void calibrateSysOffsetADC2(uint8_t shorted1,uint8_t shorted2);
void calibrateGainADC2(uint8_t vcc_pin,uint8_t gnd_pin);
void calibrateSelfOffsetADC2(void);
Expand Down Expand Up @@ -87,6 +89,7 @@ class ADS126X {
void enablePGA(void);
void bypassPGA(void);
void setGain(uint8_t gain);
uint8_t getGain(void);
void setRate(uint8_t rate);

void setReference(uint8_t negativeReference, uint8_t positiveReference);
Expand All @@ -111,6 +114,8 @@ class ADS126X {
uint8_t cs_pin; // chip select pin
bool start_used = false;
uint8_t start_pin; // start pin
bool drdy_used = false;
uint8_t drdy_pin; // drdy pin (data ready)

ADS126X_STATUS_Type STATUS; // save last status and checksum values
uint8_t CHECKSUM;
Expand Down
5 changes: 5 additions & 0 deletions src/boards/arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ void _ads126x_delay(uint16_t ms) {
delay(ms);
}

// wait for the desired microseconds
void _ads126x_delaymicro(uint16_t us) {
delayMicroseconds(us);
}

#endif // ifdef ARDUINO
3 changes: 3 additions & 0 deletions src/definitions/ADS126X_hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ void _ads126x_spi_rw(uint8_t buff[],uint8_t len);
// wait for the desired milliseconds
void _ads126x_delay(uint16_t ms);

// wait for the desired microseconds
void _ads126x_delaymicro(uint16_t us);

#endif // define ADS126X_HARDWARE_H