Термометр на atmega8 с прорисовкой графиков на ЖКИ
Температуру на ЖКИ можно выводить не только в виде цифр а так же в виде графика, что давно хотел реализовать. В данном проекте будет использован самый распространенный восьмибитный микроконтроллер atmega8 и графический жидкокристаллический индикатор от мобильного телефона NOKIA 3310.
Библиотека для ЖКИ от NOKIA 3310 уже несколько раз применялась в других проектах размещенных на сайте. Библиотека позволяет выводить произвольную графику на ЖКИ как из памяти микроконтроллера так и с внешних носителей данных (микросхемы EEPROM, dataflash и других).
Для обновления данных на ЖКИ будет использована горизонтальная развертка, скорость обновления информации на ЖКИ будет ограничиваться временем выполнения замера температуры на датчике ds18b20. Время конвертирования полученной температуры занимает 750 мс, так частота обновления будет равна примерно 1 секунде.
Для работы с датчиком температуры будет применена библиотека от автора по имени Дмитрий (samou4ka.net) так как она занимает минимум памяти в микроконтроллере, и точность измерения температуры ограничивается единицами градусов Цельсия. Значение температуры после запятой не интересует.
Исходный код программы термометра:
#include <avr/io.h> #include <util/delay.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #include <stdlib.h> #include <math.h> #include "n3310.h" #include "n3310.c" int a,l, sx=6, sy=6; //Шаг второй сетки int t=70; //Граница прорисовки графика //определяем порт и бит к которому подключено устройство 1-wire #define W1_PORT PORTD #define W1_DDR DDRD #define W1_PIN PIND #define W1_BIT 2 unsigned int temperature=0; unsigned char temperature_sign=0; void time(void); void pixel (void); void setka_y (void); //Отрисовка оси X void setka_x (void); //Отрисовка оси Y void znacheniya (void); //Вывод значений по осям X и Y void no_sensor (void); //функция определяет есть ли устройство на шине unsigned char w1_find() { unsigned char device; W1_DDR |= 1<<W1_BIT; _delay_us(485); W1_DDR &= ~(1<<W1_BIT); _delay_us(65); if((W1_PIN & (1<<W1_BIT)) ==0x00) { device = 1; } else device = 0; _delay_us(420); return device; } //функция посылает команду на устройство 1-wire void w1_sendcmd(unsigned char cmd) { unsigned char e = 0; for(e=0; e<8; e++) { if((cmd & (1<<e)) == 1<<e) { W1_DDR |= 1<<W1_BIT; _delay_us(2); W1_DDR &= ~(1<<W1_BIT); _delay_us(65); } else { W1_DDR |= 1<<W1_BIT; _delay_us(65); W1_DDR &= ~(1<<W1_BIT); _delay_us(5); } } } //функция читает один байт с устройства 1-wire unsigned char w1_receive_byte() { unsigned char data; unsigned char i = 0; for(i=0; i<8; i++) { W1_DDR |= 1<<W1_BIT; _delay_us(2); W1_DDR &= ~(1<<W1_BIT) ; _delay_us(7); if((W1_PIN & (1<<W1_BIT)) == 0x00) data &= ~(1<<i); else data |= 1<<i; _delay_us(50); } return data; } //функция преобразует полученные с датчика 18b20 данные в температуру int temp_18b20() { unsigned char data[2]; int temp = 0; if(w1_find()==1)//если есть устройство на шине { w1_sendcmd(0xcc);//пропустить ROM код, мы знаем, что у нас одно устройство или передаем всем w1_sendcmd(0x44);//преобразовать температуру _delay_ms(750);//преобразование в 12 битном режиме занимает 750ms w1_find();//снова посылаем Presence и Reset w1_sendcmd(0xcc); w1_sendcmd(0xbe);//передать байты ведущему(у 18b20 в первых двух содержится температура) data[0] = w1_receive_byte();//читаем два байта с температурой data[1] = w1_receive_byte(); //загоняем в двух байтную переменную temp = data[1]; temp = temp<<8; temp |= data[0]; //переводим в градусы temp *= 0.0625;//0.0625 градуса на единицу данных } else {no_sensor();} //возвращаем температуру return temp; } void setka_x (void) { int b,p=0; for (b=0;b<38;b++) {a=a+2; p=p+sx; LcdPixel(0,47,PIXEL_ON); //Пиксель в координатах 0,0 LcdPixel(a,47,PIXEL_ON); //Точка через 1 пиксель LcdPixel(p,46,PIXEL_ON); //Точка через шаг пикселей } LcdUpdate();} void setka_y (void) { int w,u=0; for (w=0;w<24;w++) {l=l+2; u=u+sy; LcdPixel(0,l,PIXEL_ON); //Точка через 1 пиксель LcdPixel(1,u,PIXEL_ON); //Точка через шаг пикселей } LcdUpdate();} void znacheniya (void) { LcdGotoXYFont(1,1); //Установка координат величины по X LcdFStr(FONT_1X,(unsigned char*)PSTR("T")); //Вывод величины по X LcdUpdate(); LcdGotoXYFont(12,5); //Установка координат величины по Y LcdFStr(FONT_1X,(unsigned char*)PSTR("t")); //Вывод величины по Y LcdUpdate(); } void no_sensor (void) { LcdGotoXYFont(2,2); //Установка координат величины по X LcdFStr(FONT_1X,(unsigned char*)PSTR("No sensor")); //Вывод величины по X LcdUpdate(); _delay_ms(500); //Пауза LcdGotoXYFont(2,2); //Установка координат величины по X LcdFStr(FONT_1X,(unsigned char*)PSTR(" ")); //Вывод величины по X LcdUpdate(); } int main(void) { LcdInit(); //Инициализация ЖКИ LcdClear(); //Очистка ЖКИ LcdFStr(FONT_1X,(unsigned char*)PSTR("START...")); //Вывод приветствия LcdUpdate(); //Обновление экрана _delay_ms(1000); //Пауза LcdClear(); //Очистка экрана //setka_x (); //Запуск отрисовки оси X setka_y (); //Запуск отрисовки оси Y //znacheniya (); //Вывод значений осей char buffer[16] = ""; //Переменная температуры char int temp; int shag=0; //Переменная шага графика int tempint; //Значение температуры в int //int test=20; sei(); //Разрешение прерываний while(1) { temp = temp_18b20(); //Пишем в переменную значение температуры if(temp > 1000) //если температура <0 {temp = 4096 - temp; temp = -temp;} //маркировка отрицательной температуры // sprintf(buffer, "%i.%i", temp, temp%1); //Конвертирование int в char sprintf(buffer, "%i", temp, temp%1); //Конвертирование int в char LcdGotoXYFont(5,1); //Установка в координаты 1,1 LcdStr(FONT_1X,(unsigned char*)buffer); LcdUpdate(); tempint = atoi(buffer); //Конвертация char в int // LcdLine ( shag, 46, shag, 0-tempint, PIXEL_ON); LcdUpdate(); //Вывод прямой на экран // LcdLine ( shag, 20, shag, test, PIXEL_ON); LcdUpdate(); //Вывод прямой на экран // LcdPixel (shag, tempint+10, PIXEL_ON); LcdUpdate(); //На экране!!! // LcdPixel (shag, 60-tempint, PIXEL_ON); LcdUpdate(); //при 5,1 буффер LcdPixel (shag, 60-tempint, PIXEL_ON); LcdUpdate(); //при 5,1 буффер shag=shag+1; //Добавляем к переменной Шага 1-цу LcdLine ( shag, 20, shag, 47, PIXEL_OFF); LcdUpdate(); //Вывод прямой на экран if(shag==t) //Если достигли границы прорисовки графика {shag=0;} //Идем в самое начало } }
Датчик температуры ds18b20 подключен к выводу PORTD2, ЖКИ подключен к выводам порта B. Библиотека для ЖКИ работает через аппаратный интерфейс SPI, таким образом будут задействованы выводы микроконтроллера предназначенные для его перепрошивки по интерфейсу SPI.
А схема есть?
А схема есть?