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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2017-09-28T18:22:31+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=30&amp;t=19262&amp;mode</id>
<entry>
<author><name><![CDATA[resonator]]></name></author>
<updated>2017-09-28T18:22:31+01:00</updated>
<published>2017-09-28T18:22:31+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195969#p195969</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195969#p195969"/>
<title type="html"><![CDATA[Re: TWI Atmega8 nie mogę odczytać danych z HMC5883l]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195969#p195969"><![CDATA[
<div class="quotetitle">eVol68 napisał(a):</div><div class="quotecontent"><br /><div class="quotetitle">resonator napisał(a):</div><div class="quotecontent">Miałem rację, nie jest to ten sam układ, który deklaruje sprzedawcy modułów! Jeśli się dobrze przyjrzeć obudowie to można tam odczytać oznaczenie &quot;DA5883&quot;. W necie wyczytałem że oryginalny producent układów o oznaczeniu &quot;HMC5883&quot; przestał produkować czy tam sprzedał prawa do produkcji, nie wnikałem o co chodziło. Sedno w tym, że teraz są to zupełnie inne układy o oznaczeniu &quot;QMC5883L&quot;. Mają inny adres (0x0D), Inaczej poustawiane rejestry (program wyżej był poprawny a odczytywał z rejestrów zera, ponieważ były to rejestry od danych pomiaru, który nie był wyzwalany) i w ogóle wydaje mi się, że mają mniej opcji do konfigurowania.<br /></div><br /><br />Tak, to prawda, trzeba na to zwracać uwagę. Też kupowałem HMC5883L (L883), a otrzymałem QMC5883L (DA5883), który różni się od układu Honeywell'a.<br /><br />Podobnie jak kolega <strong><em>resonator</em></strong> walczyłem z tym układem, jednak udało mi się stworzyć program do jego obsługi, lecz mam rażenie, że wyniki, które odczytuje strasznie szaleją (i chyba nie są poprawne(?)) - nie wiem :/<br /><br />PS: <strong><em>resonator</em></strong> czy udało Ci się &quot;opanować&quot; odczyt z tego magnetometru?<br /><br />Wrzucam swój kod:<br /><br />[syntax=c]/* Podstawowe biblioteki */<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/iom8.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;math.h&gt;<br /><br />/* Biblioteki zewnętrzne */<br />#include &quot;i2cmaster.h&quot;<br />#include &quot;UART_lib/UART.h&quot;<br /><br />/* Definicje */<br />#define QMC5883_I2C_ADDRESS 0x0D<br /><br />char buffer&#91;6&#93;;<br />int16_t raw_x = 0;<br />int16_t raw_y = 0;<br />int16_t raw_z = 0;<br />float headingDegrees = 0;<br /><br />/* Functions */<br />void init_QMC5883L();<br />float getHeading();<br /><br />/* Główna funkcja programu */<br />int main(void) {<br /><br />UART_init(baud_rate_19200);<br />i2c_init();<br />init_QMC5883L();<br /><br />/* Globalne przerwania */<br />//sei();<br />while(1) {<br /><br />getHeading();<br /><br />itoa(raw_x, buffer, 10);<br />UART_puts(buffer);<br />UART_puts(&quot;  &quot;);<br /><br />itoa(raw_y, buffer, 10);<br />UART_puts(buffer);<br />UART_puts(&quot;  &quot;);<br /><br />itoa(raw_z, buffer, 10);<br />UART_puts(buffer);<br />UART_puts(&quot;  &quot;);<br /><br />dtostrf(headingDegrees, 6, 2, buffer);<br />UART_puts(buffer);<br />UART_puts(&quot;  \r\n&quot;);<br />_delay_ms(100);<br /><br />}<br />}<br /><br />void init_QMC5883L(void) {<br />i2c_start((QMC5883_I2C_ADDRESS&lt;&lt;1) | I2C_WRITE);<br />i2c_write(0x0B);// QMC5883_SET_RESET_PERIOD0x0B<br />i2c_write(0x01);<br />i2c_stop();<br /><br />i2c_start((QMC5883_I2C_ADDRESS&lt;&lt;1) | I2C_WRITE);<br />i2c_write(0x09);// QMC5883_REG_CONFIG_1<br />i2c_write(0b00000001|0b00001100|0b00010000|0b00000000);// QMC5883_MODE_CONTINOUS,QMC5883_ODR_200Hz,QMC5883_RNG_8G,QMC5883_OSR_512<br />i2c_stop();<br />}<br /><br />float getHeading(void) {<br />i2c_start((QMC5883_I2C_ADDRESS&lt;&lt;1) | I2C_WRITE);<br />i2c_write(0x00);<br />i2c_stop();<br />i2c_rep_start((QMC5883_I2C_ADDRESS&lt;&lt;1) | I2C_READ);<br /><br />raw_x = ((uint8_t)i2c_readAck())&lt;&lt;8;<br />raw_x |= i2c_readAck();<br /><br />raw_z = ((uint8_t)i2c_readAck())&lt;&lt;8;<br />raw_z |= i2c_readAck();<br /><br />raw_y = ((uint8_t)i2c_readAck())&lt;&lt;8;<br />raw_y |= i2c_readNak();<br /><br />i2c_stop();<br /><br />headingDegrees = atan2((double)raw_y,(double)raw_x) * 180 / 3.141592654 + 180;<br /><br />return headingDegrees;<br />}[/syntax]</div><br /><br /><br />Tak w pewnym sensie. Na początku w jednym miejscu pomiar potrafił przeskakiwać o kilka stopni. Ja nie potrzebowałem zbyt dokładnego wyniku (starczyło by mi 30 stopni na kąt pełny <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" />), więc zmieniłem rozdzielczość z 8G na 2G, częstotliwość wyników do 50Hz i końcowe przeliczanie na liczbę całkowitą. Teraz wynik waha się o 1-2 stopnie mówiąc oczywiście o obrocie względem osi prostopadłej do Ziemi, ja potrzebuje znać kierunek niezależnie od ułożenia sensora i z tym teraz się męczę.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=8721">resonator</a> — 28 wrz 2017, o 18:22</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[eVol68]]></name></author>
<updated>2017-09-27T17:24:06+01:00</updated>
<published>2017-09-27T17:24:06+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195895#p195895</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195895#p195895"/>
<title type="html"><![CDATA[Re: TWI Atmega8 nie mogę odczytać danych z HMC5883l]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195895#p195895"><![CDATA[
<div class="quotetitle">resonator napisał(a):</div><div class="quotecontent"><br />Miałem rację, nie jest to ten sam układ, który deklaruje sprzedawcy modułów! Jeśli się dobrze przyjrzeć obudowie to można tam odczytać oznaczenie &quot;DA5883&quot;. W necie wyczytałem że oryginalny producent układów o oznaczeniu &quot;HMC5883&quot; przestał produkować czy tam sprzedał prawa do produkcji, nie wnikałem o co chodziło. Sedno w tym, że teraz są to zupełnie inne układy o oznaczeniu &quot;QMC5883L&quot;. Mają inny adres (0x0D), Inaczej poustawiane rejestry (program wyżej był poprawny a odczytywał z rejestrów zera, ponieważ były to rejestry od danych pomiaru, który nie był wyzwalany) i w ogóle wydaje mi się, że mają mniej opcji do konfigurowania.<br /></div><br /><br />Tak, to prawda, trzeba na to zwracać uwagę. Też kupowałem HMC5883L (L883), a otrzymałem QMC5883L (DA5883), który różni się od układu Honeywell'a.<br /><br />Podobnie jak kolega <strong><em>resonator</em></strong> walczyłem z tym układem, jednak udało mi się stworzyć program do jego obsługi, lecz mam rażenie, że wyniki, które odczytuje strasznie szaleją (i chyba nie są poprawne(?)) - nie wiem :/<br /><br />PS: <strong><em>resonator</em></strong> czy udało Ci się &quot;opanować&quot; odczyt z tego magnetometru?<br /><br />Wrzucam swój kod:<br /><br />[syntax=c]/* Podstawowe biblioteki */<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/iom8.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;math.h&gt;<br /><br />/* Biblioteki zewnętrzne */<br />#include &quot;i2cmaster.h&quot;<br />#include &quot;UART_lib/UART.h&quot;<br /><br />/* Definicje */<br />#define QMC5883_I2C_ADDRESS 0x0D<br /><br />char buffer&#91;6&#93;;<br />int16_t raw_x = 0;<br />int16_t raw_y = 0;<br />int16_t raw_z = 0;<br />float headingDegrees = 0;<br /><br />/* Functions */<br />void init_QMC5883L();<br />float getHeading();<br /><br />/* Główna funkcja programu */<br />int main(void) {<br /><br />UART_init(baud_rate_19200);<br />i2c_init();<br />init_QMC5883L();<br /><br />/* Globalne przerwania */<br />//sei();<br />while(1) {<br /><br />getHeading();<br /><br />itoa(raw_x, buffer, 10);<br />UART_puts(buffer);<br />UART_puts(&quot;  &quot;);<br /><br />itoa(raw_y, buffer, 10);<br />UART_puts(buffer);<br />UART_puts(&quot;  &quot;);<br /><br />itoa(raw_z, buffer, 10);<br />UART_puts(buffer);<br />UART_puts(&quot;  &quot;);<br /><br />dtostrf(headingDegrees, 6, 2, buffer);<br />UART_puts(buffer);<br />UART_puts(&quot;  \r\n&quot;);<br />_delay_ms(100);<br /><br />}<br />}<br /><br />void init_QMC5883L(void) {<br />i2c_start((QMC5883_I2C_ADDRESS&lt;&lt;1) | I2C_WRITE);<br />i2c_write(0x0B);// QMC5883_SET_RESET_PERIOD0x0B<br />i2c_write(0x01);<br />i2c_stop();<br /><br />i2c_start((QMC5883_I2C_ADDRESS&lt;&lt;1) | I2C_WRITE);<br />i2c_write(0x09);// QMC5883_REG_CONFIG_1<br />i2c_write(0b00000001|0b00001100|0b00010000|0b00000000);// QMC5883_MODE_CONTINOUS,QMC5883_ODR_200Hz,QMC5883_RNG_8G,QMC5883_OSR_512<br />i2c_stop();<br />}<br /><br />float getHeading(void) {<br />i2c_start((QMC5883_I2C_ADDRESS&lt;&lt;1) | I2C_WRITE);<br />i2c_write(0x00);<br />i2c_stop();<br />i2c_rep_start((QMC5883_I2C_ADDRESS&lt;&lt;1) | I2C_READ);<br /><br />raw_x = ((uint8_t)i2c_readAck())&lt;&lt;8;<br />raw_x |= i2c_readAck();<br /><br />raw_z = ((uint8_t)i2c_readAck())&lt;&lt;8;<br />raw_z |= i2c_readAck();<br /><br />raw_y = ((uint8_t)i2c_readAck())&lt;&lt;8;<br />raw_y |= i2c_readNak();<br /><br />i2c_stop();<br /><br />headingDegrees = atan2((double)raw_y,(double)raw_x) * 180 / 3.141592654 + 180;<br /><br />return headingDegrees;<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3993">eVol68</a> — 27 wrz 2017, o 17:24</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[resonator]]></name></author>
<updated>2017-09-25T20:33:36+01:00</updated>
<published>2017-09-25T20:33:36+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195839#p195839</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195839#p195839"/>
<title type="html"><![CDATA[Re: TWI Atmega8 nie mogę odczytać danych z HMC5883l]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195839#p195839"><![CDATA[
Miałem rację, nie jest to ten sam układ, który deklaruje sprzedawcy modułów! Jeśli się dobrze przyjrzeć obudowie to można tam odczytać oznaczenie &quot;DA5883&quot;. W necie wyczytałem że oryginalny producent układów o oznaczeniu &quot;HMC5883&quot; przestał produkować czy tam sprzedał prawa do produkcji, nie wnikałem o co chodziło. Sedno w tym, że teraz są to zupełnie inne układy o oznaczeniu &quot;QMC5883L&quot;. Mają inny adres (0x0D), Inaczej poustawiane rejestry (program wyżej był poprawny a odczytywał z rejestrów zera, ponieważ były to rejestry od danych pomiaru, który nie był wyzwalany) i w ogóle wydaje mi się, że mają mniej opcji do konfigurowania. <br /><br />Więc uwaga na moduły, których sprzedawcy deklarują że jest tam taki a nie inny układ, bo można się męczyć bardzo długo.<br /><br />Teraz próbuje coś mierzyć tym układem, na razie moduł podaje mi cały czas te same wartości(wydaje mi się, że przez chwile za pierwszym razem wyniki nawet sensownie się zmieniały), ale teraz kiedy przyszedł od nowa zapał jeszcze z tym powalczę <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" /><br /><br />Tutaj datasheet tego całego QMC <!-- m --><a class="postlink" href="https://nettigo.pl/attachments/440" >https://nettigo.pl/attachments/440</a><!-- m --><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=8721">resonator</a> — 25 wrz 2017, o 20:33</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[resonator]]></name></author>
<updated>2017-09-24T21:20:40+01:00</updated>
<published>2017-09-24T21:20:40+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195798#p195798</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195798#p195798"/>
<title type="html"><![CDATA[Re: TWI Atmega8 nie mogę odczytać danych z HMC5883l]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195798#p195798"><![CDATA[
<div class="quotetitle">roske napisał(a):</div><div class="quotecontent"><br />Dalej podajesz nie ten adres. Teraz jest to 0x0d przesunięty w lewo, czyli 0x1a (zapis) i 0x1b (odczyt). Kody statusów wskazują brak błędów więc przypuszczam, że na magistrali masz jakieś inne urządzenie i2c o tym właśnie adresie.<br />Z adresami IIC jest istna kołomyjka: jedni podają, jak ja to nazywam, slave address - siedmiobitowy adres, który do urządzania trzeba wysłać przesunięty w lewo o jeden z dodanym najmłodszym bitem WRITE lub READ. Inni podają write address i read adress - ośmiobitowe adresy, już przesunięte w lewo, z już ustawionymi bitami write/read - te podaje się tak jak są. Dataszit Twojego czujnika podaje tę drugą wersję.<br />No i teraz Ty read address (na dodatek błędny) poddajesz przesunięciu w lewo i jeszcze dodajesz bit write/read. Przemyśl na spokojnie te operacje na adresach.<br /></div><br /><br />Wiem, jak to całe i2c powinno działać, tylko gdyby tak było to wysłałbym adres z dokumentacji i odbierał po kolei dane tak jak to robię z RTC. A tutaj próbuje na dziesiątki sposobów i nic. Więc sprawdziłem przeleciałem magistralę skanerem i tu zaskoczenie nie pojawia mi się w konsoli adres 0x3C tylko 0x0D. Skaner korzysta z tej samej biblioteki co kod powyżej:<br /><a href="https://obrazkiforum.atnel.pl/8721/089d24db073b2c9b15f16ed21b2afacf.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/8721/089d24db073b2c9b15f16ed21b2afacf.png" alt="Obrazek" /></a><br />Inkrementuje uinta w każdej iteracji pętli. Gdy coś na magistarli odpowie na adres zwraca uinta do konsoli, w tym wypadku 0x0D.<br /><br />I właśnie w poście wyżej użyłem tego adresu w dokładnie ten sam sposób co skaner, co wreszcie dało jakieś rezultaty. Nie ma możliwości, żeby odpowiadał inny slave, kompas jest podłączony prosto do uC, więc jak dla mnie to z tym układem jest coś nie tak.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=8721">resonator</a> — 24 wrz 2017, o 21:20</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[SunRiver]]></name></author>
<updated>2017-09-24T20:26:37+01:00</updated>
<published>2017-09-24T20:26:37+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195788#p195788</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195788#p195788"/>
<title type="html"><![CDATA[Re: TWI Atmega8 nie mogę odczytać danych z HMC5883l]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195788#p195788"><![CDATA[
<div class="quotetitle"><b>Quote:</b></div><div class="quotecontent"><br />Co sądzisz o ośmiokanałowych podróbkach Saleae? Chodzą po 30-40zł, są chyba najtańszą opcją, jak dla mnie pewnie wystarczającą.<br /></div><br /><br />w zupełności ci wystarczy ... jest na tym samym cypressie co starsza wersja LOGIC8   i swoją pracę robi ...<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=58">SunRiver</a> — 24 wrz 2017, o 20:26</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[resonator]]></name></author>
<updated>2017-09-24T19:58:05+01:00</updated>
<published>2017-09-24T19:58:05+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195782#p195782</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195782#p195782"/>
<title type="html"><![CDATA[Re: TWI Atmega8 nie mogę odczytać danych z HMC5883l]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195782#p195782"><![CDATA[
<div class="quotetitle">roske napisał(a):</div><div class="quotecontent"><br />Nic dziwnego, że się zawiesza, skoro już funkcja i2c_start zwraca kod błędu - w tym momencie program powinien pomijać wykonanie dalszych transmisji i zająć się obsługą błędu (nawet jeżeli obsługa błędów ogranicza się tylko do pominięcia dalszego kodu). A błąd jest zapewne dlatego, że podajesz nieprawidłowy adres, który dla tego czujnika jest 0x3c dla operacji zapisu i 0x3d dla operacji odczytu (albo raczej zgodnie z konwencją tej biblioteki 0x3c+I2C_WRITE i 0x3c+I2C_READ) - Ty podajesz 0x0c i 0x0d.<br /></div><br /><br />To co napisałeś trochę mi rozjaśniło, napisałem program dokładnie tak samo jak jest napisany skaner, okazało się że adresem musi być 0x3D zamiast 0x3C (0 zamiast 3 wcześniej to literówka ze zmęczenia), nie zauważyłem też że zwrotna jedynka oznacza błąd. Teraz program już gładko przechodzi, jednak nadal jest jakiś problem z odczytem danych (niezależnie od rejestru jest to 0).<br /><a href="https://obrazkiforum.atnel.pl/8721/11a2f39ba213d8c082fe4c6c8209eb05.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/8721/11a2f39ba213d8c082fe4c6c8209eb05.png" alt="Obrazek" /></a><a href="https://obrazkiforum.atnel.pl/8721/7725b2fee24f14f35e3461211fb95eeb.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/8721/7725b2fee24f14f35e3461211fb95eeb.png" alt="Obrazek" /></a><br /><br /><div class="quotetitle">micky napisał(a):</div><div class="quotecontent"><br />Ja zabaw z interfejsami nie wyobrażam sobie bez użycia dodatkowego wyposażenia jak analizator stanów logicznych, oscyloskop z dekoderem protokołów czy np urządzeń pokroju Bus Pirate itp. Pomyśl o takim zakupie. To nieduży wydatek a zaoszczędzisz mnóstwo czasu.<br /></div><br />Już od dłuższego czasu się do tego zabieram, jednak zawsze jak do tej pory udawało mi się rozwiązać problem dosyć sprawnie tradycyjnymi metodami. Co sądzisz o ośmiokanałowych podróbkach Saleae? Chodzą po 30-40zł, są chyba najtańszą opcją, jak dla mnie pewnie wystarczającą.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=8721">resonator</a> — 24 wrz 2017, o 19:58</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[micky]]></name></author>
<updated>2017-09-24T19:10:13+01:00</updated>
<published>2017-09-24T19:10:13+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195774#p195774</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195774#p195774"/>
<title type="html"><![CDATA[Re: TWI Atmega8 nie mogę odczytać danych z HMC5883l]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195774#p195774"><![CDATA[
Ja zabaw z interfejsami nie wyobrażam sobie bez użycia dodatkowego wyposażenia jak analizator stanów logicznych, oscyloskop z dekoderem protokołów czy np urządzeń pokroju Bus Pirate itp. Pomyśl o takim zakupie. To nieduży wydatek a zaoszczędzisz mnóstwo czasu.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1546">micky</a> — 24 wrz 2017, o 19:10</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[resonator]]></name></author>
<updated>2017-09-24T18:31:35+01:00</updated>
<published>2017-09-24T18:31:35+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195763#p195763</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195763#p195763"/>
<title type="html"><![CDATA[TWI Atmega8 nie mogę odczytać danych z HMC5883l]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=19262&amp;p=195763#p195763"><![CDATA[
Męczę się z tym problemem już od bardzo długiego czasu, więc postanowiłem wreszcie poszukać pomocy na forum. Mianowicie nie potrafię w żaden sposób sprawić by ten układ wysłał mi jakiekolwiek dane. Połączenie atmegi z kompasem jest poprawne ponieważ skaner wyszukuje jego adres:<br /><a href="https://obrazki.elektroda.pl/8893125400_1506272332.png"  class="postlink"><img src="https://obrazki.elektroda.pl/8893125400_1506272332_thumb.jpg" alt="Obrazek" /></a> <br /><br />Robiąc to bardziej ręcznie funkcjami z biblioteki też działa:<br /><a href="https://obrazki.elektroda.pl/8584918300_1506272686.png"  class="postlink"><img src="https://obrazki.elektroda.pl/8584918300_1506272686_thumb.jpg" alt="Obrazek" /></a><a href="https://obrazki.elektroda.pl/4676763000_1506272694.png"  class="postlink"><img src="https://obrazki.elektroda.pl/4676763000_1506272694_thumb.jpg" alt="Obrazek" /></a><br /><br />Problem zaczyna się gdy chce coś odczytać z jakiegoś rejestru:<br /><a href="https://obrazki.elektroda.pl/3598459000_1506273305.png"  class="postlink"><img src="https://obrazki.elektroda.pl/3598459000_1506273305_thumb.jpg" alt="Obrazek" /></a><a href="https://obrazki.elektroda.pl/3763876700_1506273313.png"  class="postlink"><img src="https://obrazki.elektroda.pl/3763876700_1506273313_thumb.jpg" alt="Obrazek" /></a> Program zawiesza się czekając na dane, mimo że według dokumentacji powinien odczytać 0x20.<br /><br />Nie wiem co mogę zrobić, projekt bez tego stoi w miejscu. Program napisałem najbardziej prosty jak się da. Nie mam analizatora żeby sprawdzić co się dzieje na liniach ale pewnie niczego nowego by to nie wniosło. Na dole podaje kod biblioteki, ale wątpie że jest to jej wina ponieważ obsługiwała wcześniej RTC bez problemu. Błagam o pomoc bo już nie mam na to dziadostwo siły.<br /><br />[syntax=c]/*************************************************************************<br />* Title: I2C master library using hardware TWI interface<br />* Author: Peter Fleury &lt;pfleury@gmx.ch&gt; http://jump.to/fleury<br />* File: $Id: twimaster.c,v 1.4 2015/01/17 12:16:05 peter Exp $<br />* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3<br />* Target: any AVR device with hardware TWI <br />* Usage: API compatible with I2C Software Library i2cmaster.h<br />**************************************************************************/<br />#include &lt;inttypes.h&gt;<br />#include &lt;compat/twi.h&gt;<br />#include &quot;i2cmaster.h&quot;<br /><br />/* define CPU frequency in hz here if not defined in Makefile */<br />#ifndef F_CPU<br />#define F_CPU 16000000UL<br />#endif<br /><br />/* I2C clock in Hz */<br />#define SCL_CLOCK 100000L<br /><br /><br />/*************************************************************************<br />Initialization of the I2C bus interface. Need to be called only once<br />*************************************************************************/<br />void i2c_init(void)<br />{<br />/* initialize TWI clock: 100 kHz clock, TWPS = 0 =&gt; prescaler = 1 */<br /><br />TWSR = 0; /* no prescaler */<br />TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be &gt; 10 for stable operation */<br /><br />}/* i2c_init */<br /><br /><br />/*************************************************************************<br />Issues a start condition and sends address and transfer direction.<br />return 0 = device accessible, 1= failed to access device<br />*************************************************************************/<br />unsigned char i2c_start(unsigned char address)<br />{<br />uint8_t twst;<br /><br />// send START condition<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWSTA) | (1&lt;&lt;TWEN);<br /><br />// wait until transmission completed<br />while(!(TWCR &amp; (1&lt;&lt;TWINT)));<br /><br />// check value of TWI Status Register. Mask prescaler bits.<br />twst = TW_STATUS &amp; 0xF8;<br />if ( (twst != TW_START) &amp;&amp; (twst != TW_REP_START)) return 1;<br /><br />// send device address<br />TWDR = address;<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN);<br /><br />// wail until transmission completed and ACK/NACK has been received<br />while(!(TWCR &amp; (1&lt;&lt;TWINT)));<br /><br />// check value of TWI Status Register. Mask prescaler bits.<br />twst = TW_STATUS &amp; 0xF8;<br />if ( (twst != TW_MT_SLA_ACK) &amp;&amp; (twst != TW_MR_SLA_ACK) ) return 1;<br /><br />return 0;<br /><br />}/* i2c_start */<br /><br /><br />/*************************************************************************<br />Issues a start condition and sends address and transfer direction.<br />If device is busy, use ack polling to wait until device is ready<br /><br />Input: address and transfer direction of I2C device<br />*************************************************************************/<br />void i2c_start_wait(unsigned char address)<br />{<br />uint8_t twst;<br /><br /><br />while ( 1 )<br />{<br /> // send START condition<br /> TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWSTA) | (1&lt;&lt;TWEN);<br /><br />// wait until transmission completed<br />while(!(TWCR &amp; (1&lt;&lt;TWINT)));<br /><br />// check value of TWI Status Register. Mask prescaler bits.<br />twst = TW_STATUS &amp; 0xF8;<br />if ( (twst != TW_START) &amp;&amp; (twst != TW_REP_START)) continue;<br /><br />// send device address<br />TWDR = address;<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN);<br /><br />// wail until transmission completed<br />while(!(TWCR &amp; (1&lt;&lt;TWINT)));<br /><br />// check value of TWI Status Register. Mask prescaler bits.<br />twst = TW_STATUS &amp; 0xF8;<br />if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) <br />{  <br /> /* device busy, send stop condition to terminate write operation */<br /> TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN) | (1&lt;&lt;TWSTO);<br /> <br /> // wait until stop condition is executed and bus released<br /> while(TWCR &amp; (1&lt;&lt;TWSTO));<br /> <br /> continue;<br />}<br />//if( twst != TW_MT_SLA_ACK) return 1;<br />break;<br />}<br /><br />}/* i2c_start_wait */<br /><br /><br />/*************************************************************************<br />Issues a repeated start condition and sends address and transfer direction <br /><br />Input: address and transfer direction of I2C device<br /><br />Return: 0 device accessible<br />1 failed to access device<br />*************************************************************************/<br />unsigned char i2c_rep_start(unsigned char address)<br />{<br />return i2c_start( address );<br /><br />}/* i2c_rep_start */<br /><br /><br />/*************************************************************************<br />Terminates the data transfer and releases the I2C bus<br />*************************************************************************/<br />void i2c_stop(void)<br />{<br />/* send stop condition */<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN) | (1&lt;&lt;TWSTO);<br /><br />// wait until stop condition is executed and bus released<br />while(TWCR &amp; (1&lt;&lt;TWSTO));<br /><br />}/* i2c_stop */<br /><br /><br />/*************************************************************************<br />Send one byte to I2C device<br /><br />Input: byte to be transfered<br />Return: 0 write successful <br />1 write failed<br />*************************************************************************/<br />unsigned char i2c_write( unsigned char data )<br />{<br />uint8_t twst;<br /><br />// send data to the previously addressed device<br />TWDR = data;<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN);<br /><br />// wait until transmission completed<br />while(!(TWCR &amp; (1&lt;&lt;TWINT)));<br /><br />// check value of TWI Status Register. Mask prescaler bits<br />twst = TW_STATUS &amp; 0xF8;<br />if( twst != TW_MT_DATA_ACK) return 1;<br />return 0;<br /><br />}/* i2c_write */<br /><br /><br />/*************************************************************************<br />Read one byte from the I2C device, request more data from device <br /><br />Return: byte read from I2C device<br />*************************************************************************/<br />unsigned char i2c_readAck(void)<br />{<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN) | (1&lt;&lt;TWEA);<br />while(!(TWCR &amp; (1&lt;&lt;TWINT))); <br /><br />return TWDR;<br /><br />}/* i2c_readAck */<br /><br /><br />/*************************************************************************<br />Read one byte from the I2C device, read is followed by a stop condition <br /><br />Return: byte read from I2C device<br />*************************************************************************/<br />unsigned char i2c_readNak(void)<br />{<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN);<br />while(!(TWCR &amp; (1&lt;&lt;TWINT)));<br /><br />return TWDR;<br /><br />}/* i2c_readNak */[/syntax]<br />[syntax=c]#ifndef _I2CMASTER_H<br />#define _I2CMASTER_H<br />/************************************************************************* <br />* Title: C include file for the I2C master interface <br />* (i2cmaster.S or twimaster.c)<br />* Author: Peter Fleury &lt;pfleury@gmx.ch&gt;<br />* File: $Id: i2cmaster.h,v 1.12 2015/09/16 09:27:58 peter Exp $<br />* Software: AVR-GCC 4.x<br />* Target: any AVR device<br />* Usage: see Doxygen manual<br />**************************************************************************/<br /><br />/**<br />@file<br />@defgroup pfleury_ic2master I2C Master library<br />@code #include &lt;i2cmaster.h&gt; @endcode<br /><br />@brief I2C (TWI) Master Software Library<br /><br />Basic routines for communicating with I2C slave devices. This single master <br />implementation is limited to one bus master on the I2C bus. <br /><br />This I2c library is implemented as a compact assembler software implementation of the I2C protocol <br />which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).<br />Since the API for these two implementations is exactly the same, an application can be linked either against the<br />software I2C implementation or the hardware I2C implementation.<br /><br />Use 4.7k pull-up resistor on the SDA and SCL pin.<br /><br />Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module <br />i2cmaster.S to your target when using the software I2C implementation ! <br /><br />Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.<br /><br />@note <br />The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted <br />to GNU assembler and AVR-GCC C call interface.<br />Replaced the incorrect quarter period delays found in AVR300 with <br />half period delays. <br /><br />@author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury<br />@copyright (C) 2015 Peter Fleury, GNU General Public License Version 3<br /><br />@par API Usage Example<br />The following code shows typical usage of this library, see example test_i2cmaster.c<br /><br />@code<br /><br />#include &lt;i2cmaster.h&gt;<br /><br /><br />#define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet<br /><br />int main(void)<br />{<br />unsigned char ret;<br /><br />i2c_init(); // initialize I2C library<br /><br />// write 0x75 to EEPROM address 5 (Byte Write) <br />i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode<br />i2c_write(0x05); // write address = 5<br />i2c_write(0x75); // write value 0x75 to EEPROM<br />i2c_stop(); // set stop conditon = release bus<br /><br /><br />// read previously written value back from EEPROM address 5 <br />i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode<br /><br />i2c_write(0x05); // write address = 5<br />i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode<br /><br />ret = i2c_readNak(); // read one byte from EEPROM<br />i2c_stop();<br /><br />for(;;);<br />}<br />@endcode<br /><br />*/<br /><br /><br />/**@{*/<br /><br />#if (__GNUC__ * 100 + __GNUC_MINOR__) &lt; 304<br />#error &quot;This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !&quot;<br />#endif<br /><br />#include &lt;avr/io.h&gt;<br /><br />/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */<br />#define I2C_READ 1<br /><br />/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */<br />#define I2C_WRITE 0<br /><br /><br />/**<br />@brief initialize the I2C master interace. Need to be called only once <br />@return none<br />*/<br />extern void i2c_init(void);<br /><br /><br />/** <br />@brief Terminates the data transfer and releases the I2C bus <br />@return none<br />*/<br />extern void i2c_stop(void);<br /><br /><br />/** <br />@brief Issues a start condition and sends address and transfer direction <br /><br />@param addr address and transfer direction of I2C device<br />@retval 0 device accessible <br />@retval 1 failed to access device <br />*/<br />extern unsigned char i2c_start(unsigned char addr);<br /><br /><br />/**<br />@brief Issues a repeated start condition and sends address and transfer direction <br /><br />@param addr address and transfer direction of I2C device<br />@retval 0 device accessible<br />@retval 1 failed to access device<br />*/<br />extern unsigned char i2c_rep_start(unsigned char addr);<br /><br /><br />/**<br />@brief Issues a start condition and sends address and transfer direction <br /><br />If device is busy, use ack polling to wait until device ready <br />@param addr address and transfer direction of I2C device<br />@return none<br />*/<br />extern void i2c_start_wait(unsigned char addr);<br /><br /><br />/**<br />@brief Send one byte to I2C device<br />@param data byte to be transfered<br />@retval 0 write successful<br />@retval 1 write failed<br />*/<br />extern unsigned char i2c_write(unsigned char data);<br /><br /><br />/**<br />@brief read one byte from the I2C device, request more data from device <br />@return byte read from I2C device<br />*/<br />extern unsigned char i2c_readAck(void);<br /><br />/**<br />@brief read one byte from the I2C device, read is followed by a stop condition <br />@return byte read from I2C device<br />*/<br />extern unsigned char i2c_readNak(void);<br /><br />/** <br />@brief read one byte from the I2C device<br /><br />Implemented as a macro, which calls either @ref i2c_readAck or @ref i2c_readNak<br /><br />@param ack 1 send ack, request more data from device&lt;br&gt;<br />0 send nak, read is followed by a stop condition <br />@return byte read from I2C device<br />*/<br />extern unsigned char i2c_read(unsigned char ack);<br />#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak(); <br /><br /><br /><br />/**@}*/<br />#endif[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=8721">resonator</a> — 24 wrz 2017, o 18:31</p><hr />
]]></content>
</entry>
</feed>