Часы-метеостанция на Ардуино - ФОРУМ ДВ Робот dvrobot.ru
Суббота, 15.12.2018, 02:52
Главная Мой профиль Регистрация Выход
  • НАШ МАГАЗИН
  • Вы вошли как Гость | Группа "Гости"Приветствую Вас, Гость
    [ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
    • Страница 1 из 1
    • 1
    Модератор форума: GRACH, Serg  
    ФОРУМ ДВ Робот dvrobot.ru » DV ROBOT » Библиотека Проектов » Часы-метеостанция на Ардуино
    Часы-метеостанция на Ардуино
    Mef78Дата: Вторник, 04.03.2014, 19:08 | Сообщение # 1
    1.5 Вольт
    Группа: Пользователи
    Сообщений: 9
    Репутация: 0
    Статус: Offline
    Вот чего собрал на досуге: часы-метеостанцию на Ардуино
    Что понадобилось:
    Arduino UNO
    DS3231 (на шине i2c)
    DHT11 (на 11 ноге ардуино)
    GY-65 (BMP085) (на шине i2c)
    LCD1602 (на 2-3-4-5-6-7 ногах ардуино)
    А еще кусочек оргстекла, несколько стоек, монтажная платка.
    Код собрал из разных скетчей - примеров работы с датчиками. Собирал в основном ради интереса smile и ради попробовать.
    Температура берется с датчика давления и с dht11, значения совпадают.

    В планах прикрутить внешний температурный датчик на ds18b20, чтоб температуру на улице измерять. Или на KTY81-200 через аналоговую ногу с ацп. Тоже интересно получается, уже пробовал... Аналоговый датчик правда менее точным будет.
    Либо надо было покупать DHT22 и выносить его на улицу. У него диапазон измерения температуры шире.

    Часы устанавливал отдельным скетчем через эмулятор терминала, в данном варианте установку часов не предусматривал.

    Я кстати переписал скетч, отказавшись от использования библиотеки bmp085 v4. Сейчас в теме новый скетч.




    Сам скетч:
    ---------------------------------------------

    #include <Wire.h>
    #include <dht11.h>
    #include <LiquidCrystal.h>
    LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
    #define BMP085_ADDRESS 0x77  // I2C address of BMP085
    dht11 sensor;
    #define DHT11PIN 11
    #define DS1307_ADDRESS 0x68
    const unsigned char OSS = 0;  // Oversampling Setting
    // Calibration values
    int ac1;
    int ac2;
    int ac3;
    unsigned int ac4;
    unsigned int ac5;
    unsigned int ac6;
    int b1;
    int b2;
    int mb;
    int mc;
    int md;
    // b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
    // so ...Temperature(...) must be called before ...Pressure(...).
    long b5;
    short temperature;
    long pressure;
    void setup()
    {
    lcd.begin(16, 2);
    Wire.begin();
    bmp085Calibration();
    }
    void loop()
    {
    lcd.clear();
    for (int i=0; i<=100; i++){
    //bmp085
    temperature = bmp085GetTemperature(bmp085ReadUT());
    pressure = bmp085GetPressure(bmp085ReadUP());
    lcd.setCursor(0, 0);
    lcd.print("P=");
    int press=pressure/133.3;
    lcd.print(press);
    lcd.print("mm");
    lcd.setCursor(8, 0);
    lcd.print("T1=");
    lcd.print(temperature/10);
    lcd.print("oC");
    //dht-11
    delay (20);
    int chk = sensor.read(DHT11PIN);
    lcd.setCursor(0, 1);
    lcd.print("Hum=");
    lcd.print(sensor.humidity);
    lcd.print("%");
    lcd.setCursor(8, 1);
    lcd.print("T2=");
    lcd.print(sensor.temperature);
    lcd.print("oC");
    }

    //отсюда работа с часиками
    printDate();
    delay(40);
    }
    byte bcdToDec(byte val)
    {
    // Convert binary coded decimal to normal decimal numbers
    return ( (val/16*10) + (val%16) );
    }
    void printDate(){
    lcd.clear();
    //цикл под "живые" часики
    for (int i=0; i<=600; i++){
    // Reset the register pointer
    Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(0);
    Wire.endTransmission();
    Wire.requestFrom(DS1307_ADDRESS, 7);
    int second = bcdToDec(Wire.read());
    int minute = bcdToDec(Wire.read());
    int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
    int weekDay = bcdToDec(Wire.read()); //0-6 -> Sunday - Saturday
    int monthDay = bcdToDec(Wire.read());
    int month = bcdToDec(Wire.read());
    int year = bcdToDec(Wire.read());
    //Рисуем дату и время на lcd: День/Месяц/Год День недели
    lcd.setCursor(0, 0);
    lcd.print(monthDay);
    lcd.print("/");
    if (month==1){lcd.print ("Jan");}
    if (month==2){lcd.print ("Feb");}
    if (month==3){lcd.print ("Mar");}
    if (month==4){lcd.print ("Apr");}
    if (month==5){lcd.print ("May");}
    if (month==6){lcd.print ("Jun");}
    if (month==7){lcd.print ("Jul");}
    if (month==8){lcd.print ("Aug");}
    if (month==9){lcd.print ("Sep");}
    if (month==10){lcd.print ("Oct");}
    if (month==11){lcd.print ("Nov");}
    if (month==12){lcd.print ("Dec");}
    lcd.print("/");
    lcd.print(year+2000);
    if (weekDay==0){lcd.print (" Sun.");}
    if (weekDay==1){lcd.print (" Mon.");}
    if (weekDay==2){lcd.print (" Tue.");}
    if (weekDay==3){lcd.print (" Wed.");}
    if (weekDay==4){lcd.print (" Thu.");}
    if (weekDay==5){lcd.print (" Fri.");}
    if (weekDay==6){lcd.print (" Sat.");}
    lcd.setCursor(4, 1);
    if (hour<10) {lcd.print(0);lcd.print(hour);} else {lcd.print(hour);}
    lcd.print(":");
    if (minute<10) {lcd.print(0);lcd.print(minute);} else {lcd.print(minute);}
    lcd.print(":");
    if (second<10) {lcd.print(0);lcd.print(second);} else {lcd.print(second);}
    }
    }
    // Stores all of the bmp085's calibration values into global variables
    // Calibration values are required to calculate temp and pressure
    // This function should be called at the beginning of the program
    void bmp085Calibration()
    {
    ac1 = bmp085ReadInt(0xAA);
    ac2 = bmp085ReadInt(0xAC);
    ac3 = bmp085ReadInt(0xAE);
    ac4 = bmp085ReadInt(0xB0);
    ac5 = bmp085ReadInt(0xB2);
    ac6 = bmp085ReadInt(0xB4);
    b1 = bmp085ReadInt(0xB6);
    b2 = bmp085ReadInt(0xB8);
    mb = bmp085ReadInt(0xBA);
    mc = bmp085ReadInt(0xBC);
    md = bmp085ReadInt(0xBE);
    }
    // Calculate temperature given ut.
    // Value returned will be in units of 0.1 deg C
    short bmp085GetTemperature(unsigned int ut)
    {
    long x1, x2;

    x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
    x2 = ((long)mc << 11)/(x1 + md);
    b5 = x1 + x2;
    return ((b5 + 8)>>4);
    }
    // Calculate pressure given up
    // calibration values must be known
    // b5 is also required so bmp085GetTemperature(...) must be called first.
    // Value returned will be pressure in units of Pa.
    long bmp085GetPressure(unsigned long up)
    {
    long x1, x2, x3, b3, b6, p;
    unsigned long b4, b7;

    b6 = b5 - 4000;
    // Calculate B3
    x1 = (b2 * (b6 * b6)>>12)>>11;
    x2 = (ac2 * b6)>>11;
    x3 = x1 + x2;
    b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

    // Calculate B4
    x1 = (ac3 * b6)>>13;
    x2 = (b1 * ((b6 * b6)>>12))>>16;
    x3 = ((x1 + x2) + 2)>>2;
    b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;

    b7 = ((unsigned long)(up - b3) * (50000>>OSS));
    if (b7 < 0x80000000)
    p = (b7<<1)/b4;
    else
    p = (b7/b4)<<1;

    x1 = (p>>8) * (p>>8);
    x1 = (x1 * 3038)>>16;
    x2 = (-7357 * p)>>16;
    p += (x1 + x2 + 3791)>>4;

    return p;
    }
    // Read 1 byte from the BMP085 at 'address'
    char bmp085Read(unsigned char address)
    {
    unsigned char data;

    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(address);
    Wire.endTransmission();

    Wire.requestFrom(BMP085_ADDRESS, 1);
    while(!Wire.available())
    ;

    return Wire.read();
    }
    // Read 2 bytes from the BMP085
    // First byte will be from 'address'
    // Second byte will be from 'address'+1
    int bmp085ReadInt(unsigned char address)
    {
    unsigned char msb, lsb;

    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(address);
    Wire.endTransmission();

    Wire.requestFrom(BMP085_ADDRESS, 2);
    while(Wire.available()<2)
    ;
    msb = Wire.read();
    lsb = Wire.read();

    return (int) msb<<8 | lsb;
    }
    // Read the uncompensated temperature value
    unsigned int bmp085ReadUT()
    {
    unsigned int ut;

    // Write 0x2E into Register 0xF4
    // This requests a temperature reading
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x2E);
    Wire.endTransmission();

    // Wait at least 4.5ms
    delay(5);

    // Read two bytes from registers 0xF6 and 0xF7
    ut = bmp085ReadInt(0xF6);
    return ut;
    }
    // Read the uncompensated pressure value
    unsigned long bmp085ReadUP()
    {
    unsigned char msb, lsb, xlsb;
    unsigned long up = 0;

    // Write 0x34+(OSS<<6) into register 0xF4
    // Request a pressure reading w/ oversampling setting
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x34 + (OSS<<6));
    Wire.endTransmission();

    // Wait for conversion, delay time dependent on OSS
    delay(2 + (3<<OSS));

    // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF6);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 3);

    // Wait for data to become available
    while(Wire.available() < 3)
    ;
    msb = Wire.read();
    lsb = Wire.read();
    xlsb = Wire.read();

    up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);

    return up;
    }

    Добавлено (04.03.2014, 18:47)
    ---------------------------------------------
    Прилепил на 8 ногу датчик температуры ds18b20+
    У каждого датчика свой, уникальный адрес.
    Его искать с помощью скетча из следующего сообщения (скетч под спойлером)
    На 9 ногу перенес DHT11
    А сейчас новый код...
    ------------------------------------------------------------------------------------------------------

    #include <Wire.h> //i2c библиотека
    #include <dht11.h> // dht11 библиотека
    #include <OneWire.h> //
    #include <DallasTemperature.h>
    #define ONE_WIRE_BUS 8 //8 порт Ардуино под ds18b20
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    //адрес именно моего ds18b20
    DeviceAddress insideThermometer = { 0x28, 0x23, 0xCC, 0x55, 0x04, 0x00, 0x00, 0x35 };
    //DeviceAddress outsideThermometer = { 0x28, 0x23, 0xCC, 0x55, 0x04, 0x00, 0x00, 0x35 };
    #include <LiquidCrystal.h>
    LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
    byte gradus[8] =
    {
    B01110,
    B10001,
    B10001,
    B10001,
    B01110,
    B00000,
    B00000,
    B00000,
    };

    #define BMP085_ADDRESS 0x77  // I2C address of BMP085
    dht11 sensor;
    #define DHT11PIN 9 //9 порт ардуино под dht11
    #define DS1307_ADDRESS 0x68
    const unsigned char OSS = 0;  // Oversampling Setting
    // Calibration values
    int ac1;
    int ac2;
    int ac3;
    unsigned int ac4;
    unsigned int ac5;
    unsigned int ac6;
    int b1;
    int b2;
    int mb;
    int mc;
    int md;
    // b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
    // so ...Temperature(...) must be called before ...Pressure(...).
    long b5;
    short temperature;
    long pressure;
    void setup()
    {
    lcd.begin(16, 2);
    lcd.createChar(1, gradus);
    Wire.begin();
    bmp085Calibration();
    sensors.begin();
    sensors.setResolution(insideThermometer, 10);
    }
    void printTemperature(DeviceAddress deviceAddress)
    {
    short tempC = sensors.getTempC(deviceAddress);
    lcd.print(tempC);
    }
    void loop()
    {
    lcd.clear();
    //bmp085
    temperature = bmp085GetTemperature(bmp085ReadUT());
    pressure = bmp085GetPressure(bmp085ReadUP());
    lcd.setCursor(0, 0);
    lcd.print("P=");
    int press=pressure/133.3;
    lcd.print(press);
    lcd.print("mm");
    lcd.setCursor(8, 0);
    lcd.print("T1=");
    lcd.print(temperature/10);
    lcd.print("\1C");
    //dht-11
    int chk = sensor.read(DHT11PIN);
    lcd.setCursor(0, 1);
    lcd.print("Hum=");
    lcd.print(sensor.humidity);
    lcd.print("%");
    lcd.setCursor(8, 1);
    lcd.print("T2=");
    //ds18b20+ temp
    sensors.requestTemperatures();
    printTemperature(insideThermometer);
    // lcd.print(sensor.temperature);
    lcd.print("\1C");
    delay(3000);
    //отсюда работа с часиками
    printDate();
    delay(40);
    }
    byte bcdToDec(byte val)
    {
    // Convert binary coded decimal to normal decimal numbers
    return ( (val/16*10) + (val%16) );
    }
    void printDate(){
    lcd.clear();
    //цикл под "живые" часики
    for (int i=0; i<=600; i++){
    // Reset the register pointer
    Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(0);
    Wire.endTransmission();
    Wire.requestFrom(DS1307_ADDRESS, 7);
    int second = bcdToDec(Wire.read());
    int minute = bcdToDec(Wire.read());
    int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
    int weekDay = bcdToDec(Wire.read()); //0-6 -> Sunday - Saturday
    int monthDay = bcdToDec(Wire.read());
    int month = bcdToDec(Wire.read());
    int year = bcdToDec(Wire.read());
    //Рисуем дату и время на lcd: День/Месяц/Год День недели
    lcd.setCursor(0, 0);
    if (monthDay<10) {lcd.print(0);lcd.print(monthDay);} else {lcd.print(monthDay);}
    lcd.print("/");
    if (month==1){lcd.print ("Jan");}
    if (month==2){lcd.print ("Feb");}
    if (month==3){lcd.print ("Mar");}
    if (month==4){lcd.print ("Apr");}
    if (month==5){lcd.print ("May");}
    if (month==6){lcd.print ("Jun");}
    if (month==7){lcd.print ("Jul");}
    if (month==8){lcd.print ("Aug");}
    if (month==9){lcd.print ("Sep");}
    if (month==10){lcd.print ("Oct");}
    if (month==11){lcd.print ("Nov");}
    if (month==12){lcd.print ("Dec");}
    lcd.print("/");
    lcd.print(year+2000);
    if (weekDay==0){lcd.print (" Sun.");}
    if (weekDay==1){lcd.print (" Mon.");}
    if (weekDay==2){lcd.print (" Tue.");}
    if (weekDay==3){lcd.print (" Wed.");}
    if (weekDay==4){lcd.print (" Thu.");}
    if (weekDay==5){lcd.print (" Fri.");}
    if (weekDay==6){lcd.print (" Sat.");}
    lcd.setCursor(4, 1);
    if (hour<10) {lcd.print(0);lcd.print(hour);} else {lcd.print(hour);}
    lcd.print(":");
    if (minute<10) {lcd.print(0);lcd.print(minute);} else {lcd.print(minute);}
    lcd.print(":");
    if (second<10) {lcd.print(0);lcd.print(second);} else {lcd.print(second);}
    }
    }
    // Stores all of the bmp085's calibration values into global variables
    // Calibration values are required to calculate temp and pressure
    // This function should be called at the beginning of the program
    void bmp085Calibration()
    {
    ac1 = bmp085ReadInt(0xAA);
    ac2 = bmp085ReadInt(0xAC);
    ac3 = bmp085ReadInt(0xAE);
    ac4 = bmp085ReadInt(0xB0);
    ac5 = bmp085ReadInt(0xB2);
    ac6 = bmp085ReadInt(0xB4);
    b1 = bmp085ReadInt(0xB6);
    b2 = bmp085ReadInt(0xB8);
    mb = bmp085ReadInt(0xBA);
    mc = bmp085ReadInt(0xBC);
    md = bmp085ReadInt(0xBE);
    }
    // Calculate temperature given ut.
    // Value returned will be in units of 0.1 deg C
    short bmp085GetTemperature(unsigned int ut)
    {
    long x1, x2;

    x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
    x2 = ((long)mc << 11)/(x1 + md);
    b5 = x1 + x2;
    return ((b5 + 8)>>4);
    }
    // Calculate pressure given up
    // calibration values must be known
    // b5 is also required so bmp085GetTemperature(...) must be called first.
    // Value returned will be pressure in units of Pa.
    long bmp085GetPressure(unsigned long up)
    {
    long x1, x2, x3, b3, b6, p;
    unsigned long b4, b7;

    b6 = b5 - 4000;
    // Calculate B3
    x1 = (b2 * (b6 * b6)>>12)>>11;
    x2 = (ac2 * b6)>>11;
    x3 = x1 + x2;
    b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

    // Calculate B4
    x1 = (ac3 * b6)>>13;
    x2 = (b1 * ((b6 * b6)>>12))>>16;
    x3 = ((x1 + x2) + 2)>>2;
    b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;

    b7 = ((unsigned long)(up - b3) * (50000>>OSS));
    if (b7 < 0x80000000)
    p = (b7<<1)/b4;
    else
    p = (b7/b4)<<1;

    x1 = (p>>8) * (p>>8);
    x1 = (x1 * 3038)>>16;
    x2 = (-7357 * p)>>16;
    p += (x1 + x2 + 3791)>>4;

    return p;
    }
    // Read 1 byte from the BMP085 at 'address'
    char bmp085Read(unsigned char address)
    {
    unsigned char data;

    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(address);
    Wire.endTransmission();

    Wire.requestFrom(BMP085_ADDRESS, 1);
    while(!Wire.available())
    ;

    return Wire.read();
    }
    // Read 2 bytes from the BMP085
    // First byte will be from 'address'
    // Second byte will be from 'address'+1
    int bmp085ReadInt(unsigned char address)
    {
    unsigned char msb, lsb;

    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(address);
    Wire.endTransmission();

    Wire.requestFrom(BMP085_ADDRESS, 2);
    while(Wire.available()<2)
    ;
    msb = Wire.read();
    lsb = Wire.read();

    return (int) msb<<8 | lsb;
    }
    // Read the uncompensated temperature value
    unsigned int bmp085ReadUT()
    {
    unsigned int ut;

    // Write 0x2E into Register 0xF4
    // This requests a temperature reading
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x2E);
    Wire.endTransmission();

    // Wait at least 4.5ms
    delay(5);

    // Read two bytes from registers 0xF6 and 0xF7
    ut = bmp085ReadInt(0xF6);
    return ut;
    }
    // Read the uncompensated pressure value
    unsigned long bmp085ReadUP()
    {
    unsigned char msb, lsb, xlsb;
    unsigned long up = 0;

    // Write 0x34+(OSS<<6) into register 0xF4
    // Request a pressure reading w/ oversampling setting
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x34 + (OSS<<6));
    Wire.endTransmission();

    // Wait for conversion, delay time dependent on OSS
    delay(2 + (3<<OSS));

    // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF6);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 3);

    // Wait for data to become available
    while(Wire.available() < 3)
    ;
    msb = Wire.read();
    lsb = Wire.read();
    xlsb = Wire.read();

    up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);

    return up;
    }
     
    -----------------------------------------------------------------------------------------------------------------

     
    Вот собственно скетч для поиска адреса датчика температуры.
    Стырен где-то в интернете.



    Добавлено (04.03.2014, 19:08)
    ---------------------------------------------
    ---------------------------------
    Ссылка на среду Ардуино с подключеными нужными библиотеками

    http://yadi.sk/d/kDVQphh8JuEEX
    -----------------------------------
    Прикрепления: 7507668.jpg(260.8 Kb) · 4951665.jpg(287.1 Kb)


    Сообщение отредактировал Mef78 - Вторник, 04.03.2014, 19:17
     
    ФОРУМ ДВ Робот dvrobot.ru » DV ROBOT » Библиотека Проектов » Часы-метеостанция на Ардуино
    • Страница 1 из 1
    • 1
    Поиск:

    ДВ Робот - Чат