ATtiny2313 + DHT11 (Arduino IDE)

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 МГц)

Добавить комментарий

Войти с помощью: