Содержание

Метеостанция для записи температуры, атмосферного давления и влажности

Проекты на Arduino Uno и Slot Shield

Что должна уметь настоящая метеостанция? Измерять температуру и влажность в помещении, определять температуры за окном и атмосферное давление. А в идеале ещё и сохранять всё это в лог-файл.

Для хранения данных используем картридер для micro-SD. Данные сохранятся на карточки в виде текстового файла, который без проблем открывается на любом компьютере.

В остальном — это обычная метеостанция на Ардуино. Управляющая плата — оригинальная Arduino Uno. За температуру и влажность отвечает цифровой метеосенсор. Температуру на улице мы определяем с помощью герметичного термометра DS18B20. Атмосферное давление показывает барометр.

Что потребуется

Полный сет компонентов проекта. В сет входят:

Видеоинструкция

Как собрать

Установите Troyka Slot Shield на Arduino Uno

Подключите метеодатчик к пинам I²C разъёма A.

Вставьте Quad Display в разъёмы E и F. Пин CS подключите к 10 пину Arduino.

Барометр вставьте в пины I²C разъёма B.

Подключите термометр DS18B20 к пину 4 слота C. Для этого используйте модуль подтяжки.

Установите SD картридер в слот D и подключите к пину 8.

Скетч

Прошейте контроллер скетчем через Arduino IDE.

weather-station.ino
// библиотека для работы 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);
  }
}

Часто задаваемые вопросы

Где скачать необходимые библиотеки и как их установить?
У моего модуля QuadDisplay всего три ноги и расположены они слева. Можно ли использовать его в этом проекте?

У вас предыдущая версия модуля. Она снята с производства пару лет назад. С этим скетчем, библиотекой и схемой сборки модуль работать не будет.