Термометр на atmega8 с прорисовкой графиков на ЖКИ

Температуру на ЖКИ можно выводить не только в виде цифр а так же в виде графика, что давно хотел реализовать. В данном проекте будет использован самый распространенный восьмибитный микроконтроллер atmega8 и графический жидкокристаллический индикатор от мобильного телефона NOKIA 3310.

график термометра на atmega8

Библиотека для ЖКИ от NOKIA 3310 уже несколько раз применялась в других проектах размещенных на сайте. Библиотека позволяет выводить произвольную графику на ЖКИ как из памяти микроконтроллера так и с внешних носителей данных (микросхемы EEPROM, dataflash и других).

Для обновления данных на ЖКИ будет использована горизонтальная развертка, скорость обновления информации на ЖКИ будет ограничиваться временем выполнения замера температуры на датчике ds18b20. Время конвертирования полученной температуры занимает 750 мс, так частота обновления будет равна примерно 1 секунде.

Для работы с датчиком температуры будет применена библиотека от автора по имени Дмитрий (samou4ka.net) так как она занимает минимум памяти в микроконтроллере, и точность измерения температуры ограничивается единицами градусов Цельсия. Значение температуры после запятой не интересует.

Исходный код программы термометра:

  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. #include <avr/pgmspace.h>
  4. #include <avr/interrupt.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include "n3310.h"
  8. #include "n3310.c"
  9.  
  10. int a,l, sx=6, sy=6; //Шаг второй сетки
  11. int t=70; //Граница прорисовки графика
  12.  
  13. //определяем порт и бит к которому подключено устройство 1-wire
  14. #define W1_PORT PORTD
  15. #define W1_DDR DDRD
  16. #define W1_PIN PIND
  17. #define W1_BIT 2
  18.  
  19. unsigned int temperature=0;
  20. unsigned char temperature_sign=0;
  21.  
  22. void time(void);
  23. void pixel (void);
  24.  
  25. void setka_y (void); //Отрисовка оси X
  26. void setka_x (void); //Отрисовка оси Y
  27. void znacheniya (void); //Вывод значений по осям X и Y
  28. void no_sensor (void);
  29.  
  30. //функция определяет есть ли устройство на шине
  31. unsigned char w1_find()
  32. { unsigned char device;
  33. W1_DDR |= 1<<W1_BIT;
  34. _delay_us(485);
  35. W1_DDR &= ~(1<<W1_BIT);
  36. _delay_us(65);
  37.  
  38. if((W1_PIN & (1<<W1_BIT)) ==0x00)
  39. { device = 1; }
  40. else
  41. device = 0;
  42. _delay_us(420);
  43. return device;
  44. }
  45.  
  46. //функция посылает команду на устройство 1-wire
  47. void w1_sendcmd(unsigned char cmd)
  48. {
  49. unsigned char e = 0;
  50. for(e=0; e<8; e++)
  51. {
  52. if((cmd & (1<<e)) == 1<<e)
  53. {
  54. W1_DDR |= 1<<W1_BIT;
  55. _delay_us(2);
  56. W1_DDR &= ~(1<<W1_BIT);
  57. _delay_us(65);
  58. }
  59. else
  60. { W1_DDR |= 1<<W1_BIT;
  61. _delay_us(65);
  62. W1_DDR &= ~(1<<W1_BIT);
  63. _delay_us(5);
  64. }
  65. }
  66. }
  67. //функция читает один байт с устройства 1-wire
  68. unsigned char w1_receive_byte()
  69. { unsigned char data;
  70. unsigned char i = 0;
  71. for(i=0; i<8; i++)
  72. { W1_DDR |= 1<<W1_BIT;
  73. _delay_us(2);
  74. W1_DDR &= ~(1<<W1_BIT) ;
  75. _delay_us(7);
  76. if((W1_PIN & (1<<W1_BIT)) == 0x00)
  77. data &= ~(1<<i);
  78. else
  79. data |= 1<<i;
  80. _delay_us(50);
  81. }
  82. return data;
  83. }
  84. //функция преобразует полученные с датчика 18b20 данные в температуру
  85. int temp_18b20()
  86. { unsigned char data[2];
  87. int temp = 0;
  88. if(w1_find()==1)//если есть устройство на шине
  89. {
  90. w1_sendcmd(0xcc);//пропустить ROM код, мы знаем, что у нас одно устройство или передаем всем
  91. w1_sendcmd(0x44);//преобразовать температуру
  92. _delay_ms(750);//преобразование в 12 битном режиме занимает 750ms
  93. w1_find();//снова посылаем Presence и Reset
  94. w1_sendcmd(0xcc);
  95. w1_sendcmd(0xbe);//передать байты ведущему(у 18b20 в первых двух содержится температура)
  96. data[0] = w1_receive_byte();//читаем два байта с температурой
  97. data[1] = w1_receive_byte();
  98. //загоняем в двух байтную переменную
  99. temp = data[1];
  100. temp = temp<<8;
  101. temp |= data[0];
  102. //переводим в градусы
  103. temp *= 0.0625;//0.0625 градуса на единицу данных
  104. }
  105.  
  106. else {no_sensor();}
  107. //возвращаем температуру
  108. return temp;
  109. }
  110.  
  111.  
  112. void setka_x (void)
  113. { int b,p=0;
  114. for (b=0;b<38;b++)
  115. {a=a+2; p=p+sx;
  116. LcdPixel(0,47,PIXEL_ON); //Пиксель в координатах 0,0
  117. LcdPixel(a,47,PIXEL_ON); //Точка через 1 пиксель
  118. LcdPixel(p,46,PIXEL_ON); //Точка через шаг пикселей
  119. } LcdUpdate();}
  120.  
  121.  
  122. void setka_y (void)
  123. { int w,u=0;
  124. for (w=0;w<24;w++)
  125. {l=l+2; u=u+sy;
  126. LcdPixel(0,l,PIXEL_ON); //Точка через 1 пиксель
  127. LcdPixel(1,u,PIXEL_ON); //Точка через шаг пикселей
  128. } LcdUpdate();}
  129.  
  130.  
  131. void znacheniya (void)
  132. { LcdGotoXYFont(1,1); //Установка координат величины по X
  133. LcdFStr(FONT_1X,(unsigned char*)PSTR("T")); //Вывод величины по X
  134. LcdUpdate();
  135.  
  136. LcdGotoXYFont(12,5); //Установка координат величины по Y
  137. LcdFStr(FONT_1X,(unsigned char*)PSTR("t")); //Вывод величины по Y
  138. LcdUpdate(); }
  139.  
  140.  
  141. void no_sensor (void)
  142. {
  143. LcdGotoXYFont(2,2); //Установка координат величины по X
  144. LcdFStr(FONT_1X,(unsigned char*)PSTR("No sensor")); //Вывод величины по X
  145. LcdUpdate();
  146. _delay_ms(500); //Пауза
  147. LcdGotoXYFont(2,2); //Установка координат величины по X
  148. LcdFStr(FONT_1X,(unsigned char*)PSTR(" ")); //Вывод величины по X
  149. LcdUpdate();
  150. }
  151.  
  152.  
  153. int main(void)
  154. {
  155. LcdInit(); //Инициализация ЖКИ
  156. LcdClear(); //Очистка ЖКИ
  157. LcdFStr(FONT_1X,(unsigned char*)PSTR("START...")); //Вывод приветствия
  158. LcdUpdate(); //Обновление экрана
  159. _delay_ms(1000); //Пауза
  160. LcdClear(); //Очистка экрана
  161.  
  162.  
  163. //setka_x (); //Запуск отрисовки оси X
  164. setka_y (); //Запуск отрисовки оси Y
  165. //znacheniya (); //Вывод значений осей
  166.  
  167. char buffer[16] = ""; //Переменная температуры char
  168. int temp;
  169. int shag=0; //Переменная шага графика
  170. int tempint; //Значение температуры в int
  171. //int test=20;
  172.  
  173. sei(); //Разрешение прерываний
  174. while(1)
  175. {
  176. temp = temp_18b20(); //Пишем в переменную значение температуры
  177. if(temp > 1000) //если температура <0
  178. {temp = 4096 - temp; temp = -temp;} //маркировка отрицательной температуры
  179.  
  180. // sprintf(buffer, "%i.%i", temp, temp%1); //Конвертирование int в char
  181. sprintf(buffer, "%i", temp, temp%1); //Конвертирование int в char
  182. LcdGotoXYFont(5,1); //Установка в координаты 1,1
  183. LcdStr(FONT_1X,(unsigned char*)buffer); LcdUpdate();
  184. tempint = atoi(buffer); //Конвертация char в int
  185. // LcdLine ( shag, 46, shag, 0-tempint, PIXEL_ON); LcdUpdate(); //Вывод прямой на экран
  186. // LcdLine ( shag, 20, shag, test, PIXEL_ON); LcdUpdate(); //Вывод прямой на экран
  187.  
  188. // LcdPixel (shag, tempint+10, PIXEL_ON); LcdUpdate(); //На экране!!!
  189. // LcdPixel (shag, 60-tempint, PIXEL_ON); LcdUpdate(); //при 5,1 буффер
  190. LcdPixel (shag, 60-tempint, PIXEL_ON); LcdUpdate(); //при 5,1 буффер
  191.  
  192. shag=shag+1; //Добавляем к переменной Шага 1-цу
  193. LcdLine ( shag, 20, shag, 47, PIXEL_OFF); LcdUpdate(); //Вывод прямой на экран
  194. if(shag==t) //Если достигли границы прорисовки графика
  195. {shag=0;} //Идем в самое начало
  196. }
  197. }

график термометра точечный

Датчик температуры ds18b20 подключен к выводу PORTD2, ЖКИ подключен к выводам порта B. Библиотека для ЖКИ работает через аппаратный интерфейс SPI, таким образом будут задействованы выводы микроконтроллера предназначенные для его перепрошивки по интерфейсу SPI.

Скачать проект термометра

А схема есть?

А схема есть?