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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2016-01-11T18:40:11+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=58&amp;t=7390&amp;mode</id>
<entry>
<author><name><![CDATA[mkk13]]></name></author>
<updated>2016-01-11T18:40:11+01:00</updated>
<published>2016-01-11T18:40:11+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=150273#p150273</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=150273#p150273"/>
<title type="html"><![CDATA[Re: Pierwszy bardziej zaawansowany projekcik - Termostat z L]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=150273#p150273"><![CDATA[
Podłączyłem ekran LCD PCD8544.<br />Podłączenie wygląda tak:<br /><a href="https://obrazkiforum.atnel.pl/11698/4bde899cdc49ca425fe40f27df7c5367.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/11698/4bde899cdc49ca425fe40f27df7c5367.png" alt="Obrazek" /></a><br />PCD8544 podłączone:<br />RST - RES<br />CE - SCE<br />DC - D/C<br />DIN - SDIN<br />CLK - SCLK<br />VCC - VDD<br />BL - VOUT<br />GND - GND<br /><br />Program wygląda następująco:<br /><strong>lcd.c:</strong><br />[syntax=c]/*<br />    Plik lcd.c<br /><br />    LCD od nokia 3310 przykład 4<br />    KURS AVR-GCC (www.abxyz.bplaced.net)  <br /><br />    testowane na atmega88 (8MHz)<br />*/<br />#include &lt;stdio.h&gt;<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &quot;lcd.h&quot;<br /><br /><br /><br />// Inicjuje wyświetlacz<br />void lcd_init(void)<br />{<br />    LCD_RST_CLR; <br /><br />    LCD_RST_SET_OUT<br />    LCD_CLK_SET_OUT<br />    LCD_DATA_SET_OUT <br />    LCD_DC_SET_OUT<br />    LCD_CE_SET_OUT<br /><br /><br />   //   &lt; 30ms<br />    _delay_ms(15);    <br />    <br />    LCD_RST_SET<br /><br />    LCD_CE_SET<br /><br />    lcd_write_byte(LCD_CMD, 0x21); // Function set - extended instruction set<br />    lcd_write_byte(LCD_CMD, 0x13); // Bias - 1:48<br />    lcd_write_byte(LCD_CMD, 0x06); // Temperature Control<br />    lcd_write_byte(LCD_CMD, 0xA5); // Set Vop<br />    lcd_write_byte(LCD_CMD, 0x20); // Function set - basic instruction set, horizontal addressing<br />    lcd_write_byte(LCD_CMD, 0x0C); // Display control - normal mode <br />}<br /><br /><br />// Wysyła do LCD jeden bajt<br />// c_d: LCD_DATA|LCD_CMD<br />void lcd_write_byte(unsigned char c_d, unsigned char data )<br />{<br />    unsigned char m; <br /><br />    LCD_CE_CLR<br /><br />    if(c_d) LCD_DC_SET else LCD_DC_CLR<br /><br />    for(m=0x80; m; m&gt;&gt;=1)<br />    {<br />       if(data &amp; m)<br />          LCD_DATA_SET <br />       else <br />          LCD_DATA_CLR <br /><br />       LCD_CLK_SET<br />       LCD_NOP<br />       LCD_CLK_CLR<br />    }<br /><br />    LCD_CE_SET<br />}<br /><br /> <br />//   Wyświetla obrazek<br />//   img - dane obrazka<br />//   x   - pierwsza kolumna  0..84(96)<br />//   y   - pierwszy wiersz   0..5(7)<br />//   w   - szerokość obrazka 0..84(96)<br />//   h   - wysokość obrazka  0..5(7)<br />void lcd_image(unsigned char img&#91;&#93;,char  x, char y, char w, char h)<br />{     <br />   unsigned int i,j,k;<br />    <br />   for(i=0,j=0,k=0; i&lt;h; i++)   <br />   {  <br />   // Ustawia położenia lewego górnego robu obrazka na ekranie LCD<br />      lcd_write_byte(LCD_CMD, LCD_SETY|(i+y));<br />      lcd_write_byte(LCD_CMD, LCD_SETX|(x));<br /><br />    // Kopiuje dane obrazka z FLASH do pamięci obrazu LCD<br />      for(j=0; j&lt;w ; j++,k++)<br />          lcd_write_byte(LCD_DATA, pgm_read_byte(&amp;img&#91;k&#93;));<br />   } <br />}[/syntax]<br /><strong>lcd.h:</strong><br />[syntax=c]/*<br />    Plik &quot;lcd.h&quot;<br /><br />    LCD od nokia3310 przykład 4<br />    KURS AVR-GCC www.abxyz.bplaced.net<br /><br />    testowane na atmega88 (8MHz) <br />*/<br /><br />#ifndef PCD8544_H<br />#define PCD8544_H<br /><br /><br />// Użycie sprzętowego interfejsu SPI <br />#define ATMEGA_SPI 1<br /><br />//<br />#define LCD_X 84<br />#define LCD_Y 6<br /><br /><br />// CLK<br />#define LCD_CLK_SET       PORTB |=  (1&lt;&lt;PB5);<br />#define LCD_CLK_CLR       PORTB &amp;= ~(1&lt;&lt;PB5);<br />#define LCD_CLK_SET_OUT   DDRB  |=  (1&lt;&lt;PB5);<br />// DATA<br />#define LCD_DATA_SET      PORTB |=  (1&lt;&lt;PB3);<br />#define LCD_DATA_CLR      PORTB &amp;= ~(1&lt;&lt;PB3);<br />#define LCD_DATA_SET_OUT  DDRB  |=  (1&lt;&lt;PB3);<br />// DC<br />#define LCD_DC_SET        PORTB |=  (1&lt;&lt;PB1);<br />#define LCD_DC_CLR        PORTB &amp;= ~(1&lt;&lt;PB1);<br />#define LCD_DC_SET_OUT    DDRB  |=  (1&lt;&lt;PB1);<br />// CE<br />#define LCD_CE_SET        PORTB |=  (1&lt;&lt;PD7);<br />#define LCD_CE_CLR        PORTB &amp;= ~(1&lt;&lt;PD7);<br />#define LCD_CE_SET_OUT    DDRB  |=  (1&lt;&lt;PD7);<br />// RST<br />#define LCD_RST_SET       PORTB |=  (1&lt;&lt;PB0);<br />#define LCD_RST_CLR       PORTB &amp;= ~(1&lt;&lt;PB0);<br />#define LCD_RST_SET_OUT   DDRB  |=  (1&lt;&lt;PB0);<br /><br /><br />#define LCD_NOP           asm volatile(&quot;nop\n\t&quot;&quot;nop\n\t&quot; &quot;nop\n\t&quot; &quot;nop\n\t&quot; &quot;nop\n\t&quot; &quot;nop\n\t&quot; &quot;nop\n\t&quot; &quot;nop\n\t&quot; ::);<br /><br />#define LCD_CMD           0<br />#define LCD_DATA          1<br /><br />// INSTRUCTION - FUNCTION SET<br />#define LCD_FUNCTIONSET   0x20<br />#define LCD_FUNC_PD(x)    LCD_FUNCTIONSET | ((x) &lt;&lt; 2)   // Function set - chip is active(0)/powered-down(1)<br />#define LCD_FUNC_V(x)     LCD_FUNCTIONSET | ((x) &lt;&lt; 1)   // Function set - horizontal(0)/vertical(1) addressing<br />#define LCD_FUNC_H(x)     LCD_FUNCTIONSET | (x)          // Function set - basic(0)/extended(1) instruction set<br /><br />#define LCD_SETX          0x80   <br />#define LCD_SETY          0x40 <br /><br />#define LCD_GOTO_HOME     lcd_write_byte(LCD_CMD, LCD_SETY);lcd_write_byte(LCD_CMD, LCD_SETX);<br />#define LCD_GOTO(x,y)     lcd_write_byte(LCD_CMD, LCD_SETY|(y));lcd_write_byte(LCD_CMD, LCD_SETX|(x));<br /><br />void lcd_init(void);<br />void lcd_clear(void);<br />void lcd_write_byte( unsigned char, unsigned char );<br />void lcd_text(char &#91;&#93;, unsigned char , unsigned char );<br />void lcd_image(unsigned char &#91;&#93;,char , char , char , char );<br /><br /><br />#endif[/syntax]<br /><strong>main.c:</strong><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;util/crc16.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &quot;ds18b20.h&quot;<br />#include &quot;lcd.h&quot;<br /><br />// Obrazek z cyferkami dla wska¼nika cyfrowego<br />const unsigned char digits8x16&#91;&#93; PROGMEM = {<br />#include &quot;dig8x16.h&quot;<br />};<br /><br />// Obrazek z t³em<br />const unsigned char screen&#91;&#93; PROGMEM = {<br />#include &quot;screen.h&quot;<br />};<br /><br />volatile unsigned char odb_x;       //odebrana liczba X<br />volatile unsigned char odb_flaga =0;//flaga informujaca main o odebraniu liczby<br />volatile unsigned char wys_flaga =0;<br />#define IS_RELAY_ON PIND &amp; (1 &lt;&lt; PD2)<br />//bufor znaków ze wzorem funkcji, który wysylamy po starcie programu<br />volatile unsigned int usart_bufor_ind;           //indeks bufora nadawania<br />char usart_bufor&#91;30&#93; = &quot;Odbiornik test START&quot;;<br /><br />//<br />unsigned char tab&#91;8&#93;;<br /><br />// 9 bajtów odczytanych z ds18b20<br />unsigned char ds18b20_pad&#91;9&#93;;<br /><br />void usart_inicjuj(void)<br />{<br /> //definiowanie parametrów transmisji za pomoca makr zawartych w pliku<br /> //naglówkowym setbaud.h. Jezeli wybierzesz predkosc, która nie bedzie<br /> //mozliwa do realizacji otrzymasz ostrzezenie:<br /> //#warning &quot;Baud rate achieved is higher than allowed&quot;<br /><br />#define BAUD 9600<br />#include &lt;util/setbaud.h&gt;<br />UBRR0H = UBRRH_VALUE;<br />UBRR0L = UBRRL_VALUE;<br />#if USE_2X<br />UCSR0A |= (1 &lt;&lt; U2X0);<br />#else<br />UCSR0A &amp;= ~(1 &lt;&lt; U2X0);<br />#endif<br />// Enable receiver and transmitter<br />UCSR0B = (1&lt;&lt;RXEN0)| (1&lt;&lt;TXEN0) | (1&lt;&lt;RXCIE0);<br />// Set frame format: 8data, 2stop bit<br />UCSR0C = (1&lt;&lt;UCSZ00) | (1&lt;&lt;UCSZ01);<br />}<br /><br /><br />//--------------------------------------------------------------<br /><br /><br />ISR(USART_RX_vect)<br />{<br /> //przerwanie generowane po odebraniu bajtu<br /> odb_x = UDR0;   //zapamietaj odebrana liczbe<br /> odb_flaga = 1; //ustaw flage odbioru liczby dla main()<br />}<br /><br /><br />//--------------------------------------------------------------<br /><br />ISR(USART_UDRE_vect){<br /><br /> //przerwanie generowane, gdy bufor nadawania jest juz pusty,<br /> //odpowiedzialne za wyslanie wszystkich znaków z tablicy usart_bufor&#91;&#93;<br /><br /> //sprawdzamy, czy bajt do wyslania jest znakiem konca tekstu, czyli zerem<br /> if(usart_bufor&#91;usart_bufor_ind&#93;!= 0){<br /><br />  //zaladuj znak do rejestru wysylki i ustaw indeks na nastepny znak<br />  UDR0 = usart_bufor&#91;usart_bufor_ind++&#93;;<br /><br /> }else{<br /><br />  //osiagnieto koniec napisu w tablicy usart_bufor&#91;&#93;<br />  UCSR0B &amp;= ~(1&lt;&lt;UDRIE0); //wylacz przerwania pustego bufora nadawania<br />  wys_flaga = 1;<br /> }<br />}<br /><br /><br />//--------------------------------------------------------------<br /><br /><br />void wyslij_wynik(void){<br /><br /> //funkcja rozpoczyna wysylanie, wysylajac pierwszy znak znajdujacy sie<br /> //w tablicy usart_bufor&#91;&#93;. Pozostale wysle funkcja przerwania,<br /> //która zostanie wywolana automatycznie po wyslaniu kazdego znaku.<br /><br /> //dodaj do tekstu wyniku znaki konca linii (CR+LF), by na<br /> //ekranie terminala wyniki pojawialy sie w nowych liniach<br />unsigned char z;<br />wys_flaga = 0;<br />for(z=0; z&lt;30; z++)<br />{<br />if(usart_bufor&#91;z&#93;==0)<br />{   //czy to koniec takstu w tablicy<br />usart_bufor&#91;z&#93;   = 13;  //znak powrotu karetki CR (Carrige Return)<br />usart_bufor&#91;z+1&#93;  = 10; //znak nowej linii LF (Line Feed)<br />usart_bufor&#91;z+2&#93;  = 0;  //znak konca ciagu tekstu w tablicy<br />break;<br />}<br />}<br /><br /><br /> //Zaczekaj, az bufor nadawania bedzie pusty<br />while (!(UCSR0A &amp; (1&lt;&lt;UDRE0)));<br /><br /> //bufor jest pusty mozna wyslac<br /><br /> //nastepny znak do wysylki to znak nr 1<br />usart_bufor_ind = 0;<br /><br /> //wlacz przerwania pustego bufora UDR, co rozpocznie transmisje<br /> //aktualnej zawartosci bufora<br />UCSR0B |= (1&lt;&lt;UDRIE0);<br /><br />}<br /><br /><br />// MAIN <br />int main(void)<br />{<br />   unsigned int  crc = 0;<br />   unsigned char i;<br /><br />   int t; // wartość temperatury * 16<br />   usart_inicjuj(); //inicjuj modul USART (RS-232)<br />   lcd_init();<br /><br />   sei();<br />   wyslij_wynik();<br />   while (!wys_flaga);<br /><br /><br />   lcd_image(screen,0,0,84,6);<br /><br />while(1)<br />{<br />if(odb_flaga)<br />if(ds18b20_ConvertT())<br />{<br />sprintf(usart_bufor, &quot;Temp Conversion.&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br />// Zatrzymuje do czasu zakończenia pomiaru<br />while(!OneWireReadTimeSlot());<br /><br />sprintf(usart_bufor, &quot;Read Temp.&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br />// Odczyt danych z ds18b20<br />ds18b20_Read(ds18b20_pad);<br />sprintf(usart_bufor, &quot;Check CRC.&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br />// Oblicza sumę kontrolną CRC danych odczytanych z ds18b20<br />for (i = 0, crc =0; i &lt; 9; i++)<br />crc = _crc_ibutton_update(crc, ds18b20_pad&#91;i&#93;);<br /><br />// Jeśli suma kontrolna się zgadza,<br />// pokazuje nowe wyniki pomiaru<br />if(!crc)<br />{<br />sprintf(usart_bufor, &quot;CRC OK!&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br />// Zmienna &quot;t&quot; zawiera wartość temperatury * 16<br />t = ((ds18b20_pad&#91;0&#93; &gt;&gt; 1) - 0.25) + (ds18b20_pad&#91;7&#93; - ds18b20_pad&#91;6&#93;)/ds18b20_pad&#91;7&#93;;<br />sprintf(usart_bufor, &quot;TEMP: %d&quot;, t);<br />wyslij_wynik();<br />while (!wys_flaga);<br />} else<br />{<br />sprintf(usart_bufor, &quot;CRC BAD.&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br />}<br />odb_flaga = 0;<br />}<br />}<br /><br />       return 0;<br />}[/syntax]<br /><br />Niestety po odpaleniu Atmegi na ekranie nic się nie dzieje - a powinien widnieć elegancki ekranik.<br /><strong>Kod ekraniku:</strong><br />[syntax=c]0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x02,0x02,0x02,0xfe,0xfe,0x02,0x02,0x02,0x00,0xf8,0xf8,0x88,0x88,0x08,<br />0x00,0x00,0xf8,0xf8,0x30,0x60,0xc0,0x60,0x30,0xf8,0xf8,0x00,0x00,0xf8,0xf8,0x08,<br />0x08,0xf8,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x42,0x02,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,<br />0x0f,0x08,0x08,0x08,0x00,0x00,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,<br />0x00,0x0f,0x0f,0x01,0x01,0x01,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0x08,0x08,0x00,0x22,<br />0x21,0x29,0x36,0x00,0x1e,0x21,0x21,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff,<br />0x21,0x20,0x00,0x88,0xc4,0xa4,0x98,0x00,0x78,0x84,0x84,0x78,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,<br />0x00,0x00,0x00,0xff,0x84,0x80,0x00,0x40,0x20,0xf0,0x00,0xe0,0x10,0x10,0xe0,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x10,0x10,0x68,0x86,0x00,0x00,<br />0x78,0x80,0x80,0x80,0x78,0x00,0x00,0xf0,0x08,0x08,0x08,0x00,0x90,0xa8,0xa8,0x68,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0xff,0x80,0x80,0x80,0xff,0x10,0x00,0x00,0x00,0x00,0x03,0x00,0x81,<br />0x42,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0xfc,0x22,0x22,0x22,0xfc,0x00,0x3e,0x40,0x80,0x40,0x3e,0x00,<br />0xfe,0x12,0x32,0x52,0x8c,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x7c,0x82,0x82,0x92,<br />0xf4,0x00,0x7c,0x82,0x82,0x82,0x44,0x00,0x7c,0x82,0x82,0x82,0x44,0x00,0x00,0x00,<br />0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x42,0x02,0x02,0x00,<br />0x00,0x00,0x00,0x07,0x08,0x08,0x07,0x00[/syntax]<br /><br />Jakieś propozycje co można sprawdzić?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=11698">mkk13</a> — 11 sty 2016, o 18:40</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mkk13]]></name></author>
<updated>2016-01-10T22:27:19+01:00</updated>
<published>2016-01-10T22:27:19+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=150215#p150215</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=150215#p150215"/>
<title type="html"><![CDATA[Re: Pierwszy bardziej zaawansowany projekcik - Termostat z L]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=150215#p150215"><![CDATA[
Witam,<br /><br />Zamiast zakładać własny temat, uznałem że kontynuuję ten, bo bardzo dobrze oddaje i moją sytuację.<br />Atmega88PA-PU, USART działa i korzystam w celu debug'u. Wykorzystany termometr to <a href="http://pl.farnell.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=15001&amp;langId=-22&amp;urlRequestType=Base&amp;partNumber=9724770&amp;storeId=10170"  class="postlink">DS18S20Z+ od Maxima</a>.<br />Atmega działa póki co na 1MHz.<br /><br />Kod wygląda następująco:<br /><strong>ds18b20.h</strong><br />[syntax=c]#ifndef DS18B20_H<br />#define DS18B20_H<br /><br />// DS18B20 przyłączony do portu  PD7 AVRa<br />#define SET_ONEWIRE_PORT     PORTC  |=  _BV(PC5)<br />#define CLR_ONEWIRE_PORT     PORTC  &amp;= ~_BV(PC5)<br />#define IS_SET_ONEWIRE_PIN   PINC   &amp;   _BV(PC5)<br />#define SET_OUT_ONEWIRE_DDR  DDRC   |=  _BV(PC5)<br />#define SET_IN_ONEWIRE_DDR   DDRC   &amp;= ~_BV(PC5)<br />#define CMD_CONVERT_T        0x44<br />#define CMD_SKIP_ROM         0xCC<br />#define CMD_READ_SCRATCH     0xBE<br /><br /><br />char ds18b20_ConvertT(void);<br />char ds18b20_Read(unsigned char &#91;&#93;);<br />void OneWireStrong(char);<br />unsigned char OneWireReset(void);<br />void OneWireWriteByte(unsigned char);<br />unsigned char OneWireReadByte(void);<br />unsigned char OneWireReadTimeSlot(void);<br /><br /><br />#endif[/syntax]<br /><br /><strong>ds18b20.c</strong><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &quot;ds18b20.h&quot;<br /><br /><br /><br /><br />/**********************************************************/<br /><br />char ds18b20_ConvertT(void)<br />{<br />  if (!OneWireReset()) return 0;<br /><br />  OneWireWriteByte(CMD_SKIP_ROM);<br />  OneWireWriteByte(CMD_CONVERT_T);<br /><br />  return 0xff;<br />}<br /><br />/***********************************************************/<br /><br />char ds18b20_Read(unsigned char scratchpad&#91;&#93;)<br />{<br />  unsigned char i;<br /><br />  if (!OneWireReset()) return 0;<br /><br />  OneWireWriteByte(CMD_SKIP_ROM);<br />  OneWireWriteByte(CMD_READ_SCRATCH);<br /><br />  for(i=0; i&lt;10; i++) scratchpad&#91;i&#93; = OneWireReadByte();<br /> <br />  return 0xff;<br />}<br /><br />/**********************************************************/<br /><br />void OneWireStrong(char s)<br />{<br />  if (s)<br />  {<br />     SET_ONEWIRE_PORT; <br />     SET_OUT_ONEWIRE_DDR; <br />  }<br />  else<br />  {<br />     SET_IN_ONEWIRE_DDR; <br />  }<br />}<br /><br />/**********************************************************/<br /><br />unsigned char OneWireReset()<br />{<br />   SET_IN_ONEWIRE_DDR; <br />  CLR_ONEWIRE_PORT; <br /><br />  if (!(IS_SET_ONEWIRE_PIN)) return 0;  <br /><br />  SET_OUT_ONEWIRE_DDR; <br />  _delay_us(500);<br />  SET_IN_ONEWIRE_DDR; <br />  _delay_us(70);<br /><br />  if(!(IS_SET_ONEWIRE_PIN))<br />  {<br />    _delay_us(500);<br />    return(1);<br />  }<br /><br />  _delay_us(500);<br /><br />return(0);<br />}<br /><br />/**********************************************************/<br /><br />void OneWireWriteByte(unsigned char byte)<br />{<br />   unsigned char i;<br /><br />   SET_IN_ONEWIRE_DDR; <br />   CLR_ONEWIRE_PORT; <br /><br />   for (i=0; i&lt;8; i++)<br />   {<br />     SET_OUT_ONEWIRE_DDR; <br /><br />     if (byte &amp; 0x01)<br />     {<br />       _delay_us(7);<br />       SET_IN_ONEWIRE_DDR; <br />       _delay_us(70);<br />     }<br />     else<br />     {<br />        _delay_us(70);<br />        SET_IN_ONEWIRE_DDR; <br />        _delay_us(7);<br />     }<br /><br />     byte &gt;&gt;= 1;<br />   }<br />}<br /><br />/***********************************************************/<br /><br />unsigned char OneWireReadByte(void)<br />{<br />  unsigned char i, byte = 0;<br /><br />  CLR_ONEWIRE_PORT; <br />  SET_IN_ONEWIRE_DDR; <br />  <br />  for (i=0; i&lt;8; i++)<br />  {<br />     SET_OUT_ONEWIRE_DDR; <br />     _delay_us(7);<br />     SET_IN_ONEWIRE_DDR; <br />     _delay_us(7);<br />     byte &gt;&gt;= 1;<br />     <br />     if(IS_SET_ONEWIRE_PIN) byte |= 0x80;<br /><br />     _delay_us(70);<br />  }<br /><br />  return byte;<br />}<br /><br />/***********************************************************/<br /><br />unsigned char OneWireReadTimeSlot(void)<br />{<br />   unsigned char  byte = 0;<br /><br />   CLR_ONEWIRE_PORT; <br />   SET_IN_ONEWIRE_DDR; <br />  <br />   SET_OUT_ONEWIRE_DDR; <br />   _delay_us(7);<br />   SET_IN_ONEWIRE_DDR; <br />   _delay_us(7);<br />   <br />   if(IS_SET_ONEWIRE_PIN) byte = 0xff;<br />   _delay_us(70);<br /><br />  return byte;<br />}[/syntax]<br /><br /><strong>main.c</strong><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;util/crc16.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &quot;ds18b20.h&quot;<br /><br /><br />volatile unsigned char odb_x;       //odebrana liczba X<br />volatile unsigned char odb_flaga =0;//flaga informujaca main o odebraniu liczby<br />volatile unsigned char wys_flaga =0;<br />#define IS_RELAY_ON PIND &amp; (1 &lt;&lt; PD2)<br />//bufor znaków ze wzorem funkcji, który wysylamy po starcie programu<br />volatile unsigned int usart_bufor_ind;           //indeks bufora nadawania<br />char usart_bufor&#91;30&#93; = &quot;Odbiornik test START&quot;;<br /><br />//<br />unsigned char tab&#91;8&#93;;<br /><br />// 9 bajtów odczytanych z ds18b20<br />unsigned char ds18b20_pad&#91;9&#93;;<br /><br />void usart_inicjuj(void)<br />{<br /> //definiowanie parametrów transmisji za pomoca makr zawartych w pliku<br /> //naglówkowym setbaud.h. Jezeli wybierzesz predkosc, która nie bedzie<br /> //mozliwa do realizacji otrzymasz ostrzezenie:<br /> //#warning &quot;Baud rate achieved is higher than allowed&quot;<br /><br />#define BAUD 9600<br />#include &lt;util/setbaud.h&gt;<br />UBRR0H = UBRRH_VALUE;<br />UBRR0L = UBRRL_VALUE;<br />#if USE_2X<br />UCSR0A |= (1 &lt;&lt; U2X0);<br />#else<br />UCSR0A &amp;= ~(1 &lt;&lt; U2X0);<br />#endif<br />// Enable receiver and transmitter<br />UCSR0B = (1&lt;&lt;RXEN0)| (1&lt;&lt;TXEN0) | (1&lt;&lt;RXCIE0);<br />// Set frame format: 8data, 2stop bit<br />UCSR0C = (1&lt;&lt;UCSZ00) | (1&lt;&lt;UCSZ01);<br />}<br /><br /><br />//--------------------------------------------------------------<br /><br /><br />ISR(USART_RX_vect)<br />{<br /> //przerwanie generowane po odebraniu bajtu<br /> odb_x = UDR0;   //zapamietaj odebrana liczbe<br /> odb_flaga = 1; //ustaw flage odbioru liczby dla main()<br />}<br /><br /><br />//--------------------------------------------------------------<br /><br />ISR(USART_UDRE_vect){<br /><br /> //przerwanie generowane, gdy bufor nadawania jest juz pusty,<br /> //odpowiedzialne za wyslanie wszystkich znaków z tablicy usart_bufor&#91;&#93;<br /><br /> //sprawdzamy, czy bajt do wyslania jest znakiem konca tekstu, czyli zerem<br /> if(usart_bufor&#91;usart_bufor_ind&#93;!= 0){<br /><br />  //zaladuj znak do rejestru wysylki i ustaw indeks na nastepny znak<br />  UDR0 = usart_bufor&#91;usart_bufor_ind++&#93;;<br /><br /> }else{<br /><br />  //osiagnieto koniec napisu w tablicy usart_bufor&#91;&#93;<br />  UCSR0B &amp;= ~(1&lt;&lt;UDRIE0); //wylacz przerwania pustego bufora nadawania<br />  wys_flaga = 1;<br /> }<br />}<br /><br /><br />//--------------------------------------------------------------<br /><br /><br />void wyslij_wynik(void){<br /> //dodaj do tekstu wyniku znaki konca linii (CR+LF), by na<br /> //ekranie terminala wyniki pojawialy sie w nowych liniach<br />unsigned char z;<br />wys_flaga = 0;<br />for(z=0; z&lt;30; z++)<br />{<br />if(usart_bufor&#91;z&#93;==0)<br />{   //czy to koniec takstu w tablicy<br />usart_bufor&#91;z&#93;   = 13;  //znak powrotu karetki CR (Carrige Return)<br />usart_bufor&#91;z+1&#93;  = 10; //znak nowej linii LF (Line Feed)<br />usart_bufor&#91;z+2&#93;  = 0;  //znak konca ciagu tekstu w tablicy<br />break;<br />}<br />}<br /><br /><br /> //Zaczekaj, az bufor nadawania bedzie pusty<br />while (!(UCSR0A &amp; (1&lt;&lt;UDRE0)));<br /><br /> //bufor jest pusty mozna wyslac<br /><br /> //nastepny znak do wysylki to znak nr 1<br />usart_bufor_ind = 0;<br /><br /> //wlacz przerwania pustego bufora UDR, co rozpocznie transmisje<br /> //aktualnej zawartosci bufora<br />UCSR0B |= (1&lt;&lt;UDRIE0);<br /><br />}<br /><br /><br />// MAIN <br />int main(void)<br />{<br />   unsigned int  crc = 0;<br />   unsigned char i;<br /><br />   int t; // wartość temperatury * 16<br />   usart_inicjuj(); //inicjuj modul USART (RS-232)<br />   sei();<br />   wyslij_wynik();<br />   while (!wys_flaga);<br /><br />while(1)<br />{<br />if(odb_flaga)<br />if(ds18b20_ConvertT())<br />{<br />sprintf(usart_bufor, &quot;Temp Conversion.&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br /><br />// Zatrzymuje do czasu zakończenia pomiaru<br />while(!OneWireReadTimeSlot());<br /><br />sprintf(usart_bufor, &quot;Read Temp.&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br /><br />// Odczyt danych z ds18b20<br />ds18b20_Read(ds18b20_pad);<br /><br />sprintf(usart_bufor, &quot;Check CRC.&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br /><br />// Oblicza sumę kontrolną CRC danych odczytanych z ds18b20<br />for (i = 0, crc =0; i &lt; 9; i++)<br />crc = _crc_ibutton_update(crc, ds18b20_pad&#91;i&#93;);<br /><br />// Jeśli suma kontrolna się zgadza,<br />// pokazuje nowe wyniki pomiaru<br />if(!crc)<br />{<br />sprintf(usart_bufor, &quot;CRC OK!&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br /><br />// Zmienna &quot;t&quot; zawiera wartość temperatury<br />t = ((ds18b20_pad&#91;0&#93; &gt;&gt; 1) - 0.25) + (ds18b20_pad&#91;7&#93; - ds18b20_pad&#91;6&#93;)/ds18b20_pad&#91;7&#93;;<br /><br />sprintf(usart_bufor, &quot;TEMP: %d&quot;, t);<br />wyslij_wynik();<br />while (!wys_flaga);<br />} else<br />{<br />sprintf(usart_bufor, &quot;CRC BAD.&quot;);<br />wyslij_wynik();<br />while (!wys_flaga);<br />}<br />odb_flaga = 0;<br />}<br />}<br /><br />       return 0;<br />}[/syntax]<br /><br />Kod powinien:<br />-na samym początku przez USART przesłać napis [DZIAŁA]<br />-po odebraniu sygnału przez USART odpalić pętlę mierzenia temperatury [DZIAŁA]<br />-wypisać zmierzoną temperaturę [DZIAŁA]<br />-temperatura mogłaby być poprawna...[NIE DZIAŁA]<br /><br />Niestety w RealTermie dostaję informację, że temperatura wynosi 3 stopnie...siedzę w podkoszulku i zapewniam Was, że tak nie jest. Płytka jest niedaleko wiatraka od komputera...ale nie dość, że nie wieje centralnie na nią, to jeszcze temperatura również się nie zgadza <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" />.<br /><br />Wrzucam jeszcze schemat gdzie widać jak podłączona jest Atmega do zasilania oraz termometru:<br /><a href="https://obrazkiforum.atnel.pl/11698/47d8b104aa4277e85abaf6ffd89c6405.jpg"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/11698/47d8b104aa4277e85abaf6ffd89c6405.jpg" alt="Obrazek" /></a><br /><br /><strong><span style="color: #808000">------------------------ [ Dodano po: 57 minutach ]</span></strong><br /><br /><div class="quotetitle">mkk13 napisał(a):</div><div class="quotecontent"><br />Witam,<br /><br />Zamiast zakładać własny temat, uznałem że kontynuuję ten, bo bardzo dobrze oddaje i moją sytuację.<br />Atmega88PA-PU, USART działa i korzystam w celu debug'u. Wykorzystany termometr to <a href="http://pl.farnell.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=15001&amp;langId=-22&amp;urlRequestType=Base&amp;partNumber=9724770&amp;storeId=10170"  class="postlink">DS18S20Z+ od Maxima</a>.<br />Atmega działa póki co na 1MHz.<br /><br />Kod wygląda następująco:<br /><em>(...)</em><br /></div><br />Problem rozwiązałem. O dziwo za szybko zgarniałem temperaturę i termometr nie wyrabiał z zapisem.<br />Jako że nie jest zasilany pasożytniczo, to mogę nasłuchiwać na porcie, aż oznajmi kiedy zakończy konwersję temperatury.<br /><strong>Zmiana w pliku ds18b20.c:</strong><br />[syntax=c]char ds18b20_ConvertT(void)<br />{<br />    if (!OneWireReset()) return 0;<br /><br />    OneWireWriteByte(CMD_SKIP_ROM);<br />    OneWireWriteByte(CMD_CONVERT_T);<br />    // FIX:<br />    SET_IN_ONEWIRE_DDR;<br />    while(!(IS_SET_ONEWIRE_PIN));<br /><br />    return 0xff;<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=11698">mkk13</a> — 10 sty 2016, o 22:27</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[majster]]></name></author>
<updated>2014-08-23T18:58:56+01:00</updated>
<published>2014-08-23T18:58:56+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=92607#p92607</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=92607#p92607"/>
<title type="html"><![CDATA[Re: Pierwszy bardziej zaawansowany projekcik - Termostat z L]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=92607#p92607"><![CDATA[
Bardzo fajny projekcik i lcd godne uwagi.<br /><br /><br /><br />Namazane ze smarta.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1628">majster</a> — 23 sie 2014, o 18:58</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[ashi]]></name></author>
<updated>2014-08-23T18:15:36+01:00</updated>
<published>2014-08-23T18:15:36+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=92599#p92599</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=92599#p92599"/>
<title type="html"><![CDATA[Re: Pierwszy bardziej zaawansowany projekcik - Termostat z L]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=92599#p92599"><![CDATA[
Witam,<br />to mój pierwszy post na forum więc serdecznie wszystkich witam. <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />Mnie do stworzenia termostatu zmusiła sytuacja. Okazyjnie zakupiłem nastoletnią chłodziarkę przemysłową Vestfrost, taka sklepowa lodówka na napoje. Okazało się, że temperatura chłodzenia jest zbyt niska i nawet wbudowany termostat z regulacją nie był w stanie zapewnić oczekiwanych warunków pracy - od 10 do 15°C. Poza tym wentylator wymuszający obieg powietrza pracuje ciągle, co uważam za niedopuszczalne - z uwagi na hałas oraz nieefektywną wymianę powietrza (i ciepła). Stąd pomysł na termostat oparty o mikrokontroler.<br /><br />Kiedyś miałem styczność z BASCOMem, choć na co dzień działam w PHP. Znalazłem stronę Pana Mirka, kursy Eagla, jeszcze jakieś blogi o mikrokontrolerach. Zamówiłem na aukcji wyświetlacz lcd 128x64 na płytce z Atmega8, wyprowadzeniami do DS18B20 i goldpinami do programatora (ok. 60 zł + wysyłka). Nawet wgrany był wsad pokazujący temperaturę z 4 czujników Dallasa - na początek starczy, czego chcieć więcej? <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> Aha... 4 microswitche też są.<br /><br />Założyłem, że program ma realizować następujące funkcję:<br />- sprawdzanie temperatury w lodówce,<br />- włączanie/wyłączanie agregatu w odpowiednim momencie,<br />- włączanie/wyłączanie wentylatora z opóźnieniem w stosunku do agregatu,<br />- wyświetlanie temperatury wraz z rysowaniem wykresu (tyle pikseli w lcd nie może się marnować <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />),<br />- regulacja temperatury maksymalnej i minimalnej (włączającej i wyłączającej agregat),<br />- regulacja opóźnienia wł/wył. wentylatora,<br />- wyświetlanie stanu pracy (czy włączony agregat/wiatrak, temp. min, max, aktualna).<br /><br />Do obsługi wyświetlacza wykorzystałem biblioteki u8g. Debouncing klawiszy znalazłem na blogu o mikrokontrolerach. Szybko okazało się, że 8 kB pamięci to wcale nie jest dużo i dały znać o sobie moje braki w znajomości C. Obecnie program jest &quot;na styk&quot; a chciałbym go jeszcze rozbudować (automatyczna histereza, zapis ustawień w eeprom). Z nieba spadł mi kurs C++ kolegi Mokrowski, po którym jeszcze szczęki nie mogę znaleźć - praca jaką włożył w przygotowanie tutoriali iście tytaniczna. Przyznam bez bicia, że zarejestrowałem się tylko co by te listingi zobaczyć <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" />. Mam nadzieję, że po przepisaniu programu do C++ i uporządkowaniu wszystkiego, wywalczę jakiś wolny kB może dwa <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" />.<br /><br />Od razu chciałbym zaznaczyć, że w C jestem początkujący. Ostatni program w tym języku pisałem jakieś 10 lat temu i to na PC. Z uC styczności nie miałem chyba jeszcze dłużej, a i tak był to BASCOMowy Basic. Stąd też prośba - gdyby ktoś z bardziej obeznanych kolegów wychwycił jakieś herezje czy kombinacje alpejskie - będę bardzo wdzięczny za uwagi.<br /><br />[syntax=c]#include &lt;stdlib.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;math.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &quot;u8g.h&quot;<br /><br />#define KEYBOARD_DEBOUNCE_MS 50   //czas zwloki debouncera w &#91;ms&#93;<br /><br />#define KEY1_PINPC5     //definicja klawiatury<br />#define KEY1_PORTPORTC<br />#define KEY1_PIN_REGPINC<br />#define KEY1_DIRDDRC<br />#define KEY2_PINPC4<br />#define KEY2_PORTPORTC<br />#define KEY2_PIN_REGPINC<br />#define KEY2_DIRDDRC<br />#define KEY3_PINPC3<br />#define KEY3_PORTPORTC<br />#define KEY3_PIN_REGPINC<br />#define KEY3_DIRDDRC<br />#define KEY4_PINPC2<br />#define KEY4_PORTPORTC<br />#define KEY4_PIN_REGPINC<br />#define KEY4_DIRDDRC<br /><br />// 1-wire configuration<br />#define ONEWIRE_PINPD0<br />#define ONEWIRE_PORTPIND<br />#define ONEWIRE_DDRDDRD<br /><br />// DS18S20 commands<br />#define SKIP_ROM0xCC<br />#define CONVERT_T0x44<br />#define READ0xBE<br /><br />// ports<br />#define set_LED  PORTB |= (1&lt;&lt;PINB5)      // --&gt;LED = 1<br />#define clear_LED  PORTB &amp;= ~(1&lt;&lt;PINB5)   // --&gt;LED = 0<br />#define set_AGR PORTD |= (1&lt;&lt;PIND1)      // --&gt;AGR = 1<br />#define clear_AGRPORTD &amp;= ~(1&lt;&lt;PIND1)   // --&gt;AGR = 0<br />#define set_FAN  PORTD |= (1&lt;&lt;PIND2)      // --&gt;FAN = 1<br />#define clear_FAN  PORTD &amp;= ~(1&lt;&lt;PIND2)   // --&gt;FAN = 0<br /><br /><br />static uint8_t onewire_reset()<br />{<br />ONEWIRE_DDR |= (1&lt;&lt;ONEWIRE_PIN);<br />_delay_us(480);<br />ONEWIRE_DDR &amp;= ~(1&lt;&lt;ONEWIRE_PIN);<br />_delay_us(70);<br />uint8_t ret = ~(ONEWIRE_PORT &amp; (1&lt;&lt;ONEWIRE_PIN));<br />_delay_us(410);<br />return ret;<br />}<br /><br />static void _onewire_write_bit(uint8_t value)<br />{<br />uint8_t sreg = SREG;<br />cli();<br />ONEWIRE_DDR |= (1&lt;&lt;ONEWIRE_PIN);<br />_delay_us(1);<br />if(value)<br />{<br />ONEWIRE_DDR &amp;= ~(1&lt;&lt;ONEWIRE_PIN);<br />_delay_us(59);<br />}<br />else<br />{<br />_delay_us(59);<br />ONEWIRE_DDR &amp;= ~(1&lt;&lt;ONEWIRE_PIN);<br />}<br />SREG = sreg;<br />_delay_us(30);<br />}<br /><br />static uint8_t _onewire_read_bit()<br />{<br />uint8_t sreg = SREG;<br />cli();<br />ONEWIRE_DDR |= (1&lt;&lt;ONEWIRE_PIN);<br />_delay_us(1);<br />ONEWIRE_DDR &amp;= ~(1&lt;&lt;ONEWIRE_PIN);<br />_delay_us(15);<br />uint8_t ret = ONEWIRE_PORT &amp; (1&lt;&lt;ONEWIRE_PIN);<br />SREG = sreg;<br />_delay_us(75);<br />return ret;<br />}<br /><br />static void onewire_write_byte(uint8_t value)<br />{<br />for(uint8_t i = 0; i &lt; 8; i++)<br />{<br />_onewire_write_bit(value &amp; 0x01);<br />value = value &gt;&gt; 1;<br />}<br />}<br /><br />static uint8_t onewire_read_byte()<br />{<br />uint8_t ret = 0;<br />for(uint8_t i = 0; i &lt; 8; i++)<br />{<br />ret = ret &gt;&gt; 1;<br />if(_onewire_read_bit()) ret |= 0x80;<br />}<br />return ret;<br />}<br /><br />volatile uint8_t stan_przyciskow, poprzedni_stan_przyciskow;  //4LSB zawieraja informacje o stanie<br />//przyciskow 1-wcisniety, 0-wolny<br />volatile uint8_t stable_state&#91;4&#93;;  //tablica do szybkich operacji w petli<br />volatile uint8_t debounce_timer&#91;4&#93;;  //tablica do szybkich operacji w petli<br /><br />void SetupKeyboard (void) {    //konfiguracja klawiatury<br />KEY1_DIR &amp;= ~(1&lt;&lt;KEY1_PIN);   //pin przycisku jako wejscie<br />KEY1_PORT |= (1&lt;&lt;KEY1_PIN);   //podciagniecie pinu do VCC<br />KEY2_DIR &amp;= ~(1&lt;&lt;KEY2_PIN);<br />KEY2_PORT |= (1&lt;&lt;KEY2_PIN);<br />KEY3_DIR &amp;= ~(1&lt;&lt;KEY3_PIN);<br />KEY3_PORT |= (1&lt;&lt;KEY3_PIN);<br />KEY4_DIR &amp;= ~(1&lt;&lt;KEY4_PIN);<br />KEY4_PORT |= (1&lt;&lt;KEY4_PIN);<br />}<br />void InitDebounceTimer (void)  //konfiguracja timera0<br />{<br />TCNT0 = 0x1;    //zmiana ustawien powinna byc dla wartosci !0xFF i !0x0<br />TCCR0 |= (1&lt;&lt;CS01);   //preskaler = 8 (dla 1&#91;MHz&#93; przepelnienia co 2.048&#91;ms&#93;)<br />TCCR0 &amp;= ~((1&lt;&lt;CS00) | (1&lt;&lt;CS02));<br />TIMSK |= (1&lt;&lt;TOIE0);  //obsluga przerwania od przepelnienia<br />}<br /><br /><br />void SetupHardware (void)<br />{<br />//ACSR &amp;= ~(1&lt;&lt;ACD);    //wylaczenie zbedznie pracujacego ACD<br />SetupKeyboard();<br />InitDebounceTimer();<br />}<br /><br /><br />ISR(TIMER0_OVF_vect)<br />{<br />uint8_t key_value&#91;4&#93;;  //tablica wartosci dla klawiatury<br /><br />//odczyt klawiatury (przycisk: 1-&gt;wcisniety, 0-wolny)<br />if(KEY1_PIN_REG &amp; (1&lt;&lt;KEY1_PIN)) {key_value&#91;0&#93; = 0;} else {key_value&#91;0&#93; = 1;}<br />if(KEY2_PIN_REG &amp; (1&lt;&lt;KEY2_PIN)) {key_value&#91;1&#93; = 0;} else {key_value&#91;1&#93; = 1;}<br />if(KEY3_PIN_REG &amp; (1&lt;&lt;KEY3_PIN)) {key_value&#91;2&#93; = 0;} else {key_value&#91;2&#93; = 1;}<br />if(KEY4_PIN_REG &amp; (1&lt;&lt;KEY4_PIN)) {key_value&#91;3&#93; = 0;} else {key_value&#91;3&#93; = 1;}<br /><br />for(uint8_t i = 0; i &lt; 4; i++) {  //obsluga kazdego przycisku z osobna<br />if(debounce_timer&#91;i&#93; &gt; 0) {   //gdy odmierzanie czasu zwloki<br />if((--debounce_timer&#91;i&#93; == 0) &amp;&amp; (stable_state&#91;i&#93; ^ key_value&#91;i&#93;)) {<br />stable_state&#91;i&#93; ^= 0x1;  //aktualizacja stanu klawiatury gdy koniec zwloki<br />stan_przyciskow ^= (1&lt;&lt;i); //i zmienil sie stan logiczny na wejsciu<br />}<br />} else {       //skanowanie klawiatury<br />if(stable_state&#91;i&#93; ^ key_value&#91;i&#93;) { //wykrycie zmiany stanu<br />debounce_timer&#91;i&#93; = KEYBOARD_DEBOUNCE_MS / 2; //ustawienie czasu zwloki<br />}<br />}<br />}<br />}<br /><br /><br /><br /><br />char w_temp&#91;5&#93; =&quot;{0}&quot;, w_lo&#91;5&#93; = &quot;{0}&quot;, w_hi&#91;5&#93; = &quot;{0}&quot;, buf&#91;5&#93; = &quot;{0}&quot;, info&#91;22&#93; = &quot;{0}&quot;;<br />float fTemp = 0;<br />int16_t iTemp = 0, iTemp_lo = 220, iTemp_hi = 230;<br />uint8_t wykres&#91;66&#93; = {0};<br />uint8_t switch_agr = 0, switch_fan = 0, opoznienie = 3;<br />u8g_t u8g;<br /><br />void draw(void)<br />{<br />uint8_t b;<br /><br />// Wykres i linie graniczne<br />for (b=1; b&lt;66; b++)<br />{<br />if (wykres&#91;b-1&#93;&gt;0) {<br />u8g_DrawLine(&amp;u8g, b, wykres&#91;b&#93;, b-1, wykres&#91;b-1&#93;);<br />}<br />if (b%3 == 1 )// Przerywane linie graniczne<br />{<br />u8g_DrawPixel(&amp;u8g, b, 62-iTemp_lo/5);<br />u8g_DrawPixel(&amp;u8g, b, 62-iTemp_hi/5);<br />}<br />}<br /><br />// Oznaczenia temp. na skali pionowej (30, 25, 20, 15, 10, 5 stopni)<br />u8g_SetFont(&amp;u8g, u8g_font_blipfest_07n);<br />for (b=5; b&lt;=55; b+=10) {<br />u8g_DrawStr(&amp;u8g, 70, b, itoa(32-(b/2), buf, 10) );<br />u8g_DrawLine(&amp;u8g, 67, b-3, 68, b-3);<br />}<br /><br />//<br />u8g_DrawBox(&amp;u8g, 79, 0, 49, 54);//Ciemne tlo pod glowny <br />u8g_DrawLine(&amp;u8g, 66, 0, 66, 53);//Linia osi pionowej wykresu<br />u8g_DrawLine(&amp;u8g, 0, 53, 66, 53);//Linia osi poziomej wykresu<br /><br /><br />u8g_SetColorIndex(&amp;u8g, 0);<br /><br />// jasny prostokat pod napisem AGREGAT<br />if (switch_agr == 1)<br />{<br />u8g_DrawBox(&amp;u8g, 81, 28, 45, 11);<br />}<br /><br />// jasny prostokat pod napisem WIATRAK<br />if (switch_fan == 1)<br />{<br />u8g_DrawBox(&amp;u8g, 81, 41, 45, 11);<br />}<br />u8g_SetFont(&amp;u8g, u8g_font_fub17n);<br />u8g_DrawStr(&amp;u8g, 80, 22, w_temp);<br />u8g_SetColorIndex(&amp;u8g, 1);<br />u8g_SetFont(&amp;u8g, u8g_font_6x12r);<br />u8g_DrawStr(&amp;u8g, 83, 37, &quot;AGREGAT&quot;);<br />u8g_DrawStr(&amp;u8g, 83, 50, &quot;WIATRAK&quot;);<br />u8g_DrawStr(&amp;u8g, 13, 63, info);<br /><br />}<br /><br /><br /><br />int main(void)<br />{<br />uint8_t i, a, lag_counter = 0;<br />const char *kropa = &quot;.&quot;;<br />char cTempH = 0, cTempL = 0;<br /><br />DDRB = 0b11111111;<br />PORTB = 0b00000000;<br />DDRD= 0b11111111;<br />//PORTD = 0b00000000;<br /><br />sei();     //wlaczenie obslugi przerwan<br />SetupHardware();  //konfiguracja sprzetu<br />u8g_InitSPI(&amp;u8g, &amp;u8g_dev_uc1601_c128032_2x_sw_spi, PN(1,2), PN(1,3), PN(1,0), PN(1,1), U8G_PIN_NONE); // inicjalizacja lcd po spi<br />u8g_Delay(50);<br /><br />set_LED;<br />u8g_SetColorIndex(&amp;u8g, 1);<br /><br />// glowna petla<br />for(i=0; ; i++)<br />{<br />// wykrycie przycisniecia microswitcha<br />if ( stan_przyciskow != poprzedni_stan_przyciskow)<br />{<br />switch( stan_przyciskow )<br />{<br />case 0b1:// micro_sw 1zmniejsza temp min o 0.5'C<br />iTemp_lo -= 5;<br />break;<br /><br />case 0b10:// micro_sw 2zwieksza temp min o 0.5'C<br />//if (iTemp_hi-iTemp_lo &gt; 10)// wylaczone z powodu braku pamieci<br />iTemp_lo += 5;<br />break;<br /><br />case 0b100:// micro_sw 3zmniejsza temp max o 0.5'C<br />//if (iTemp_hi-iTemp_lo &gt; 10)// wylaczone z powodu braku pamieci<br />iTemp_hi -= 5;<br />break;<br /><br />case 0b1000:// micro_sw 4zwieksza temp max o 0.5'C<br />iTemp_hi += 5;<br />break;<br /><br />// wcisniecie dwoch klawiszy razem zmienia opoznienie<br />case 0b1100:// micro_sw 3+4<br />if (opoznienie &lt; 9)<br />opoznienie ++;<br />break;<br /><br />case 0b11:// micro_sw 1+2<br />if (opoznienie &gt; 1)<br />opoznienie --;<br />break;<br /><br />}<br /><br />// migniecie podswietlenia lcd sygnalizuje odczyt przycisku<br />clear_LED;<br />u8g_Delay(10);<br />set_LED;<br />// zmiana licznika petli zeby wskazywal na kolejny cykl odswiezenia wyswietlacza<br />i += 32-i%32;<br />} else {<br />poprzedni_stan_przyciskow = stan_przyciskow;<br />}<br /><br />if (i &gt;= 256) {<br />i = 0;<br />}<br /><br />// cykl odczytu temperatury, sterowania i odswiezania wyswietlacza<br />if ( i % 32 == 0 ) {<br />// Odczyt temperatury z DS18B20 po 1-wire (jeden czujnik)<br />onewire_reset();<br />onewire_write_byte(SKIP_ROM);<br />onewire_write_byte(CONVERT_T);<br />u8g_Delay(30);<br />onewire_reset();<br />onewire_write_byte(SKIP_ROM);<br />onewire_write_byte(READ);<br />cTempL = onewire_read_byte();<br />cTempH = onewire_read_byte();<br />fTemp = (float)(cTempL+(cTempH&lt;&lt;8))/16;<br />// Konwersja odczytanej temperatury<br />iTemp = fabs(fTemp)*10;// zamiast operacowac na float mnozy temp przez 10 i trzyma wartosc w int<br />itoa(iTemp/10, w_temp, 10);<br />strcat(w_temp, kropa);<br />strcat(w_temp, itoa(iTemp%10, buf, 10));// przeksztalcenie temp do tablicy char &quot;23.5&quot;<br /><br />itoa(iTemp_lo/10, w_lo, 10);<br />strcat(w_lo, kropa);<br />strcat(w_lo, itoa(iTemp_lo%10, buf, 10));<br /><br />itoa(iTemp_hi/10, w_hi, 10);<br />strcat(w_hi, kropa);<br />strcat(w_hi, itoa(iTemp_hi%10, buf, 10));<br /><br />// Linijka informacyjna<br />*info = '\0';<br />strcat(info, &quot;Lo=&quot;);<br />strcat(info, w_lo);<br />strcat(info, &quot; D=&quot;);<br />strcat(info, itoa(opoznienie, buf, 10));<br />strcat(info, &quot; Hi=&quot;);<br />strcat(info, w_hi);<br /><br />// Zapisywanie stanow wykresu w tablicy<br />if ( i == 32 )<br />{<br />wykres&#91;65&#93; = 62-iTemp/5;<br /><br />if (iTemp &gt;= 315)wykres&#91;65&#93; = 1;<br />if (iTemp &lt; 50)wykres&#91;65&#93; = 52;<br /><br />// przesuwanie tablicy<br />for (a=0; a&lt;65;  a++)<br />{<br />wykres&#91;a&#93; = wykres&#91;a+1&#93;;<br />}<br /><br />}<br /><br />// Wlaczenie agregatu<br />if ( iTemp &gt;= iTemp_hi ) {<br />if ( switch_agr == 0 )<br />{<br />set_AGR;<br />switch_agr = 1;<br />lag_counter = opoznienie*8;<br />}<br />}<br /><br />// Wylaczenie agregatu (opoznienie wylaczenia wentylatora 2x wieksze)<br />if ( iTemp &lt;= iTemp_lo ) {<br />if ( switch_agr == 1 )<br />{<br />clear_AGR;<br />switch_agr = 0;<br />lag_counter = opoznienie*16;<br />}<br />}<br /><br />// Wlaczenie/wylaczenie wentylatora z opoznieniem<br />if (lag_counter &gt; 1)<br />{<br />lag_counter--;<br />} else {<br />if (switch_agr == 1)<br />{<br />set_FAN;<br />switch_fan = 1;<br />} else {<br />clear_FAN;<br />switch_fan = 0;<br />}<br />lag_counter = 0;<br />}<br /><br />// Rysowanie na lcd<br />u8g_FirstPage(&amp;u8g);<br />do<br />{<br />draw();<br />} while ( u8g_NextPage(&amp;u8g) );<br />}<br /><br />// Ponizsza wartosc ma wplyw na skale czasu wykresu<br />u8g_Delay(25);<br /><br />}<br />}[/syntax]<br /><br />Obecnie próbuję przetrawić wcześniej wspomniany kurs C++ i przepisać wszystko od nowa, tak jak się to powinno w cpp robić. A propos estetyki kodu - co sądzicie o Ruby w uC? Zawracanie głowy czy warte spróbowania?<br />Zdaje się, że też wpadłem w ten mikrokompot <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />.<br /><br />Pozdrawiam<br /><br /><a href="http://forum.atnel.pl/_obrazki/o/5550/60559fa3a5b1949145d1c3a333d003c9.JPG"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/5550/60559fa3a5b1949145d1c3a333d003c9.JPG" alt="Obrazek" /></a><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5550">ashi</a> — 23 sie 2014, o 18:15</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[nowak90]]></name></author>
<updated>2014-06-11T16:25:25+01:00</updated>
<published>2014-06-11T16:25:25+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84122#p84122</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84122#p84122"/>
<title type="html"><![CDATA[Re: Pierwszy bardziej zaawansowany projekcik - Termostat z L]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84122#p84122"><![CDATA[
Dziękuje bardzo za pomoc. Wiem już chociaż gdzie mam braki i jak to powinno działać. Już się biorę za czytanie o flagach, przerabianie i testowanie.<br />Będę informował o postępach lub jakiś problemach <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br />Nie takie hop siup ten termostat <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=4115">nowak90</a> — 11 cze 2014, o 16:25</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Nefarious19]]></name></author>
<updated>2014-06-11T15:18:23+01:00</updated>
<published>2014-06-11T15:18:23+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84108#p84108</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84108#p84108"/>
<title type="html"><![CDATA[Re: Pierwszy bardziej zaawansowany projekcik - Termostat z L]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84108#p84108"><![CDATA[
Odnośnie nastawiania temperatury zadanej, ja rozbudowałbym obsługę drgań styków pokazaną przez Pana Mirka na jego blogu mniej więcej w taki sposób:<br /><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br /> <br />//makra z pinami do których podłączone są klawisze<br />#define KEY1 (1&lt;&lt;PC1)<br />#define KEY2 (1&lt;&lt;PC2)<br />#define KEY3 (1&lt;&lt;PC3)<br /><br />#define PRZYROST 2 //przyrost temperatury  w stopniach<br /><br />//definicje zmiennych globalnych<br />uint8_t key_lock1, key_lock2, key_lock3;<br />uint8_t temp_zadana;<br />uint8_t flaga;<br /><br />int main(void) {<br /> <br /> PORTC |= KEY1 | KEY2 | KEY3;  // podciągamy linie klawiszy do VCC<br /><br /> temp_zadan = 23;<br />// oczekiwanie na ustalenie się stanu wysokiego na wejściu klawisza<br /> _delay_ms(10); <br /> <br /> while(1) <br />  {<br /> <br /> if( !key_lock1 &amp;&amp; !(PINC &amp; KEY1 ) ) //jeżeli klawisz S1 wcisniety<br /> {<br />   <br /> key_lock1 = 1; //key_lock1 = 1<br /> <br /><br /> } <br /> else if( key_lock1 &amp;&amp; (PINC &amp; KEY1 ) ) //jeżeli nie<br />{<br /> key_lock1++;  //to zwiększaj key_lock aż będzie równe 0 - eliminacja drgań styków<br /> flaga = 0;   //i ustaw flage na zero<br />}<br /> else if( key_lock1 &amp;&amp; !(PINC &amp; KEY1) ) flaga = 1; //  jeżeli key_lock1 &gt; 0 ale klawisz nadal wcisnięty<br />               // ustaw flage na jeden<br /> <br /> <br /> if (flaga == 1) //jeżeli flaga równa jest jeden co oznacza że S1 wcinięty to<br />  {<br />      if( !key_lock2 &amp;&amp; !(PINC &amp; KEY2 ) ) //jeżeli klawisz S2 wciniety zrób przyrost <br />      {//-jednokrotne wcinięcie - pojednczy przyrost<br />      <br />      key_lock2 = 1; //eliminacja drgań styków<br />      temp_zadana = temp_zadana + PRZYROST;<br /><br /><br />      } <br />      else if( key_lock2 &amp;&amp; (PINC &amp; KEY2 ) ) key_lock2++; //eliminacja drgań styków<br />      <br /><br />      if( !key_lock3 &amp;&amp; !(PINC &amp; KEY3 ) )                  //jeżeli klawisz S3 wciniety zmniejsz przyrost <br />      {////-jednokrotne wcinięcie - pojednczy spadek<br />      key_lock3 = 1;         //eliminacja drgań styków<br />      temp_zadana = temp_zadana - PRZYROST;<br /><br />      } <br />      else if( key_lock3 &amp;&amp; (PINC &amp; KEY3 ) ) key_lock3++; //elominacja drgań styków<br /><br />    }<br /><br /><br /> }<br /> <br />}[/syntax]<br /><br />okomentowałem kod, nie kompilowałem ani nie sprawdzałem, to tylko idea. Wydaję mi się że trafna. Być może koledzy z forum polecą Ci lepszą metodę obsługi klawiszy <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />W programie musisz jakoś uwzględnić co chcesz w danej chwili pokazywać. Podowiem Ci tak:<br /><br />Jak S1 nie wciśnięty jakaś flaga = 0<br />Jak S1 wciśniety jakaś flaga = 1<br /><br />jak jakaś flaga = 0 to rób to co masz robić, wyświetlaj temperatur itd.<br />jak jakaś flaga = 1 to pokazuje na wyświetlaczu aktualnie nastawioną temp i S2 albo S3 ją zwiększaj<br /><br />trzeba troszkę pomyśleć:)<br /><br />do funkcji od wyswietlania temperatury możesz dopisać że np:<br /><br />[syntax=c]uint8_t temp_aktualna; //definicja przed funkcją main jako zmienna globalna<br /><br />//w funkcji display_temp<br />temp_aktualna = cel;[/syntax]<br /><br />a później sprawdzać czy temperatura nastawiona jest mniejsza od odczytanej i:<br />jeżeli tak to DIODA ON<br />jeżeli nie to DIODA OFF<br /><br />oczywiście nie uwzględniam tutaj czy temp jest ujemna czy dodatnia. o tym informuje Cie zmienna subzero którą też możesz wykorzytsać w warunku do gaszenia i zapalnia diodełki:)<br /><br />to takie moje rozkminy na szybko. Może Ci coś w głowie zaświta:)<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2500">Nefarious19</a> — 11 cze 2014, o 15:18</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[nowak90]]></name></author>
<updated>2014-06-12T11:13:30+01:00</updated>
<published>2014-06-11T11:30:00+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84074#p84074</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84074#p84074"/>
<title type="html"><![CDATA[Pierwszy bardziej zaawansowany projekcik - Termostat z LCD]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7390&amp;p=84074#p84074"><![CDATA[
Witam serdecznie!<br />Postanowiłem zrobić termostat z LCD na czujniku DS18B20. Zmontowałem układ na płytce stykowej (sporządzając wcześniej schemat <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> ) i z pomocą książki i CD Pana Mirka odpaliłem magistrale 1WIRE <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br />Chciałbym aby za pomocą trzech przycisków dało się nastawić &quot;temperature zadana&quot; Np. trzymając S1 (nastaw) operujemy przyciskami S2 (+) i S3 (-) następnie puszczamy przycisk S1.<br />Grzałką jest dioda LED która ma się zapalać po spadku temp i wyłączać po jej osiągnięciu (czujnik nagrzewam przez dotkniecie palcem).  Później może wzbogacę program o jakaś nastawialną histerezę, ale na razie nie potrzeba.<br /><br />W tej chwili odczytuje mi ładnie temp, ale nie wiem jak zapisać wartość temperatury i zastosować do niej jakąś arytmetykę. Próbowałem również aby trzymając przycisk S1(nastaw) wyświetlacz<br />wyświetlał mi inny tekst, ale migotał i był mało czytelny <img src="https://forum.atnel.pl/images/smilies/icon_e_sad.gif" alt=":(" title="Smutny" /> <br />Uda się coś pomóc? Czy jestem zbyt początkujący?<br /><br />Oto mój schemacik:<br /><a href="http://forum.atnel.pl/_obrazki/o/4115/3accf711691722db1623c4146df5a303.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/4115/3accf711691722db1623c4146df5a303.jpg" alt="Obrazek" /></a><br /><br />I main Pana Mirka który przerobiłem pod siebie: <br />[syntax=c]#include &quot;lcd44780.h&quot;<br />#include &quot;ds18x20.h&quot;<br /><br />void display_temp(uint8_t x);<br /><br />uint8_t czujniki_cnt;/* ilość czujników na magistrali */<br />volatile uint8_t s1_flag;/* flaga tyknięcia timera co 1 sekundę */<br />volatile uint8_t sekundy;/* licznik sekund 0-59 */<br /><br />uint8_t subzero, cel, cel_fract_bits;<br /><br />int main(void) {<br /><br /><br />/* ustawienie TIMER0 dla F_CPU=11,0592MHz */<br />TCCR2 |= (1&lt;&lt;WGM21);/* tryb CTC */<br />TCCR2 |= (1&lt;&lt;CS22)|(1&lt;&lt;CS02);/* preskaler = 1024 */<br />OCR2 = 107;/* dodatkowy podział przez 108 (rej. przepełnienia) */<br />TIMSK |= (1&lt;&lt;OCIE2);/* zezwolenie na przerwanie CompareMatch */<br />/* przerwanie wykonywane z częstotliwością ok 10ms (100 razy na sekundę) */<br />/* do naszych celów nie musi być to bardzo dokładne 10ms */<br /><br />lcd_init();/* inicjalizacja LCD */<br /><br />        lcd_str(&quot;Projekt:&quot;);<br />        lcd_locate(1,0);<br />        lcd_str(&quot;REGULATOR TEMP.&quot;);<br />        _delay_ms(4000);<br />        lcd_cls();          //napis powitalny<br /><br />/* sprawdzamy ile czujników DS18xxx widocznych jest na magistrali */<br />czujniki_cnt = search_sensors();<br /><br /><br />/* wysyłamy rozkaz wykonania pomiaru temperatury<br /> * do wszystkich czujników na magistrali 1Wire<br /> * zakładając, że zasilane są w trybie NORMAL,<br /> * gdyby był to tryb Parasite, należałoby użyć<br /> * jako pierwszego prarametru DS18X20_POWER_PARASITE */<br />DS18X20_start_meas( DS18X20_POWER_EXTERN, NULL );<br /><br />/* czekamy 750ms na dokonanie konwersji przez podłączone czujniki */<br />_delay_ms(1500);<br /><br />/* dokonujemy odczytu temperatury z pierwszego czujnika o ile został wykryty */<br />/* wyświetlamy temperaturę gdy czujnik wykryty */<br />if( DS18X20_OK == DS18X20_read_meas(gSensorIDs&#91;0&#93;, &amp;subzero, &amp;cel, &amp;cel_fract_bits) ) display_temp(0);<br />else {<br />lcd_locate(1,0);<br />lcd_str(&quot; error &quot;);/* wyświetlamy informację o błędzie jeśli np brak czujnika lub błąd odczytu */<br />}<br /><br /><br />sei();/* włączamy globalne przerwania */<br /><br />lcd_locate(0,0);<br />lcd_str_P(PSTR(&quot;Temp:   xDS18B20&quot;)); /* wyświetl napisy w zerowej linii LCD */<br /><br />/* pętla nieskończona */<br />while(1) {<br /><br />if(s1_flag) {/* sprawdzanie flagi tyknięć timera programowego co 1 sekundę */<br /><br />/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 0 sprawdzaj ilość dostępnych czujników */<br />if( 0 == (sekundy%3) ) {<br /><br />uint8_t *cl=(uint8_t*)gSensorIDs;// pobieramy wskaźnik do tablicy adresów czujników<br />for( uint8_t i=0; i&lt;MAXSENSORS*OW_ROMCODE_SIZE; i++) *cl++ = 0; // kasujemy całą tablicę<br />czujniki_cnt = search_sensors();// ponownie wykrywamy ile jest czujników i zapełniamy tablicę<br />lcd_locate(0,7);<br />lcd_int( czujniki_cnt );// wyświetlamy ilość czujników na magistrali<br />}<br /><br />/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 1 wysyłaj rozkaz pomiaru do czujników */<br />if( 1 == (sekundy%3) ) DS18X20_start_meas( DS18X20_POWER_EXTERN, NULL );<br /><br />/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 2 czyli jedną sekundę po rozkazie konwersji<br /> *  dokonuj odczytu i wyświetlania temperatur z 2 czujników jeśli są podłączone, jeśli nie<br /> *  to pokaż komunikat o błędzie<br /> */<br />if( 2 == (sekundy%3) ) {<br />if( DS18X20_OK == DS18X20_read_meas(gSensorIDs&#91;0&#93;, &amp;subzero, &amp;cel, &amp;cel_fract_bits) ) display_temp(0);<br />else {<br />lcd_locate(1,0);<br />lcd_str(&quot; error &quot;);<br />}<br />}<br /><br />/* zerujemy flagę aby tylko jeden raz w ciągu sekundy wykonać operacje */<br />s1_flag=0;<br />} /* koniec sprawdzania flagi */<br />} /* koniec pętli nieskończonej */<br />}<br /><br />/* wyświetlanie temperatury na pozycji X w drugiej linii LCD */<br />void display_temp(uint8_t x) {<br />lcd_locate(1,x);<br />if(subzero) lcd_str(&quot;-&quot;);/* jeśli subzero==1 wyświetla znak minus (temp. ujemna) */<br />else lcd_str(&quot; &quot;);/* jeśli subzero==0 wyświetl spację zamiast znaku minus (temp. dodatnia) */<br />lcd_int(cel);/* wyświetl dziesiętne części temperatury  */<br />lcd_str(&quot;.&quot;);/* wyświetl kropkę */<br />lcd_int(cel_fract_bits); /* wyświetl dziesiętne części stopnia */<br />lcd_str(&quot; C &quot;); /* wyświetl znak jednostek (C - stopnie Celsiusza) */<br />}<br /><br /><br />/* ================= PROCEDURA OBSŁUGI PRZERWANIA – COMPARE MATCH */<br />/* pełni funkcję timera programowego wyznaczającego podstawę czasu = 1s */<br />ISR(TIMER2_COMP_vect)<br />{<br />static uint8_t cnt=0;/* statyczna zmienna cnt do odliczania setnych ms */<br /><br />if(++cnt&gt;99) {/* gdy licznik ms &gt; 99 (minęła 1 sekunda) */<br />s1_flag=1;/* ustaw flagę tyknięcia sekundy */<br />sekundy++;/* zwiększ licznik sekund */<br />if(sekundy&gt;59) sekundy=0; /* jeśli ilość sekund &gt; 59 - wyzeruj */<br />cnt=0;/* wyzeru licznik setnych ms */<br />}<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=4115">nowak90</a> — 11 cze 2014, o 11:30</p><hr />
]]></content>
</entry>
</feed>