Hi,
for my hobby project I need a voltage measurement from a 14Bit ADC with around 500kSamples/s. I also want to understand what is going on.
I am using a TI ADS 7279 (Datasheet). The data is sent via SPI from the ADC to the Teensy 4.1.
I use the Arduino IDE with the normal included SPI library.
With my code I see the correct analog voltage in the Serial Monitor of my Teensy. So the basic stuff works and the wiring on the breadboard should be fine.
For the Teensy EOC Pin input (pin 14) I am using a 10k pull up resistor.
The ADC is configured for an external clock (SCK from Teensy) and a manual trigger (Convst Pin falling edge).
The EOC (End of Conversion) Pin is always low during a conversion and high when the conversion is finished.
The SPI interface, CONVST and EOC signal can be seen in the attached screenshot of my scope.
You can also see my issue in the screenshot. Every 2nd data transfer the Teensy is not waiting for the rising edge of the EOC input.
So the same two readings are taken for each conversion because the Teensy does not wait for the finished conversion of the ADC.
I guess it is a timing/logic issue in my code.
I would be grateful if someone with more knowledge could help me with that. Thank you very much
My Code:
for my hobby project I need a voltage measurement from a 14Bit ADC with around 500kSamples/s. I also want to understand what is going on.
I am using a TI ADS 7279 (Datasheet). The data is sent via SPI from the ADC to the Teensy 4.1.
I use the Arduino IDE with the normal included SPI library.
With my code I see the correct analog voltage in the Serial Monitor of my Teensy. So the basic stuff works and the wiring on the breadboard should be fine.
For the Teensy EOC Pin input (pin 14) I am using a 10k pull up resistor.
The ADC is configured for an external clock (SCK from Teensy) and a manual trigger (Convst Pin falling edge).
The EOC (End of Conversion) Pin is always low during a conversion and high when the conversion is finished.
The SPI interface, CONVST and EOC signal can be seen in the attached screenshot of my scope.
You can also see my issue in the screenshot. Every 2nd data transfer the Teensy is not waiting for the rising edge of the EOC input.
So the same two readings are taken for each conversion because the Teensy does not wait for the finished conversion of the ADC.
I guess it is a timing/logic issue in my code.
I would be grateful if someone with more knowledge could help me with that. Thank you very much
My Code:
C:
#include <SPI.h>
const int ADC_convstPin = 9; // CONVST Pin to trigger Conversion for ADS7279 ADC -- GPIO7 Bit 11
const int ADC_csPin = 10; // Chip Select Pin for ADS7279 ADC -- GPIO7 Bit0
const int ADC_eocPin = 14; // EOC/INT Pin for finished conversion of ADS7279 ADC -- GPIO6 Bit 18
const int numSamples = 32000; // Number of Samples to calculate Current ADC Average Measurement
const float VREF = 4.9997; //Reference Voltage for ADC
const uint32_t SPI_CLK_FREQ = 20000000; // SPI-CLK = 20MHz, max 50MHz
void setup() {
pinMode(ADC_csPin, OUTPUT);
digitalWriteFast(ADC_csPin, HIGH);
pinMode(ADC_convstPin, OUTPUT);
digitalWriteFast(ADC_convstPin, HIGH);
pinMode(ADC_eocPin, INPUT);
SPI.begin();
// Configuration:
// Opcode (D15-D12): 1110 (Write CFR Register)
// Mode (D11): 1 (Auto Channel Select)
// Channel (D10): 0 (ADC CLK from SCK/Teensy CLK=SCK/2)
// Trigger (D9): 1 (Manual Trigger start with falling edge of CONVST pin)
// EOC (D6): 1 (Configure Pin as EOC Pin)
// --> 1110 1011 1111 1101 = EBFD
delay(1);
writeADS7279Register(0xEBFD);
}
void writeADS7279Register(uint16_t ADC_config) {
// ADS7279 uses SPI Mode 0, MSB first, up to 50 MHz
SPI.beginTransaction(SPISettings(SPI_CLK_FREQ, MSBFIRST, SPI_MODE0));
digitalWriteFast(ADC_csPin, LOW);
// Transfer configuration 0xEBFD
SPI.transfer16(ADC_config);
// Transfer end
digitalWriteFast(ADC_csPin, HIGH);
SPI.endTransaction();
}
int16_t readADS7279Register() {
uint8_t b1, b2, b3;
// Trigger for conversion start
digitalWriteFast(ADC_convstPin, LOW);
delayNanoseconds(100); // at least 40ns Delay regarding ADC datasheet
digitalWriteFast(ADC_convstPin, HIGH);
delayNanoseconds(100);
//Wait until EOC Pin is low from Conversion Start Trigger CONVST
while (digitalReadFast(ADC_eocPin) == HIGH) {
}
// Start ADC SPI Data Transfer
SPI.beginTransaction(SPISettings(SPI_CLK_FREQ, MSBFIRST, SPI_MODE0));
digitalWriteFast(ADC_csPin, LOW);
// Reading 24Bit, one Sample (3CCLKs) and one Conversion (18 CCLKs) takes all in all 21 CCLKs
b1 = SPI.transfer(0x00);
b2 = SPI.transfer(0x00);
b3 = SPI.transfer(0x00);
// Finish ADC Reading
digitalWriteFast(ADC_csPin, HIGH);
SPI.endTransaction();
// Combine 1. and 2. Byte
uint16_t raw16 = (b1 << 8) | b2;
// 14 Bit ADC but 16 Bit read, so 2 Bits must be shifted
return (raw16 >> 2) & 0x3FFF;
}
void loop() {
uint32_t SumOfMeas = 0; // Sum of all measurements
uint16_t bitValue = 0; // Shifted 14Bit Measurement from 14Bit ADC ADS7279
float bitValueAverage = 0; // Average of several Measurements in Bits
float voltageMeas = 0; // Average Voltage Measurement - used for Control
// Calculate Average of Measurement over numSamples
for (int i = 0; i < numSamples; i++) {
bitValue = readADS7279Register();
SumOfMeas += bitValue;
}
bitValueAverage = float(SumOfMeas)/(float)numSamples;
// 14-Bit value to Voltage conversion
voltageMeas = (float)bitValueAverage * VREF / 16384.0;
Serial.print("Voltage: ");
Serial.println(voltageMeas, 5);
}