DHT11 — датчик температуры и влажности. Цифровой датчик основаны на протоколе, который для связи использует один провод/шину с открытым коллектором, поэтому обязательна подтяжка резистором 5-10 кОм к плюсу питания. Датчик DHT11 может выпускаться в виде модуля в котором уже установлен подтягивающий резистор и светодиод (индикатор питания). Напряжение питания датчика может быть в диапазоне от 3,5 до 5 В, измерение температуры проводится в интервале от 0 до 50 ºС, а влажности от 20 до 95 %. Погрешность при измерении температуры может достигать 2 ºС, а влажности до 5 %.
В датчике установлен термистор для измерения температуры и емкостной датчик влажности представляющий из себя конденсатор с переменной емкостью, который содержит токопроводящие обкладки из медной фольги на текстолите. Этот конденсатор заключен в герметичный чехол, поверх которого расположен влагопоглощающий слой. При попадании частиц воды на этот слой, меняется его диэлектрическая проницаемость, что приводит к изменению емкости конденсатора.
Используя микроконтроллер ATiny2313 можно сделать простой измеритель температуры и влажности, в качестве индикатора используется модуль TM1637 который представляет собой 4-х разрядный семисегментный дисплей на базе драйвера TM1637.
С интервалом в 3 секунды поочередно на индикатор будет выводится показания влажности и температуры.
Перед загрузкой скетча рекомендую ознакомится со статьей — ATtiny2313 + Arduino IDE
byte data_dht[5]; void setup(){} void loop() { dht_read(); delay(3000); print_time(data_dht[2],0,7,1); delay(3000); print_time(data_dht[0],0,7,0); } void tm_dec(byte dig){ for(int i = 0; i < 8; i++) { DDRB |= (1 << 0);del(); if (dig & 0x01) DDRB &= ~(1 << 1); else DDRB |= (1 << 1);del(); DDRB &= ~(1 << 0);del(); dig = dig >> 1; } DDRB |= (1 << 0); DDRB &= ~(1 << 1);del(); DDRB &= ~(1 << 0);del(); if (((PINB >> 1) & 1) == 0) DDRB |= (1 << 1);del(); DDRB |= (1 << 0);del(); } void tm_stop(){ DDRB |= (1 << 1);del(); DDRB &= ~(1 << 0);del(); DDRB &= ~(1 << 1);del(); } void tm_start(){ DDRB |= (1 << 1);del(); } void print_time(int t, byte pd_t, int br, bool mn){ tm_start();tm_dec(0b10001000 + br);//tm_stop();tm_start(); tm_dec(0x40);tm_stop();tm_start(); int data0; if(mn == 1){data0 = 11;}else{data0 = 12;} int data1 = 10; int data2 = t / 10 % 10; int data3 = t % 10; for(byte n = 0; n < 4; n++){ int data; switch(n){ case 0: data = data0;break; case 1: data = data1;break; case 2: data = data2;break; case 3: data = data3;break; } switch(data){ // XGFEDCBA case 0: data = 0b00111111;break; // 0 case 1: data = 0b00000110;break; // 1 case 2: data = 0b01011011;break; // 2 case 3: data = 0b01001111;break; // 3 case 4: data = 0b01100110;break; // 4 case 5: data = 0b01101101;break; // 5 case 6: data = 0b01111101;break; // 6 case 7: data = 0b00000111;break; // 7 case 8: data = 0b01111111;break; // 8 case 9: data = 0b01101111;break; // 9 case 10: data = 0b00000000;break; // пусто case 11: data = 0b01111000;break; // t case 12: data = 0b01110110;break; // H } if(n == 0){data0 = data;} if(n == 1){data1 = data;} if(n == 2){data2 = data;} if(n == 3){data3 = data;} } switch(pd_t){ case 1 : data2 = data2+0b10000000;break; case 2 : data1 = data1+0b10000000;break; case 3 : data0 = data0+0b10000000;break; } tm_dec(0xC0);tm_dec(data0);tm_dec(data1);tm_dec(data2);tm_dec(data3);tm_stop(); } void del(){delayMicroseconds(200);} int dht_read(){ byte i = 0,i1 = 0; for(i = 0;i < 5;i++){data_dht[i] = 0;} DDRB |=(1 << 2); PORTB &= ~(1 << 2); delay(18); PORTB |= (1 << 2); delayMicroseconds(40); DDRB &= ~(1 << 2); delayMicroseconds(80); while(PINB & (1 << 2)); for (i = 0; i < 5; i++){ data_dht[i]=0; for (i1=0; i1<8; i1++){ while(!(PINB & (1 << 2))); delayMicroseconds(30); if (PINB & (1 << 2)){data_dht[i] |= 1 << (7-i1);} while(PINB & (1 << 2)); }}return 1;}
Скетч использует 1250 байт (61%) памяти устройства. Всего доступно 2048 байт.
Глобальные переменные используют 14 байт (10%) динамической памяти, оставляя 114 байт для локальных переменных. Максимум: 128 байт.Arduino IDE 1.8.9 | Плата для прошивки версии 1.2.5 (выбрать в менеджере плат)
Для расширения функциональных возможностей я решил в измеритель температуры и влажности добавить часы, для доработки Вам понадобятся всего две кнопки для установки времени.
Каждые 15 секунд на 3 секунды поочередно выводятся показания температуры и влажности. Время устанавливается кнопками HH MM, точка на индикаторе мигает в такт секундам. Индикатор TM1637 в моем случае имеет разделительные точки в разрядах, но можно применить индикатор с двумя точками по середине.
byte data_dht[5]; int it,it1,hh,mm,bb; void setup(){ DDRB = 0b00000000; PORTB |= (1 << 3) | (1 << 4); cli(); TCCR1A = 0; TCCR1B = 0; OCR1A = 18750; // 0.1 s (25000 для 16 МГц) TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS11) | (1 << CS10); // 64 TIMSK |= (1 << OCIE1A); sei(); } void loop() { if(((PINB >> 3) & 1) == 0){mm++; if(mm>59){mm = 0;} delay(200);} if(((PINB >> 4) & 1) == 0){hh++; if(hh>23){hh = 0;} delay(200);} if(it == 0 || it == 300){dht_read();delay(300);} else if(it > 100 && it < 130){print_time(data_dht[2],0,7,1);} else if(it > 250 && it < 280){print_time(data_dht[0],0,7,0);} else if(it > 400 && it < 430){print_time(data_dht[2],0,7,1);} else if(it > 550 && it < 580){print_time(data_dht[0],0,7,0);} else{print_time(hh * 100 + mm, bb, 7, 2);if(it1 <= 5){bb = 2;}else{bb = 0;}} } void tm_dec(byte dig){ for(int i = 0; i < 8; i++) { DDRB |= (1 << 0);del(); if (dig & 0x01) DDRB &= ~(1 << 1); else DDRB |= (1 << 1);del(); DDRB &= ~(1 << 0);del(); dig = dig >> 1; } DDRB |= (1 << 0); DDRB &= ~(1 << 1);del(); DDRB &= ~(1 << 0);del(); if (((PINB >> 1) & 1) == 0) DDRB |= (1 << 1);del(); DDRB |= (1 << 0);del(); } void tm_stop(){ DDRB |= (1 << 1);del(); DDRB &= ~(1 << 0);del(); DDRB &= ~(1 << 1);del(); } void tm_start(){ DDRB |= (1 << 1);del(); } void print_time(int t, byte pd_t, int br, byte mn){ tm_start();tm_dec(0b10001000 + br);//tm_stop();tm_start(); tm_dec(0x40);tm_stop();tm_start(); int data0,data1; if(mn == 1){data0 = 11;data1 = 10;} if(mn == 0){data0 = 12;data1 = 10;} if(mn == 2){data0 = t / 1000;data1 = t / 100 % 10;} int data2 = t / 10 % 10; int data3 = t % 10; for(byte n = 0; n < 4; n++){ int data; switch(n){ case 0: data = data0;break; case 1: data = data1;break; case 2: data = data2;break; case 3: data = data3;break; } switch(data){ // XGFEDCBA case 0: data = 0b00111111;break; // 0 case 1: data = 0b00000110;break; // 1 case 2: data = 0b01011011;break; // 2 case 3: data = 0b01001111;break; // 3 case 4: data = 0b01100110;break; // 4 case 5: data = 0b01101101;break; // 5 case 6: data = 0b01111101;break; // 6 case 7: data = 0b00000111;break; // 7 case 8: data = 0b01111111;break; // 8 case 9: data = 0b01101111;break; // 9 case 10: data = 0b00000000;break; // пусто case 11: data = 0b01111000;break; // t case 12: data = 0b01110110;break; // H } if(n == 0){data0 = data;} if(n == 1){data1 = data;} if(n == 2){data2 = data;} if(n == 3){data3 = data;} } switch(pd_t){ case 1 : data2 = data2+0b10000000;break; case 2 : data1 = data1+0b10000000;break; case 3 : data0 = data0+0b10000000;break; } tm_dec(0xC0);tm_dec(data0);tm_dec(data1);tm_dec(data2);tm_dec(data3);tm_stop(); } void del(){delayMicroseconds(200);} int dht_read(){ byte i = 0,i1 = 0; for(i = 0;i < 5;i++){data_dht[i] = 0;} DDRB |=(1 << 2); PORTB &= ~(1 << 2); delay(18); PORTB |= (1 << 2); delayMicroseconds(40); DDRB &= ~(1 << 2); delayMicroseconds(80); while(PINB & (1 << 2)); for (i = 0; i < 5; i++){ data_dht[i]=0; for (i1=0; i1<8; i1++){ while(!(PINB & (1 << 2))); delayMicroseconds(30); if (PINB & (1 << 2)){data_dht[i] |= 1 << (7-i1);} while(PINB & (1 << 2)); }}return 1;} ISR(TIMER1_COMPA_vect){ it++;it1++; if(it1 > 9){it1 = 0;} if(it > 599){mm++;it = 0;} if(mm > 59){hh++;mm = 0;} if(hh > 23){hh = 0;} }
При использовании кварцевого резонатора на 16 МГц измените строку:
OCR1A = 18750; // 0.1 s (25000 для 16 МГц)
на
OCR1A = 25000; // 0.1 s (25000 для 16 МГц)