What`s the reason for it?I changed V(ref) to 5V,
Oh yes.Is there a mistake I made
Hi Klaus,Hi
What`s the reason for it?
In the very most cases this reduces system performance. Maybe down to less than 7 bits.
Mind: the performance of an ADC always worse than the performance of it´s REF.
5V supply isn´t a REF at all. It drifts with time, with temperature, with load current and is noisy.
There is a big difference between 5V supply and 5V REF.
One valid reason to use 5V supply as REF could be to have a ratiometric analog input to the ADC.
But still in this case I´d use VREF (or amplified VREF) to supply the ratiometric circuit.
Oh yes.
Indeed I wonder about this question, because the ADC datasheet provides good informations on how to choose a suitable input amplifier. It even tells some good choices.
Just to avoid that I have to repeat all the datasheet section here, please read it carefully and tell us what you understand and where you need help.
***
Reading datasheets in general:
.. may be annoying. I agree. But is Í see no way around. Every professional designer does it (has to do it).
I guess I step through more than 100 pages of dataseet in average per day. This does not mean I read every word on every page. I rather go through the headline of the chapters ... and focus on the informations I need.
So with increasing experience you need less time to get the expected informaton from the datasheet .. consuming less time.
Back to REF: Here also the datasheet gives good support.
Just to give you a number of what your REF and OPAMP choice will result in:
The datasheet says the ADC can have an ENOB (number of bits you can rely on) of up to 12 Bits up to nyquist.
Your choice may result in maybe 30% of amplitude error at 1MHz (OPAMP GBW) that just leaves you less than 2 reliable bits. This sounds awful .. but it´s worst case ... and it´s becoming better at lower frequencies.
Coosing supply voltage (ST L7805 datasheet) as VRef my result in +/-2% (4% in total) inital voltage error at constant 25°C. Since this can be cancelled out we don´t include it in the ENOB calculation.
So let´s focus on drift: (No worst case "Max" values, just the typical vlues used!)
* Line regulation: 2mV
* Load regulation 25mV
* 40° temperature drift: 44mV
* noise: 50uV RMS .. --> about 300uVpp (I wonder about this low noise)
* long term drift: not specified
* load transients and line transient regulation: realistically on properly bypassed 7805: 5mV (guessed)
added: 78mV
realistically (depends on circuit) you may expect 40mV.
40mV on 5V is a bit less than 1% or a ratio of 1:125.
125 is about 128 which is 2^7. This means there just are about 7bits you can rely on. It´s just a 7 bit ADC performance.
And sadly this does not improve with lower signal frequency.
Conclusion:
* Choosing 5V as VRef reduces ENOB to about 7 bits over the full bandwidth
* choosing your OPAMP reduces ENOB further down below 2 bits at high signal frequencies
Klaus
Sorry for missing infos.Hi,
there are a lot of informations missing and other issues:
* what is the input voltage range (min to max)
* where is the OPAMP bypass capacitor (like datasheet recommendation)?
* why do you connect a capacitor of 3.3nF at the output (datasheet says it drives 500pF max.)
* "doesn´t give any output" is impossible. What voltage do you measure?
* why does U2 have a (noise) gain of 2, while the datasheet says it needs a gain >5 to be stable?
* You try to add 2V, but the circuit just adds 1.54V (@ output)
* removing R7 will make the output to saturate at negative supply. No good idea.
* as already told it´s no good idea to use the supply voltage as a "Refernce" for the "+2V idea". It reduces performance drastically.
My recommendation: Amplification plus level shift with one OPAMP:
Klaus
added:
And thake the datsheet sentece serionously: " The traces connecting the pins and the bypass capacitors must be kept as short as possible "
This means: A breadboard is not suitable.
Ah, yes: Show a photo of your circuit (max 100kBytes)
So the gain of the first stage is +10:The input min -200mV/max +200mV
Datasheet page 9 tells to use bypass capacitors at the power supply.There was a bypass cap at Vss, but to try something different I removed it in this design according to the diagram on the datasheet.
This won´t work reliably. Especially at the ADC. It drops stability and conversion performance.since I don't have 2.2uF, I used 0.1uF for every cap
and what about the 10k series resistor? You think you just can omit it? No.I put 3.3nF.
This really confuses my now. It is DC? Why then a 50 MHz OPAMP, and a 4.5 MSampl/s ADC?technically it's a dc signal
Me neither ... before I read the datasheet ;-)*I didn't know that I should keep gain at min 5
Again: this makes the whole circuit inoperable. Not useful at all.With removed R7,
Without a schematic it´s a useless information.I tried to do that with only one opamp with a non-inverting differential opamp, but it didn't work
it works when you use a true 2V source. But you used a 1k/1.5K voltage divider from 5V. It gives 2V unloaded, but as soon as you load it, it will show it´s source impedance of 0.6k (0.6K = 1.5k || 1k) and drop the voltage.It was around 1.54V as you said. What is wrong there?
My -not meant offinding- opinion: You tried a different solution, but you did nothing to find/solve the true problem.but since it didn't work I'm trying different things to find the problem.
Ah, yes it's correct. I forgot that.So the gain of the first stage is +10:
Then the output shoud be expected as -2V to +2V.
But you should be aware that the output can only be within the supply rails. 0V, +5V.
So output of negative voltage clearly is impossible.
Actually, I use a bypass cap for Vdd that is in common use with ADC's Vdd.Datasheet page 9 tells to use bypass capacitors at the power supply.
If VSS is GND, then you don´t use a capacitor here, but still you need it at VDD.
My bad, it's a sampled signal. It's like in the picture.This really confuses my now. It is DC? Why then a 50 MHz OPAMP, and a 4.5 MSampl/s ADC?
There must be something wrong!
I just wanted to test the first opamp.Again: this makes the whole circuit inoperable. Not useful at all.
I gave the schematic. Again:Without a schematic it´s a useless information.
I'll do it.(I don´t recommend to use 5V at all: Thus the not recommended solution was: omit R6. And build a voltage divider 2k / 2k from ADC_VRef. )
I'm soldering gnds to unused copper to get a fully gnd plane.PCB: You need a rock solid GND plane and decoupling capacitors! Otherwise the resulting poor performance is just a waste of money.
You are free to do it your own way ... but usually the datasheet says "as close as possible". A "common" capacitor can not satisfy this., I use a bypass cap for Vdd that is in common use with ADC's Vdd.
This sounds like "copper pour" where the GND is divided into many pieces.I'm soldering gnds to unused copper to get a fully gnd plane.
Hi Klaus,Hi
You are free to do it your own way ... but usually the datasheet says "as close as possible". A "common" capacitor can not satisfy this.
This sounds like "copper pour" where the GND is divided into many pieces.
This is about the opposite as my "rock solid" recommendation.
I already used this example:
Imagine a styrofoam "in one piece" in the size of 5m x 5m on water. Now let's say 5 people have to work together on this platform. Precise, fast, heavy work. But not a big problem, because all of them rely on the same "ground".
Now cut the styrofoam into let's say 10 unequal pieces .. and let the people do the same job.
It's way more difficult. Different people rely on different "ground". Each ground is much smaller and its more difficult to balance while working.
The same happens when you cut the GND plane into pieces.
Copper pour - in my eyes - simply is no GND plane at all.
The total performance mainly depends on the "weakest" part.
You use a 14 Bit 4.5MSmpl/s ADC. It is a 1:16,000 resolution. It's 250uV... it needs to be stable within a fraction of 250 ns.
... and no common GND to rely on. It's simply impossible.
Klaus
#include <SPI.h>
const int csPin = 10; // Chip select pin
const int sdoPin = 12; // SDO pin
const int sckPin = 13; // SCK pin
void setup() {
// Initialize the SPI communication
SPI.begin();
// Set the chip select pin as an output
pinMode(csPin, OUTPUT);
// Set the chip select pin high to deselect the ADC
digitalWrite(csPin, HIGH);
// Set the serial port baud rate
Serial.begin(115200);
}
void loop() {
// Select the ADC by setting the chip select pin low
digitalWrite(csPin, LOW);
// Wait for one conversion latency cycle
// delayMicroseconds(0.25);
// Read the data from the ADC
unsigned int data = SPI.transfer16(0x0000);
// Deselect the ADC by setting the chip select pin high
digitalWrite(csPin, HIGH);
// Shift the data to the right by one bit to remove the leading zeros
data >>= 1;
// Convert the data to a voltage using the reference voltage
float voltage = (data / 16383.0) * 4.096;
// Print the voltage to the serial port
Serial.println(voltage);
// Delay for a short period before reading the next value
delay(0.001);
}
I also tested with deleted that delay, the results were almost the same. Sorry, Arduino plotter doesn't provide a timescale or I couldn't find it.Whaaaaat?
Why on earth are you adding a 1us delay to every sample??? Thats just limiting your input frequency to 500 KHz. And, i don’t know arduino, but i dont even know if you can use a fractional number for delay().
And a timescale on your plots would be helpful. We don’t even know what your sample clock is.
I tested the 1MHz input signal on the integral ADC with the same float convertor. The result was much better.Nice experiment about real time data processing. At first sight, the effective sampling rate is < 1 kHz, you should probably start with e.g. 10 Hz generator frequency to reproduce a sine with the present code.
Next steps might be:
1. Make a test setup to determine the actual sampling rate. Hint, it's most likely limited by Arduino float arithmetic.
2. Consider which sampling rate can be achieved if ADC samples are stored in a RAM buffer and dumped later.
int analogValue = analogRead(ADC_pin);
// convert the analog value to a voltage
float voltage = analogValue * (5.0 / 1023.0);
"For this particular case, the acquisition time period and conversion clock period are designed as 4 data clock periods (TACQ = 45.7ns) and 16data clock periods (TCONV = 182.9ns) respectively, yielding a throughput time of 228.6ns."HI,
It simply is a timing problem.
What you see are undersampling effects (alias frequencies) combined with distortion/noise caused by clock jitter.
Let's say you have a 14 bit ADC, and the input is a full scale sine with 10kHz.
Then the sine has an amplitude of 13 bits or 8192 LSB.
The max rise rate of the sine = 2 x Pi x f x A = 2 x 3.14 x 10,000 x 8192 = about 500 million LSB/s
Or 2ns/LSB.
So to get a 14 bit performance your sampling period needs to be precise down to 2ns. Yes, nanoseconds!
(Welcome in the area of serious measurement electronics)
Now with your code you try to determine the sampling period by runtime.
This is the worst ideas of all, because runtime in a (main) loop like yours is far from being known nor is it constant.
Your loop timing is:
.. timing for digitalWrite
+ timing for SPI transfer
+ timing for digitalWrite
+ timing for shift
+ timing for math operation of a float
+ timing for converting float to ASCII and UART transfer
+ timing for delay
+ timing for loop control
+ timing for OS overhead
=======
Most of them are variable in time. Forming a float into ASCII may take from a couple of us to some hundreds of us.
Transferring "1.234\n" via UART takes at least 6 bytes = 60 bits = 520us (@115200 baud)
This all makes a sampling rate above 1ks/s impossible.
If you want to be faster, then you need to avoid all your real time operations.
Means: you need to divide your code into a "fast sampling part" and a "slow transferring part"
Fast sampling means for example: just doing 256 conversions and store the results into an array.
But indeed, if you want some quality, you need an interrupt for timing, or even better a hardware timing.
(Not sure if hardware timing is possible with your microcontroller/schematic)
Even with interrupts you may expect jitter in the region of low microseconds.
Klaus
Is it because the internal ADC also gives better results because the internal is 10-bit? When I saw this result, I thought there was no problem with the float.You are not sampling at a fixed rate, due to execution of float math and serial printing
in your acquisition loop.
You might set a pin just before the math and clear it after the serial print and look at
that interval with a scope. If you scope has color graduated persistence on triggers look
at the variation caused to sampling by those operations. Even simple infinite persistence
in the scope will show you how much jitter you have in sampling.
Processing 1 Mhz 16 bit data results in an Arduino with serial and float in a loop not doable......?
Create a simple test of this w/o using A/D to see if processor capable. Convert your float calculations
to integer math.....get rid of serial print operation using DAC.......for troubleshooting.
Speed of floating point operations -- test results
Was curious as to the speed of floating point operations on the 16MHz Arduino Diecimila. Could only find a few threads about that (e.g., http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1206534749), with no answer, so I ran some tests. Here's a graph of results comparing the speed of a multiply...forum.arduino.cc
Regards, Dana.
Yes, it's an Arduino Uno. I totally forgot to set the SCK clock. How can I set it as you stated?Hi,
you are using a 14 Bit SAR ADC in combination with an Arduino (Uno?). So the maximum SPI clock frequency is half of the MCU clock. For an Arduino Uno, this leads to a maximum SPI clock of 8 MHz. You need at least 20 clock cycles to get a valid sample, which means an update rate of 400 kS/s. In case of using the Arduino SPI library, where a read instruction reads 8 bits, you need 24 clock cycles, leading to an update rate of 333 kS/s.
This is theoretically possible if you are not introducing artificial delays, and if you are not performing the conversion immediately.
BR
Yes, it's an Arduino Uno. I totally forgot to set the SCK clock. How can I set it as you stated?
It´s not the SPI timing that is the problem, it rather is the /CS timing."For this particular case, the acquisition time period and conversion clock period are designed as 4 data clock periods (TACQ = 45.7ns) and 16data clock periods (TCONV = 182.9ns) respectively, yielding a throughput time of 228.6ns."
According to this statement in the datasheet, I added a 250ns(also tried 1000ns) conversion delay, but it didn't have much effect. Doesn't the internal ADC work properly indicating that it has something to do with SPI?
Thanks! I tried I think I'm still doing some mistakes. I played with delays, But no change on plots.(Also deleted them to test)
const int csPin = 10; // Chip select pin
const int sdoPin = 12; // SDO pin
const int sckPin = 13; // SCK pin
void setup() {
// Initialize the SPI communication
SPI.begin();
// Set the chip select pin as an output
pinMode(csPin, OUTPUT);
// Set the chip select pin high to deselect the ADC
digitalWrite(csPin, HIGH);
// Set the serial port baud rate
Serial.begin(9600);
// Set the SPI clock frequency to 4 MHz
SPI.setClockDivider(SPI_CLOCK_DIV2);
// Set the data order to MSB first
SPI.setDataMode(SPI_MODE0);
// Set the clock polarity to idle low
SPI.setBitOrder(MSBFIRST);
}
void loop() {
// Select the ADC by setting the chip select pin low
digitalWrite(csPin, LOW);
// Wait for one conversion latency cycle
delayMicroseconds(0.1);
// Read the data from the ADC
unsigned int data = SPI.transfer16(0x0000);
// Deselect the ADC by setting the chip select pin high
digitalWrite(csPin, HIGH);
// Shift the data to the right by two bits to remove the leading zeros(shifting by one is giving the correct voltage)
data >>= 1;
// Convert the data to a voltage using the reference voltage
float voltage = (data / 16383.0) * 4.096;
// Print the voltage to the serial port
Serial.println(voltage);
// Delay for a short period before reading the next value
delayMicroseconds(0.1);
}
Thank you very much Klaus! My analog signal is 1MHz, so I think I should use at least a 2MHz sampling frequency. Also, I need live results, so storing the data wouldn't it be unnecessary? Even at frequencies like 10kHz and 100Hz, I can't get sine waves exactly. (with reduced delays).Hi,
It´s not the SPI timing that is the problem, it rather is the /CS timing.
--> The falling edge of /CS starts a conversion process. Thus the timing from /CS falling to /CS falling needs to be known (=sampling period, sampling frequency) and it needs to be very very constant.
In your case I guess its:
734,032ns, 701,543ns, 684,634ns, 759,677ns, ... (randomly jumping around. Just to give you values)
Let´s say you want a sampling frequency of 10kHz = sampling period of 100us.
Then the time from /CS falling to /CS falling needs to be 100us. Exactly 100us!
In best case 100,000 ns +/- a couple of ns. For sure a hard job for an arduino nano.
this is what you want: 100,000ns, 100,000ns, 100,000ns, 100,000ns, 100,000ns, 100,000ns...
A software delay() function including all the unknown processing times of the other functions is no good way.
I guess the variation from one conversion to the other conversion will vary in the range of 50us at least.
This is a factor of 5000 (at least) away from what one wants.
Running a timer and starting within an ISR will be much better, but still suffers from maybe 250ns caused by delayed ISR. (still a factor of 50 from what one wants)
One idea comes into my mind: (for best performance)
* Using a hardware PWM to control the /CS line should be the most precise with an Arduino nano.
With this you get most precise data acquisition timing. This is what counts for the conversion results.
* Then the falling edge of /CS (PWM) should raise an interrupt.
* Within this ISR: do the 16 bit SPI transfer with highest speed possible.... and store the result in an array or FIFO.
still within the ISR use a counter to run a dedicated number of samples (maybe 250). If done stop the PWM and set a flag (global, volatile bool variable) to inform the main loop that the 250 samples are finished.
Depending on what exactly you want to do (how you want to process, transmit, store the data) you will make some adjustments on the software. (like two buffers for storing in the one buffer while at the same time processing the data of the other buffer. Or using extra interrupts for SPI transfer..)
*****
I have a lot of experience doing most precise measurements with so small microcontrollers. Like 7 channels quasi simultaneous, continous, real time (no gap), true RMS measurements and UART communication (every 100ms) on 50Hz mains signals with an ATMEGA328.
So the better you explain (with expected timing, frequencies, resolution, precision...) what you want to do the more detailed our replies.
Klaus
My analog signal is 1MHz, so I think I should use at least a 2MHz sampling frequency. Also, I need live results, so storing the data wouldn't it be unnecessary? Even at frequencies like 10kHz and 100Hz, I can't get sine waves exactly. (with reduced delays).
The plot for 10kHz with 100us(with the code above(conversion delay is 1us))
My analog signal is 1MHz
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?