<?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=8&amp;t=6755&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-04-14T22:34:55+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=8&amp;t=6755&amp;mode</id>
<entry>
<author><name><![CDATA[barney]]></name></author>
<updated>2014-04-14T22:34:55+01:00</updated>
<published>2014-04-14T22:34:55+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78077#p78077</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78077#p78077"/>
<title type="html"><![CDATA[Re: FatFS, buforowanie danych z ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78077#p78077"><![CDATA[
<div class="quotetitle">markaj napisał(a):</div><div class="quotecontent"><br />czy wtedy konwersja tak dużej ilości danych nie spowolni samej procedury zapisu?<br /></div> Tak czy siak musisz tą konwersję wykonać, a nie widzę powodu dla którego musiałaby się odbywać w przerwaniu (przechowywanie wartości w stringu zwiększa jedynie zajętość pamięci; konwersja w przerwaniu wydłuża je, mogąc powodować przerwanie jakiejś ważnej operacji w głównej pętli na zbyt długo - konwertując poza przerwaniem masz możliwość kontroli tego).<br /><div class="quotetitle">markaj napisał(a):</div><div class="quotecontent"><br />jak zatem wyznaczyć poziom zajętości bufora? czekać do jego całkowitego wypełnienia?<br /></div> Temat przecież powstał między innymi dlatego, że nowe dane nadlatują Ci zanim zwolnisz dla nich miejsce... bufor musi mieć więc rozmiar (co najmniej) zapisywanej paczki + rozmiar danych które nadlecą podczas zapisywania tejże paczki.<br /><div class="quotetitle">markaj napisał(a):</div><div class="quotecontent"><br />jakiej wielkości bufor pozwoli na uzyskanie jak największej częstotliwości próbkowania<br /></div> Na AVRach jest to bez znaczenia. Znaczenie za to ma sposób w jaki go oprogramujesz.<br /><div class="quotetitle">markaj napisał(a):</div><div class="quotecontent"><br />czytałem, że zapis do karty SD odbywa się całymi sektorami po 512 Mbajtów. czy z tego wynika, taką wielkość powinno się stosować?<br /></div> Nie Mbajtów, a bajtów. I nie 512, a co najmniej 512. Warto to stosować, o ile jesteś w stanie zapewnić, że zapisywane dane o wielkości sektora nie będą rozłożone pomiędzy 2 sektorami.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=973">barney</a> — 14 kwi 2014, o 22:34</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[markaj]]></name></author>
<updated>2014-04-14T21:18:47+01:00</updated>
<published>2014-04-14T21:18:47+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78070#p78070</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78070#p78070"/>
<title type="html"><![CDATA[Re: FatFS, buforowanie danych z ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78070#p78070"><![CDATA[
Dzięki za odpowiedź <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> <br /><br />czyli sugerujesz, żeby jednak dane z bufora konwertować na string w pętli głównej po przekroczeniu jakiegoś poziomu zajętości? konwersja pojedynczej wartości za pomocą funkcji itoa jest stosunkowo prosta. ale jakie podejście przyjąć przy całej tablicy liczb? zastosować do tego pętlę for? czy wtedy konwersja tak dużej ilości danych nie spowolni samej procedury zapisu? jak zatem wyznaczyć poziom zajętości bufora? czekać do jego całkowitego wypełnienia? jakiej wielkości bufor pozwoli na uzyskanie jak największej częstotliwości próbkowania. czytałem, że zapis do karty SD odbywa się całymi sektorami po 512 Mbajtów. czy z tego wynika, taką wielkość powinno się stosować?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3331">markaj</a> — 14 kwi 2014, o 21:18</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[barney]]></name></author>
<updated>2014-04-14T20:54:12+01:00</updated>
<published>2014-04-14T20:54:12+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78063#p78063</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78063#p78063"/>
<title type="html"><![CDATA[Re: FatFS, buforowanie danych z ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78063#p78063"><![CDATA[
<div class="quotetitle">markaj napisał(a):</div><div class="quotecontent"><br />Zatem czy takie wywołanie się przerwania w trakcie zapisu nie powoduje, że zapis jest w pewien sposób zaburzony? Kolejne pytanie dotyczy możliwości tracenia próbekz ADC. Czy zastosowanie 2 buforów rozwiązuje ten problem? Jeśli tak, to jak mniej więcej zabrać się za ich implementację?<br /></div> Nie wiem jak pewne rzeczy są w libsie Elm-Chana zrealizowane, ale operując na niższej warstwie (tzn. bezpośrednio na sektorach karty) zrealizowałbym zapis tworząc w RAMie AVRa bufor FIFO z którego dane są ściągane (zapisywane na kartę) po przekroczeniu rozmiaru sektora.<br /><br />Pewnie nie masz takich możliwości, więc zrób sobie bufor FIFO do przechowywania wartości dwójkowo, a konwersji na stringa i zapisu dokonuj dopiero po przekroczeniu jakiegoś poziomu zajętości bufora.<br /><br />Swoją drogą, to jeżeli zaimplementujesz obsługę karty w odpowiedni sposób, to możesz sobie wysyłać bit po bicie z dowolnie długimi przerwami między nimi <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=973">barney</a> — 14 kwi 2014, o 20:54</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[markaj]]></name></author>
<updated>2014-04-14T20:22:48+01:00</updated>
<published>2014-04-14T20:22:48+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78058#p78058</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78058#p78058"/>
<title type="html"><![CDATA[Re: FatFS, buforowanie danych z ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78058#p78058"><![CDATA[
dobrze, poprawiłem znaczniki kodu, mam nadzieję, że teraz ktoś się odezwie:)<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3331">markaj</a> — 14 kwi 2014, o 20:22</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[markaj]]></name></author>
<updated>2014-04-14T14:37:46+01:00</updated>
<published>2014-04-14T14:37:46+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78009#p78009</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78009#p78009"/>
<title type="html"><![CDATA[FatFS, buforowanie danych z ADC]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=6755&amp;p=78009#p78009"><![CDATA[
Witam wszystkich serdecznie:)<br /><br />Od dłuższego czasu pracuję nad prototypem elektronicznego stetoskopu, który dokonuje akwizycję danych pomiariwych na karcie SD.<br />W związku z tym, że interesujące mnie pasmo dochodzi do 500Hz, częstotliwość próbkowania jaką muszę uzyska to minimum 1kHz.Wykorzystuję Atmegę 328p.Prcuję zatem nad biblioteką FatFS i odpowiednim systemem buforowania próbek pochodzących z ADC. Póki co staram się zaimplementować1 bufor lecz w domyśle, ostatecznie planuję zastosować 2 bufory. Bardzo proszę o zweryfikowanie mojej koncepcji. Zdefiniowałem sobie funkcję, która zwraca ilość cyfr podanych jako argumet i zastosowałem ją w obsłudze przerwania, aby przesunąć wskaźnik o odpowiednią ilość miejsc w moim buforze.Doszedłem bowiem do wniosku, że biblioteczna funkcja itoa (wykorzystywana w celu skonwertowania danych z ADC do stringa) nie zwraca wskaźnika do ostatniego miejsca w tablicy, do której wpisuje pomiary. Wydaje mi się jednak, że stosowanie funkcji operującej na stringach w przerwaniu może nie być dobrym pomysłem.W obsłudze przerwania zewnętrznego dokonuję prymitywnego multipleksowania kanału ADC, ponieważ projekt zakłada podawanie na analogowy filtr przestrajany częstotliwością fali prostokątnej generowanej w trybie CTC. Wartość podawana z potencjometrudeterminuje zatem cutoff filtra dolnoprzepustowego. Nie wiem również jakiej wielkości bufor zastosować, żeby nie zaśmiecić zbytnio pamięci RAM. W trybie podawania częstotliwości odcięcia przetwornik działa poprawnie. Natomiast w trybie zapisu danych na SD na wyświetlaczu LCD widoczne są zmienne wartości. Natomiast na karcie w tym czasie zapisuje się w zasadzie stała wartość, ok 380. Przetwornik jest skonfigurowany w trybie free running mode. Dane chcę zapisywać w postaci kolumny, żeby móc sobie wygenerować od razu plik .csv. Mam też wątpliwości co do samego działania zapisu w momencie wywołania przerwania od ADC. Wydaje mi się, że czas obsługi tego przerwania powinien być krótszy niż sama procedura zapisu na SD. Zatem czy takie wywołanie się przerwania w trakcie zapisu nie powoduje, że zapis jest w pewien sposób zaburzony? Kolejne pytanie dotyczy możliwości tracenia próbekz ADC. Czy zastosowanie 2 buforów rozwiązuje ten problem? Jeśli tak, to jak mniej więcej zabrać się za ich implementację? Przepraszam za dużą ilość zakomentowanych linii i ewentualną nieczytelność ale to jest bardzo robocza wersja kodu. Jeśli coś wymaga dokładniejszego wyjaśnienia to oczywiście postaram się sprecyzować o co chodzi.  Będę bardzo wdzięczy za wszelkie sugestie i pomoc.<br /><br />Pozdrawiam:)<br /><br /><br /><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;string.h&gt;<br />#include &quot;LCD/HD44780.h&quot;<br />#include &quot;ADC/ADC_Handle.h&quot;<br />#include &quot;generator/generator.h&quot;<br />#include &quot;FatFs/ff.h&quot;<br /><br />// deklaracja funkcji obliczającej ilosc cyfr<br />static inline unsigned int digit_num(unsigned int num);<br /><br /><br />//potrzebne do FsFat<br /><br />typedef struct {<br />WORDyear;/* 2000..2099 */<br />BYTEmonth;/* 1..12 */<br />BYTEmday;/* 1.. 31 */<br />BYTEwday;/* 1..7 */<br />BYTEhour;/* 0..23 */<br />BYTEmin;/* 0..59 */<br />BYTEsec;/* 0..59 */<br />} RTC;<br /><br /><br />DWORD get_fattime ()<br />{<br />RTC rtc;<br /><br /><br />/* Get local time */<br />//rtc_gettime(&amp;rtc);<br />rtc.year = 2010;<br />rtc.month = 10;<br />rtc.mday = 21;<br />rtc.hour = 17;<br />rtc.min = 45;<br />rtc.sec = 0;<br /><br />/* Pack date and time into a DWORD variable */<br />return  ((DWORD)(rtc.year - 1980) &lt;&lt; 25)<br />| ((DWORD)rtc.month &lt;&lt; 21)<br />| ((DWORD)rtc.mday &lt;&lt; 16)<br />| ((DWORD)rtc.hour &lt;&lt; 11)<br />| ((DWORD)rtc.min &lt;&lt; 5)<br />| ((DWORD)rtc.sec &gt;&gt; 1);<br /><br /><br />}<br /><br />//zmienne do obslugi FatFs<br /><br />char file_name&#91;&#93; = &quot;test.csv&quot;;<br />char bufor&#91;4&#93;; <br /><br />//zmienne do obsługi przerwań<br /><br />volatile long unsigned int luiPressButtonCounter = 0;// zmienna sterująca programem, naprzemienny tryb ustawinia częstotl. i zapisu<br />volatile int adc;<br />volatile int adc1;<br />volatile unsigned char kanal = 1;<br />char buff1&#91;128&#93;;<br />//char buff2&#91;64&#93;;<br />char* p_buff_write = buff1;<br />//volatile char buff_used = 1; // zmienne do 2 buforów<br />//volatile char buff_finish = 0;//<br /><br /><br />//funkcja glowna<br /><br />int main(void) {<br /><br />// zmienne do obslugi FatFs<br /><br />BYTE res;<br />UINT s1;<br />FATFS fs;<br />FIL fat;<br /><br />//zmienne do obslugi LCD<br /><br />char wy&#91;4&#93;;//bufor wyniku - 4bit tablica - zapis decymalny<br />long wynik; //zmienna z wynikiem po konwersji<br /><br />// Inicjalizacja SPI<br /><br />#define SCK PB5<br />#define MOSI PB3<br />#define MISO PB4<br />#define CS PB0<br /><br /><br />DDRB = (1&lt;&lt;MOSI)|(1&lt;&lt;SCK)|(1&lt;&lt;CS);<br />SPCR = (1&lt;&lt;SPE)|(1&lt;&lt;MSTR)|(1&lt;&lt;SPR0); //pamietac o dopasowaniu preskalera, nie za maly!<br /><br /><br />// Inicjalizacja przerwania zewnetrznego INT1 falling<br /><br />EICRA |= (1&lt;&lt;ISC01);<br />EIMSK |= (1&lt;&lt;INT0);<br /><br /><br />//inicjalizacja LCD<br /><br />   LCD_Initalize();<br />   LCD_Home();     //Ustawienie kursora w pozycji (0,0)<br />   LCD_WriteText(&quot;Start!&quot;);<br />   _delay_ms(2000);<br />   LCD_Clear();<br /><br />   //Inicjalizacja ADC<br /><br />   ADCSRA |= (1&lt;&lt;ADPS2) | (1&lt;&lt;ADPS1); // wybor preskalera 64 - 3 ostatnie bity<br />   ADCSRA |= (1&lt;&lt;ADIE); // przerwanie od ADC<br />   ADCSRA |= (1&lt;&lt;ADATE);// wyzwalanie konwersji<br />   ADMUX |= (1&lt;&lt;REFS0); //| (1&lt;&lt;REFS1); //wybór Aref jako Vinternal<br />   ADMUX &amp;= ~0x07;// maskowanie 3 bitów<br />   ADMUX |= kanal; // kanal 4 do czestotliwosci na wejsciu programu<br />   ADCSRA |= (1&lt;&lt;ADEN);    // włączenie ADC<br />   ADCSRA |= (1&lt;&lt;ADSC); // start konwersji<br />   DDRC &amp;=~ (1&lt;&lt;PC5); // Ustawienie Wejścia ADC<br />   DDRC &amp;=~ (1&lt;&lt;PC4);<br />   ADCSRB &amp;= ~(1&lt;&lt;ADTS2);  //<br />   ADCSRB &amp;= ~(1&lt;&lt;ADTS1); //<br />   ADCSRB &amp;= ~(1&lt;&lt;ADTS0); //tryb free running<br /><br /><br />   //Inicjalizacja generatora<br /><br />   generator_setup(15,1); // z biblioteki generator.h<br /><br />   // globalne odblokowanie przerwan<br /><br />   sei();<br /><br />   //petla glowna<br /><br />  while(1)<br />  {<br /><br />if(luiPressButtonCounter%2 == 0){<br /><br /> wynik = map(adc1, 0, 1023, 2000, 50000);  //konwersja wyniku ADC do danego przedzialu<br /><br /> set_frequency(wynik, 1); // ustawienie cut off filtra<br /><br /> LCD_Clear();<br /> LCD_Home();<br /> LCD_WriteText(&quot;Freq:&quot;);<br /> LCD_GoTo(0, 1);         //Ustawienie kursora w pozycji (0,1)<br /> LCD_WriteText(&quot;     &quot;);   //kasowanie poprzedniej wartosci<br /> itoa(wynik/100,wy,10);      //konwersja wyniku do tablicy char - biblioteka stdlib<br /> LCD_GoTo(0, 1);         //Ustawienie kursora w pozycji (0,1)<br /> LCD_WriteText(wy); //Wyświetlenie wyniku<br /> _delay_ms(100);//opóźnienie<br /> LCD_Clear();<br />}<br /><br />else {<br /><br />itoa(adc1, buff1, 10);<br /><br /> LCD_Home();<br /> LCD_WriteText(&quot;Zapis&quot;);<br /> LCD_GoTo(0,1);<br /> LCD_WriteText(&quot;     &quot;);<br /> LCD_GoTo(0,1);<br /> LCD_WriteText(buff1);// wypisanie częstotliwoci na LCD<br /><br /> //zapis na SD<br /><br />res = f_mount(0,&amp;fs);<br /><br />if(res == FR_OK) {<br />res = f_open(&amp;fat, file_name, FA_OPEN_ALWAYS | FA_WRITE);<br /><br />if(res == FR_OK) {<br /><br /><br />f_lseek(&amp;fat, fat.fsize);<br />uint16_t bytes_count = 123;//(uint32_t)p_buff_write - (uint32_t)buff;<br /><br />//if(buff_used == 1) p_buff_ready = buff2; // do 2 buforów<br />//else p_buff_ready = buff1;<br />res = f_write(&amp;fat, buff1, bytes_count, &amp;s1);<br />//f_lseek(&amp;fat, fat.fsize);<br />f_close (&amp;fat);<br />f_mount(0,NULL);<br />//buff_finish = 1;<br /><br />}<br /><br />}<br /><br />}<br /><br />  }<br />}<br /><br /><br /><br />ISR(INT0_vect){<br /><br />luiPressButtonCounter++;//inkrementacja licznika do sterowania programem<br />if(kanal == 1) kanal = 0;//zmiana kanalu ADC<br />else kanal=1;<br /><br />ADMUX &amp;= ~0x07; //maskowanie 3 bitow rejestru<br />ADMUX |= kanal; // ustawienie kanalu 4 lub 5<br /><br />}<br /><br /><br />ISR(ADC_vect){<br /><br />static unsigned int count_tab;<br />unsigned int offset; // przesunięcie wskaźnika w buforze<br />adc1 = ADC;<br />static int g;<br />char *pc;<br />//if(g&lt;24) { //~128/5 -&gt; zapis po max 5 znaków - chyba zły pomysł<br />adc=(unsigned int)adc1;<br /><br />if(count_tab&lt;5) {<br /><br />offset = digit_num(adc1);<br />itoa(ADC, p_buff_write, 10);<br /><br />//}<br /><br />static int licznik;<br />//pc = itoa(licznik, p_buff_write, 10);<br />licznik++;<br />count_tab++;<br />//p_buff_write += 4;<br />p_buff_write += offset;<br />*(p_buff_write++) = '\0';<br />g++;<br />}<br /><br />//else g=0; //{<br /><br />//g=0;<br />//buff_finish = 0;<br />/*if(buff_used == 1) {<br />p_buff_write = buff2;<br />buff_used = 2;<br />}<br /><br />else {<br /><br />p_buff_write = buff1;<br />buff_used = 1;<br />}*/<br />//}<br /><br />}<br /><br /><br />static inline unsigned int digit_num(unsigned int num) {<br /><br />unsigned int temp = num;<br />unsigned int counter = 0;<br /><br />while(temp) {<br /><br />counter++;<br />temp/=10;<br />}<br /><br />if(counter==0) return 1;<br />else return counter;<br /><br />}[/syntax]<br /><br /><span style="color: #00AA00">Kody źródłowe umieszczamy w znacznikach synax=c, bez odbioru! //kila</span><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3331">markaj</a> — 14 kwi 2014, o 14:37</p><hr />
]]></content>
</entry>
</feed>