31.10.10

Погодная станция на Ардуино

Ну если быть откровенным, то конечно же не погодная станция, а скорее термометр, барометр и гигрометр в одном флаконе.


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

Итак, в ролях:
  • Arduino Duemillanove
  • BMP085 от Bosch Sensortec - датчик давления и температуры
  • HIH-4030 от Honeywell - датчик влажности

Датчик влажности прост и незамысловат - подаете на него 5 вольт и получаете напряжение, линейно зависящее от влажности.
Датчик давления и температуры сложнее, он подключается по шине I2C и, кроме того,  использует для питания 3.3V.

Итак собираем схему.
Датчик влажности подключаем к земле и питанию, ногу out подключаем к аналоговому входу №0 ардуино.

Датчик давления подключаем к земле и питанию 3.3 вольта, выходы SDA и SLC подключаем к аналоговым входам 4 и 5 соответственно.

Для получения значения влажности нам понадобятся некоторые константы, которые можно найти в даташите на HIH-4030:


static const int offset = 958;
static const int slope_coef = 10;
static const int slope = 307;

offset - напряжение, соответствующее нулевой относительной влажности, а slope - соотношение между напряжением и влажностью, составляющий 30.68 mV. Поскольку я собираюсь использовать только целочисленную арифметику, то slope заведем как 307 и добавим дополнительный делитель 10.

Функция получения относительной влажности будет выглядеть так:


int get_humidity() {
   long voltage = analogRead(0); // получить значение 0..1023
   voltage = voltage * 5000 / 1023; // преобразовать в микровольты
   // вычислим относительную влажность в процентах
   return ((voltage - offset) * slope / slope_coef) / 100;
}

Код для работы с BMP085 я стянул тут. Имейте в виду, у меня этот код не заработал сразу из-за путаницы с использованием типов int, unsigned int и long. Работающий код можно взять из репозитория на bitbucket.org или из zip-файла в конце статьи.

Для удобства все функции для работы с датчиками удобно собрать в библиотеку. Библиотека в IDE Arduino - это папка с файлами, лежащая в каталоге libraries в каталоге arduino. Библиотека содержит как минимум два файла - заголовочный h-файл и cpp-файл с кодом.

Я сделал такой заголовочный файл:


/*
Library of utility classes and functions for Arduino weather station
*/

#ifndef WEATHER_H
#define WEATHER_H

#include "WProgram.h"

// interface for humidity sensor HIH-4030
class Humidity {
  private:
    static const int offset = 958;
    static const int slope_coef = 10;
    static const int slope = 307;

    int pin;
  public:
    Humidity(const int pin = 0);

    // returns relative humidity in percents * 10
    // to get actual humidity delete results by ten
    long get_humidity();

    int get_humidity_int();
};

#define I2C_ADDRESS 0x77
#define DEFAULT_OVERSAMPLING 3

class TemperaturePressure {
  private:
    int i2c_address;
    unsigned char oversampling_setting; //oversamplig for measurement

    static const unsigned char pressure_waittime[];// = { 5, 8, 14, 26 };

    //taken straight from the BMP085 datasheet
    int ac1, ac2, ac3;
    unsigned int ac4, ac5, ac6;
    int b1, b2, mb, mc, md;

    int _temp;
    long _pressure;

    void get_calibration_data();
 
    int read_int_register(unsigned char reg);
    char read_register(unsigned char reg);
    void write_register(unsigned char reg, unsigned char value);

    unsigned int read_ut();
    long read_up();

    void read_temperature_and_pressure();
  public:
    TemperaturePressure();
    TemperaturePressure(const int i2c_address, const int oversampling);

    void read_data_from_sensor();

    int get_temperature();
    long get_pressure();

    long get_pressure_hg();

    void begin();
};

#endif

Как видно, библиотека содержит два класса - Humidity, для работы с датчиком влажности и TemperaturePressure, для работы с датчиком давления и температуры.
Для работы с датчиком давления используется библиотека Wire, которая включена в стандартный набор библиотек Arduino. К сожалению я не понял, как можно задействовать в своей библиотеке стандартные библиотеки ардуино, так что пришлось в программе включать два заголовочных файла - Wire.h и Weather.h

CPP-файл я показывать здесь не буду, чтобы не загромождать все текстом.

Ну и наконец скетч для ардуино, который использует библиотеку Weather:

#include <wire.h>
#include <weather.h>

#define HUMIDITY_PIN 0

Humidity humidity(HUMIDITY_PIN);
TemperaturePressure tempPres;

void setup() {
  Serial.begin(9600);
  Serial.println("Calibrating...");
  tempPres.begin();
  Serial.println("Calibrated");

  // Light the LED when ready
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
}

void loop() {
  int h = humidity.get_humidity_int();

  tempPres.read_data_from_sensor();
  int t = tempPres.get_temperature();
  float p = tempPres.get_pressure() * 7.5006e-3; // convert to mmHg

  Serial.print(t/10.0);
  Serial.print(";");
  Serial.print(p);
  Serial.print(";");
  Serial.println(h);

  delay(60000);
}

Скетч получает данные о температуре, относительной влажности и давлении и передает их через последовательный порт на десктоп, где простой python-скрипт записывает их в CSV-файл. Из результирующих данных можно, к примеру, построить графики изменения параметров во времени.


Исходники библиотеки и скетча можно скачать отсюда или с помощью Mercurial забрать с bitbucket

3 коментарі:

  1. Спасибо за статью. Попробую собрать что-то подобное в свободное время.

    ВідповістиВидалити
  2. А есть схема соединения? а то купил датчик не знаю как его и куда подсоединить...

    ВідповістиВидалити