user85620: I'm trying to make a mildly accurate oscilloscope using Arduino Uno R3 and I've done some research on the best method to do so. First of all I need to measure the voltage with a rather high sampling rate and then I'm going to transfer my data through the serial port and plot the data using Python or Matlab.
According to what I have read the analogread() function will cause some delay and therefore some inaccuracies and thus it is not suitable for my purpose.
I found on this website some good info about how I should write my code, but I have some questions:

I want my reference voltage to be 1.1 V so that by dividing it to 1023 parts I will have an accuracy of about 1 mV. How should I edit the mentioned code in order to do so?

The code in the void loop() setup is of no use to me (I prefer not to save the measured data on the Arduino and then send to my PC because of memory limitations). After deleting it will the data still be sent to the serial port?

Will sending the data through the serial port affect my sample rate/accuracy? I mean how does it effect my accuracy?


P.S: by mildly accurate this is what I mean: I want to measure voltage accurately with 1 mV precision for frequencies of max. 500 kHz (a bit less or more won't hurt).

user7508: 
I want my reference voltatge to be 1.1v so that by dividing it to
1023 parts I will have the accuracy of about 1mv.

You will have a resolution of about 1 mV. The accuracy will be
significantly worse than that due to the imperfections of the ADC
(offset error, gain error, non-linearity) and noise.

how should I edit the mentioned code in order to do so?

The reference is configured by the bits REFS0 and REFS1 of the
ADMUX register. The internal 1.1 V reference is selected by
setting both bits, as shown in table 24-3 of the
datasheet. You can then patch the original code like this:
@@ -8,7 +8,7 @@
   ADCSRA = 0;             // clear ADCSRA register
   ADCSRB = 0;             // clear ADCSRB register
   ADMUX |= (0 & 0x07);    // set A0 analog input pin
-  ADMUX |= (1 << REFS0);  // set reference voltage
+  ADMUX |= (1 << REFS0) | (1 << REFS1);  // set reference voltage
   ADMUX |= (1 << ADLAR);  // left align ADC value to 8 bits from ADCH register
 
   // sampling rate is [ADC clock] / [prescaler] / [conversion clock cycles]


the code in the void loop() setup is of no use for me (I prefer not
to save the measured data on the arduino and then send to my pc
because of memory limitations). after deleting it will the data still
be sent to the serial port?

In the linked code, loop() is the only function sending anything to
the serial port. If you remove it, nothing will be sent. You could
Serial.write() in the ISR though, in which case an empty loop()
would be fine.
Note that writing to Serial from within an ISR is generally
discouraged. Your situation though (an oscilloscope code) is one of the
very few cases where it does make sense to do so.

will sending the data through the serial port affect my sample
rate/accuracy?

It can certainly affect your sampling rate. Serial.write() is usually
non-blocking, as all it does is write the data to the RAM-based transmit
buffer. If the buffer fills up, however, Serial.write() will block
waiting for the serial port to actually send the data, and make enough
room in the buffer.
This means that, in order for the oscilloscope to not miss samples, you
have to make sure that the serial port can send the data at least as
fast as the ADC is acquiring it.
Example calculation: If you clock the ADC at 1 MHz, you get one
sample every 13 µs. You can follow the example given in the code
you linked to, and discard the last two bits in order to transmit only
8 bits of the sample. Transmitting those in plain binary will take
10 “bits” worth of the serial port bandwidth (one start bit,
8 data bits and one stop bit). Each bit should then take less than
1.3 µs, which translates to a baud rate of 769,231 bits per
second. You will probably have no other choice than configuring the
serial port for 1 Mb/s.
If you want to transmit the whole 10 bits of the ADC readings, you
will have to lower the sampling rate by a factor two.
At this point you may notice that the serial port, rather than the ADC,
is the bottleneck for the performance of your oscilloscope. If this is
too limiting, you may consider building a scope that works by bursts: it
stores a burst of samples in memory, then sends it at a leisurely rate
through the serial port.

85620: <p>I'm trying to make a mildly accurate oscilloscope using Arduino Uno R3 and I've done some research on the best method to do so. First of all I need to measure the voltage with a rather high sampling rate and then I'm going to transfer my data through the serial port and plot the data using Python or Matlab.</p>
<p>According to what I have read the <code>analogread()</code> function will cause some delay and therefore some inaccuracies and thus it is not suitable for my purpose.</p>
<p>I found on <a href="http://yaab-arduino.blogspot.com/2015/02/fast-sampling-from-analog-input.html" rel="nofollow noreferrer"><strong>this</strong></a> website some good info about how I should write my code, but I have some questions:</p>
<ol>
<li><p>I want my reference voltage to be 1.1 V so that by dividing it to 1023 parts I will have an accuracy of about 1 mV. How should I edit the mentioned code in order to do so?</p>
</li>
<li><p>The code in the <code>void loop()</code> setup is of no use to me (I prefer not to save the measured data on the Arduino and then send to my PC because of memory limitations). After deleting it will the data still be sent to the serial port?</p>
</li>
<li><p>Will sending the data through the serial port affect my sample rate/accuracy? I mean how does it effect my accuracy?</p>
</li>
</ol>
<p>P.S: by mildly accurate this is what I mean: I want to measure voltage accurately with 1 mV precision for frequencies of max. 500 kHz (a bit less or more won't hurt).</p>
 7508: <blockquote>
<p>I want my reference voltatge to be 1.1v so that by dividing it to
1023 parts I will have the accuracy of about 1mv.</p>
</blockquote>
<p>You will have a <em>resolution</em> of about 1 mV. The accuracy will be
significantly worse than that due to the imperfections of the ADC
(offset error, gain error, non-linearity) and noise.</p>
<blockquote>
<p>how should I edit the mentioned code in order to do so?</p>
</blockquote>
<p>The reference is configured by the bits <code>REFS0</code> and <code>REFS1</code> of the
<code>ADMUX</code> register. The internal 1.1 V reference is selected by
setting both bits, as shown in table 24-3 of <a href="https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf#G3.1738867" rel="nofollow noreferrer">the
datasheet</a>. You can then patch the original code like this:</p>
<pre><code>@@ -8,7 +8,7 @@
   ADCSRA = 0;             // clear ADCSRA register
   ADCSRB = 0;             // clear ADCSRB register
   ADMUX |= (0 &amp; 0x07);    // set A0 analog input pin
-  ADMUX |= (1 &lt;&lt; REFS0);  // set reference voltage
+  ADMUX |= (1 &lt;&lt; REFS0) | (1 &lt;&lt; REFS1);  // set reference voltage
   ADMUX |= (1 &lt;&lt; ADLAR);  // left align ADC value to 8 bits from ADCH register
 
   // sampling rate is [ADC clock] / [prescaler] / [conversion clock cycles]
</code></pre>
<blockquote>
<p>the code in the <code>void loop()</code> setup is of no use for me (I prefer not
to save the measured data on the arduino and then send to my pc
because of memory limitations). after deleting it will the data still
be sent to the serial port?</p>
</blockquote>
<p>In the linked code, <code>loop()</code> is the only function sending anything to
the serial port. If you remove it, nothing will be sent. You could
<code>Serial.write()</code> in the ISR though, in which case an empty <code>loop()</code>
would be fine.</p>
<p>Note that writing to <code>Serial</code> from within an ISR is generally
discouraged. Your situation though (an oscilloscope code) is one of the
very few cases where it does make sense to do so.</p>
<blockquote>
<p>will sending the data through the serial port affect my sample
rate/accuracy?</p>
</blockquote>
<p>It can certainly affect your sampling rate. <code>Serial.write()</code> is usually
non-blocking, as all it does is write the data to the RAM-based transmit
buffer. If the buffer fills up, however, <code>Serial.write()</code> will block
waiting for the serial port to actually send the data, and make enough
room in the buffer.</p>
<p>This means that, in order for the oscilloscope to not miss samples, you
have to make sure that the serial port can send the data at least as
fast as the ADC is acquiring it.</p>
<p><strong>Example calculation</strong>: If you clock the ADC at 1 MHz, you get one
sample every 13 µs. You can follow the example given in the code
you linked to, and discard the last two bits in order to transmit only
8 bits of the sample. Transmitting those in plain binary will take
10 “bits” worth of the serial port bandwidth (one start bit,
8 data bits and one stop bit). Each bit should then take less than
1.3 µs, which translates to a baud rate of 769,231 bits per
second. You will probably have no other choice than configuring the
serial port for 1 Mb/s.</p>
<p>If you want to transmit the whole 10 bits of the ADC readings, you
will have to lower the sampling rate by a factor two.</p>
<p>At this point you may notice that the serial port, rather than the ADC,
is the bottleneck for the performance of your oscilloscope. If this is
too limiting, you may consider building a scope that works by bursts: it
stores a burst of samples in memory, then sends it at a leisurely rate
through the serial port.</p>
