<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/2466/accurate-adc-measurement-without-the-soft-device</link><description>I&amp;#39;d like to measure the voltage of a lithium ion battery every minute or so in a way that&amp;#39;s highly accurate. I need to do this without using the Soft Device because a) I need all the memory I can get for logging the voltages and b) what I&amp;#39;m really testing</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 21 May 2014 14:03:59 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/2466/accurate-adc-measurement-without-the-soft-device" /><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9954?ContentTypeID=1</link><pubDate>Wed, 21 May 2014 14:03:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:40f99746-6f06-4833-afc3-edc9c29344fe</guid><dc:creator>Eliot Stock</dc:creator><description>&lt;p&gt;Understood, thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9953?ContentTypeID=1</link><pubDate>Wed, 21 May 2014 12:46:51 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b43095c5-4d59-463e-9252-06751ac49a4d</guid><dc:creator>H&amp;#229;kon Alseth</dc:creator><description>&lt;p&gt;normally you want your program flow to look like this:
int main()
{
init();
while(1)
{
/* do something*/
}
// return will never execute
return 0;
}&lt;/p&gt;
&lt;p&gt;What you want to do in your while-loop is to execute the functions that you need to run in a loop, then go to sleep (WFI for instance). Since you&amp;#39;re using the app_timer, most of your functionality will be executed via interrupts, so you can just put a while(1){__WFI();}&lt;/p&gt;
&lt;p&gt;Prior to the while-loop you must have all the init-functions. Like creating and starting the app_timer instance and other init functions.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9952?ContentTypeID=1</link><pubDate>Wed, 21 May 2014 11:09:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7708eeac-06da-4f87-8a28-3c077fd112f6</guid><dc:creator>Eliot Stock</dc:creator><description>&lt;p&gt;Thanks. No, what&amp;#39;s shown above is the entire main() function in main.c, there&amp;#39;s none of the usual while loop stuff at the moment. Should there be? It seems that anything after:&lt;/p&gt;
&lt;p&gt;NRF_TIMER0-&amp;gt;TASKS_SHUTDOWN = 1;&lt;/p&gt;
&lt;p&gt;won&amp;#39;t execute anyway? Or will it?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9951?ContentTypeID=1</link><pubDate>Wed, 21 May 2014 11:01:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:561f1861-e559-4b0a-8b4e-767893fb0c02</guid><dc:creator>H&amp;#229;kon Alseth</dc:creator><description>&lt;p&gt;Hi Eliot,&lt;/p&gt;
&lt;p&gt;Using the RTC (app_timer) to create this 30 sec tick is the way to do it, especially when thinking of current consumption.&lt;/p&gt;
&lt;p&gt;Returns from main aren&amp;#39;t recommended in embedded applications. I do not know on which level you&amp;#39;re calling this return, but if this is set in the main-while loop, then you&amp;#39;ll return to an unknown state.
I assume this is some sort of function call, since there&amp;#39;s no sleep-call at the end of it?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9950?ContentTypeID=1</link><pubDate>Tue, 20 May 2014 11:40:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d0a13f97-3c2b-4ed1-bb78-375f4506c174</guid><dc:creator>Eliot Stock</dc:creator><description>&lt;p&gt;Hi Håkon,&lt;/p&gt;
&lt;p&gt;I think what you&amp;#39;ve addressed above is helping reduce power consumption &lt;em&gt;while&lt;/em&gt; reading the ADC. But that only takes a fraction of a second. What about reducing consumption in between samples? (I sample once every 30s for now.)&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve tried using NRF_TIMER0-&amp;gt;TASKS_SHUTDOWN for this and it seems to work but I want to check my approach. My main() looks like this (note the return from main, which seems a bit weird).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;	uint32_t err_code;
	app_timer_id_t timer_id;

	timers_init();
	battery_level_init();

	start_clock();

	err_code = app_timer_create(&amp;amp;timer_id, APP_TIMER_MODE_REPEATED, generator_test_timeout_handler);
	APP_ERROR_CHECK(err_code);

	err_code = app_timer_start(timer_id, APP_TIMER_TICKS(30000, 0), NULL);
	APP_ERROR_CHECK(err_code);

	// Shutdown and wait for timer to timeout.
	NRF_TIMER0-&amp;gt;TASKS_SHUTDOWN = 1;
	return 0;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;battery_level_init() sets up the ADC. start_clock() starts the LF clock explicitly, since we&amp;#39;re not using the Soft Device. The timeout handler is simply:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void generator_test_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    battery_level_read();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;in battery_level_read() I use your &amp;quot;safest approach&amp;quot; above.&lt;/p&gt;
&lt;p&gt;Seems to work, even with the debugger, but I haven&amp;#39;t yet tested the power consumption. Does all this seem OK to you?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9949?ContentTypeID=1</link><pubDate>Thu, 08 May 2014 11:19:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:089dae62-61d6-42b0-af6d-0b91c9ff06e8</guid><dc:creator>Eliot Stock</dc:creator><description>&lt;p&gt;No problem, this looks like the lowest power consumption approach to my problem too. Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9948?ContentTypeID=1</link><pubDate>Thu, 08 May 2014 11:11:44 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:feb6483e-20fa-4500-96d3-49e6171c7930</guid><dc:creator>H&amp;#229;kon Alseth</dc:creator><description>&lt;p&gt;Eliot, I must apologize for going off-topic.
This is a continuation of the WFE-talk in the comments area.&lt;/p&gt;
&lt;p&gt;As events and interrupts are closely coupled in the MCU core, you&amp;#39;ll need to enable this in the INTENSET register prior to using SEV/WFE.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;you enable SEV instruction in SCB-&amp;gt;SRC.&lt;/li&gt;
&lt;li&gt;You enable the event/interrupt for HFCLK-started (INTENSET)&lt;/li&gt;
&lt;li&gt;Start the task enabled in 2)&lt;/li&gt;
&lt;li&gt;The first WFE will cause the MCU to go to sleep and wake up on EVENTS_HFCLKSTARTED.&lt;/li&gt;
&lt;li&gt;SEV will set the Event Register in the core register.&lt;/li&gt;
&lt;li&gt;Second WFE will see that the event register is set, and clear this. No sleep will be executed at this call.&lt;/li&gt;
&lt;li&gt;EVENTS_HFCLKSTARTED and IRQn is cleared.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;u&gt;&lt;strong&gt;Safest approach:&lt;/strong&gt;&lt;/u&gt;
I had a chat with our nrf_soc developer, and was told a better implementation.
The above usage of WFE/SEV/WFE can cause you to wake up immediately if the internal event register is already set.&lt;/p&gt;
&lt;p&gt;To be certain that you wake up on the correct event, you should do like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
NRF_CLOCK-&amp;gt;INTENSET = CLOCK_INTENSET_HFCLKSTARTED_Msk;
// Enable wake-up on event
SCB-&amp;gt;SCR |= SCB_SCR_SEVONPEND_Msk; 
NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK-&amp;gt;TASKS_HFCLKSTART = 1; 
while (NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED == 0) 
{
  __WFE();
}
NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;
NVIC_ClearPendingIRQ(POWER_CLOCK_IRQn);

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In general, I recommend reading up on WFI/WFE/SEV instructions:
&lt;a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/CIHEGBBF.html"&gt;infocenter.arm.com/.../index.jsp&lt;/a&gt;
&lt;a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15473.html"&gt;infocenter.arm.com/.../index.jsp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;BR
Håkon&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9947?ContentTypeID=1</link><pubDate>Thu, 08 May 2014 09:45:56 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c7ad66dc-ed7d-4706-8b93-02eb2cc12432</guid><dc:creator>FormerMember</dc:creator><description>&lt;p&gt;Håkon, can you please explain the code snippet that you&amp;#39;ve posted. What is the advantage of using the method that you have posted to enabling the interrupt for POWER_CLOCK and using WFI? And why SEV between WFE?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9946?ContentTypeID=1</link><pubDate>Wed, 07 May 2014 14:51:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:17f80e52-de59-427b-945a-4816ae8bd49f</guid><dc:creator>H&amp;#229;kon Alseth</dc:creator><description>&lt;p&gt;You can save a bit of power by using SEV/WFE instead of polling (been meaning to learn how this WFE works):
NRF_CLOCK-&amp;gt;INTENSET = CLOCK_INTENSET_HFCLKSTARTED_Msk;
// Enable wake-up on event
SCB-&amp;gt;SCR |= SCB_SCR_SEVONPEND_Msk;&lt;br /&gt;
//NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK-&amp;gt;TASKS_HFCLKSTART = 1;&lt;br /&gt;
__WFE();
__SEV();&lt;br /&gt;
__WFE();
NVIC_ClearPendingIRQ(POWER_CLOCK_IRQn);
NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;&lt;/p&gt;
&lt;p&gt;Hope this helps on power consumption.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9945?ContentTypeID=1</link><pubDate>Wed, 07 May 2014 14:21:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:672bf1e2-3987-45e7-a82c-22494ced818a</guid><dc:creator>Eliot Stock</dc:creator><description>&lt;p&gt;Looks good, thanks very much.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Accurate ADC measurement without the Soft Device</title><link>https://devzone.nordicsemi.com/thread/9944?ContentTypeID=1</link><pubDate>Wed, 07 May 2014 13:49:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c75d30ce-1a97-4e03-8903-55dc717445e9</guid><dc:creator>H&amp;#229;kon Alseth</dc:creator><description>&lt;p&gt;Hi Eliot,&lt;/p&gt;
&lt;p&gt;You&amp;#39;ll have to manually start the 16M XTAL in a sequence like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    
if (!(NRF_CLOCK-&amp;gt;HFCLKSTAT &amp;amp; (BIT_0 | BIT_16)))
{
    NRF_CLOCK-&amp;gt;TASKS_HFCLKSTART = 1;
    while (NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED == 0);
    NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;
}
    
/*
Do something, then stop the HFCLK.
*/
NRF_CLOCK-&amp;gt;TASKS_HFCLKSTOP = 1;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Best regards
Håkon&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>