<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=4&amp;t=14357&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2016-01-31T17:22:45+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=14357&amp;mode</id>
<entry>
<author><name><![CDATA[mkk13]]></name></author>
<updated>2016-01-31T17:22:45+01:00</updated>
<published>2016-01-31T17:22:45+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=14357&amp;p=152210#p152210</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=14357&amp;p=152210#p152210"/>
<title type="html"><![CDATA[WatchDogTimer + zmienna = usypianie na Xminut?]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=14357&amp;p=152210#p152210"><![CDATA[
Cześć wszystkim,<br /><br />Jestem w trakcie swojego małego projekciku termostatu i z powodu uszkodzenia nogi RTC, który dysponuje solidnymi timerami, zmuszony jestem wybudzać jakoś swój układ za pomocą czegoś innego. Korzystam z ATmegi88PA-PU<br /><br />Zdecydowałem się na taki system:<br />1. Jest odpalony timer z okresem 8s i posiada licznik, co w sumie zapewnia przepełnienie co minutę.<br />2A. Jeśli wciśnięty zostanie dowolny klawisz, timer z pkt.1. jest resetowany.<br />2B. Jeśli timer z pkt.1. się przepełni, to odpala WatchDogTimer i usypia układ.<br />3. WatchDogTimer ma okres 8s i posiada licznik, co w sumie zapewnia przepełnienie co 15min.<br /><br />Przy usypianiu gaszone jest kilka modułów, co powoduje mniejsze zjadanie przez nie energii.<br />Przy budzeniu przez WDT sprawdzany jest licznik:<br />[*] Jeśli ten spadł do 0, to wołane jest wdt_disable() i odpalane są moduły. Liczniki timera i WDT są resetowane.<br />[*] Jeśli jest &gt;0, to następuje jego dekrementacja, a następnie ponownie odpalany jest WDT i usypiany układ.<br /><br />Ponadto istnieje flaga &quot;isAsleep&quot;, która jest ustawiana na 1 przez Timer przy pierwszym odpaleniu WDT i usuwana przez WDT wybudzającego w pełni procek. Główna pętla programu wykonuje swoje instrukcje tylko jeśli isAsleep==0, inaczej to jest while(1);<br /><br />Niestety póki co pomysł nie działa - prawidłowo idzie spać, tylko jeśli nie korzystam z guzików, prawidłowo gasi moduły przed i odpala je po wybudzeniu, jednak ilość czasu, którą spędza w śnie jest zdecydowanie za krótka. Procek siedzi w temp ok. 30 stopni, bo obok wentylatora komputera, a zatem i programatora (dane odczytane z modułu termometru).<br /><br />Jakieś pomysły? Oczywiście na czas testowania ustawiłem sobie mniejsze wartości - timer przepełnia się po 16s, WDT tak samo.<br /><br />Poniżej wrzucam pseudo kody implementacji tego usypiania. Funkcje do sleepa i wdt brane są z bibliotek avr <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br />main:<br />[syntax=c]int main()<br />{<br />    initTimers();<br />    isAsleep = 0;<br />    while(1)<br />    {<br />        if (!isAsleep)<br />        {<br />            checkTimers();<br />            *wykonaj petle itd*<br />        }<br />    }<br />    return 0;<br />}[/syntax]<br /><br />checkTimers:<br />[syntax=c]void checkTimers()<br />{<br />if(!sleepCounter)<br />{<br />                // reset timerów<br />sleepCounter = SLEEP_TIME;<br />                wdtCounter = WATCH_TIME;<br />cli();<br />isAsleep = 1;<br />wylaczModuly();<br />watchDogInit();<br />sleepInit();<br />}<br />}[/syntax]<br /><br />WDT i sleep inits:<br />[syntax=c]void watchDogInit()<br />{<br />wdt_reset();<br />WDTCSR = (1 &lt;&lt; WDCE);<br />WDTCSR = (1 &lt;&lt; WDIE) | (1 &lt;&lt; WDP3) | (1 &lt;&lt; WDP0);<br />}<br /><br />void sleepInit()<br />{<br />sleep_enable();<br />sei();<br />sleep_cpu();<br />sleep_disable();<br />}[/syntax]<br /><br />initTimers:<br />[syntax=c]void initTimers()<br />{<br />cli();<br /><br />// set timer1 for polling power-saving<br />TCCR1B |= (1 &lt;&lt; CS12) | (1 &lt;&lt; CS10); // preskaler 1024<br />TIMSK1 |= (1 &lt;&lt; TOIE1); // overflow interrupt<br /><br />sleepCounter = SLEEP_TIME;<br />wdtCounter = WATCH_TIME;<br /><br />// Set sleep mode<br />set_sleep_mode(SLEEP_MODE_PWR_DOWN);<br />sei();<br />}[/syntax]<br /><br />Przerwania:<br />[syntax=c]ISR(TIMER1_OVF_vect)<br />{<br />uint8_t n;<br /><br />n = sleepCounter;<br />if (n)<br />sleepCounter = --n;<br />}<br /><br />ISR(WDT_vect)<br />{<br />cli();<br />if (wdtCounter)<br />{<br />wdtCounter--;<br />watchDogInit();<br />sleepInit();<br />} else<br />{<br />wdt_disable();<br />wdtCounter = WATCH_TIME;<br />sleepCounter = SLEEP_TIME;<br />isAsleep = 0;<br />                wlaczModuly();<br />}<br /><br />sei();<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=11698">mkk13</a> — 31 sty 2016, o 17:22</p><hr />
]]></content>
</entry>
</feed>