Термометр на ардуино уно с дисплеем: Ардуино термометр на основе Uno и модуля DS18B20

Содержание

Эксперимент 15. Комнатный термометр [Амперка / Вики]

Список деталей для эксперимента

Для дополнительного задания

Принципиальная схема

Схема на макетке

Обратите внимание

Скетч

p150_bar_thermometer.ino
// Огромное количество готового кода уже написано другими людьми
// и хранится в виде отдельных файлов, которые называются
// библиотеками. Для использования кода из библиотеки, её нужно
// подключить (англ. include). Библиотека «math» даёт разные
// математические функции, в том числе функцию логарифма
// (англ. log), которая нам понадобится далее
#include <math.h>
 
#define FIRST_LED_PIN 2
#define LED_COUNT     10
 
// Параметр конкретного типа термистора (из datasheet):
#define TERMIST_B 4300 
 
#define VIN 5.0
 
void setup()
{
  for (int i = 0; i < LED_COUNT; ++i)
    pinMode(i + FIRST_LED_PIN, OUTPUT);
}
 
void loop()
{
  // вычисляем температуру в °С с помощью магической формулы.
  // Используем при этом не целые числа, а вещественные. Их ещё
  // называют числами с плавающей (англ. float) точкой. В
  // выражениях с вещественными числами обязательно нужно явно
  // указывать дробную часть у всех констант. Иначе дробная
  // часть результата будет отброшена
 
   float voltage = analogRead(A0) * VIN / 1023.0;
   float r1 = voltage / (VIN - voltage);
 
 
   float temperature = 1./( 1./(TERMIST_B)*log(r1)+1./(25. + 273.) ) - 273;
 
  for (int i = 0; i < LED_COUNT; ++i) {
    // при 21°С должен гореть один сегмент, при 22°С — два и
    // т.д. Определяем должен ли гореть i-й нехитрым способом
    boolean enableSegment = (temperature >= 21+i);
    digitalWrite(i + FIRST_LED_PIN, enableSegment);
  }
}

Пояснения к коду

  • Директивы для подключения библиотек #include включаются в начало программы.

  • В этом эксперименте мы подключаем библиотеку math.h для того, чтобы использовать функцию взятия натурального логарифма x log(x).

  • В переменных типа float можно хранить дробные числа, числа с плавающей точкой.

  • При использовании переменных данного типа имейте в виду:

    • при операциях с их использованием, указывайте нулевую дробную часть у целых констант, как в примере

    • они могут принимать значения от -3.4028235×1038 до 3.4028235×1038,

    • при этом количество значащих цифр может быть 6-7: всех цифр, не только после запятой!

    • точность вычислений с такими данными невелика, у вас могут возникнуть неожиданные ошибки, например, при использовании float в условном операторе. Не полагайтесь на точность!

    • вычисления с float происходят медленнее, чем с целыми числами

  • Показания термистора связаны с температурой нелинейно, поэтому нам приходится использовать такую громоздкую формулу.

Вопросы для проверки себя

  1. Как нужно подключить термистор, чтобы получать на Arduino данные о температуре?

  2. Каким образом можно воспользоваться ранее разработанными функциями, не переписывая их в программный код?

  3. Чем неудобно использование чисел с плавающей точкой на Arduino?

  4. Что за выражение стоит справа от = при объявлении булевой переменной enableSegment?

Задания для самостоятельного решения

  1. Измените код программы таким образом, чтобы индикатор включался при 0 градусов и его показания прирастали на одно деление каждые 5 градусов.

  2. Добавьте в схему пьезопищалку и доработайте программу так, чтобы срабатывала звуковая сигнализация при достижении температуры, например, 25 градусов.


← Счётчик нажатий | Оглавление | Метеостанция →

Бюджетный GSM термометр на Arduino Nano

Внимание! Команды выделенные жирным шрифтом
могут быть выполнены только с основного номера, так как отвечают за конфигурацию устройства. Команды можно отправлять через смс сообщения или вводить в командной строке монитора порта Arduino IDE.

Команды управления не чувствительны к регистру:
AddPhone — Добавить номер телефона. Всего может быть добавлено не более 9 номеров + 1 основной номер который автоматически сохраняется в память при первом звонке на устройство после сброса на заводские установки командами ResetPhone, FullResetили MemTest. То есть кто первый позвонил на устройство после его сброса на заводские установки тот и «главный», этот номер заносится в первую ячейку памяти и его невозможно изменить или удалить через смс.

Пример команды:

AddPhone:2+71234567891risp
AddPhone:3+71234567892s
AddPhone:4+71234567893sp
AddPhone:5+71234567894r

Синтаксис команды:

AddPhone — команда
: — разделитель
5 — записать в пятую ячейку памяти
+71234567890 — номер телефона
s — Параметр «SMS» — будет отправлено sms сообщение при срабатывании датчиков
r — Параметр «Ring» — будет совершен голосовой вызов при срабатывании датчиков
p — Параметр «Power» — будет отправлено sms сообщение при включении/отключении внешнего питания

i — Параметр «Info» — будет отправлено sms сообщение о включении или отключении оповещения при изменении температуры
При отсутствии параметров «s», «r», «p»,«i» телефон заносится в память, но никак не используется.


DeletePhone — Удалить номер телефона.
Пример команды:
DeletePhone:+71234567891

Синтаксис команды:

DeletePhone — команда
: — разделитель
+71234567891 — номер телефона


EditMainPhone — Изменить параметры «s», «r», «p», «i» основного телефона, этот номер занесён в первую ячейку памяти.
Пример команды:
EditMainPhone:spri

Синтаксис команды:

EditMainPhone — команда
: — разделитель
srpi — параметры


RingTime — Длительность тревожного голосового вызова, параметр может иметь значение от 10 до 255 секунд.
Пример команды:
RingTime:40

Синтаксис команды:

RingTime — команда
: — разделитель
40 — длительность вызова составит 40 секунд, после чего будет вызван следующий абонент.


ModemID — Принудительная установка модели используемого модема. Возможные значения: 0 — автоопределение модема, 1 — M590, 2 — SIM800l, 3 — A6_Mini.
Пример команды:
ModemID:2

Синтаксис команды:

ModemID — команда
: — разделитель
2 — ID модема.


NetCheckTime — Интервал проверки регистрации модема в сети оператора в минутах, параметр может иметь значение от 1 до 60 минут. При значении 0 проверка отключена.
Пример команды:
NetCheckTime:10

Синтаксис команды:

NetCheckTime — команда
: — разделитель
10 — каждые 10 минут будет производиться поочерёдная проверка уровня сигнала сети или проверка регистрации модема в домашней сети оператора, то есть весь цикл проверки будет занимать 20 минут. В случае отсутствия сигнала или регистрации в домашней сети модем будет перезагружен.


TempCheckTime — Интервал автоматического обновления температуры, параметр может иметь значение от 1 до 60 минут.
Пример команды:
TempCheckTime:10

Синтаксис команды:

TempCheckTime — команда
: — разделитель
10 — каждые 10 минут будет производиться снятие показаний с датчика температуры.


LowTemp — Нижний порог температуры при достижении которого будет отправлено оповещение. Параметр может иметь значение от -50 до 125 и не может превышать или равняться значению параметра HighTemp.
Пример команды:
LowTemp:25

Синтаксис команды:

LowTemp — команда
: — разделитель
25 — температура


HighTemp — Верхний порог температуры при достижении которого будет отправлено оповещение. Параметр может иметь значение от -50 до 125 и не может быть меньше или равняться значению параметра LowTemp.
Пример команды:
HighTemp:60

Синтаксис команды:

HighTemp — команда
: — разделитель
60 — температура


WatchPowerTime — Время в минутах по истечении которого будет отправлено смс сообщение об отключении внешнего источника питания. Если внешнее питание будет восстановлено до истечения установленного времени, то сообщение не будет отправлено.
Пример команды:
WatchPowerTime:5

Синтаксис команды:

WatchPowerTime — команда
: — разделитель
5 — 5 минут до отправки смс сообщения


WatchPowerOn1 — включить контроль внешнего питания, смс сообщение об отключении внешнего питания будет отправлено при условии что включено оповещение при изменении температуры (GuardOn).

WatchPowerOn2 — включить контроль внешнего питания, смс сообщение об отключении внешнего питания в любом случае будет отправлено

WatchPowerOff — выключить контроль внешнего питания

BalanceNum — Изменение номера запроса баланса и обработка длины ответа запроса. Значение по умолчанию для Beeline: #100#L22.
Пример команды:

BalanceNum:#103#L24

Синтаксис команды:

BalanceNum — команда
: — разделитель
#103# — номер запроса баланса
L24 — Длина (len) пересылаемого ответа 24 символа, обрезаем спам из запроса баланса.


Reboot — перезагрузка устройства (только Arduino)

ResetConfig — сброс настроек на заводские установки

ResetPhone — удаление из памяти всех телефонных номеров

FullReset — сброс настроек, удаление из памяти всех телефонных номеров, восстановление значения по умолчанию команды BalanceNum.

GuardOn — включить оповещение при изменении температуры
GuardOff — выключить оповещение при изменении температуры

Info — проверить состояние, в ответ на это сообщение будет отправлено sms с информацией о текущей температуре, нижней и верхней границах контроля температуры, о частоте автоматического обновления температуры, и о том с какого номера было включено или выключено оповещение при изменении температуры и текущее состояние.

TestOn — включается тестовый режим.
TestOff — выключается тестовый режим.

LedOff — выключает светодиод режима ожидания.
LedOn — включает светодиод режима ожидания.

Money — запроса баланса.

ClearSms — Удалить из памяти все sms

ListPhone — вывод в монитор порта списка сохранённых в памяти телефонов

Memtest — тест энергонезависимой памяти устройства, все настройки устройства будут сброшены, аналогично команде FullReset.

ListConfig — вывод в монитор порта текущей конфигурации устройства.

Цифровой термометр DS18B20 и ARDUINO UNO

Казалось бы, что может быть интересного и нового в измерении температуры при помощи Ардуино? Написаны сотни статей, объемом десятки мегабайт, может чуть меньше, а может и чуть больше скетчей… А вот еще и моя статья. Зачем? Честно говоря, я тоже думал, что вопрос этот «разжеван вдоль и поперек», пока сам не столкнулся с измерением температуры. А тут полезло. Что-то не работает, что-то работает не так, возникает масса вопросов, на которые ответы приходится «выцарапывать» перерывая половину интернета, причем не только русскоязычного. Данная статья, в отличие от моих прошлых статей на данном ресурсе гораздо более практичная, но начнем сначала. Зачем, собственно измерять температуру чем-то новым, когда термометров продается – на любой вкус и кошелек? А дело в том, что температуру, зачастую, приходится не только измерять, но потом, на основе полученных данных что-то делать, либо просто регистрировать с целью отслеживания изменений. Соединив, при помощи Ардуино, термодатчик с релейным блоком получим простейший терморегулятор, а если данный терморегулятор сможет отслеживать температуру по нескольким точкам (зонам) и действовать по определенному алгоритму получим довольно серьезный прибор, промышленный аналог которого стоит сопоставимо со стоимостью неплохого ноутбука. Однако, целью данной статьи не является создание заумно-сложных устройств. Цель в другом — предложить новичку простое, проверенное на практике, решение для измерения температуры. Также, как и предыдущие статьи эта будет состоять из частей. В каждой из которых будет рассмотрен свой вопрос. Части будут идти по возрастанию сложности.

Часть первая. Простейшая, но тоже полезная

Итак, от слов к делу! Для реализации данного проекта на первом этапе нам понадобится цифровой термодатчик DS18B20, ARDUINO UNO, резистор на 4,7 кОм (мощность особого значения не имеет, от 0,125 до 2 Вт целиком подходит, но имеет значение точность, чем точнее – тем лучше), кусочек 3-жильного провода (и отдельные проводки на этапе эксперимента тоже подойдут), а еще — несколько штырьков для платы. Хотя и без них тоже можно, если аккуратно, конечно. Выбор данного датчика не случаен. Дело в том, что он может отслеживать температуру в диапазоне от -55оС до +125оС с точностью в основной части диапазона 0,5оС, что вполне хватает для управления, как бытовым отоплением, так и разнообразными морозильными и холодильными установками, а также банями, саунами, теплицами, инкубаторами, рассадниками и прочим. Напоминаю, что ARDUINO UNO можно свободно приобрести здесь: arduino-kit.com.ua/uno-r3-new.html или здесь: arduino-kit.com.ua/arduino-leonardo-original-italiya-new-rev3.html , термодатчик DS18B20 — arduino-kit.com.ua/18b20-sensor-datchik-temperatury-dlya-arduino.html , хотя лично у меня – такой:arduino-kit.com.ua/cifrovoy-datchik-temperatury-odnozhilnyy-ds18b20.html достоинство моего — малые размеры, сопоставимые с размерами кабеля. Недостатки – отсутствие платы, что в некоторых условиях отрицательно сказывается на удобстве монтажа и жизнеспособности датчика. Также – у датчика arduino-kit.com.ua/18b20-sensor-datchik-temperatury-dlya-arduino.html встроен резистор и больше никаких резисторов паять не нужно, зато исчезает возможность подключить несколько датчиков «цепочкой». Подключение датчика к Ардуино видно на Рис. 1 и указано в Таблице 1. На термодатчике определить контакты просто. Нужно взять его так, чтобы смотреть на срез с цифрами, а ножки были внизу. Крайняя левая ножка будет GND, средняя DQ, а крайняя правая VDD. 

Таблица 1.

Пин Ардуино Уно

Пин DS18B20

Примечание

GND

GND

«-»

+5V

VDD

+5V, также подпаивается одна ножка резистора 4,7 кОм.

10

DQ

Цифровой ввод, также подпаивается вторая ножка резистора 4,7 кОм.


Рисунок 1. Подключение одного термодатчика.

На рисунке видно, что было использовано два резистора. Это связано с тем, что найденный мной резистор с маркировкой «4К7», на самом деле имел довольно высокую погрешность, которую и пришлось компенсировать вторым резистором. Общее сопротивление данной сборки составило 4,695 кОм, что я считаю вполне приемлемым. Также на рисунке можно видеть, что датчик не подпаян непосредственно к проводам (обрезок шлейфа), а вставлен в разъем. Сделано это было из соображений развития эксперимента. Паять данные датчики настоятельно рекомендуется. Сам скетч также получился довольно компактным:
Файл DS18B20.ino

Всего 14 строчек кода с комментариями. Любому новичку будет по силам разобраться. В результате работы программа выдаст нечто подобное:

 
Рисунок 2. Результат работы с одним датчиком.

Часть вторая. Немного усложненная.

Усложним мы эту часть тем, что добавим еще один датчик. Предположим, что нам нужно измерять температуру на улице и в помещении. Для этого всего лишь допаиваем один датчик «в цепочку». Очень напоминает параллельное подключение. Знатоки электрики поймут, о чем я. Но отличие есть: в данном случае выводы от центрального провода должны быть как можно короче. 

 
Рисунок 3. Плата с двумя датчиками.

Скетч вырос всего на 3 строчки. Теперь в нем 17 строк:
Файл DS18B20_2.ino

Результаты работы этого скетча видно на Рисунке 4. 

 
Рисунок 4. Работа с двумя датчиками.

Часть третья. Заключительная.

А теперь подключим к Ардуино светодиод, который будет загораться при достижении определенной температуры. Такой себе «пороговый сигнализатор». Для этого нужен обычный светодиод и токоограничивающий резистор. Мне под руку попался на 100 Ом, его я и использовал, подключив к 7-у контакту Ардуино. Длинную ножку светодиода (анод) подпаиваем к резистору, а короткую (катод) подключаем к контакту GND Ардуино. Должно получиться, примерно, как на рисунке 5. 

Скетч также вырос совсем не на много:
Файл DS18B20_2_plus_diod.ino

Работа данной программы на компьютере отображается точно также, как показано на Рисунке 4. Естественно переменной sensors.getTempCByIndex(1) можно оперировать в очень широких пределах и управление светодиодиком лишь самый простой пример из всех возможных.

И в заключение данной статьи еще один шаг. Сейчас я расскажу, как к одной Ардуинке подключить несколько «гирлянд» данных устройств. Дело в том, что длина «гирлянды» не может быть бесконечной, более того – она очень сильно ограничена. В идеальных условиях – 300 метров, но создание «идеальных» условий – довольно дорогостоящее удовольствие. В реальных условиях – не рекомендуется превышать 10 метров. Для обычного «комнатного» термометра этого более чем достаточно, но если речь идет о каком-либо более серьезном оборудовании – этого катастрофически мало. Тем более, что для стабильной работы необходимо, чтобы датчики располагались как можно ближе к проводникам шины – «гирляндой». Отводить, конечно, тоже можно, но точность и помехозащищенность в этом случае будут крайне низкими. Итак, подключаем мы несколько «гирлянд» именно для того, чтобы собрать информацию с большого числа точек, при этом сохранив достаточную точность и помехозащищенность. Добавляем контакты согласно таблице 2:

Пин Ардуино Уно

Пин DS18B20

Примечание

GND

GND

«-»

+5V

VDD

+5V, также подпаивается одна ножка резисторов 4,7 кОм.

10

DQ

Цифровой ввод, также подпаивается вторая ножка резистора 4,7 кОм.

8

DQ

Цифровой ввод, также подпаивается вторая ножка резистора 4,7 кОм.

Как видно из таблицы – ничего сложного нет, точно такая же шина, только на другой цифровой вод. Не стал паять на 9-й контакт только из соображений удобства и скорости пайки.
Скетч:
Файл DS18B20_2_plus_1.ino

Вряд ли скетч нуждается в излишних комментариях.

Результат работы скетча выглядит так:

 
Рисунок 6. Работа одновременно двух линий датчиков.

А плата с подключенными двумя линиями выглядит так: 

 
Рисунок 7. Плата с двумя шинами.

Из рисунка видно, что резистор 4,7кОм для повышения точности также выполнен составным. 

Библиотеки, примененные для написания скетчей рассмотренных в статье находятся здесь: 
OneWire.h
DallasTemperature.h 

Обзор подготовил Павел Сергеев

OLED часы (термометр) на arduino и DS3231 – RobotChip

/*

  Тестирование производилось на Arduino IDE 1.8.0

  Дата тестирования 17.02.2017г.

*/

 

#include <OLED_I2C.h>                                  // Подключение библиотеки OLED_I2C

#include <DS3231.h>                                    // Подключение библиотеки DS3231

OLED  myOLED(SDA, SCL, 8);                            

DS3231  rtc(SDA, SCL);                                

extern uint8_t MegaNumbers[];                          // Подключение больших шрифтов

extern uint8_t SmallFont[];                            // Подключение маленьких шрифтов

 

int x = 0;                                             // Создаем переменную «х»

 

void setup()

{

  myOLED.begin();                                      // Инициализация Oled дисплея

  rtc.begin();                                         // Инициализация RS3231

}

void loop()

{

  if (x >= 10) {temp();                                // Если «x», больше или равно 10, выполняем цикл «temp»

      x=0;}                                            // Обнулить «x»

  else {clock();}                                      // Если «x», меньше 10, выполняем цикл «clock»

      x++;                                             // Увеличить «x» на 1

}

 

void clock()                                           // Цикл считывания и отображения времени

{  

  myOLED.clrScr();                                     // Очищаем экран

  myOLED.setFont(SmallFont);                           // Включаем маленький шрифт

  myOLED.print(rtc.getDOWStr(), CENTER, 0);            // Отображение дня недели

  String stringOne = rtc.getTimeStr();

  myOLED.setFont(MegaNumbers);                         // Включаем большой шрифт

  myOLED.print(stringOne.substring(0,2), 4, 12);       // Отображение часов

  myOLED.print(«/», 51, 12);                           // Отображение двоеточие

  myOLED.print(stringOne.substring(3,5), 75, 12);      // Отображение минут

  myOLED.setFont(SmallFont);                           // Включаем маленький шрифт

  myOLED.print(rtc.getDateStr(), CENTER, 57);          // Отображение даты

  myOLED.update();                                     // Обновляем информацию на дисплее

  delay(500);                                          // Пауза

  myOLED.setFont(MegaNumbers);                         // Включаем большой шрифт

  myOLED.print(«-«, 51, 12);                           // Убираем двоеточие

  myOLED.update();                                     // Обновляем информацию на дисплее

  delay(500);                                          // Пауза

}

 

void temp()                                            // Цикл считывания и отображения температуры

{

  myOLED.clrScr();                                     // Очищаем экран

  myOLED.setFont(MegaNumbers);                         // Включаем большой шрифт

  myOLED.print(String(rtc.getTemp() , 1), CENTER, 12);

  myOLED.setFont(SmallFont);                           // Включаем маленький шрифт

  myOLED.print(«Temperature», CENTER, 57);             // Отображение надписи

  myOLED.update();                                     // Обновляем информацию на дисплее

  delay(2000);                                         // Пауза

}

Метеостанция c двумя термометрами, гигрометром и барометром [Амперка / Вики]

// библиотека для работы I²C
#include <Wire.h>
// библиотека для работы с метеосенсором
#include <TroykaMeteoSensor.h>
// Подключаем библиотеку для работы с дисплеем
#include <QuadDisplay2.h>
// библиотека для работы с модулями IMU
#include <TroykaIMU.h>
// библиотека для работы с протоколом 1-Wire
#include <OneWire.h>
// библиотека для работы с датчиком DS18B20
#include <DallasTemperature.h>
 
// сигнальный пин датчика DS18B20
#define ONE_WIRE_BUS 5
 
// создаём объект для работы с метеосенсором
TroykaMeteoSensor meteoSensor;
// создаём объект класса QuadDisplay и передаём номер пина CS
QuadDisplay qd(10);
// создаём объект для работы с барометром
Barometer barometer;
// создаём объект для работы с библиотекой OneWire
OneWire oneWire(ONE_WIRE_BUS);
// создадим объект для работы с библиотекой DallasTemperature
DallasTemperature sensor(&oneWire);
 
// перечисляем имена операций, которые мы будем выводить на дисплей
enum {
  IN,         // имя для операции, которая выводит на дисплей надпись "In"
  TEMP_IN,    // имя для операции, которая выводит на дисплей температуру с метеосенсора
  CEL,        // имя для операции, которая выводит на дисплей символ °C
  HUM_IN,     // имя для операции, которая выводит на дисплей влажность с метеосенсора
  PPM,        // имя для операции, которая выводит на дисплей символ %
  BAR_IN,     // имя для операции, которая выводит на дисплей давление с барометра в миллиметрах ртутного столба
  MER,        // имя для операции, которая выводит на дисплей надпись "Hg"
  EMPTY,      // имя для операции, которая очищает дисплей
  OUT,        // имя для операции, которая выводит на дисплей надпись "Out"
  TEMP_OUT    // имя для операции, которая выводит на дисплей температуру с датчика DS18B20
};
// создаем массив, в котором будем хранить последовательность операций
int chain[] = {
  IN,
  TEMP_IN,
  CEL,
  HUM_IN,
  PPM,
  BAR_IN,
  MER,
  EMPTY,
  OUT,
  TEMP_OUT,
  CEL,
  EMPTY
};
 
// создаем объект класса long для хранения счетчика
unsigned long respite_Time = 0;
 
// создаем объект для регулировки времени показа значений на экране
int slowdown_qd = 1000;
// создаем объект для хранения номера выполняемой операции
int number_qd = 0;
 
void setup() {
  // инициализация дисплея
  qd.begin();
  // инициализируем метеосенсора
  meteoSensor.begin();
  // инициализация барометра
  barometer.begin();
  // инициализируем работу с датчиком DS18B20
  sensor.begin();
  // устанавливаем разрешение датчика от 9 до 12 бит
  sensor.setResolution(12);
}
 
void loop() {
  // запускаем бесконечный счетчик. Его содержимое будет обрабатываться с периодом равным slowdown_qd
  if (millis() - respite_Time > slowdown_qd) {
    // запускаем процесс, который будет выполнять операции согласно последовательности в chain
switch (chain[number_qd]) {
      case IN:
        qd.displayDigits(QD_I, QD_n, QD_NONE, QD_NONE);
        break;
      case TEMP_IN:
        showData(meteoSensor.getTemperatureC());
        break;
      case CEL:
        qd.displayDigits(QD_NONE, QD_NONE, QD_DEGREE, QD_C);
        break;
      case HUM_IN:
        showData(meteoSensor.getHumidity());
        break;
      case PPM:
        qd.displayDigits(QD_NONE, QD_NONE, QD_DEGREE, QD_UNDER_DEGREE);
        break;
      case BAR_IN:
        qd.displayInt(barometer.readPressureMillimetersHg());
        break;
      case MER:
        qd.displayDigits(QD_NONE, QD_NONE, QD_H, QD_9);
        break;
      case EMPTY:
        qd.displayClear();
        break;
      case OUT:
        qd.displayDigits(QD_O, QD_u, QD_t, QD_NONE);
        break;
      case TEMP_OUT:
        // переменная для хранения температуры
        float temperature;
        // отправляем запрос на измерение температуры
        sensor.requestTemperatures();
        // выводим значение с датчика DS18B20 на экран
        qd.displayFloat(sensor.getTempCByIndex(0), 1);
        break;
 
    }
    number_qd++;
    // проверяем не превысил ли номер операции количество операций
    if (number_qd > sizeof(chain) / sizeof(int) - 1)
      number_qd = 0;
    respite_Time = millis();
  }
}
 
 
// функция работы датчика температуры и влажности
void showData(float data) {
  // считываем данные с датчика
  int stateSensor = meteoSensor.read();
  switch (stateSensor) {
    // выводим показания на дисплей
    case SHT_OK:
      qd.displayFloat(data, 1);
      break;
    // выводим сообщение "Errd", если ошибка данных или сенсор не подключён
    case SHT_ERROR_DATA:
      qd.displayDigits(QD_E, QD_r, QD_r, QD_d);
    // выводим сообщение "ErrC", если ошибка контрольной суммы
    case SHT_ERROR_CHECKSUM:
      qd.displayDigits(QD_E, QD_r, QD_r, QD_C);
      break;
  }
}

Метеостанция для записи температуры, атмосферного давления и влажности [Амперка / Вики]

// библиотека для работы I²C
#include <Wire.h>
// библиотека для работы с метеосенсором
#include <TroykaMeteoSensor.h>
// Подключаем библиотеку для работы с дисплеем
#include <QuadDisplay2.h>
// библиотека для работы с модулями IMU
#include <TroykaIMU.h>
// библиотека для работы с протоколом 1-Wire
#include <OneWire.h>
// библиотека для работы с датчиком DS18B20
#include <DallasTemperature.h>
// библиотека для работы с SPI
#include <SPI.h>
// библиотека для работы с SD-картами
#include <SD.h>
 
// сигнальный пин датчика DS18B20
#define ONE_WIRE_BUS 5
// даём разумное имя для CS пина microSD-карты
#define SD_CS_PIN  8
 
// создаём объект для работы с метеосенсором
TroykaMeteoSensor meteoSensor;
// создаём объект класса QuadDisplay, передаём номер пина CS, включаем режим работы с SPI
QuadDisplay qd(10, true);
// создаём объект для работы с барометром
Barometer barometer;
// создаём объект для работы с библиотекой OneWire
OneWire oneWire(ONE_WIRE_BUS);
// создадим объект для работы с библиотекой DallasTemperature
DallasTemperature sensor(&oneWire);
 
// перечисляем имена операций, которые мы будем выводить на дисплей
enum {
  SAVE_SD,    // имя для операции, которая записывает на SD данные
  IN,         // имя для операции, которая выводит на дисплей надпись "In"
  TEMP_IN,    // имя для операции, которая выводит на дисплей температуру с метеосенсора
  CEL,        // имя для операции, которая выводит на дисплей символ °C
  HUM_IN,     // имя для операции, которая выводит на дисплей влажность с метеосенсора
  PPM,        // имя для операции, которая выводит на дисплей символ %
  BAR_IN,     // имя для операции, которая выводит на дисплей давление с барометра в миллиметрах ртутного столба
  MER,        // имя для операции, которая выводит на дисплей надпись "Hg"
  EMPTY,      // имя для операции, которая очищает дисплей
  OUT,        // имя для операции, которая выводит на дисплей надпись "Out"
  TEMP_OUT    // имя для операции, которая выводит на дисплей температуру с датчика DS18B20
};
// создаем массив, в котором будем хранить последовательность операций
int chain[] = {
  IN,
  TEMP_IN,
  CEL,
  HUM_IN,
  PPM,
  BAR_IN,
  MER,
  EMPTY,
  OUT,
  TEMP_OUT,
  CEL,
  EMPTY,
  SAVE_SD
};
 
// создаем объект класса long для хранения счетчика
unsigned long respite_Time = 0;
 
// создаем объект для регулировки времени показа значений на экране
int slowdown_qd = 1000;
// создаем объект для хранения номера выполняемой операции
int number_qd = 0;
 
// создаем объект для записи данных на SD строкой
String  dataString = "";
 
void setup() {
  // инициализация дисплея
  qd.begin();
  // инициализируем метеосенсора
  meteoSensor.begin();
  // инициализация барометра
  barometer.begin();
  // инициализируем работу с датчиком DS18B20
  sensor.begin();
  // устанавливаем разрешение датчика от 9 до 12 бит
  sensor.setResolution(12);
  // инициализируем карту памяти
  SD.begin(SD_CS_PIN);
  // собираем верхнюю строчку с наименованием данных
  dataString = "TEMP_IN (ºC)\tHUM_IN (%)\tBAR_IN (mmHg)\tTEMP_OUT (ºC)";
  // вызываем функцию сохранения данных на SD
  saveSD(dataString);
}
 
void loop() {
  // запускаем бесконечный счетчик. Его содержимое будет обрабатываться с периодом равным slowdown_qd
  if (millis() - respite_Time > slowdown_qd) {
    // запускаем процесс, который будет выполнять операции согласно последовательности в chain
    switch (chain[number_qd]) {
      case IN:
        qd.displayDigits(QD_I, QD_n, QD_NONE, QD_NONE);
        break;
      case TEMP_IN:
        showData(meteoSensor.getTemperatureC());
        break;
      case CEL:
        qd.displayDigits(QD_NONE, QD_NONE, QD_DEGREE, QD_C);
        break;
      case HUM_IN:
        showData(meteoSensor.getHumidity());
        break;
      case PPM:
        qd.displayDigits(QD_NONE, QD_NONE, QD_DEGREE, QD_UNDER_DEGREE);
        break;
      case BAR_IN:
        qd.displayInt(barometer.readPressureMillimetersHg());
        break;
      case MER:
        qd.displayDigits(QD_NONE, QD_NONE, QD_H, QD_9);
        break;
      case EMPTY:
        qd.displayClear();
        break;
      case OUT:
        qd.displayDigits(QD_O, QD_u, QD_t, QD_NONE);
        break;
      case TEMP_OUT:
        // переменная для хранения температуры
        float temperature;
        // отправляем запрос на измерение температуры
        sensor.requestTemperatures();
        // выводим значение с датчика DS18B20 на экран
        qd.displayFloat(sensor.getTempCByIndex(0), 1);
        break;
      case SAVE_SD:
        // собираем в строку сначала температура с метеосенсора
        dataString = String(meteoSensor.getTemperatureC()) + "\t";
        // потом влажность
        dataString += String(meteoSensor.getHumidity()) + "\t";
        // давление
        dataString += String(barometer.readPressureMillimetersHg()) + "\t";
        // и температура с датчика DS18B20
        dataString += String(sensor.getTempCByIndex(0)) + "\t";
        // вызываем функцию сохранения данных на SD
        saveSD(dataString);
        break;
    }
    number_qd++;
    // проверяем не превысил ли номер операции количество операций
    if (number_qd > sizeof(chain) / sizeof(int) - 1)
      number_qd = 0;
    respite_Time = millis();
  }
}
 
// функция работы датчика температуры и влажности
void showData(float data) {
  // считываем данные с датчика
  int stateSensor = meteoSensor.read();
  switch (stateSensor) {
    // выводим показания на дисплей
    case SHT_OK:
      qd.displayFloat(data, 1);
      break;
    // выводим сообщение "Errd", если ошибка данных или сенсор не подключён
    case SHT_ERROR_DATA:
      qd.displayDigits(QD_E, QD_r, QD_r, QD_d);
    // выводим сообщение "ErrC", если ошибка контрольной суммы
    case SHT_ERROR_CHECKSUM:
      qd.displayDigits(QD_E, QD_r, QD_r, QD_C);
      break;
  }
}
 
// функция сохранения данных на карту памяти
void saveSD(String data) {
  // создаем файл для записи данных
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // если файл существует и открылся
  if (dataFile) {
    // сохраняем данные
    dataFile.println(data);
    // закрываем файл
    dataFile.close();
  } else {
    // если файл не доступен выводим ошибку на дисплей
    qd.displayDigits(QD_E, QD_r, QD_r, QD_S);
  }
}

Цифровой термометр DS18B20 и ARDUINO UNO

Казалось бы, что может быть интересного и нового в измерении температуры при помощи Ардуино? Написаны сотни статей, объемом десятки мегабайт, может чуть меньше, а может и чуть больше скетчей… А вот еще и моя статья. Зачем? Честно говоря, я тоже думал, что вопрос этот «разжеван вдоль и поперек», пока сам не столкнулся с измерением температуры. А тут полезло. Что-то не работает, возникает масса вопросов, которые приходится решать «выцарапывать» перерывая половину интернета, причем не только русскоязычного.Данная статья, в отличие от прошлых статей на данном ресурсе более необычно, но начнем сначала. Зачем, собственно измерять температуру чем-то новым, когда термометров продается — на любой вкус и кошелек? А дело в том, что температуру, часто, приходится не только измерять, но потом, на основе полученных данных что-то делать, либо просто регистрировать с целью выполнения изменений. Соединив, при помощи Ардуино, термодатчик с релейным устройством получим простейший терморегулятор, а если данный терморегулятор позволяет блокировать температуру по нескольким точкам (зонам) и действовать по определенному алгоритму получим довольно серьезный прибор, промышленный аналог которого стоит сопоставимо со стоимостью неплохого ноутбука.Однако, данной статьи не является создание заумно-сложных устройств. Цель в другом — предложить новичку простое, проверенное на практике, решение для измерения температуры. Также, как и предыдущие статьи эта будет состоять из частей. В каждой из которых будет рассмотрен свой вопрос. Части будут идти по возрастанию сложности.

Часть первая. Простейшая, но тоже полезная

Итак, от слов к делу! Для реализации данного проекта на первом этапе нам понадобится цифровой термодатчик DS18B20, ARDUINO UNO, резистор на 4,7 кОм (мощность особого значения не имеет, от 0,125 до 2 Вт целиком подходит, но имеет значение точности, чем точнее — тем лучше), кусочек 3-жильного провода (и отдельные проводки на этапе эксперимента тоже подойдут), а еще — несколько штырьков для платы.Хотя и без них тоже можно, если аккуратно, конечно. Выбор данного датчика не случаен. Дело в том, что он может измерять температуру в диапазоне от -55оС до + 125оС с точностью в основной части диапазона 0,5оС, что вполне хватает для управления, как бытовым отоплением, так и разнообразными морозильными и холодильными установками, а также банями, саунами , теплицами, инкубаторами, рассадниками и прочим. Напоминаю, что ARDUINO UNO можно свободно приобрести здесь: arduino-kit.com.ua/uno-r3-new.html или здесь: arduino-kit.com.ua/arduino-leonardo-original-italiya-new-rev3.html, термодатчик DS18B20 — arduino-kit.com.ua/18b20-sensor-datchik-temperatury-dlya-arduino.html, хотя лично у меня — такой: arduino-kit.com.ua/cifrovoy-datchik-temperatury-odnozhilnyy-ds18b20.html достоинство моего — малые размеры, сопоставимые с размерами кабеля. Недостатки — отсутствие отрицательной платы, что в некоторых условиях сказывается на удобстве монтажа и жизнеспособности датчика. Также — у датчика arduino-kit.com.ua/18b20-sensor-datchik-temperatury-dlya-arduino.html встроенный резистор и больше никаких резисторов паять не нужно, зато исчезает возможность подключить несколько датчиков «цепочкой». Подключение датчика к Ардуино видно на Рис. 1 и указано в Таблице 1. На термодатчике определить контакты просто. Нужно взять его так, чтобы смотреть на срез с цифрами, а ножки были внизу. Крайняя левая ножка будет GND, средняя DQ, крайняя правая VDD.

Таблица 1.

Пин Ардуино Уно

Пин DS18B20

Примечание

ЗЕМЛЯ

ЗЕМЛЯ

«-»

+ 5В

VDD

+ 5V, также подпаивается одна ножка резистора 4,7 кОм.

10

DQ

Цифровой ввод, также подпаивается вторая ножка резистора 4,7 кОм.


Рисунок 1. Подключение одного термодатчика.

На рисунке видно, что было использовано два резистора. Это связано с тем, что найденный мной резистор с маркировкой «4К7», на самом деле, имеет довольно высокую погрешность, которую пришлось компенсировать вторым резистором.Общее сопротивление данной сборки составило 4,695 кОм, что я вполне приемлемо приемлемым. Также на рисунке можно видеть, что датчик не подпаян непосредственно к проводам (обрезок шлейфа), а вставлен в разъем. Сделано это было из соображений развития эксперимента. Паять данные датчики рекомендуется рекомендуется. Сам скетч также получился довольно компактным:
Файл DS18B20.ino

Всего 14 строчек кода с комментариями. Любому новичку будет по силам разобраться. В результате программа выдаст нечто подобное:


Рисунок 2.Результат работы с одним датчиком.

Часть вторая. Немного усложненная.

Усложним мы эту часть тем, что добавим еще один датчик. Предположим, что нам нужно измерить температуру на улице и в помещении. Для этого всего лишь допаиваем один датчик «в цепочку». Очень напоминает параллельное подключение. Знатоки электрики поймут, о чем я. Но отличие есть: в данном случае выводы от центрального провода должны быть как можно короче.


Рисунок 3. Плата с двумя датчиками.

Скетч вырос всего на 3 строчки. Теперь в нем 17 строк:
Файл DS18B20_2.ino

Результаты работы этого скетча видно на Рисунках 4.


Рисунок 4. Работа с двумя датчиками.

Часть третья. Заключительная.

А теперь подключим к Ардуино светодиод, будет загораться при достижении установленной температуры. Такой себе «пороговый сигнализатор». Для этого нужен обычный светодиод и токоограничивающий резистор. Мне под руку попался на 100 Ом, его я и использовал, подключив к 7-у контакту Ардуино.Длинную ножку светодиода (анод) подпаиваем к резистору, а короткую (катод) подключаем к контакту GND Ардуино. Должно получиться, примерно, как на рисунке 5.

Скетч также вырос совсем не на много:
Файл DS18B20_2_plus_diod.ino

Работа данной программы на компьютере отображается точно также, как показано на Рисунке 4. Естественно различные датчики. GetTempCByIndex (1) можно оперировать в очень широких пределах и управление светодиодом лишь самый простой пример из всех агентов.

И в данной статье еще один шаг. Сейчас я расскажу, как к одной Ардуинке подключить несколько «гирлянд» данных устройств. Дело в том, что длина «гирлянды» не может быть бесконечной, более того — она ​​очень сильно ограничена. В идеальных условиях — 300 метров, но создание «идеальных» условий — довольно дорогостоящее удовольствие. В реальных условиях — не указано 10 метров. Для обычного «комнатного» термометра этого более чем достаточно, но если речь идет о каком-либо более серьезном оборудовании — этого катастрофически мало.Тем более, что для стабильной работы необходимо, чтобы датчики располагались как ближе к проводникам шины — «гирляндой». Отводить, конечно, тоже можно, но точность и помехозащищенность в этом случае будут крайне низкими. Итак, подключаем мы несколько «гирлянд» именно для того, чтобы собрать информацию с большого числа точек, при этом показав достаточную точность и помехозащищенность. Добавляем контакты согласно таблице 2:

Пин Ардуино Уно

Пин DS18B20

Примечание

ЗЕМЛЯ

ЗЕМЛЯ

«-»

+ 5В

VDD

+ 5V, также подпаивается одна ножка резисторов 4,7 кОм.

10

DQ

Цифровой ввод, также подпаивается вторая ножка резистора 4,7 кОм.

8

DQ

Цифровой ввод, также подпаивается вторая ножка резистора 4,7 кОм.

Как видно из таблицы — ничего сложного нет, точно такая же шина, только на другой цифровой вод.Не стал паять на 9-й контакт только из соображений удобства и скорости пайки.
Скетч:
Файл DS18B20_2_plus_1.ino

Вряд ли скетч нуждается в излишних комментариев.

Результат работы скетча выглядит так:


Рисунок 6. Работа одновременно двух линий датчиков.

А плата с подключенными двумя линиями выглядит так:


Рисунок 7. Плата с двумя шинами.

Из рисунка видно, что резистор 4,7кОм для повышения точности также выполнен составным.

Библиотеки, примененные для написания скетчей рассмотренных в статье находятся здесь:
OneWire.h
DallasTemperature.h

Обзор подготовил Павел Сергеев

.

Эксперимент 15. Комнатный термометр [Амперка / Вики]

Список деталей для эксперимента

Для дополнительного задания

Принципиальная схема

Схема на макетке

Обратите внимание

Скетч

p150_bar_thermometer.ino
 // Огромное количество готового кода уже написано другими людьми
// и хранится в виде отдельных файлов, которые называются
// библиотеками.Для использования кода из библиотеки, её нужно
// подключить (англ. include). Библиотека «математика» даёт разные
// математические функции, в том числе функцию логарифма
// (англ. журнал), которая нам понадобится далее
#include 

#define FIRST_LED_PIN 2
#define LED_COUNT 10

// Параметр конкретного типа термистора (из даташита):
#define TERMIST_B 4300

#define VIN 5.0

установка void ()
{
  для (int i = 0; i  = 21 + i);
    digitalWrite (я + FIRST_LED_PIN, enableSegment);
  }
} 

Пояснения к коду

  • Директивы для подключения библиотек #include включаются в начало программы.

  • В этом эксперименте мы подключаем библиотеку math.h для того, чтобы использовать функцию взятия натурального логарифма x log (x) .

  • В параметре float можно хранить дробные числа, число с плавающей точкой.

  • При использовании использования данного типа имейте в виду:

    • при операциях с их использованием, указывайте нулевую дробную часть у целых констант, как в примере

    • они могут принимать значения от -3.4028235 × 10 38 до 3.4028235 × 10 38 ,

    • при этом количестве значащих цифр может быть 6-7: всех цифр, не только после запятой!

    • вычислений с такими данными невелика, у вас могут быть неожиданные ошибки, например, при использовании float в условном операторе.Не полагайтесь на точность!

    • вычисления с float проходят медленнее, чем с целыми числами

  • Показания термистора связаны с температурой нелинейно, поэтому нам приходится использовать такую ​​громоздкую формулу.

Вопросы для проверки себя

  1. Как нужно подключить термистор, чтобы получить на Arduino данные о температуре?

  2. Каким образом можно использовать ранее разработанные функции, не переписывая их в программный код?

  3. Чем неудобно использование чисел с плавающей точкой на Arduino?

  4. Что за выражение стоит справа от = при объявлении булевой новой enableSegment ?

Задания для самостоятельного решения

  1. Измените код программы таким образом, чтобы индикатор включился на 0 градусов и его показания прирастали на одно деление каждые 5 градусов.

  2. Добавьте в схему пьезопищалку и доработайте программу так, чтобы срабатывала звуковая сигнализация при достижении температуры, например, 25 градусов.


← Счётчик прочий | Оглавление | Метеостанция →

.

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *