Arduino: цифровой термометр с web-мониторингом

Мониторинг температуры через Интернет
Недавно обнаружил удобный онлайн-сервис для ведения статистики любой числовой информации и отображение её в виде графиков. Немного подумав, решил на его основе сделать цифровой термометр.


Внимание! Содержимое данной статьи уже неактуально, так как сервис Pachube прекратил своё существование. Статья оставлена как есть просто для истории.


Необходимые компоненты:

  • Arduino (Freeduino, *duino);
  • Ethernet Shield;
  • цифровой датчик температуры DS18B20;
  • резистор 4.7 кОм;
  • прямые руки 🙂

Вот собственно сам цифровой датчик DS18B20:
DS18B20
И его распиновка:
Распиновка DS18B20

Его мы будем подключать по шине 1-wire по схеме с паразитным питанием. При этом, можно использовать несколько таких датчиков (все они соединяются параллельно двумя проводами) и считывать с каждого отдельную температуру. Таким образом, при желании, можно контролировать температуру в каждом уголке комнаты 🙂
Напоминаю, что Ethernet Shield использует для своих нужд пины 10, 11, 12 и 13, поэтому использовать их нельзя.

temperature-1-wire_bb
temperature-1-wire_shem
Теперь зальём в ардуино следующий скетч:

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
#include <ERxPachube.h>
#include <Ethernet.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
 
//************************************************************************************
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC-адрес
byte ip[] = { 192, 168, 1, 177   };                  // IP-адрес
 
#define PACHUBE_API_KEY  "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" // ВАШ PACHUBE_API_KEY
#define PACHUBE_FEED_ID  00000 // ВАШ ID
#define DATA_STREAM  1 //Номер PACHUME DATASTREAM
#define ONE_WIRE_BUS  2 // Номер цифрового порта, к которому подключен термодатчик
//************************************************************************************
 
ERxPachubeDataOut dataout(PACHUBE_API_KEY, PACHUBE_FEED_ID);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
 
float SumTemp, CountTemp;
unsigned long dt;
 
void setup() {
  Serial.begin(9600); //для отладки
  Ethernet.begin(mac, ip);
  sensors.begin();
  CountTemp = 0;
  SumTemp = 0;
  dt=millis();
 
  dataout.addData(1); //добавляем поток данных
}
 
void loop() {
  //делаем синхронизацию и запрашиваем температуру
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  sensors.setWaitForConversion(true);
 
  //разрешение датчика
  int resolution = 12;
  delay(750/ (1 << (12-resolution)));
 
  // получаем данные о температуре
  float fSensorData=sensors.getTempCByIndex(0);
 
  SumTemp=SumTemp+fSensorData;
  CountTemp++;
 
  //Раз в минуту усредняем данные и отправляем на сервер
  if (abs(millis()-dt)>=60000 )
  {
    fSensorData=SumTemp/CountTemp;
    char test[20];
    //обновляем данные
    dataout.updateData(1, floatToString(test, fSensorData, 2, 7));
    int status = dataout.updatePachube();
    //для отладки выводим показания в консоль
    Serial.println(fSensorData);
 
    CountTemp = 0;
    SumTemp = 0;
    dt=millis();
  }
  delay(5000);
}
 
//функция для перевода из десятичной дроби в строковый вид
char * floatToString(char * outstr, double val, byte precision, byte widthp){
  char temp[16]; //increase this if you need more digits than 15
  byte i;
 
  temp[0]='\0';
  outstr[0]='\0';
 
  if(val < 0.0){
    strcpy(outstr,"-\0");  //print "-" sign
    val *= -1;
  }
 
  if( precision == 0) {
    strcat(outstr, ltoa(round(val),temp,10));  //prints the int part
  }
  else {
    unsigned long frac, mult = 1;
    byte padding = precision-1;
 
    while (precision--)
      mult *= 10;
 
    val += 0.5/(float)mult;      // compute rounding factor
 
    strcat(outstr, ltoa(floor(val),temp,10));  //prints the integer part without rounding
    strcat(outstr, ".\0"); // print the decimal point
 
    frac = (val - floor(val)) * mult;
 
    unsigned long frac1 = frac;
 
    while(frac1 /= 10)
      padding--;
 
    while(padding--)
      strcat(outstr,"0\0");    // print padding zeros
 
    strcat(outstr,ltoa(frac,temp,10));  // print fraction part
  }
 
  // generate width space padding
  if ((widthp != 0)&&(widthp >= strlen(outstr))){
    byte J=0;
    J = widthp - strlen(outstr);
 
    for (i=0; i< J; i++) {
      temp[i] = ' ';
    }
 
    temp[i++] = '\0';
    strcat(temp,outstr);
    strcpy(outstr,temp);
  }
 
  return outstr;
}

Обратите внимание на следующие строки:

1
2
3
4
5
6
7
8
9
//************************************************************************************
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC-адрес
byte ip[] = { 192, 168, 1, 177   };                  // IP-адрес
 
#define PACHUBE_API_KEY  "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" // ВАШ PACHUBE_API_KEY
#define PACHUBE_FEED_ID  00000 // ВАШ ID
#define DATA_STREAM  1 //Номер PACHUME DATASTREAM
#define ONE_WIRE_BUS  2 // Номер цифрового порта, к которому подключен термодатчик
//************************************************************************************
Значения надо будет заменить своими данными. Вводим IP, который получит ардуина в локальной сети. С последним параметром (ONE_WIRE_BUS) надеюсь всё ясно — это номер цифрового порта Arduino, к которому подключен термодатчик. Рассмотрим остальные параметры, которые вы получите на сайте pachube.com :

1. Регистрируемся на сайте pachube.com.
2. Создаём новую ленту (feed) в которой будут отображаться показания термодатчика. Для этого в правом меню выбираем «Create a feed»:
snag-0000
Вводим название ленты, описание, теги, при необходимости указываем местоположение.
snag-0001
Можно ввести адрес своего сайта и e-mail для связи.
Указываем, расположен ли датчик внутри помещения (indoor) или снаружи (outdoor), фиксированный (fixed) или мобильный (mobile), а также является ли он реальным (physical) или виртуальным (virtual).
После этого добавляем поток данных (Add a datastream), где вводим числовой ID (это как раз и будет параметром DATA_STREAM), теги, единицу измерения (Celsius) и символ (°C). Не забываем сохранить данные, нажав на кнопку «Save».
snag-0002
3. Теперь в правом меню выбираем «My keys». Затем «create a new key here».
snag-0003
snag-0005
Придумываем название ключа. Выбираем пункт «Use specific feed(s)», в выпадающем левом списке выбираем созданный ранее feed (Номер этой ленты будет параметром PACHUBE_FEED_ID). Если вы хотите, чтобы ключ работал только для одного потока данных, то в правом выпадающем списке выбираем конкретный номер потока. В параметрах доступа (Access Privileges) ставим галочки READ и UPDATE.
После этого жмём кнопку «Create».
snag-0008
Видим созданный нами ключик (это будет параметр PACHUBE_API_KEY). Не сообщайте его никому, он даёт доступ к обновлению данных.
snag-0009

Прошиваем скетч с вашими параметрами в ардуину, подключаем Ethernet Shield, термодатчик, ethernet-кабель. Включаем!
Опрос термодатчика происходит каждые 10 секунд. Один раз в минуту значения усредняются и отправляются на сервер. Следить за температурой можно по ссылке https://pachube.com/feeds/00000 , где вместо 00000 подставьте свой ID.
У меня график выглядел так:
temp_p

P.S. данный сервис можно применять не только для контроля температуры, но и многих других данных: влажность, скорость ветра, энергопотребление и т.д.

Файлы
Скетч (3.43 KB)
Библиотеки:
DallasTemperature (22.27 KB)
ERxPachube (10.8 KB)
Ethernet (29.73 KB)
OneWire (8.54 KB)
SPI (7.49 KB)

Работа проверялась с Arduino IDE v0.22

Предупреждение!
Автор не несёт ответственности за возможную порчу оборудования. Всё, что вы делаете — вы делаете на свой страх и риск!

Похожие записи:

11 Комментарии “Arduino: цифровой термометр с web-мониторингом

  1. Спасибо! Очень интересный пример по работе с 18В20 и программирования Arduino.
    Я не большой знаток Си но видимо это оттуда, что значит звездочка * в объявлении символьной переменной «char * floatToString(char * outstr,…..»
    И зачем мы передаем пустую строку test[20] в эту функцию??

    1. Звёздочка означает что это указатель.
      Функцию floatToString я не сам писал, этот массив там нужен для каких-то внутренних нужд, сильно в его работу я не вникал.

  2. Предлагаю присоединиться к отечественному проекту Народного мониторинга (http://narodmon.ru) для отображения на карте показаний датчиков с устр-в измерения в различных городах РФ и СНГ.
    На данный момент устр-в на базе Arduino нет, предлагаю стать первым!
    Для оперативной связи ICQ 98-068-235

  3. Судя по всему на у сервиса изменился интерфейс, что-то никак не получается отправить данные на pachube …

  4. Данные уходят,но сайт их не принимает, на всякий случай пробовал без роутера, но увы. Проверил ip у портала не поменялись, скетч проходит без проблем. При создании устройства выбирал как обычный feed так и Arduino устройство. Ключи проверял, генерировал как ограниченные так и не ограниченные. На сайте смотрел примеры, сверял и вашими вариантом, вроде похоже. Возможно где-то я сделал не правильно, но увы пока не нашёл. Пытаюсь разобраться ,если получится, то напишу или может вы подскажете. (Arduino IDE v0.22 Ubuntu 10.04)

      1. Спасибо, надеюсь успею сам добить проблему, чувствую она рядом =)),но если не успею, буду признателен за ваш ответ.

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

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