#include // библиотека для работы с датчиком DS18B20 OneWire ds(10); // подключаем уличный датчик к 10 пину //Пин подключен к SH_CP входу 74HC595 int clockPin = 6; //Пин подключен к ST_CP входу 74HC595 int latchPin = 7; //Пин подключен к DS входу 74HC595 int dataPin = 8; int tempHomePin = A0; // градусник в помещении // Пины разрядов цифер int pins_numbers[4] = {2, 3, 4, 5}; // Биты для отображения цифер от 0-9, минуса и символ градуса цельсия byte numbers_array[22] = { B00111111, B00000110, B01011011, B01001111, // 0 1 2 3 B01100110, B01101101, B01111101, B00000111, // 4 5 6 7 B01111111, B01101111, B01000000, B01100011, // 8 9 - о // цифры с точкой внизу (+12 к индексу элемента) B10111111, B10000110, B11011011, B11001111, // 0 1 2 3 B11100110, B11101101, B11111101, B10000111, // 4 5 6 7 B11111111, B11101111 // 8 9 }; int cel_celsius = 0; // переменная для хранения градусов на улице float tempHome = 0; // переменная для хранения градусов в помещении const long tempInterval = 3000; // интервал запроса актуальной температуры unsigned long previousMillis = 0; // время предыдущего запроса unsigned long previousMillis_delay = 0; // хранения последней даты срабатывания, для второй задержки bool startQuery = false; // флаг, для обозначения начала запроса температуры bool firstQuery = true; // флаг первого запуска, при котором получаем температуру без задержек bool showhome = true; // флаг, который указывают какую температуру показывать - комнату или улицу int sec_show = 5000; // интервал смены отображения погоды unsigned long showhomeMillis_delay = 0; // хранения последней переключения градусников // функция для вывода чисел на индикаторе void showNumber(int numNumber, int number){ // зажигаем нужные сегменты digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, numbers_array[number]); digitalWrite(latchPin, HIGH); // включаем нужный разряд(одну из четырех цифр) int num_razryad = pins_numbers[numNumber-1]; for(int i; i<4; i++){ // выключаем все digitalWrite(pins_numbers[i], HIGH); } // включаем нужную digitalWrite(num_razryad, LOW); delay(5); } void setup() { //устанавливаем режим OUTPUT pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); for(int i; i<4; i++){ pinMode(pins_numbers[i], OUTPUT); digitalWrite(pins_numbers[i], HIGH); } Serial.begin(9600); // меняем опорное напряжение на 1.1 В, относительно которого происходят аналоговые измерения analogReference(INTERNAL); } void loop() { // зажигаем дисплей только после получения температуры if(!firstQuery){ if(showhome){ // градусник в помещении char digHome[5]; // дробное число переводим в десятичное и разбиваем на символы // умножаем на 100, чтоб откинуть дробную часть sprintf(digHome,"%d", (int)(tempHome * 100)); // тут отрицательных температур не будет // и меньше 10 градусов тоже не будет // поэтому не буду заморачиваться с лишними условиями showNumber(4, digHome[0] - '0'); showNumber(3, (digHome[1] - '0') + 12); // число с точкой внизу showNumber(2, digHome[2] - '0'); }else{ // градусник на улице // разбираем число градусов по одному символу char digStreet[2]; sprintf(digStreet,"%d",abs(cel_celsius)); // включить сразу несколько цифр нельзя, поэтому очень быстро показываем по одной if(abs(cel_celsius) > 9){ showNumber(3, digStreet[0] - '0'); showNumber(2, digStreet[1] - '0'); // если ниже нуля, то вывод знака минуса if(cel_celsius < 0){ showNumber(4, 10); } }else{ showNumber(2, digStreet[0] - '0'); // если ниже нуля, то вывод знака минуса if(cel_celsius < 0){ showNumber(3, 10); } } } showNumber(1, 11); // значок градуса } // переменные для работы с температурным датчиком byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius; // проверяем пришло ли время получить актуальную температуру unsigned long currentMillis = millis(); if ( (currentMillis - previousMillis >= tempInterval) || startQuery || firstQuery) { previousMillis = currentMillis; // читаем данные от датчика на улицы if ( !ds.search(addr)) { ds.reset_search(); //delay(250); return; } // если ни чего не получили или получили не понятные данные if (OneWire::crc8(addr, 7) != addr[7]) { return; } // читаем первый байт и определяем тип датчика switch (addr[0]) { case 0x10: // DS18S20 type_s = 1; break; case 0x28: // DS18B20 type_s = 0; break; case 0x22: // DS1822 type_s = 0; break; default: return; } // делаем запрос на получение данных от датчика ds.reset(); ds.select(addr); ds.write(0x44); // ждем startQuery = true; // delay(1000); if ( currentMillis - previousMillis_delay >= 1000 ) { previousMillis_delay = currentMillis; }else{ return; } startQuery = false; // и получаем ответ present = ds.reset(); ds.select(addr); ds.write(0xBE); // берем только первые 9 байт for ( i = 0; i < 9; i++) { data[i] = ds.read(); } // данные приходят в битах, переводим их в десятичное число int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } celsius = (float)raw / 16.0; // для удобства округляем до целых cel_celsius = round(celsius); Serial.print("DS18B20: "); Serial.println(celsius); // читаем комнатный датчик int reading = analogRead(tempHomePin); // переводим в градусы цельсия tempHome = reading / 9.31; Serial.print("LM35: "); Serial.println(tempHome); firstQuery = false; } // смена отображения градусников: в помещении / на улице if ( currentMillis - showhomeMillis_delay >= sec_show ) { showhomeMillis_delay = currentMillis; showhome = !showhome; } }