<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>LeafLabs Garden &#187; Topic: Tuning ADC to a specific sample rate (i.e. 8000Hz)</title>
		<link>http://forums.leaflabs.com/topic.php?id=849</link>
		<description>A place to share, learn, and grow...</description>
		<language>en-US</language>
		<pubDate>Fri, 22 Jan 2016 00:08:17 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://forums.leaflabs.com/search.php</link>
		</textInput>
		<atom:link href="http://forums.leaflabs.com/rss.php?topic=849" rel="self" type="application/rss+xml" />

		<item>
			<title>gbulmer on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-7162</link>
			<pubDate>Sat, 12 Nov 2011 20:53:26 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">7162@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;hbdgas - there is an ongoing development of SD access using DMA by polpla, see:&#60;br /&#62;
&#60;a href=&#34;http://forums.leaflabs.com/topic.php?id=112&#38;amp;page=5#post-6711&#34; rel=&#34;nofollow&#34;&#62;http://forums.leaflabs.com/topic.php?id=112&#38;amp;page=5#post-6711&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;Edit: oops you already have :-)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>hbdgas on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-7160</link>
			<pubDate>Sat, 12 Nov 2011 19:34:33 +0000</pubDate>
			<dc:creator>hbdgas</dc:creator>
			<guid isPermaLink="false">7160@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;gbulmer,&#60;/p&#62;
&#60;p&#62;Thank you for the quick response. I think I will try the external trigger. One more question, admittedly I am not a great programmer, and I was planning on using the SDFat library to do the SD writes. I do not think the library supports DMA at this time(I could be wrong). How hard is it to write to SD using DMA?
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-7156</link>
			<pubDate>Sat, 12 Nov 2011 16:22:35 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">7156@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;hbdgas - it is relatively straightforward to slow anything down by using a busy loop.&#60;/p&#62;
&#60;p&#62;If you want roughly a 16KHz sample rate, you could do something like:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;const unsigned usecs_duration = 1000000/16000;   // actually 62.5 usec, but this is integer division
//...

loop() {
    // ...
    unsigned now = micros();
    int val = analogueRead(pin);
    while ((micros()-usecs_duration) &#38;lt; now) ; /* do nothing */
    //...
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This won't be very accurate though, because the amount of time is actually 62.5 usec (so almost 1% error), the micros() function doesn't take the same amount of time every time it is called, and there are concurrent interrupts stealing time. &#60;/p&#62;
&#60;p&#62;So a better approach would be to trigger the ADC conversion with a timer.&#60;br /&#62;
This is described in the manual RM0008 (from ST Micro) in section 11.7 &#34;Conversion on external trigger&#34;.&#60;br /&#62;
You could save the converted values to RAM with DMA, and move it to SD using DMA.&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62; The desired sampling rate is 16kHz, but I read earlier in this topic that the slowest sample time for the adc is equivalent to 50kHz.
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;As you will have read in post &#60;a href=&#34;http://forums.leaflabs.com/topic.php?id=849#post-5140&#34; rel=&#34;nofollow&#34;&#62;http://forums.leaflabs.com/topic.php?id=849#post-5140&#60;/a&#62;&#60;br /&#62;
this adjustable sample time is primarily intended to ensure the electronics of the ADC gets an accurate sample of the input voltage. It is not really intended to be used to adjust the ADC to a specific sample rate, it is a bit too crude for that. Using this mechanism in this case would have the effect of blocking a program inside the &#60;code&#62;analogRead()&#60;/code&#62; function, unless you implemented that yourself. Blocking inside &#60;code&#62;analogRead()&#60;/code&#62; would just waste time that you might need to do some processing (though it is no more wasteful that the busy loop I wrote here).&#60;/p&#62;
&#60;p&#62;(full disclosure: I am not a member of LeafLabs staff.)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>hbdgas on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-7154</link>
			<pubDate>Sat, 12 Nov 2011 15:10:45 +0000</pubDate>
			<dc:creator>hbdgas</dc:creator>
			<guid isPermaLink="false">7154@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Hi,&#60;/p&#62;
&#60;p&#62;I'm currently working on a school project that involves sampling audio data from a microphone and saving the data to a SD card. In order to give the CPU as much time as possible to write to the SD card, I'm considering using DMA. The desired sampling rate is 16kHz, but I read earlier in this topic that the slowest sample time for the adc is equivalent to 50kHz. Does anyone have any suggestions on how to slow the sampling rate further?
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-6232</link>
			<pubDate>Thu, 08 Sep 2011 20:36:30 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">6232@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;robodude666 - dump all the TIMER3 registers. There must be something different.&#60;/p&#62;
&#60;p&#62;I calculate as follows:&#60;br /&#62;
&#60;code&#62;uint32_t cycles = (uint32_t)(22.671f * (float)CYCLES_PER_MICROSECOND);&#60;/code&#62;&#60;br /&#62;
is 22.671 * 72 -&#38;gt; cycles is 1632&#60;br /&#62;
&#60;code&#62;uint16_t pre = (uint16_t)((cycles &#38;gt;&#38;gt; 16) + 1);&#60;/code&#62;&#60;br /&#62;
1632 &#38;gt;&#38;gt; 16 = 0, so pre is 1&#60;/p&#62;
&#60;p&#62;so&#60;br /&#62;
&#60;code&#62;timer_set_prescaler(TIMER3, pre);&#60;/code&#62; is &#60;code&#62;timer_set_prescaler(TIMER3, 1);&#60;/code&#62;&#60;br /&#62;
and&#60;br /&#62;
&#60;code&#62;Timer3.setPrescaleFactor(pre);&#60;/code&#62; is &#60;code&#62;Timer3.setPrescaleFactor(1);&#60;/code&#62;&#60;br /&#62;
In which case mbolivar's point would explain it. In one case the precscaler divides the clock by 1, and in the other, by 2.&#60;/p&#62;
&#60;p&#62;If you dump TIM3_PSC in both cases, it should be clear. (if that isn't the explanation, dump all the registers :-)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>mbolivar on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-6219</link>
			<pubDate>Thu, 08 Sep 2011 02:57:10 +0000</pubDate>
			<dc:creator>mbolivar</dc:creator>
			<guid isPermaLink="false">6219@http://forums.leaflabs.com/</guid>
			<description>&#60;blockquote&#62;&#60;p&#62;
With the same pre and cycles values as calculated above&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;Careful!  timer.h uses prescaler values appropriate for writing to the PSC registers (i.e., 0-based).  HardwareTimer uses 1-based prescalers.&#60;/p&#62;
&#60;p&#62;Are you sure you're not off by one?
&#60;/p&#62;</description>
		</item>
		<item>
			<title>robodude666 on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-6199</link>
			<pubDate>Tue, 06 Sep 2011 11:59:50 +0000</pubDate>
			<dc:creator>robodude666</dc:creator>
			<guid isPermaLink="false">6199@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Sorry for the late response.&#60;/p&#62;
&#60;p&#62;I printed out the CR1 register using:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;Serial2.print(&#38;quot;CR1: &#38;quot;);
Serial2.println((TIMER3-&#38;gt;regs).bas-&#38;gt;CR1, HEX);&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;and in both cases the CR1 register is set to 0x81. This configures the timer to be in up-count mode using edge-alignment.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-6193</link>
			<pubDate>Sun, 04 Sep 2011 19:15:52 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">6193@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;robodude666 - have you printed the value of &#60;code&#62;pre&#60;/code&#62; and &#60;code&#62;cycles&#60;/code&#62; in both example programs?&#60;/p&#62;
&#60;p&#62;As 43,520 is exactly twice 21,760, I guess the interrupt is firing only half as often. My suspicion is, in the higher frequency the counter is in 'upcounting' mode, and in the lower frequency case, it is in 'center-aligned' or 'up/down counting' mode (section 15.3.2 of RM0008). In center-aligned, it might generate only one interrupt/up+down cycle.&#60;/p&#62;
&#60;p&#62;Maybe print out TIM3_CR1 register (in hex) to see if the bits are set in the same way for both cases.&#60;br /&#62;
If they aren't, try assigning to the register.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>robodude666 on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-6187</link>
			<pubDate>Sat, 03 Sep 2011 12:36:30 +0000</pubDate>
			<dc:creator>robodude666</dc:creator>
			<guid isPermaLink="false">6187@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Okay, so I'm finally getting around to driving my ADC sampling via a timer interrupt. I've so far been using &#60;code&#62;delayMicroseconds()&#60;/code&#62;, and while it's working, I need to clean up my main() function to be less blocking.&#60;/p&#62;
&#60;p&#62;I'm trying to sample two ADC inputs (D2 and D3) at a rate of 44.1kHz (audio sample rate) and store the value into a circular buffer. I've come to the following timer configuration:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;uint32_t cycles = (uint32_t)(22.671f * (float)CYCLES_PER_MICROSECOND);
uint16_t pre = (uint16_t)((cycles &#38;gt;&#38;gt; 16) + 1);

timer_pause(TIMER3);

timer_set_mode(TIMER3, TIMER_CH1, TIMER_OUTPUT_COMPARE);
timer_attach_interrupt(TIMER3, TIMER_CC1_INTERRUPT, handler3b);

timer_set_prescaler(TIMER3, pre);
timer_set_reload(TIMER3, cycles / pre - 1);
timer_set_compare(TIMER3, TIMER_CH1, 1);

timer_resume(TIMER3);&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This configures cycles to 1632, prescaler to 1, and a reload value of 1631. I've found that handler3b gets called 21,760 within 1 second (by monitoring handler3b's &#60;code&#62;counts++&#60;/code&#62; value using a millis() loop in main). Is this value right? Shouldn't it be called ~44,100 times in a single second?&#60;/p&#62;
&#60;p&#62;Thinking it may be an issue with my configuration, I looked at the deep note Maple Mini example and tried this:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;Timer3.pause();
Timer3.setChannel1Mode(TIMER_OUTPUTCOMPARE);
Timer3.setPrescaleFactor(pre);
Timer3.setOverflow((cycles / pre) - 1);
Timer3.setCompare1(1);
Timer3.attachCompare1Interrupt(handler3b);
Timer3.resume();&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;With the same pre and cycles values as calculated above. The overflow &#34;reload&#34; value still comes out to 1631. This time the interrupt is called 43,520 times per second -- twice that of the previous configuration getting closer to the desired 44.1kHz. Is this a designed feature of &#60;code&#62;HardwareTimer&#60;/code&#62; ? I don't see &#60;code&#62;HardwareTimer&#60;/code&#62; doing anything outside of calling the low-level C libmaple functions I previously configured.&#60;/p&#62;
&#60;p&#62;-robodude666
&#60;/p&#62;</description>
		</item>
		<item>
			<title>mbolivar on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-5144</link>
			<pubDate>Sat, 11 Jun 2011 22:51:21 +0000</pubDate>
			<dc:creator>mbolivar</dc:creator>
			<guid isPermaLink="false">5144@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;gbulmer,&#60;/p&#62;
&#60;p&#62;Thanks for the clarifying remarks.  I now see that the comment describing adc_smp_rate was misleading, and have replaced it with one that should be more accurate:&#60;/p&#62;
&#60;p&#62;&#60;a href=&#34;https://github.com/leaflabs/libmaple/commit/76b9fd0a7b9dd3b09f16aeb5ff98d57df2a86386&#34; rel=&#34;nofollow&#34;&#62;https://github.com/leaflabs/libmaple/commit/76b9fd0a7b9dd3b09f16aeb5ff98d57df2a86386&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;In particular, the comment no longer specifies that an adc_smp_rate determines &#34;conversion&#34; time.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-5140</link>
			<pubDate>Sat, 11 Jun 2011 13:59:54 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">5140@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;robodude666&#60;br /&#62;
&#60;blockquote&#62;I noticed that the adc.h header file defines an adc_smp_rate enum which features sample rates in a # of ADC cycles per sample, but that seems rather fast. I also understand (I hope) the ADC clock is running at 12MHz (72MHz / 6 divider). At the very slowest sample rate of 239.5 ADC clocks per sample that's 20uS per sample, or 50kHz.&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;The ADC sample rate is actually made up of two parts.&#60;br /&#62;
1. Sample the input signal by charging a 'sample and hold circuit' (a capacitor). This is the part affected by adc_smp_rate&#60;br /&#62;
2. Convert the voltage on the sample and hold circuit (capacitor) to a binary number. The conversion takes a fixed number of ADC cycles (12.5 cycles). The ADC electronics disconnects the sample and hold circuit from the outside world (so it won't change while it is converting it) and uses the voltage value on the sample and hold circuit for the conversion.&#60;/p&#62;
&#60;p&#62;For 1 to work properly, the capacitor needs to be charged up to match the input voltage.&#60;br /&#62;
If the input signal has a very high output impedance (it can't supply much current), the sample capacitor charges slowly.&#60;br /&#62;
If the input signal is a low impedance (it can supply lots of current), the sample capacitor charges quickly.&#60;/p&#62;
&#60;p&#62;The sample part of the ADC can be programmed to allow for a sample time as short as 1.5 clocks (of that 12MHz ADC clock) upto 239.5 clocks (Section 11.12.4 &#34;ADC sample time register 1 (ADC_SMPR1)&#34; of RM0008).&#60;/p&#62;
&#60;p&#62;So this isn't quite setting the conversion rate. It is allowing the ADC to adjust the time to charge the sample and hold circuit (capacitor) to account for the output impedance (ability to supply current) of each source signal connected to each ADC channel.&#60;br /&#62;
The ADC can be used as slow as you like, but it can't be faster than this time. &#60;/p&#62;
&#60;p&#62;The library sets the sample time to a conservative value (55.5 cycles?) to allow for quite high output impedance signals. This allows Maple users to get reasonable results without dipping into the underlying details.&#60;/p&#62;
&#60;p&#62;I'm with poslathian; use a timer to set the sample rate.&#60;br /&#62;
It is possible to trigger an ADC conversion from a timer, and a DMA, but it will be much easier to code and debug if you keep things simple and do the work 'by hand' in your own code. People have written straightforward code which runs at well over 100,000 samples/second.&#60;/p&#62;
&#60;p&#62;(full disclosure: I am not a member of LeafLabs staff)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>poslathian on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-5125</link>
			<pubDate>Fri, 10 Jun 2011 15:10:59 +0000</pubDate>
			<dc:creator>poslathian</dc:creator>
			<guid isPermaLink="false">5125@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;robodude,&#60;br /&#62;
  For 44KHz, I would probably just use (have used in the past) a timer interrupt. BUT, even if you dont need a crazy sample rate, if you are doing some serious crunching on those samples, the DMA might give you the extra performance you need elsewhere. The is a fairly high cost incurred for going the interrupt route. &#60;/p&#62;
&#60;p&#62;My advice would be go with interrupts until you run out of performance, then upgrade to DMA style.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>robodude666 on "Tuning ADC to a specific sample rate (i.e. 8000Hz)"</title>
			<link>http://forums.leaflabs.com/topic.php?id=849#post-5124</link>
			<pubDate>Fri, 10 Jun 2011 15:00:48 +0000</pubDate>
			<dc:creator>robodude666</dc:creator>
			<guid isPermaLink="false">5124@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Hey guys,&#60;/p&#62;
&#60;p&#62;I'm starting to play around with the ADC functionality and was wondering: How would one configure the ADC for a specific sample rate (i.e. xxx samples per second)?&#60;/p&#62;
&#60;p&#62;I noticed that the &#60;a href=&#34;https://github.com/leaflabs/libmaple/blob/master/libmaple/adc.h#L292&#34;&#62;adc.h&#60;/a&#62; header file defines an &#60;code&#62;adc_smp_rate&#60;/code&#62; enum which features sample rates in a # of ADC cycles per sample, but that seems rather fast. I also understand (I hope) the ADC clock is running at 12MHz (72MHz / 6 divider). At the very slowest sample rate of 239.5 ADC clocks per sample that's 20uS per sample, or 50kHz. That's great, but what if I want a 8000Hz sample rate, or 44.1kHz sample rate?&#60;/p&#62;
&#60;p&#62;I've gotten ADC samples to be stored in SRAM via the DMA1 Channel 1 controller, but it's going too fast (I know, right?). Very primitive benchmarks [1] suggest a ~550kHz sample rate with ADC_SMPR_7_5, though I know my benchmark is VERY bad (polling the ISR bit !== smart) but the DMA interrupt stuff isn't working right just yet.&#60;/p&#62;
&#60;p&#62;Would I be best off setting up a timer with a xxxHz interrupt and sample the ADC manually rather than using the ADC's DMA? It's probably meant for people who need high sample rates.&#60;/p&#62;
&#60;p&#62;Cheers,&#60;br /&#62;
-robodude666&#60;/p&#62;
&#60;p&#62;[1] &#60;a href=&#34;https://gist.github.com/1019639&#34; rel=&#34;nofollow&#34;&#62;https://gist.github.com/1019639&#60;/a&#62; - My primitive ADC + DMA testing/benchmarking. There, it's on gist and not inline =].
&#60;/p&#62;</description>
		</item>

	</channel>
</rss>
