Съдържание:

Монитор на температурата и нивото на осветеност с показване на LCD NOKIA 5110: 4 стъпки
Монитор на температурата и нивото на осветеност с показване на LCD NOKIA 5110: 4 стъпки

Видео: Монитор на температурата и нивото на осветеност с показване на LCD NOKIA 5110: 4 стъпки

Видео: Монитор на температурата и нивото на осветеност с показване на LCD NOKIA 5110: 4 стъпки
Видео: Zigbee датчик освещенности, температуры и влажности с экраном на электронных чернилах Moes 2024, Юли
Anonim
Image
Image

Здравейте всички!

В този раздел правим просто електронно устройство за наблюдение на температурата и нивото на светлината. Измерванията на тези параметри се показват на LCD NOKIA 5110. Устройството се основава на микроконтролера AVR ATMEGA328P. Устройството за наблюдение е оборудвано с цифров термометър DS18B20 и фоторезистор за измерване на нивото на светлината.

Стъпка 1: Описание на компонентите

Описание Компоненти
Описание Компоненти
Описание Компоненти
Описание Компоненти

Основни компоненти на устройството за наблюдение:

  • Микроконтролер AVR «ATMEGA328P»
  • Монохромен графичен LCD «NOKIA 5110»
  • Програмируема разделителна способност 1-жичен цифров термометър «DS18B20»
  • Резистор, зависим от светлина
  • Проводници

Микроконтролер AVR «ATMEGA328P»

Устройството за наблюдение използва следните периферни функции на микроконтролера:

  1. 16-битов таймер/прекъсване на брояча
  2. 8-канален 10-битов ADC
  3. Главен/подчинен SPI сериен интерфейс

Монохромен графичен LCD «NOKIA 5110»

Спецификации:

  1. 48 x 84 точки LCD дисплей
  2. Интерфейс на серийна шина с максимална висока скорост 4 Mbits/S
  3. Вътрешен контролер/драйвер «PCD8544»
  4. LED подсветка
  5. Работете при напрежение 2.7-5 волта
  6. Ниска консумация на енергия; подходящ е за приложения на батерии
  7. Температурен диапазон от -25˚C до +70˚C
  8. Поддържа CMOS вход за сигнал

Работа с LCD адрес (адресиране):

Адресната подредба на паметта, която се показва на LCD дисплея (DDRAM), е матрица, която се състои от 6 реда (Y адрес) от Y-адрес 0 до Y-адрес 5 и 84 колони (X адрес) от X-адрес 0 до X- Адрес 83. Ако потребителят иска достъп до позицията на показване на резултата на LCD дисплея, трябва да се позове на връзката между X-адрес и Y-адрес.

Данните, които ще бъдат изпратени за показване, са 8 бита (1 байт) и ще бъдат подредени като вертикална линия; в този случай Bit MSB ще бъде по -нисък и Bit LSB ще бъде по -горен, както е показано на снимката.

Програмируема разделителна способност 1-жичен цифров термометър DALLAS «DS18B20»

Характеристика:

  1. Уникалният 1-Wire® интерфейс изисква само един порт за връзка
  2. Намалете броя на компонентите с интегриран температурен сензор и EEPROM
  3. Измерва температури от -55 ° C до +125 ° C (-67 ° F до +257 ° F)
  4. ± 0,5 ° C Точност от -10 ° C до +85 ° C
  5. Програмируема разделителна способност от 9 бита до 12 бита
  6. Не са необходими външни компоненти
  7. Режимът на паразитно захранване изисква само 2 извода за работа (DQ и GND)
  8. Опростява разпределените приложения за температурно измерване с възможност за многократно подаване
  9. Всяко устройство има уникален 64-битов сериен код, съхраняван във вградения ROM
  10. Гъвкави, дефинирани от потребителя енергонезависими (NV) алармени настройки с команда за търсене на аларма Идентифицира устройства с температури извън програмирани граници

Приложения:

  1. Термостатичен контрол
  2. Индустриални системи
  3. Потребителски продукти
  4. Термометри
  5. Термично чувствителни системи

Резистор, зависим от светлина

Светлозависим резистор (LDR) е преобразувател, който променя съпротивлението си, когато светлината пада върху повърхността му.

Обикновено LDR ще има от един мегаОм до два мегаома при пълна тъмнина, от десет до двадесет килоОма при десет LUX, от два до пет килоома при 100 LUX. Съпротивлението между двата контакта на сензора намалява с интензитета на светлината или проводимостта между два контакта на сензора се увеличава.

Използвайте верига с делител на напрежение, за да преобразувате промяната на съпротивлението в промяна на напрежението.

Стъпка 2: Код на фърмуера на микроконтролера

#ifndef F_CPU #определи F_CPU 16000000UL // казваща кристална честота на кристала (16 MHz AVR ATMega328P) #endif

// SPI ИНТЕРФЕЙС ОПРЕДЕЛЯ #дефинирайте MOSI 3 // MOSI това е PORT B, PIN 3 #define MISO 4 // MISO е PORT B, PIN 4 #define SCK 5 // SCK е PORT B, PIN 5 #define SS 2 // SS това е PORT B, PIN 2

// ВЪЗСТАНОВЯВАЙТЕ ДИСПЛЕЯ #define RST 0 // RESET това е ПОРТ В, ПИН 0

// DISPLAY MODE SELECT - Вход за избор на команда/адрес или въвеждане на данни. #define DC 1 // DC това е PORT B, PIN 1

// кодира масив от отрицателни знациstatic const unsigned char neg [4] = {0x30, 0x30, 0x30, 0x30};

// кодира масив от цифри [0..9] static const unsigned char font6x8 [10] [16] = {{0xFC, 0xFE, 0xFE, 0x06, 0x06, 0xFE, 0xFE, 0xFC, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 0 {0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00}, // 1 { 0x0C, 0x8E, 0xCE, 0xE6, 0xE6, 0xBE, 0x9E, 0x0C, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 2 {0x00, 0x04, 0x06, 0x26, 0x76, 0xD,, 0x8C, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 3 {0x3C, 0x3E, 0x7C, 0x60, 0x60, 0xFC, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01}, // 4 {0x1C, 0x3E, 0x3E, 0x36, 0x36, 0xF6, 0xF6, 0xE4, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 5 {0xFC, 0xFE, 0xFE, 0x36, 0x36, 0xF6, 0xF6, 0xE4, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 6 {0x04, 0x06, 0x06, 0x86, 0xE6, 0xEE, 0xEx, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00}, // 7 {0xCC, 0xFE, 0xFE, 0x36, 0x36, 0xFE, 0xFE, 0xCC, 0x01, 0x03, 0x03, 0x03, 0x03, 0х03 0x0 3, 0x01}, // 8 {0x3C, 0x7E, 0x7E, 0x66, 0x66, 0xFE, 0xFE, 0xFC, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01} // 9};

// кодира масив от дума "TEMP:" static const unsigned char TEMP_1 [165] = {0x02, 0x06, 0x06, 0xFE, 0xFE, 0xFE, 0x06, 0x06, 0x02, 0x00, 0xFC, 0xFE, 0xFE, 0x26, 0x26, 0x24, 0x00, 0xFC, 0xFE, 0xFE, 0x1C, 0x38, 0x70, 0x38, 0x1C, 0xFE, 0xFE, 0xFC, 0x00, 0xFC, 0xFE, 0xFE, 0x66, 0x66, 0x7E, 0x7C, 0x3, 0x7E, 0x7C, 0x3 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0х00 0x01, 0x03, 0x01, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0C, 0x1E, 0x33, 0x33, 0x1E, 0x0C, 0x00, 0xF8, 0x0C, 0x00, 0xF8, 0x9C, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x01,};

// кодира масив от дума "LUX:" const unsigned char TEMP_2 [60] = {0xFC, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xFC, 0x00, 0x00, 0xFC, 0xFE, 0xFC, 0x00, 0x04, 0x8E, 0xDE, 0xFC, 0xF8, 0xFC, 0xDE, 0x8E, 0x04, 0x00, 0x8C, 0x8C, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x01};

#включва

#включи #включи

// Инициализация на портовеvoid Port_Init () {DDRB = (1 << MOSI) | (1 << SCK) | (1 << SS) | (1 << RST) | (1 << DC); // Задайте MOSI, SCK, SS, RST, DC като изход, всички останали вход PORTB | = (1 << RST); // Задайте RST извод като висок PORTB | = (1 << SS); Деактивиране на DDRC = 0xFFu; // Задайте всички изводи на PORTC като изход. DDRC & = ~ (1 << 0); // Прави първия извод на PORTC като вход PORTC = 0x00u; // Задайте ниски всички щифтове на PORTC, което го изключва. }

// ADC Initialization void ADC_init () {// Активиране на ADC, честота на извадката = osc_freq/128 задаване на прескалиране на максимална стойност, 128 ADCSRA | = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); ADMUX = (1 << REFS0); // Изберете еталон на напрежение за ADC // Изберете нула на канал по подразбиране с помощта на регистъра за избор на мултиплексор на ADC (ADC0). }

// Функция за четене на резултата от аналогово -цифрово преобразуване uint16_t get_LightLevel () {_delay_ms (10); // Изчакайте известно време каналът да избере ADCSRA | = (1 << ADSC); // Стартирайте преобразуването на ADC, като зададете бит ADSC. запишете 1 на ADSC докато (ADCSRA & (1 << ADSC)); // изчакайте завършването на преобразуването // ADSC отново става 0 до тогава, изпълнявайте цикъла непрекъснато _delay_ms (10); връщане (ADC); // Връща 10-битовия резултат}

// SPI Initialization void SPI_Init () {SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); регистрирам }

// инициализираме 16 битов Timer1, прекъсване и променлива void TIMER1_init () {// настройка на таймер с прескалиране = 256 и режим CTC TCCR1B | = (1 << WGM12) | (1 << CS12); // инициализираме брояча TCNT1 = 0; // инициализираме стойността за сравнение - 1 сек. OCR1A = 62500; // разрешаване на прекъсване за сравнение TIMSK1 | = (1 << OCIE1A); // разрешаване на глобални прекъсвания sei (); }

// Display Enable void SPI_SS_Enable () {PORTB & = ~ (1 << SS); // Активиране на SS щифта към логика 0}

// Display Disable void SPI_SS_Disable () {PORTB | = (1 << SS); // Деактивиране на SS щифта към логика 1}

// Функция за изпращане на данни в буфера за показване void SPI_Tranceiver (неподписани символни данни) {SPDR = данни; // Зареждаме данни в буфера while (! (SPSR & (1 << SPIF))); // Изчакайте, докато предаването завърши}

// Нулиране на дисплея в началото на инициализацията void Display_Reset () {PORTB & = ~ (1 << RST); _ закъснение_ms (100); PORTB | = (1 << RST); }

// Функция за запис на команда void Display_Cmnd (беззнакови char данни) {PORTB & = ~ (1 << DC); // прави DC pin към логика 0 за командна операция SPI_Tranceiver (данни); // изпращане на данни в регистър на данни PORTB | = (1 << DC); // направете DC pin към логиката висока за работа с данни}

// Инициализиране на Display void Display_init () {Display_Reset (); // нулиране на дисплея Display_Cmnd (0x21); // набор от команди в режим на добавяне Display_Cmnd (0xC0); // задайте напрежението, като изпратите C0 означава VOP = 5V Display_Cmnd (0x07); // задаване на темп. коефициент до 3 Display_Cmnd (0x13); // зададена стойност на напрежение Bias System Display_Cmnd (0x20); // команда в основен режим Display_Cmnd (0x0C); // показва резултата в нормален режим}

// Изчистване на пустотата на дисплея Display_Clear () {PORTB | = (1 << DC); // прави DC pin към логиката висока за работа с данни за (int k = 0; k <= 503; k ++) {SPI_Tranceiver (0x00);} PORTB & = ~ (1 << DC); // прави DC pin към логика нула за командна операция}

// задаваме колоната и реда в позиция на показване на резултата на LCD дисплея void Display_SetXY (беззнаков знак x, беззнаков символ y) {Display_Cmnd (0x80 | x); // колона (0-83) Display_Cmnd (0x40 | y); // ред (0-5)}

// Функция за показване на отрицателен знак void Display_Neg (unsigned char neg) {Display_SetXY (41, 0); // Задайте адреса на позицията на дисплея за (int index = 0; index0) {SPDR = 0x30;} // Заредете данните в буфера на дисплея (покажете отрицателен знак) else {SPDR = 0x00;} // Заредете данните в буфера на дисплея (ясен отрицателен знак) while (! (SPSR & (1 << SPIF))); // Изчакайте, докато предаването завърши _delay_ms (100); }}

// Функция за изчистване на цифровия знак void Off_Dig (unsigned char x, unsigned char y) {Display_SetXY (x, y); // Задайте адреса на позицията на дисплея (най -горния ред) за (int index = 0; index <8; index ++) {SPI_Tranceiver (0);} // Заредете данните в буфера на дисплея (изчистете горната част на цифровия знак) y ++; Display_SetXY (x, y); // Задайте адреса на позицията на дисплея (долния ред) за (int index = 0; index <8; index ++) {SPI_Tranceiver (0);} // Заредете данните в буфера на дисплея (изчистете долната част на цифровия знак)}

// Функция за показване на цифров знак void Display_Dig (int dig, unsigned char x, unsigned char y) {Display_SetXY (x, y); // Задайте адреса на позицията на дисплея (горен ред) за (int index = 0; index <16; индекс ++) {if (индекс == 8) {y ++; Display_SetXY (x, y);} // Задайте адреса на позицията на дисплея (долния ред) SPI_Tranceiver (font6x8 [изкопайте] [индекс]); // Зарежда кодове масив от цифри данни в буфера на дисплея _delay_ms (10); }}

// Инициализация на DS18B20 неподписан символ DS18B20_init () {DDRD | = (1 << 2); // Задайте PD2 щифт на PORTD като изход PORTD & = ~ (1 << 2); // Задайте пина PD2 като нисък _delay_us (490); // Време за инициализация DDRD & = ~ (1 << 2); // Задайте PD2 пина на PORTD като вход _delay_us (68); // Време OK_Flag = (PIND & (1 << 2)); // получавам импулс на сензора _delay_us (422); връщане OK_Flag; // сензорът за връщане на 0-ок е включен, сензорът за 1 грешка е изключен}

// Функция за четене на байт от DS18B20 unsigned char read_18b20 () {unsigned char i, data = 0; за (i = 0; i <8; i ++) {DDRD | = (1 << 2); // Задайте PD2 щифт на PORTD като изход _delay_us (2); // Време за DDRD & = ~ (1 1; // Следващ бит if (PIND & (1 << 2)) данни | = 0x80; // поставяне на бит в байт _delay_us (62);} връщане на данни;}

// Функция за запис на байт в DS18B20 void write_18b20 (беззнакови char данни) {unsigned char i; за (i = 0; i <8; i ++) {DDRD | = (1 << 2); // Задайте PD2 щифт на PORTD като изход _delay_us (2); // Време за if (данни & 0x01) DDRD & = ~ (1 << 2); // ако искаме да напишем 1, освобождаваме реда else DDRD | = (1 1; // Следващ бит _delay_us (62); // Време за DDRD & = ~ (1 << 2); // Задаваме PD2 пина на PORTD като вход _delay_us (2);}}

// Функция за показване на нивото на светлина void Read_Lux () {uint16_t буфер; без подпис int temp_int_1, temp_int_2, temp_int_3, temp_int_0; // едноцифрени, двуцифрени, тройни цифри, четвърт цифри буфер = get_LightLevel (); // чете резултата от аналогово -цифрово преобразуване на нивото на светлина temp_int_0 = буфер % 10000 /1000; // четвъртцифрен temp_int_1 = буфер % 1000 /100; // трицифрен temp_int_2 = буфер % 100 /10; // двуцифрен temp_int_3 = буфер % 10; // едноцифрено if (temp_int_0> 0) // ако резултатът е четвъртцифрено число {Display_Dig (temp_int_0, 32, 2); // показва 1 цифра ниво на осветеност Display_Dig (temp_int_1, 41, 2); // показване на 2 цифри ниво на осветеност Display_Dig (temp_int_2, 50, 2); // показва 3 цифри ниво на осветеност Display_Dig (temp_int_3, 59, 2); // показва 4-цифрено ниво на светлина} else {if (temp_int_1> 0) // ако резултатът е трицифрено число {Off_Dig (32, 2); // изчистване на 1 знак на номер Display_Dig (temp_int_1, 41, 2); // показва 1 цифра ниво на осветеност Display_Dig (temp_int_2, 50, 2); // показване на 2 цифри ниво на осветеност Display_Dig (temp_int_3, 59, 2); // показва 3-цифрено ниво на светлина} else {if (temp_int_2> 0) // ако резултатът е двуцифрено число {Off_Dig (32, 2); // изчистване на 1 знак на номер Off_Dig (41, 2); // изчистване 2 знак на номер Display_Dig (temp_int_2, 50, 2); // показва 1 цифра ниво на осветеност Display_Dig (temp_int_3, 59, 2); // показва 2-цифрено ниво на светлина} else // ако резултатът е едноцифрено число {Off_Dig (32, 2); // изчистване на 1 знак на номер Off_Dig (41, 2); // изчистване 2 знак на номер Off_Dig (50, 2); // изчистване на 3 знака на номер Display_Dig (temp_int_3, 59, 2); // показва 1 цифра ниво на осветеност}}}}

// Функция за показване на температурата void Read_Temp () {unsigned int буфер; без подпис int temp_int_1, temp_int_2, temp_int_3; // единични цифри, двойни цифри, тройни цифри, четвърти цифри без знак char Temp_H, Temp_L, OK_Flag, temp_flag; DS18B20_init (); // Инициализация на DS18B20 write_18b20 (0xCC); // Проверка на сензорен код write_18b20 (0x44); // Преобразуване на стартовата температура _delay_ms (1000); // Закъснение при анкетиране на сензора DS18B20_init (); // Инициализация на DS18B20 write_18b20 (0xCC); // Проверка на сензорен код write_18b20 (0xBE); // Команда за четене на съдържанието на сензорната RAM Temp_L = read_18b20 (); // Прочетете първите два байта Temp_H = read_18b20 (); temp_flag = 1; // 1-положителна температура, 0-отрицателна температура // Получаване на отрицателна температура if (Temp_H & (1 << 3)) // Sign Bit Check (ако е зададен бит-отрицателна температура) {sign int temp; temp_flag = 0; // флагът е зададен 0 - отрицателна температура temp = (Temp_H << 8) | Temp_L; temp = -temp; // Конвертираме допълнителния код в директен Temp_L = temp; Temp_H = temp >> 8; } буфер = ((Temp_H 4); temp_int_1 = буфер % 1000 /100; // трицифрен temp_int_2 = буфер % 100 /10; // двуцифрен temp_int_3 = буфер % 10; // едноцифрен

// Ако температурата е отрицателна индикация за температурата, иначе ясна

if (temp_flag == 0) {Display_Neg (1);} else {Display_Neg (0);} if (temp_int_1> 0) // ако резултатът е трицифрено число {Display_Dig (temp_int_1, 45, 0); // показва 1 цифра от температурата Display_Dig (temp_int_2, 54, 0); // показване на 2 цифри от температурата Display_Dig (temp_int_3, 63, 0); // показва 3-цифрена температура} else {if (temp_int_2> 0) // ако резултатът е двуцифрено число {Off_Dig (45, 0); // изчистване на 1 знак на номер Display_Dig (temp_int_2, 54, 0); // показва 1 цифра от температурата Display_Dig (temp_int_3, 63, 0); // показва 2-цифрена температура} else // ако резултатът е едноцифрено число {Off_Dig (45, 0); // изчистване на 1 знак на номер Off_Dig (54, 0); // изчистване 2 знак на номер Display_Dig (temp_int_3, 63, 0); // показва 1 цифра температура}}}

// Този ISR се задейства винаги, когато възникне съвпадение на брояча на таймера със стойността за сравнение (на всеки 1 секунда) ISR (TIMER1_COMPA_vect) {// Четене, показване на температурата и нивото на светлината Read_Temp (); Read_Lux (); }

// Функция за показване на думи "TEMP" и "LUX" void Display_label () {// Word "TEMP" Display_SetXY (0, 0); // Задайте адреса на позицията на дисплея (ред нагоре) за (int index = 0; index <105; index ++) {if (index == 40) {Display_SetXY (0, 1);} // Задайте адреса на позиция на дисплея (долния ред) if (индекс == 80) {Display_SetXY (72, 0);} // Задайте адреса на позицията на дисплея (горен ред) if (индекс == 92) {Display_SetXY (72, 1); } // Задайте адреса на позицията на дисплея (долния ред) SPDR = TEMP_1 [индекс]; // Зареждане на данни от масиви с кодове в буфера на дисплея while (! (SPSR & (1 << SPIF))); // Изчакайте, докато предаването завърши _delay_ms (10); } // Word "LUX" Display_SetXY (0, 2); // Задайте адреса на позицията на дисплея (ред нагоре) за (int index = 0; index <60; index ++) {if (index == 30) {Display_SetXY (0, 3);} // Задайте адреса на позиция на дисплея (долния ред) SPDR = TEMP_2 [индекс]; // Зареждане на данни от масиви с кодове в буфера на дисплея while (! (SPSR & (1 << SPIF))); // Изчакайте, докато предаването завърши _delay_ms (10); }}

int main (void)

{Port_Init (); // Порт инициализация ADC_init (); // ADC инициализация SPI_Init (); // Инициализация на SPI SPI_SS_Enable (); // Display Enable DS18B20_init (); // Инициализация на DS18B20 Display_init (); // Инициализация на дисплея Display_Clear (); // Показва ясен Display_label (); // Показване на думи "TEMP" и "LUX" TIMER1_init (); // Timer1 Инициализация. Започнете мониторинг. Получаване на параметри всяка секунда. // Безкраен цикъл while (1) {}}

Стъпка 3: Мигащ фърмуер към микроконтролер

Качване на HEX файл във флаш паметта на микроконтролера. Гледайте видеоклипа с подробно описание на изгарянето на флаш паметта на микроконтролера: Изгарянето на флаш паметта на микроконтролера …

Стъпка 4: Контрол на веригата на устройството

Контрол на веригата на устройството
Контрол на веригата на устройството
Контрол на веригата на устройството
Контрол на веригата на устройството

Свържете компонентите в съответствие със схематична диаграма.

Включете захранването и той работи!

Препоръчано: