На ATtiny2313 с использованием цифрового датчика температуры DS18B20 можно собрать простой электронный термометр. В качестве индикатора электронного термометра используется модуль TM1637 который представляет собой 4-х разрядный семисегментный дисплей на базе драйвера TM1637. Дисплей имеет десятичные точки в разрядах.
DS18B20 это датчик температуры с цифровым последовательным интерфейсом 1-Wire.
Основные характеристики датчика:
- Погрешность измерения не больше 0,5 °С (для температур от -10 °С до +85 °С)
- Температурный диапазон измерений от -55 С до +125 °С
- Датчик питается напряжением от 3,3 В до 5 В.
- Разрешающая способность от 9 до 12 бит
- Каждый датчик обладает своим уникальным серийным кодом (адрес)
- Не требуются дополнительные внешние элементы.
- Можно подключить сразу до 127 датчиков к одной линии связи.
- Информация передается по протоколу 1-Wire.
Схема подключения
При использовании модуля устанавливать подтягивающий резистор не нужно, он уже установлен на плате модуля.
Схема электронного термометра
Электронный термометр может измерять отрицательную температуру, старший разряд индикатора рассчитан на индикацию знака «-«.
Перед загрузкой скетча рекомендую ознакомится со статьей — ATtiny2313 + Arduino IDE
void setup(){} void loop() { if(read_temp()<0){print_time(abs(read_temp()),1,7,1);} else{print_time(read_temp(),1,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 = 10;} int 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 = 0b01000000;break; // - } 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);} // reset uint8_t therm_reset(){ uint8_t i; PORTB &= ~(1 << 2); DDRB |= (1 << 2); delayMicroseconds(480); DDRB &= ~(1 << 2); delayMicroseconds(60); i=((PINB >> 2) & 1); delayMicroseconds(420); return i; } // write bit void therm_write_bit(uint8_t bit){ PORTB &= ~(1 << 2); DDRB |= (1 << PB2); delayMicroseconds(1); if(bit) DDRB &= ~(1 << PB2); delayMicroseconds(60); DDRB &= ~(1 << PB2); } // read bit uint8_t therm_read_bit(void){ uint8_t bit=0; PORTB &= ~(1 << PB2); DDRB |= (1 << PB2); delayMicroseconds(1); DDRB &= ~(1 << PB2); delayMicroseconds(14); if(PINB & (1 << 2)) bit=1; delayMicroseconds(45); return bit; } // read byte uint8_t therm_read_byte(void){ uint8_t i=8, n=0; while(i--){n>>=1;n|=(therm_read_bit()<<7);} return n; } // write byte void therm_write_byte(uint8_t byte){ uint8_t i=8; while(i--){therm_write_bit(byte&1);byte >>= 1; } } // read temp int read_temp(){ uint8_t temperature[2]; float temper; therm_reset(); therm_write_byte(0xCC); therm_write_byte(0x44); while(!therm_read_bit()); therm_reset(); therm_write_byte(0xCC); therm_write_byte(0xBE); temperature[0]=therm_read_byte(); temperature[1]=therm_read_byte(); therm_reset(); temper = (temperature[1] << 8 | temperature[0])/1.60; return (int)temper; }
Здравствуйте. А для ардуино скетч термометра на данном индикаторе можете выложить. В сети полно примеров, но они без минуса. А сам разобраться не могу(
Этот скетч без переделок будет работать на ардуино нано
PB0=D8
PB1=D9
PB2=D10
Спасибо, заработало)
Только у меня дисплей с двоеточием, и показывает как на фото. Где выключить младший разряд, или в идеале сделать знак градуса?
int data3 = t % 10;
замените на:
int data3 = 12;
после строчки:
case 11: data = 0b01000000;break;
добавьте строчку:
case 12: data = 0b00000000;break;
и составьте из байта 0b00000000 знак градуса
Огромное спасибо!
Теперь термометр с градусом.
Подскажите, где встроить задержку секунд на 5, дабы исключить самонагрев датчика от частого опроса.
Пробовал добавить delayMicroseconds(5000); перед последней фигурной скобкой, разницы в работе не заметил
void loop(){
if(read_temp()<0){print_time(abs(read_temp()),1,7,1);}
else{print_time(read_temp(),1,7,0);}
delay(5000);
}
Ага, я понял свою ошибку. Использовал не тот оператор в не том месте)))
Теперь работает идеально!
Я вам премного благодарен!
Осталось корпус напечатать, и установить на место)
Ps: как бы научится так в программировании разбираться? С ардуинками давно знаком, а дальше правки чужих кодов не могу(