В данной статье мы рассмотрим создание на основы платы Arduino Nano и датчика температуры DS18B20 термометра с красивым внешним видом для измерения температуры в комнате. Измеренная температура будет отображаться с помощью адресной светодиодной ленты.
Необходимые компоненты
- Плата Arduino Nano (купить на AliExpress).
- Digilent WS2812 Addressable LED Strip (адресная светодиодная лента) (купить на AliExpress).
- Датчик температуры DS18B20 (купить на AliExpress).
- Кнопочный переключатель.
Общие принципы работы проекта
В данной статье мы рассмотрим создание термометра для измерения комнатной температуры, то есть в диапазоне примерно от 10 до 35 градусов Цельсия.
Измерять температуру мы будем с помощью датчика DS18B20, обладающего точностью измерения температуры в 0,5 градуса. Более подробно о его характеристиках и способу подключения к плате Arduino вы можете прочитать в данной статье. Измеренная температура будет отображать на адресном светодиодном индикаторе (LED bar) WS2812, который содержит 50 светодиодов. С помощью данного индикатора значение температуры будет отображаться весьма наглядно, используя для этого цвет светодиодов.
При изменении температуры цвет свечения светодиодов будет постепенно изменяться от темно-синего (для низких температур), далее к светло-синему, затем к зеленому (область комфортных температур) и далее до красного (высокие температуры). То есть одного беглого взгляда на термометр будет достаточно чтобы определить находится ли температура в "комфортной зоне" или нет.
Кнопочный переключатель в нашем проекте будет использоваться для изменения режимов работы термометра. Когда переключатель будет отжат, термометр будет функционировать в режиме "DOT" (точка) и текущая температура будет отображаться с помощью свечения одного светодиода.
При нажатии кнопочного переключателя режим работы термометра будет изменяться на линейный. В этом режиме будут светиться все светодиоды, начиная от начальной точки и до измеренной температуры. Если мы нажмем на кнопочный переключатель еще раз, то термометр будет переключать в тестовый режим – все светодиоды на индикаторы будут последовательно зажигаться один за другим. Если мы нажмем кнопку еще раз, то термометр снова вернется в режим DOT и т.д.
Схема проекта
Схема комнатного термометра на основе платы Arduino Nano представлена на следующем рисунке.
Исходный код программы (скетча)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
#include "Wire.h" // библиотека для работы с протоколом I2C #include <OneWire.h> #include <DallasTemperature.h> #include <Adafruit_NeoPixel.h> #define ONE_WIRE_BUS 5 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); float Celcius=0; int buttonPin = 2; // к этому контакту подключена кнопка int oldButtonVal = 0; #define NUM_PIXEL 50 #define PIN 6 Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXEL, PIN, NEO_GRB + NEO_KHZ800); int nPatterns = 3; int lightPattern = 1; int out =0; int t =0; void setup() { Serial.begin(9600); // последовательная связь со скоростью 9600 бод strip.begin(); clearStrip(); strip.show(); strip.setBrightness(10); pinMode(buttonPin, INPUT); digitalWrite(buttonPin, HIGH); // по умолчанию на контакте кнопки уровень HIGH, при нажатии кнопки на этом контакте уровень 0 sensors.begin(); } void testing(){ for(int L = 0; L<50; L++) { clearStrip(); strip.setPixelColor(L,wheel(((205+(L*3)) & 255)));// градиент от синего цвета (холодные температуры) к зеленому (комфортные температуры) и далее к красному (жаркие температуры), первое значение 205 = стартовый цвет, второе значение 42 = конечный цвет strip.show(); delay(100); } for(int L = 49; L>=0; L--) { clearStrip(); strip.setPixelColor(L,wheel(((205+(L*3)) & 255)));// градиент от синего цвета (холодные температуры) к зеленому (комфортные температуры) и далее к красному (жаркие температуры), первое значение 205 = стартовый цвет, второе значение 42 = конечный цвет strip.show(); delay(100); } delay(1000); } void dot() { sensors.requestTemperatures(); Celcius=sensors.getTempCByIndex(0)*2; int t = map(Celcius, 20, 70, 0, NUM_PIXEL); for(uint16_t L = 0; L<t; L++) { clearStrip(); strip.setPixelColor(L,wheel(((205+(L*3)) & 255))); // градиент от синего цвета (холодные температуры) к зеленому (комфортные температуры) и далее к красному (жаркие температуры), первое значение 205 = стартовый цвет, второе значение 42 = конечный цвет } strip.show(); //Output on strip Serial.print("The Temperature is: "); Serial.print(Celcius); delay(1000); } void line() { sensors.requestTemperatures(); Celcius=sensors.getTempCByIndex(0)*2; int t = map(Celcius, 20, 70, 0, NUM_PIXEL); for(uint16_t L = 0; L<t; L++) { strip.setPixelColor(L,wheel(((205+(L*3)) & 255))); // градиент от синего цвета (холодные температуры) к зеленому (комфортные температуры) и далее к красному (жаркие температуры), первое значение 205 = стартовый цвет, второе значение 42 = конечный цвет } strip.show(); //Output on strip Serial.print("The Temperature is: "); Serial.print(Celcius); delay(1000); } void loop() { // считываем нажатия кнопки int buttonVal = digitalRead(buttonPin); if (buttonVal == LOW && oldButtonVal == HIGH) {// кнопка была нажата lightPattern = lightPattern + 1; } if (lightPattern > nPatterns) lightPattern = 1; oldButtonVal = buttonVal; switch(lightPattern) { case 1: dot(); break; case 2: line(); break; case 3: testing(); break; } } //Color wheel ################################################################ uint32_t wheel(byte WheelPos) { if(WheelPos < 85) { return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } else if(WheelPos < 205) { WheelPos -= 85; return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } else { WheelPos -= 205; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } } void clearStrip(){ for(int i = 0; i < NUM_PIXEL; i++) { strip.setPixelColor(i, 0); } } |
А можно сделать уличный? Ведь ds18b20 от -55 до +125 градусов. Что для этого нужно?
Нужно внести изменения в строки int t = map(Celcius, 20, 70, 0, NUM_PIXEL), где вместо 20 и 70 поставить те границы диапазона температур, которые вам нужны
К соржалению у меня так ничего и не получилось. Программы void dot() { и void line() { абсолютно одинаковые, кроме строк
59 for(uint16_t L = 0; L<t; L++) {
60 clearStrip(); и строк
76 for(uint16_t L = 0; L<t; L++) {
77 нет ничего.
Пробовал вставить clearStrip(); режим line вообще не запускается. Непонятно.
Так разница между функциями void dot() и void line() как раз и заключается в наличии функции clearStrip() - из-за нее в режиме dot и светится всего один светодиод, а не все светодиоды до него как в режиме line. Попробуйте в цикл for подставлять вместо t какие-нибудь константные значения в диапазоне от 0 до 50 и посмотрите меняется ли у вас при этом что нибудь. А clearStrip() из void line() уберите
Я имел ввиду строку 76 for(uint16_t L = 0; L<t; L++) { , но она не отправилась. Строка 78 strip.setPixelColor(L,wheel(((205+(L*3)) & 255)));} это повышение температуры, а для понижения ничего нет.Я программировать еще не умею,спасибо за помощь,будем учиться.
Для понижения нужно просто цикл в обратную сторону развернуть, например, как в строке 44: for(int L = 49; L>=0; L--).
Применительно к 76 строке это тогда будет выглядеть следующим образом: for(uint16_t L = t-1; L>=0; L--).
Почему-то часть сообщения обрывается, ну я думаю Вы меня поняли.
В скетче void line строка 76 for(uint16_t L = 0; Lt,куда вставить for(uint16_t L = 0; L>t; L--) { ? У меня что-то ничего не получается.
А можно скинуть мне рабочий скетч.
Так строка 76 и есть цикл for. Я что то не очень понял что вы хотите с ней сделать. Скетч не могу, к сожалению, скинуть, мне же не на чем его отладить поскольку у меня нет этой схемы в собранном виде.
Все работает нормально кроме уменьшения температуры. С одним светодиодом изменение температуры изменяется и его положение, а со столбиком с ростом температуры растет вверх и остается там и при понижении температуры. Что изменить в скетче?
Ну если проблемы именно со столбиком, то это функция void line(). По всей видимости не совсем корректно работает строка с номером 78 в данной функции
У меня вопрос, почему при изменении температура вверх светодиодный столбик загорается вверх, а при уменьшении остается в верхнем положении и не изменяется.
А в режиме тестирования все корректно работает?
А вы можете подсказать как изменить показания от 50* до 120*
Вы имеете ввиду изменение диапазона измеряемых температур или использование адресной светодиодной ленты с большим количеством светодиодов?
Вы правильно поняли -диапазон Для бани .
Ну тогда вам нужен как минимум другой датчик температуры. Согласно даташиту DS18B20 имеет диапазон измерения температуры от -55°C до +125°C. А если другой датчик температуры, то и код программы тоже поменяется
А разве мой запрос не входит в диапазон DS18B20 до +125°C можно и до 100°C Ч то то получилось заменой этой строки в программе int t = map(Celcius, 50, 100, 0, NUM_PIXEL);
Тогда я перепутал, почему то я подумал что вам нужно измерение температуры до 150 градусов. Вам тогда для преобразования температуры необходимо записать int t = map(Celcius, 50, 120, 0, NUM_PIXEL); Тогда ваши градусы от 50 до 120 конвертируются в диапазон от 0 до NUM_PIXEL
Я очень много занимаюсь ремонтом радиотехники и меня все время напрягает когда кто то принесет какое нибудь самодельное изделие с просьбой отремонтировать. Схемы нет ,что производитель пытался сделать не понятно .Так и со скетчем -ладо был бы я крутым программистом я бы чужие скетчи щелкал бы как семечки ,но увы если я с ремонтируемым изделием еще могу разобраться ,то со скетчем увы я дуб.
Ну может в будущем потихоньку улучшите свои навыки в этом направлении. Из всех проектов, которые у меня есть на сайте, на мой взгляд, именно скетчи для Ардуино обладают наиболее простым для понимания кодом. Поэтому, если в будущем собираетесь улучшить свои навыки в программировании, наверное, вам стоит начать именно с платформы Ардуино
Из вашей же ветке изделий собрал в протеусе Часы бесконечности работают отлично -как часы
Ну, к сожалению от таких не очень приятных моментов никто не застрахован. Коды программ могут устаревать со временем и из-за этого переставать работать, либо просто может закрасться опечатка. Ну хотя бы другой аналогичный проект у вас без проблем заработал. У меня сейчас пока нет доступа к железу и поэтому я не могу так сразу найти опечатку/ошибку в этом скетче. Ну если кто из читателей поможет
Собрал сей градусник на ардуино нано 168 серии При первом включении показал температуру одним СД .При нагреве датчика СД точка пошла в верх ,при охлаждении вниз При нажатии кнопки выбора режимов ,переключилось на столбик ,при нагреве датчика столбик полез в красный диапазон ,при охлаждении ничего не происходит ???? .При повторном нажатии кнопки выбора режимов СД точка бегает в верх вниз .при следующим нажатии ничего не происходит ??? Кнопку выбора режимов приходится нажимать по несколько раз ???? Такое происходит пока не нажмешь кнопку сброса на плате ардуино ,потом все повторяется Разъясните где что искать ?
Добавьте в программу вывод значений температуры и значений переменной WheelPos в окно монитора последовательной связи. Я думаю, тогда вы быстро поймете в чем проблема
Если бы я был такой же умный в программировании как вы ,то я так бы и поступил ,а так я товарищь дерево и пока мне не обьяснишь что к чему для меня это тёмный лес .
Посмотрите для примера эту статью - подключение датчика температуры и влажности DHT22 к Arduino. В ней есть пример вывода отладочной информации в окно монитора последовательной связи. Там в функции void setup() нужно инициализировать сначала последовательный порт командой Serial.begin(115200), а потом в функции void loop() просто выводить нужную информацию с помощью функции Serial.print.
Попытка запустить изделие в Proteus 8 Professional результатов не принес по сравнению с другими изделиями при вставке скетча в протеус .Ваш не работает ни при каких попытках запустить .
К сожалению скетч большой, могла закрасться опечатка, или что-нибудь в библиотеках изменилось с момента написания этой статьи. Тут так однозначно я уже не могу сказать в чем может быть ошибка. Здесь надо разбивать скетч на маленькие части и тестировать их работу по частям - так проще всего будет найти ошибку. Сможете разбить скетч на маленькие части? Я так мог бы попытаться помочь вам найти ошибку. У вас, скорее всего ошибка с логикой работы режимов. Сможете закомментировать код всех режимов, а оставить только работу в одном режиме?