Проблема с BMP-280?

Петрович
Offline
Зарегистрирован: 17.03.2016

Нет, пока есть пара проблем в железе и огромная проблема со временем - внук у меня родился. Много времени уходит на помощь дочери (в поликлиннику свозить, документы оформить, прописать в квартире и т.д.) А с железом вот какая проблема. Было все собрано на DIP ATMega 328, на макетке. В нее сразу залил загрузчик с Ардуины 3-х вольтовой и потом скетч. Сначала все работало нормально, потом изображение на индикаторе пропало. Ресет не помог. Выключил - оставил так. Через пару часов включил, все работает. Потом снова все отключается. Закономерности по времени никакой нет, может и трое суток проработать, может через час выключиться. И на включение похожая ситуация, может сразу включиться, а может только через сутки. Не пойму. Хотя есть догадка - кварц на меге поставил тот который был - на 12 МГц, а нужен на 8. Может по этому через время срывается генерация...? 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Я для narodmon.ru буду делать на Wemos D1, жду датчики, едут два BMP-280, DS18B20 у меня россыпью штук 50 есть, еще едут DS3231 и еще какие-то, на HMC5883L хотел флюгер сделать, но думаю проще будет на энкодере 360 градусов, но он по цене кусается 1500= )))
Я поколдую с твоим скетчем, запущу под I2C, скину здесь

Вот болванка под I2C, датчики не ставил, дисплей работает )))
Компилировал под 1.6.12 но некоторые библиотеки из под старых версий ставят систему в позу, подправил пути для файлов библиотек

/* Метео станция от Евгения, RA6FNQ, г.Ставрополь в модификации
 *  UA6EM под различные конфигурации
 *  1. 08.12.2016 Прикрутил дисплей LCD-1602 по I2C
 *  2. Создал раздел выбора конфигурации
 *  3. кое-какие заготовки под другие дисплеи
 */

// *** Раздел выбора конфигурации *** //
/*                                    */

//#define HARDWARE_LCD1602             // обычный дисплей 
#define HARDWARE_LCD1602_I2C         // дисплей подключенный по I2C
#define HARDWARE_DHT22               // датчик 1
#define HARDWARE_BMP280
#define interval 330                  // обновление дисплея мс 

#ifdef HARDWARE_LCD1602_I2C
#include <LiquidCrystal_I2C.h>  
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
#endif

#ifdef HARDWARE_LCD1602
#include <LiquidCrystal.h>  
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);  // подправьте под свою схему
#endif

long previousMillis = 0; 

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

#ifdef HARDWARE_DHT22
#include "DHT.h"
#define DHTPIN 9                        // 9 pin для датчика DHT22
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#endif

#ifdef HARDWARE_BMP280
#define BMP_CS 10   // hardware SPI
#define SEALEVELPRESSURE_HPA (1013.25)  // 
Adafruit_BMP280 bme(BMP_CS);            // работаем по шине  hardware SPI
#endif


long temp3 = 0, Pressure = 0, Altitude = 0;

void setup() {

 #ifdef HARDWARE_LCD1602
   lcd.begin(16, 2);
 #endif
 
 #ifdef HARDWARE_LCD1602_I2C
   lcd.begin(16,2);
 #endif
 
  lcd.print(" Meteo v01_1602H"); // приветствие
  lcd.setCursor(0,1);
  lcd.print(" RA6FNQ 2016 11"); // версия 0.3
  delay(3000);
  lcd.clear();

  Wire.begin(); 
  
  dht.begin();
  bme.begin(); //запуск BME280
  delay(2000);
}

void loop() 
{
  Pressure = bme.readPressure();
  Altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
  temp3 = bme.readTemperature();

  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature(); // Read temperature as Celsius
  delay(1000);
  
lcd.clear(); // очистим лсд дисплей
lcd.setCursor(0, 0);
lcd.print("T");//задаем температуру снаружи, DHT22
lcd.setCursor(2, 0);
lcd.print(t, 1);
lcd.setCursor(8, 0);
lcd.print("t");//задаем температуру
lcd.setCursor(10, 0);
lcd.print(bme.readTemperature(), 1); //Это температура с барометра);
lcd.setCursor(14, 0);
lcd.print("*C");


  delay (1000); // Задержка 1 с

}

Ты BMP-280 к чему и как подключаешь?
У меня он не заработал, видимо брак, ни по I2C - ни по SPI-SOFT

Viacon
Offline
Зарегистрирован: 28.11.2016

Это заработавший скетч на библиотеке "SparkFun_BME280" - сокращёный пример, но есть несколько "но".

#include "SparkFunBME280.h"
#include "Wire.h"
BME280 mySensor;
 
void setup() {
mySensor.settings.commInterface = I2C_MODE;
mySensor.settings.I2CAddress = 0x76;
mySensor.settings.runMode = 3; //Normal mode
mySensor.settings.tStandby = 0;
mySensor.settings.filter = 0;
mySensor.settings.tempOverSample = 1;
mySensor.settings.pressOverSample = 1;
mySensor.settings.humidOverSample = 1;
 
Serial.begin(57600);
delay(10);
Serial.println(mySensor.begin(), HEX);
}
 
void loop() {
Serial.print("Temperature: ");
Serial.print(mySensor.readTempC(), 2);
Serial.println("*C");
 
Serial.print("Temperature: ");
Serial.print(mySensor.readTempF(), 2);
Serial.println("F");
 
Serial.print("Pressure: ");
Serial.print(mySensor.readFloatPressure(), 2);
Serial.println("Pa");
 
  Serial.print("Pressure: ");
  Serial.print((mySensor.readFloatPressure(), 2)/133.3333);
  Serial.println("mmHg");
  
Serial.print("Altitude: ");
Serial.print(mySensor.readFloatAltitudeMeters(), 2);
Serial.println("m");
 
Serial.print("Altitude: ");
Serial.print(mySensor.readFloatAltitudeFeet(), 2);
Serial.println("ft");
 
Serial.print("%RH: ");
Serial.print(mySensor.readFloatHumidity(), 2);
Serial.println("%");
Serial.println();
 
delay(5000);
}
- скетч получается аж 10 644 байт (34%) - есть мысли как запустить на библиотеке "Grove_BME280-master", мне кажется размер будет гораздо меньше.
- не удалось вычислить давление в мм ртутн. столба - перепробовал несколько вариантов - есть что подсказать?
- без строки "Serial.println(mySensor.begin(), HEX);" не выводится параметр "Pressure" - Давление, а с этой строкой также в начале выводится цифра 58 - ну и как это победить?
ra6fnq
ra6fnq аватар
Offline
Зарегистрирован: 26.10.2011

ua6em пишет:
Ты BMP-280 к чему и как подключаешь?
У меня он не заработал, видимо брак, ни по I2C - ни по SPI-SOFT

паяю smd-шный 1117 прям на датчик давления, SCL-13, SDA-11, CSB-10, SD0-12, по IIC надо менять адрес в библиотеке, на 076

не знаю как тут вставлять картинки.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Viacon пишет:

- не удалось вычислить давление в мм ртутн. столба - перепробовал несколько вариантов - есть что подсказать?
- без строки "Serial.println(mySensor.begin(), HEX);" не выводится параметр "Pressure" - Давление, а с этой строкой также в начале выводится цифра 58 - ну и как это победить?

1. умножить на коэффициент (ртуть в 13 с гаком раз тяжелее воды к примеру) или напрямую к примеру 1000 гектопаскалей это 750 мм ртутного столба

2. А через String?

Genri5
Offline
Зарегистрирован: 31.05.2016

Привет всем. Когдо сам занимался этой темой перепробывал много библиотек. И с уверенностью могу отметить, что самая оптимальная, для меня, оказалась библиотека - "cactus_io_BME280_I2C.h"

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Genri5 пишет:

Привет всем. Когдо сам занимался этой темой перепробывал много библиотек. И с уверенностью могу отметить, что самая оптимальная, для меня, оказалась библиотека - "cactus_io_BME280_I2C.h"

Отсюда?

Genri5
Offline
Зарегистрирован: 31.05.2016

Да.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ra6fnq пишет:

ua6em пишет:
Ты BMP-280 к чему и как подключаешь?
У меня он не заработал, видимо брак, ни по I2C - ни по SPI-SOFT

паяю smd-шный 1117 прям на датчик давления, SCL-13, SDA-11, CSB-10, SD0-12, по IIC надо менять адрес в библиотеке, на 076

не знаю как тут вставлять картинки.

Картинки вставлять просто, нажимаешь кнопку изображение, далее кнопку выбор на сервере, потом загрузить, потом вставить и всё

Sherzod
Offline
Зарегистрирован: 17.04.2016

Получил китайский BMP-280, но настроить пока не получается. 
Распиновка:
SCL - 13
SDA - 11
CSB - 10
SDO - 12

Запустил Adafruit'овский тестовый скетч. Библиотека естественно от Adafruit, но в архиве не было файла Adafruit_Sensor.h. Докачал откуда то, тоже вроде с github. 

Температура в комнате где тестировался датчик примерно 25 градусов
Давление у нас по данным гидрометеостанций примерно 767 мм рт. ст.
А высота примерно 495 м над уровнем моря.
 
Сначала не стал паять ножки к плате датчика, а просто воткнул и соединил кабелями. Результаты были разные когда датчик просто лежал (результат №1) и когда прижимал кабели плотнее к датчику для лучшего соединения (результат №2):
Temp = 25.43 *C
Pressure = 562.72 mm.rt.st
~Height = 2465.58 m
 
Temp = 42.82 *C
Pressure = 728.79 mm.rt.st
~Height = 336.41 m

Из этого можно увидеть что на первом результате температура правильная, а вот давление и высота над уровнем моря вообще не то. 
А на втором результате температура очень завышена, давление более менее нормальная, высота тоже не ахти но уже тоже более менее близка к правде.

Потом запаял ножки к датчику и тогда получаю только результаты ближе к №2.
Temp = 41.76 *C
Pressure = 723.45 mm.rt.st
~Height = 415.29 m

Temp = 41.73 *C
Pressure = 723.46 mm.rt.st
~Height = 415.07 m
 
Как получить правильные данные? А именно:
1. Температуру
2. Давление и высоту. Вроде надо поменять значение 1013.25 на другое. Так вот на какое? Из какой формулы рассчитать для моей местности эту значению? Или же надо копать в другую сторону?
gulin176
Offline
Зарегистрирован: 03.09.2016

если датчик меняет значения адекватно, то просто в скетче сделайте вот так 

lcd.print((uint32_t)mySensor.readFloatPressure() / 100 + 15); lcd.print("Pa "); //+15 korrekcija

это я подогнал показания bme280 под показания домашней метеостанции орегон. а вы можете в своей местности посмотреть на народмон и также подкорректировать показания

_zerabot_
Offline
Зарегистрирован: 26.05.2017

Всем привет, вчера закончил программу для своей погодной станции. Пока гуглил по датчику BMP280 натыкался на эту ветку форума.

У меня возникло одно замечание, для всех ваших скетчей, вы слишком часто опрашиваете датчики, у меня, когда я опрашиваю чаще чем 5-10 секунд, медленно но заметно начинает повышатся температура DHT3231 и DS18D20. За BMP280 такой беды не замеченно, но на всякий случай я опрашиваю датчики 1 раз в минуту.

Я собрал станцию (пока на макетке) на часах DHT3231, внешнем датчике температуры DS18D20, барометр BMP280, экран 20*4 I2C, гигрометр DHT-11 (знаю, гадость, но у нас из-за боевых действий другие купить проблематично) и 7 сегментный дисплей на TM1637 чтобы было издалека видно время.

Погодная станция прогнозирует изменение погоды по алгоритму Zambretti, основываясь на динамике изменения давления за последние 3 часа. Может строить график изменения давления, температуры внутри и снаружи за последние 20 часов. Запоминает время достижения минимального и максимального значения 2 температур, влажности и давления за эти сутки. Выводит основные показатели на COM порт. Возможность выставлять время, дату и день недели кнопками. На остальное не хватило памяти. Скорее всего, как разбогатею, куплю еще 1 микроконтроллер, на него повешу опрос всех датчиков и экраны и буду передавать через COM порт на 2-й МК, в котором будут обрабатываться данные, и прочие плюшки =)

 

Комменты на английском, мне так легче, ненавижу язык переключать =)


//lcd
#include <LiquidCrystal_PCF8574.h>
LiquidCrystal_PCF8574 lcd(0x27);

//Clock
#include <Wire.h>
#include "Sodaq_DS3231.h"
#include <DallasTemperature.h>
char weekDay[][4] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };



//barometr
#include <BME280I2C.h>
BME280I2C bme;
float hPa = 0;
float Altitude = 0;
float MaxPressure = 0, MinPressure = 65000;
float MaxTempO = -200, MinTempO = 200, MaxTempIn = -200, MinTempIn = 200;
DateTime MaxPressureT, MinPressureT;
DateTime MaxTempOT, MinTempOT, MaxTempInT, MinTempInT, TempTime;
float Pres = 0;
float InT, OutT;




//LedDisplay
#include "TM1637.h" // Подключаем библиотеку
#define CLK 13 // К этому пину подключаем CLK
#define DIO 12 // К этому пину подключаем DIO
TM1637 tm1637(CLK, DIO);

//humidity
#include <SimpleDHT.h>
int pinDHT11 = 9;
SimpleDHT11 dht11;
byte Hum = 0;
byte DHT11temperature = 0;
byte MaxHum = 0, MinHum = 101;
DateTime MaxHumT, MinHumT;



//buttons
#define BTN 6
#define BTNUP 5
#define BTNDOWN 4



//int LCDled = 3;           // the PWM pin the LED is attached to

//Main Display mode 1- show main screen,2 shov max and min time... etc..
int DisplayMode = 0;

int  _m, _s, _mon, _day, _week;
int _h, _year;





//unsigned long RefreshLCD;
unsigned long TimeReturn;
DateTime now;
DateTime PowerOn;
byte LastRead, ResetVals;
unsigned long old_ts = 0;




float PressureHistory [20] = {
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700
};

float TempHistoryIn [20] = {
  -127, -127, -127, -127, -127,
  -127, -127, -127, -127, -127,
  -127, -127, -127, -127, -127,
  -127, -127, -127, -127, -127
};
float TempHistoryOut [20] = {
  30, 40, 42, 39, 38,
  10, 40, 42, 39, 38,
  -1, 40, 42, 39, 38,
  30, 40, 42, 39, 38
};


//OutTemp
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);


//Chars for graph
byte ArrCharIndex[9] = {
  254, 2, 95, 3, 4, 176, 5, 6, 7
};

//Zambretty array
byte Zarr[32] =
{ 0,//a
  0,//b
  0,//d
  1,//h
  5,//o
  5,//r
  5,//u
  5,//v
  5,//x
  0,//a
  0,//b
  1,//e
  2,//k
  4,//n
  5,//p
  5,//s
  5,//w
  5,//x
  8,//z
  0,//a
  0,//b
  0,//c
  0,//f
  1,//g
  2,//i
  3,//j
  3,//l
  3,//m
  6,//q
  6,//t
  7,//y
  8//z
};

String ForecastText[] =
{
  "Will fine",//0
  "Fine>shower",//1
  "Shower>imp.",//2
  "Changeable>imp.",//3
  "Showery/bright",//4
  "Rain",//5
  "Unsettled",//6
  "Storm",//7
  "Storm>rain"//8
};

//hum icon
byte HumCHR[8] = {
  B00100,
  B00100,
  B01010,
  B01010,
  B10001,
  B10001,
  B10001,
  B01110
};
//temp icon
byte Temp[8] = {
  B00100,
  B01010,
  B01010,
  B01110,
  B01110,
  B11111,
  B11111,
  B01110
};

//graph char 1/8
byte ch1[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111
};
//graph char 2/8 is _ char

//graph char 3/8
byte ch3[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B00000,
  B00000
};
//graph chars 4/8
byte ch4[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B00000,
  B00000,
  B00000
};

//graph char 5/8 is - char

//graph chars 6/8
byte ch6[8] = {
  B00000,
  B00000,
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

//graph char 7/8
byte ch7[8] = {
  B00000,
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

//graph char 8/8
byte ch8[8] = {
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};
void setup ()
{

  pinMode(BTN, INPUT_PULLUP);
  pinMode(BTNUP, INPUT_PULLUP);
  pinMode(BTNDOWN, INPUT_PULLUP);






  Wire.begin();
  Wire.beginTransmission(0x27);

  lcd.begin(20, 4); // initialize the lcd
  //load custom chars
  lcd.createChar (0, Temp);
  lcd.createChar (1, HumCHR);
  lcd.createChar (2, ch1);
  lcd.createChar (3, ch3);
  lcd.createChar (4, ch4);
  lcd.createChar (5, ch6);
  lcd.createChar (6, ch7);
  lcd.createChar (7, ch8);

  //must be called after loading chars
  lcd.home();
  lcd.clear();
  lcd.print("Wait");

  while (!bme.begin()) {
    lcd.clear();
    lcd.print("PrSensorError");
  }
  while (!rtc.begin()) {
    lcd.clear();
    lcd.print("ClockError");
  }
  lcd.setBacklight(255);

  // SetBrightness(brightness);
  tm1637.init();
  tm1637.set(7);

  //just read data from sensors ds18d20 sometimes in first read return 85.0C
  readSensors(rtc.now(), true, false);

  PowerOn = rtc.now();
  LastRead = rtc.now().hour();
  ResetVals = rtc.now().date();
  //store first values  from sensors to limit values
  readSensors(rtc.now(), true, true);
  //save current values from the sensors to history
  //for normal graph view in first 20 hours of work
  for (int tt = 0; tt < 20; tt++)
  {
    PressureHistory[tt] = Pres;
    TempHistoryIn[tt] = InT;
    TempHistoryOut[tt] = OutT;

  }
  //show main screen by default
  DisplayMode = 1;
  //try to forecast =)
  Forecast(now.month());
  Serial.begin(9600);
}



void loop ()
{
  //return to main screen from any other mode in 10 sec inactivity
  if ( millis() - TimeReturn > 10000) {
    if (DisplayMode != 1) {
      lcd.clear();
      lcd.home();
      DisplayMode = 1;
    }
    TimeReturn = millis();
  }
  //main screen
  if (DisplayMode == 1 ) {
    now = rtc.now(); //get the current date-time
    uint32_t ts = now.getEpoch();
    //check second changed or not
    if (old_ts != ts) {
      old_ts = ts;
      //Write time  on tm1367
      tm1637.display(0, now.hour() / 10);
      tm1637.display(1, now.hour() % 10);
      tm1637.display(2, now.minute() / 10);
      tm1637.display(3, now.minute() % 10);
      //blink dot
      tm1637.point(ts % 2 == 0 ? POINT_OFF : POINT_ON);
      //write current time and date on 20*4
      WriteTimeDT(now, 0, 0);
      WriteDateDT(now, 6, 0);
      //if hour changes store current sensor values to history
      if (LastRead != now.hour())
      {
        LastRead = now.hour();
        readSensors(rtc.now(), true,  true);
        for (byte i = 0; i < 19; i++) {
          PressureHistory[i] = PressureHistory[i + 1];
          TempHistoryIn[i] = TempHistoryIn[i + 1];
          TempHistoryOut[i] = TempHistoryOut[i + 1];

        }
        TempHistoryIn[19] = InT;
        TempHistoryOut[19] = OutT;
        PressureHistory[19] = Pres;
        //if date changes reset limit values
        if ( ResetVals != now.date()) {
          ResetVals = now.date();
          MaxTempO = -200;
          MinTempO = 200;
          MaxTempIn = -200;
          MinTempIn = 200;
          MaxPressure = 0;
          MinPressure = 65000;
          MaxHum = 0;
          MinHum = 101;
          readSensors(rtc.now(), true, true);
        }
      }
      //read sensors values
      //each sensor interrogated 1 time per 60 seconds
      //and 20 seconds delay between different sensors
      if (now.second() % 10 == 0 &&  now.second() > 0)
      {
        readSensors(now, false, true);
        lcd.setCursor(0, 3);
        lcd.print("               ");
        lcd.setCursor(0, 3);
        //try to forecast
        //this function wrute on 4 line forecast
        lcd.print(Forecast(now.month()));
        //serial write some data
        Serial.print("<h");
        Serial.print(now.hour());
        Serial.print("m");
        Serial.print(now.minute());
        Serial.print("s");
        Serial.print(now.second());
        Serial.print("D");
        Serial.print(now.date());
        Serial.print("M");
        Serial.print(now.month());
        Serial.print("Y");
        Serial.print(now.year());
        Serial.print("d");
        Serial.print(weekDay[now.dayOfWeek() - 1]);
        Serial.print("InT");
        Serial.print(InT);
        Serial.print("Out");
        Serial.print(OutT);
        Serial.print("Hum");
        Serial.print(Hum);
        Serial.print("Pres");
        Serial.print(Pres);
        Serial.print("F-t");
        Serial.print(Forecast(now.month()));
        Serial.println(">");
      }
    }

    //2 line
    lcd.setCursor(0, 1);
    //write in temp
    lcd.print("In");
    //write custom temp char
    lcd.print(char(0));
    lcd.print(InT);
    //write out temp
    lcd.print(" Out");
    //write custom temp char
    lcd.print(char(0));
    lcd.print(OutT);
    //3 line
    lcd.setCursor(0, 2);
    //write custom humidity char
    lcd.print(char(1));
    //write humidity
    lcd.print(Hum);
    lcd.print("% ");
    lcd.print(Pres);
    lcd.print("mmHg ");
  }

  //show limit waluea for out temp
  if (DisplayMode == 2)
  {
    lcd.setCursor(0, 0);
    lcd.print("Max out t");
    WriteTimeDT(MaxTempOT, 0, 13);
    lcd.setCursor(0, 1);
    lcd.print(MaxTempO);
    lcd.setCursor(0, 2);
    lcd.print("Min out t");
    WriteTimeDT(MinTempOT, 2, 13);
    lcd.setCursor(0, 3);
    lcd.print(MinTempO);
  }
  //draw graph for out temp
  if (DisplayMode == 3)
  {
    lcd.setCursor(0, 0);
    lcd.print("Out t hist");
    drawGraphFullScreen(TempHistoryOut);
  }
  //show limit walues for in temp
  if (DisplayMode == 4)
  {
    lcd.setCursor(0, 0);
    lcd.print("Max in t");
    WriteTimeDT(MaxTempInT, 0, 13);
    lcd.setCursor(0, 1);
    lcd.print(MaxTempIn);
    lcd.setCursor(0, 2);
    lcd.print("Min in t");
    WriteTimeDT(MinTempInT, 2, 13);
    lcd.setCursor(0, 3);
    lcd.print(MinTempIn);
  }
  //draw graph for in temp
  if (DisplayMode == 5)
  {
    lcd.setCursor(0, 0);
    lcd.print("In t hist");
    drawGraphFullScreen(TempHistoryIn);
  }
  //show limit walues for pressure
  if (DisplayMode == 6)
  {
    lcd.setCursor(0, 0);
    lcd.print("Max pressure");
    WriteTimeDT(MaxPressureT, 0, 13);
    lcd.setCursor(0, 1);
    lcd.print(MaxPressure);
    lcd.setCursor(0, 2);
    lcd.print("Min pressure");
    WriteTimeDT(MinPressureT, 2, 13);
    lcd.setCursor(0, 3);
    lcd.print(MinPressure);
  }
  //draw graph for pressure
  if (DisplayMode == 7)
  {
    lcd.setCursor(0, 0);
    lcd.print("Pressure hist");
    drawGraphFullScreen(PressureHistory);
  }
  //show limit walues for humidity
  if (DisplayMode == 8)
  {
    lcd.setCursor(0, 0);
    lcd.print("Max humidity");
    WriteTimeDT(MaxHumT, 0, 13);
    lcd.setCursor(0, 1);
    lcd.print(MaxHum);
    lcd.setCursor(0, 2);
    lcd.print("Min humidity");
    WriteTimeDT(MinHumT, 2, 13);
    lcd.setCursor(0, 3);
    lcd.print(MinHum);
  }

  //show Altitude, uptime and (c)
  if (DisplayMode == 9)
  {
    lcd.setCursor(0, 0);
    lcd.print("Altitude ");
    lcd.print(Altitude);
    lcd.print("m ");

    lcd.setCursor(0, 1);
    lcd.print("PowerOn");
    WriteTimeDT(PowerOn, 2, 0);
    WriteDateDT(PowerOn, 6, 2);
    lcd.setCursor(0, 3);
    lcd.print("(c)IvanchenkoAV 2017");
  }

  //if button up pressed
  if (!digitalRead(BTNUP) && DisplayMode < 100)
  {
    DisplayMode++;
    lcd.clear();

  }
  //if button down pressed
  if (!digitalRead(BTNDOWN) && DisplayMode < 100)
  {
    DisplayMode--;
    lcd.clear();

  }
  //display menu limits
  if (DisplayMode == 10)
  {
    DisplayMode = 1;
  }
  //display menu limits
  if (DisplayMode == 0)
  {
    DisplayMode = 9;
  }

  //set button pressed
  if (!digitalRead(BTN)) {
    TimeReturn = millis();
    //if set button pressed in main screen mode
    if (DisplayMode < 100)
    {
      DisplayMode = 100;
      //save current time to temp values
      TempTime = rtc.now();
      _h = TempTime.hour();
      _m = TempTime.minute();
      _day = TempTime.date();
      _mon = TempTime.month();
      _year = TempTime.year();
      _week = TempTime.dayOfWeek();
    }
    else
      //if button pressed in set mode
      DisplayMode++;
    //menu limit
    if (DisplayMode == 107) {
      lcd.setCursor(0, 1);
      lcd.print("Cancel");
      delay(3000);
      DisplayMode = 1;
      lcd.clear();
    }
    //delay(300);

  }
  delay(200);
  //disp.set(brightness / 64 + 1);

  //reset time return if any buton pressed
  if (!digitalRead(BTNUP) || !digitalRead(BTNDOWN)) {
    TimeReturn = millis();
  }
  //temp hour set
  if (DisplayMode == 100)
  {
    if (!digitalRead(BTNUP))
      _h++;
    if (!digitalRead(BTNDOWN))
      _h--;

    if (_h > 23)
      _h = 0;
    if (_h < 0)
      _h = 23;
    lcd.clear();
    lcd.home();
    lcd.print("Hour ");
    lcd.print(_h);
  }
  //temp minute set
  if (DisplayMode == 101)
  {

    if (!digitalRead(BTNUP))
      _m++;
    if (!digitalRead(BTNDOWN))
      _m--;

    if (_m >= 60)
      _m = 0;
    if (_m < 0)
      _m = 59;
    lcd.clear();
    lcd.home();
    lcd.print("Minute ");
    lcd.print(_m);
  }
  //temp date set
  if (DisplayMode == 102)
  {

    if (!digitalRead(BTNUP))
      _day++;
    if (!digitalRead(BTNDOWN))
      _day--;

    if (_day > 31)
      _day = 1;
    if (_day < 1)
      _day = 31;
    lcd.clear();
    lcd.home();
    lcd.print("Day ");
    lcd.print(_day);
  }
  //temp month set
  if (DisplayMode == 103)
  {
    if (!digitalRead(BTNUP))
      _mon++;
    if (!digitalRead(BTNDOWN))
      _mon--;

    if (_mon > 12)
      _mon = 1;
    if (_mon < 1)
      _mon = 12;
    lcd.clear();
    lcd.home();
    lcd.print("Month ");
    lcd.print(_mon);
  }
  //temp year set
  if (DisplayMode == 104)
  {

    if (!digitalRead(BTNUP))
      _year++;
    if (!digitalRead(BTNDOWN))
      _year--;

    if (_year > 3000)
      _year = 1;
    if (_year < 1)
      _year = 3000;

    lcd.clear();
    lcd.home();
    lcd.print("Year ");
    lcd.print(_year);
  }
  //temp weekday set
  if (DisplayMode == 105)
  {
    if (!digitalRead(BTNUP))
      _week++;
    if (!digitalRead(BTNDOWN))
      _week--;

    if (_week > 7)
      _week = 1;
    if (_week < 1)
      _week = 7;


    lcd.clear();
    lcd.home();
    lcd.print("WeekDay ");
    lcd.print(weekDay[_week - 1]);
  }
  // set new time?
  if (DisplayMode == 106)
  {
    lcd.clear();
    lcd.home();
    lcd.print("Save Y/N?");

    //if button up pressed save new time
    if (!digitalRead(BTNUP))
    {
      DateTime dt(_year, _mon, _day, _h, _m, 0, _week);
      rtc.setDateTime(dt);
      lcd.setCursor(0, 1);
      lcd.print("Ok");
      delay(3000);
      DisplayMode = 1;
      lcd.clear();
    }
    //if button down pressed - exit to main screen
    if (!digitalRead(BTNDOWN)) {
      lcd.setCursor(0, 1);
      lcd.print("Cancel");
      delay(3000);
      DisplayMode = 1;
      lcd.clear();
    }
  }
}
//write time in x,y of lcd
void WriteTimeDT(DateTime Time, byte y, byte x) {
  lcd.setCursor(x, y);
  if (Time.hour() < 10)
    lcd.print('0');
  lcd.print(Time.hour());
  lcd.print(Time.second() % 2 == 0 ? ':' : ' ');
  if (Time.minute() < 10)
    lcd.print('0');
  lcd.print(Time.minute());
}
//write date in x,y of lcd
void WriteDateDT(DateTime Time, int x, int y) {
  lcd.setCursor(x, y);
  if (Time.date() < 10)
    lcd.print('0');
  lcd.print(Time.date());
  lcd.print('/');
  if (Time.month() < 10)
    lcd.print('0');
  lcd.print(Time.month());
  lcd.print('/');
  lcd.print(Time.year());
  lcd.print(' ');
  lcd.print(weekDay[Time.dayOfWeek() - 1]);
}



//draw graph
void drawGraphFullScreen(float x[20]) {
  //
  float maxp = -30000, minp = 30000;
  float divider;
  byte curVal;
  //saerch max and min values in history
  for (byte i = 0; i < 20; i++)
  {
    if ( x[i] > maxp)
      maxp =  x[i];
    if ( x[i] < minp)
      minp =  x[i];
  }
  //graph draw in 3 lines, so we have 24 pixels height graph
  //Do not deny yourself anything =)
  //  divider - value of division of 1 pixel +0.01 to prevert division by 0
  divider = (maxp - minp) / 24 + 0.01;
  //write value of division
  lcd.setCursor(14, 0);
  lcd.print(divider);

  for (byte i = 0; i < 20; i++)
  {

    //draw 4 line, bottom of graph
    curVal = byte((x[i] - minp) / divider);
    lcd.setCursor(i, 3);
    //if current value of graph catch in value 0 to 8*divider
    //we draw chart
    if (curVal <= 8)
    {
      //seach appropriate char in array of custom chars
      if (curVal > 0)
        lcd.print(char(ArrCharIndex[curVal]));
      else
        //if current val = min
        lcd.print(char(2));
    }
    else
      //if chart line upper than current line print blank char
      lcd.print(char(ArrCharIndex[0]));
    //draw 3 line - middle of graph
    lcd.setCursor(i, 2);
    if (curVal <= 16 && curVal > 8)
      //if current value of graph catch in value  8*divider to 16*divider
      //we draw chart
      //seach appropriate char in array of custom chars
      lcd.print(char(ArrCharIndex[curVal - 8]));
    else
      //if chart line upper or lover than current line print blank char
      lcd.print(char(ArrCharIndex[0]));

    lcd.setCursor(i, 1);
    //draw 4 line, bottom of graph
    if (curVal <= 24 && curVal > 16)
      //if current value of graph catch in value  16*divider to 24*divider
      lcd.print(char(ArrCharIndex[curVal - 16]));
    else
      //if chart line lover than current line print blank char
      lcd.print(char(ArrCharIndex[0]));
  }
}

//read data from sensors depending on currend second
//bool Now means read all data immideatly
//bool store mean save limiting values data or not
void readSensors (DateTime Time, boolean Now, boolean store)
{
  if (!Now) {
    switch  ( Time.second()) {

      case 20:
        //out temp dht18d20
        sensors.requestTemperatures();
        OutT = sensors.getTempCByIndex(0);
        //store limiting values and time when they arrived
        if (store) {
          if (OutT > MaxTempO) {
            MaxTempO = OutT;
            MaxTempOT = Time;
          }
          if (OutT < MinTempO) {
            MinTempO = OutT;
            MinTempOT = Time;
          }
        }

        break;
      case 30:

        dht11.read(pinDHT11, &DHT11temperature, &Hum, NULL);
        //store limiting values and time when they arrived
        if (store) {
          if (Hum > MaxHum) {
            MaxHum = Hum;
            MaxHumT = Time;
          }
          if (Hum < MinHum) {
            MinHum = Hum;
            MinHumT = Time;
          }

        }
        break;
      case 40:

        float  hum(NAN);
        uint8_t pressureUnit(0);                                           // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
        bme.read(Pres, InT, hum, true, pressureUnit);
        hPa = Pres / 100 + Altitude / 9.4;
        Pres = Pres * 0.00750063755419211;
        Altitude = bme.alt(true);
        //store limiting values and time when they arrived
        if (store) {
          if (Pres > MaxPressure) {
            MaxPressure = Pres;
            MaxPressureT = Time;
          }
          if (Pres < MinPressure) {
            MinPressure = Pres;
            MinPressureT = Time;
          }

          if (InT > MaxTempIn) {
            MaxTempIn = InT;
            MaxTempInT = Time;
          }
          if (InT < MinTempIn) {
            MinTempIn = InT;
            MinTempInT = Time;
          }

        }
        break;


    }
  }
  else {

    if (store) {

    }
    //out temp dht18d20
    sensors.requestTemperatures();
    OutT = sensors.getTempCByIndex(0);
    //read humidity
    dht11.read(pinDHT11, &DHT11temperature, &Hum, NULL);
    //reap pressure and temp
    float  hum(NAN);
    uint8_t pressureUnit(0);                                           // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
    bme.read(Pres, InT, hum, true, pressureUnit);
    hPa = Pres / 100 + Altitude / 9.4;
    //convert hPa to mmHh
    Pres = Pres * 0.00750063755419211;
    Altitude = bme.alt(true);
    //store limiting values and time when they arrived
    if (store) {
      if (Pres > MaxPressure) {
        MaxPressure = Pres;
        MaxPressureT = Time;
      }
      if (Pres < MinPressure) {
        MinPressure = Pres;
        MinPressureT = Time;
      }
      if (InT > MaxTempIn) {
        MaxTempIn = InT;
        MaxTempInT = Time;
      }
      if (InT < MinTempIn) {
        MinTempIn = InT;
        MinTempInT = Time;
      }
      if (Hum > MaxHum) {
        MaxHum = Hum;
        MaxHumT = Time;
      }
      if (Hum < MinHum) {
        MinHum = Hum;
        MinHumT = Time;
      }
      if (OutT > MaxTempO) {
        MaxTempO = OutT;
        MaxTempOT = Time;
      }
      if (OutT < MinTempO) {
        MinTempO = OutT;
        MinTempOT = Time;
      }

    }


  }

}


// Select weather index Zambretti
String Forecast(byte Mon)
{
  float z = 0;
  char a;
  //Pressure is up
  if (PressureHistory[19] - PressureHistory[18] > 0.8 && PressureHistory[18] - PressureHistory[17] > 0.8)
  {
    z = 179 - 2 * hPa / 12.9;
    if (Mon >= 5 && Mon <= 9)
      z -= 2;
    if (Mon < 5 || Mon > 9)
      z -= 1;
    return "_-" + ForecastText[Zarr[int(z)]];
  }
  else
    // Pressure is down
    if (PressureHistory[19] - PressureHistory[18] < -0.8 && PressureHistory[18] - PressureHistory[17] < -0.8) {
      z = 130 - hPa / 8.1;
      return "-_" + ForecastText[Zarr[int(z)]];
      if (Mon >= 5 && Mon <= 9)
        z += 2;
      if (Mon < 5 || Mon > 9)
        z += 1;
    } else {
      //stable pressure
      z = 147 - 5 * hPa / 37.6;
      return "--" + ForecastText[Zarr[int(z)]];
    }
  //return forecast string

}

Фото основного экрана

еще фото

/sites/default/files/u29096/img_2017-05-26_123030_hdr.jpg

/sites/default/files/u29096/img_2017-05-26_123033_hdr.jpg

/sites/default/files/u29096/img_2017-05-26_123041_hdr.jpg

/sites/default/files/u29096/img_2017-05-26_123045_hdr.jpg

/sites/default/files/u29096/img_2017-05-26_123051_hdr.jpg

/sites/default/files/u29096/img_2017-05-26_123058_hdr.jpg

/sites/default/files/u29096/img_2017-05-26_123051_hdr_0.jpg

/sites/default/files/u29096/img_2017-05-26_123105_hdr.jpg

/sites/default/files/u29096/img_2017-05-26_123124_hdr.jpg

фоткать меню выставления времени не стал )

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Красиво получилось

Genri5
Offline
Зарегистрирован: 31.05.2016

ua6em пишет:

Красиво получилось

Что красивового то? Красиво - это когда черным по белому и понятным родным языком написано! :-)

Хотя бы вот так - 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Genri5 пишет:

ua6em пишет:

Красиво получилось

Что красивового то? Красиво - это когда черным по белому и понятным родным языком написано! :-)

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

К коду замечания есть? есть - свой код в студию, посозерцаем на ваши шедевры

Лично я лучшей математики в реализации метеостанции не видел, носом ткните если знаете, что такое есть

_zerabot_
Offline
Зарегистрирован: 26.05.2017

Genri5 пишет:

Что красивового то? Красиво - это когда черным по белому и понятным родным языком написано! :-)

Как война закончится (надеюсь когда-нибудь это случится), куплю нормальный экран с поддержкой кирилицы, а не выдранный из неведомой хрени на барахолке и корейским шрифтом.

И как уже говорилось выше, если у вас экран это поддерживает, замените в исходнике текст, дело 5 минут. А тратить драгоценную память переменных под русские буквы, для меня непозволительно. И так думаю уже о объединении 2 МК в одном устройстве, для освобождения ресурсов. Один чисто как хранилище данных использовать. Кстати, в данном виде, если вы проведете русификацию, у вас не загрузится прошивка, не хватит бамяти. В этом коде если использовать еще 42 байта памяти переменных программа начинает работать нестабильно, из-за нехватки памяти. Тут каждая команда выверена и 3 раза оценена именно с точки зрения уменьшения объема кода. Я пробовал разные варианты одного и того же, и выбирал самый легковесный. В планах еще поковырять библиотеки, возможно там есть за счет чего освободить память.

Лично для меня основная фишка прибора - именно прогноз. Я на непосредственно программу потратил от силы 5-6 часов. С подключением устройств и долбежкой с библиотеками. И примерно 20 часов искал в интернете что то вменяемое, что можно запрограммировать.

И второй фишкой является то, что на приборе можно выставлять время без сторонних примочек.

Сейчас буду пытаться подключить к программатору эту плату, надеюсь мне очень очень повезет и эта штука окажется рабочей, несмотря на то, что в плату явно попало 220.

Нашел на барахолке, не знаю что это, но явно втыкалось в комп.

Если заработает, я спасен и я смогу сделать еще кучу хотелок.

В планах, если заработает:

*Внести все варианты ветвления прогноза калькулятора Zambretti без обобщений и сокращений, с плавной прокруткой длинных строк, что то типа бегущей строки но 1-й;

*График изменения влажности (не хватило памяти);

*Графики с заполнением, а не черточки как сейчас. И шаг графиков 6 минут, вместо 1 часа,  получается очень красиво красиво, но сейчас не хватает памяти даже для 1 параметра;

*Автоматическая плавная яркость 2 экранов;

*Будильник;

*RGB Подсветка с плавным переходом оттенков в зависимости от внешней t. (холодно - синий, по мере потепления - желтый, зона комфорта - зеленый, жарко - красный;

*Внешние радио датчики температуры, влажности, освещенности и т.п. связуемые через 433мГц передатчик;

*Датчик солнечной радиации;

*Счетчик Гейгера (уже готов, собран на другом МК, но на погодной станции не хватает памяти, чтобы получать данные с него). Планировал подключение через 433мГц пердатчик, чтобы счетчик Гейгера был автономным самсодостаточным устройством, но если окажется включенным в зоне погодной станции, чтобы она автоматом тянула с него показания.

Все это можно сделать за пару часов, но... Где бы мне купить Мегу 256 по цене как на Али, а не за 4700 рублей как у нас. =)

ЗЫ мне отчасти английский даже понятнее, жене - всеравно, мелкому пока вообще всеравно какая погода, время суток и температура)

ЗЫЫ а кто сказал, что для меня русский - родной ;)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AD73360 однозначно вжаренная, шесть 16 битных ацп

Genri5
Offline
Зарегистрирован: 31.05.2016

_zerabot_, не принимайте все близко к сердцу. Извините, если обидел. Главное, Вы достигли цели, Вас это устраевает, а остальное .... .

_zerabot_
Offline
Зарегистрирован: 26.05.2017

>>Genri5 Да какие обиды. Просто у каждого свои вкусы и фломастеры на вкус и цвет разные )

>>ua6em Меня на плате интересует Мега 128, там есть где разгуляться в плане ресурсов. Кстати, сейчас гуглил по вопросу нехватки памяти, возможно я нашел выход. Нашел код, который позволяет хранить строковые данные в области памяти программы. А у меня там около 8 кб свободно еще, такчто возможно живем еще.

Если кто то хочет пострадать с прогнозом погоды http://monatkodenis.blogspot.com/2016/09/zambretti-3.html

Алгоритм брал отсюда. Лучше алгоритм можете не искать, т.к. похоже инфа по прогнозированию погоды является чуть ли не достоянием нации и не подлежит широкой огласке. Сведения о прогнозировании очень туманны и слабо поддаются систематизации.

_zerabot_
Offline
Зарегистрирован: 26.05.2017

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

По сравнению с предыдущим вариантом добавлено:

* Автояркость на основании аналогового фоторезистора

* Меню для пользовательского выставления высоты, вызывается одновременным нажатием кнопок + и -, изменение ими же, сохранение - кнопка Set.

* Реализованны все ветвления калькулятора Zambretti в оригинальном виде без изменений.

* Уменьшенны пороги определения динамики изменения погоды. Теперь считается, что давление падает или растет если изменилось на 0.2 мм за 3 часа или 0.3 мм за 4 часа.

* Исправленна ошибка размерности, при приведении давления к уровню моря в прогнозе прибавлял mmHg к hPa.

* Все массивы использующиеся в прогнозировании объявленны константами и закинуты в память программы. Таким образом, несмотря на значительное добавление записей в эти массивы освободил около 180 байт памяти переменных.

* Косметические изменения функции вывода времени (на основном экране точки мигают, на остальных экранах всегда отображаются статично)

* Автопрокрутка длинных строк для прогноза.

* Приделан костыль для датчика 18d20, который 50/50 при первых 1-2 замерах показывает температуру 85.0, после работает стабильно неделями. Уже не первый раз сталкиваюсь.

* Почасовой график влажности.

#include <EEPROM.h>
//lcd
#include <LiquidCrystal_PCF8574.h>
LiquidCrystal_PCF8574 lcd(0x27);

//Clock
#include <Wire.h>
#include "Sodaq_DS3231.h"

char weekDay[][4] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };



//barometr
#include <BME280I2C.h>
BME280I2C bme;
float hPa = 0;
float Altitude = 0;
float MaxPressure = 0, MinPressure = 65000;
float MaxTempO = -200, MinTempO = 200, MaxTempIn = -200, MinTempIn = 200;
DateTime MaxPressureT, MinPressureT;
DateTime MaxTempOT, MinTempOT, MaxTempInT, MinTempInT, TempTime;
float Pres = 0;
float InT, OutT;




//LedDisplay
#include "TM1637.h" // Подключаем библиотеку
#define CLK 13 // К этому пину подключаем CLK
#define DIO 12 // К этому пину подключаем DIO
TM1637 tm1637(CLK, DIO);

//humidity
#include <SimpleDHT.h>
int pinDHT11 = 9;
SimpleDHT11 dht11;
byte Hum = 0;
byte DHT11temperature = 0;
byte MaxHum = 0, MinHum = 101;
DateTime MaxHumT, MinHumT;



//buttons
//set button
#define BTN 6
//+ button
#define BTNUP 5
//- button
#define BTNDOWN 4
//press + and -  to set user altitude

//int LCDled = 3;           // the PWM pin the LED is attached to

//Main Display mode 1- show main screen,2 shov max and min time... etc..
int DisplayMode = 0;

int  _m, _s, _mon, _day, _week;
int _h, _year;





//unsigned long RefreshLCD;
unsigned long TimeReturn;
DateTime now;
DateTime PowerOn;
byte LastRead, ResetVals;
unsigned long old_ts = 0;




float PressureHistory [20] = {
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700
};

float HumHistory [20] = {
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700,
  700, 700, 700, 700, 700
};
float TempHistoryIn [20] = {
  -127, -127, -127, -127, -127,
  -127, -127, -127, -127, -127,
  -127, -127, -127, -127, -127,
  -127, -127, -127, -127, -127
};
float TempHistoryOut [20] = {
  30, 40, 42, 39, 38,
  10, 40, 42, 39, 38,
  -1, 40, 42, 39, 38,
  30, 40, 42, 39, 38
};


//OutTemp
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);


//Chars for graph
byte ArrCharIndex[9] = {
  254, 2, 95, 3, 4, 176, 5, 6, 7
};

//Zambretty array
const byte Zarr[32] PROGMEM  =
{ 0,//a
  1,//b
  3,//d
  7,//h
  14,//o
  17,//r
  20,//u
  21,//v
  23,//x
  0,//a
  1,//b
  4,//e
  10,//k
  13,//n
  15,//p
  18,//s
  22,//w
  23,//x
  25,//z
  0,//a
  1,//b
  2,//c
  5,//f
  6,//g
  8,//i
  9,//j
  11,//l
  12,//m
  16,//q
  19,//t
  24,//y
  25//z
};




const char string_0[] PROGMEM =  "Settled fine";//0
const char string_1[] PROGMEM =  "Fine weather";//0
const char string_2[] PROGMEM =  "Becaming fine";//0
const char string_3[] PROGMEM =  "Fine, becoming less settled";//0
const char string_4[] PROGMEM =  "Fine, possible showers";//0
const char string_5[] PROGMEM =  "Fairly fine, improving";//0
const char string_6[] PROGMEM =  "Fairly fine, possible showers early";//0
const char string_7[] PROGMEM =  "Fairly fine, showery later";//0
const char string_8[] PROGMEM =  "Showery early, improving";//0
const char string_9[] PROGMEM =  "Changeable, mending";//0
const char string_10[] PROGMEM =  "Fairly fine, showers likely";//0

const char string_11[] PROGMEM =  "Rather unsettled clearing later";//0
const char string_12[] PROGMEM =  "Unsettled, probably improving";//0
const char string_13[] PROGMEM =  "Showery, bright intervals";//0
const char string_14[] PROGMEM =  "Showery, becoming less settled";//0
const char string_15[] PROGMEM =  "Changeable, some rain";//0
const char string_16[] PROGMEM =  "Unsettled, short fine intervals";//0
const char string_17[] PROGMEM =  "Unsettled, rain later";//0
const char string_18[] PROGMEM =  "Unsettled, some rain";//0
const char string_19[] PROGMEM =  "Mostly very unsettled";//0
const char string_20[] PROGMEM =  "Occasional rain, worsening";//0

const char string_21[] PROGMEM =  "Rain at times, very unsettled";//0
const char string_22[] PROGMEM =  "Rain at frequent intervals";//0
const char string_23[] PROGMEM =  "Rain, very unsettled";//0
const char string_24[] PROGMEM =  "Stormy, may improve";//0
const char string_25[] PROGMEM =  "Stormy, much rain";//0

const char* const string_table[] PROGMEM = {
  string_0,
  string_1,
  string_2,
  string_3,
  string_4,
  string_5,
  string_6,
  string_7,
  string_8,
  string_9,
  string_10,
  string_11,
  string_12,
  string_13,
  string_14,
  string_15,
  string_16,
  string_17,
  string_18,
  string_19,
  string_20,
  string_21,
  string_22,
  string_23,
  string_24,
  string_25
};

//hum icon
const byte HumCHR[8] = {
  B00100,
  B00100,
  B01010,
  B01010,
  B10001,
  B10001,
  B10001,
  B01110
};
//temp icon
const byte Temp[8] = {
  B00100,
  B01010,
  B01010,
  B01110,
  B01110,
  B11111,
  B11111,
  B01110
};

//graph char 1/8
const byte ch1[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111
};
//graph char 2/8 is _ char

//graph char 3/8
const byte ch3[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B00000,
  B00000
};
//graph chars 4/8
const byte ch4[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B00000,
  B00000,
  B00000
};

//graph char 5/8 is - char

//graph chars 6/8
const byte ch6[8] = {
  B00000,
  B00000,
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

//graph char 7/8
const byte ch7[8] = {
  B00000,
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};

//graph char 8/8
const byte ch8[8] = {
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};
int scroll = 0;
char buffer [33];
byte UpDownStable = 0;
int UserAltitude;
void setup ()
{

  pinMode(3, OUTPUT);
  pinMode(BTN, INPUT_PULLUP);
  pinMode(BTNUP, INPUT_PULLUP);
  pinMode(BTNDOWN, INPUT_PULLUP);






  Wire.begin();
  Wire.beginTransmission(0x27);

  lcd.begin(20, 4); // initialize the lcd
  //load custom chars
  // lcd.setBacklight(255);
  lcd.createChar (0, Temp);
  lcd.createChar (1, HumCHR);
  lcd.createChar (2, ch1);
  lcd.createChar (3, ch3);
  lcd.createChar (4, ch4);
  lcd.createChar (5, ch6);
  lcd.createChar (6, ch7);
  lcd.createChar (7, ch8);

  //must be called after loading chars
  lcd.home();
  lcd.clear();
  while (!bme.begin()) {
    lcd.clear();
    lcd.print("PrSensorError");
  }
  while (!rtc.begin()) {
    lcd.clear();
    lcd.print("ClockError");
  }
  

  // SetBrightness(brightness);
  tm1637.init();
  tm1637.set(7);
  
  //Высота над уровнем моря
  UserAltitude = EEPROMReadInt(0);
  
  //just read data from sensors. ds18d20 sometimes in first 1-2 read return 85.0C
   while(OutT==85)
  readSensors(rtc.now(), true, false);
  
  PowerOn = rtc.now();
  LastRead = rtc.now().hour();
  ResetVals = rtc.now().date();
  //store first values  from sensors to limit values
 
  
  
  readSensors(rtc.now(), true, true);
  //save current values from the sensors to history
  //for normal graph view in first 20 hours of work
  for (int tt = 0; tt < 20; tt++)
  {
    PressureHistory[tt] = Pres;
    TempHistoryIn[tt] = InT;
    TempHistoryOut[tt] = OutT;
    HumHistory[tt]=Hum;

  }
  //show main screen by default
  DisplayMode = 1;
  //try to forecast =)
  Forecast(now.month());
  Serial.begin(9600);
  
}



void loop ()
{
  //return to main screen from any other mode in 10 sec inactivity
  if ( millis() - TimeReturn > 10000) {
    if (DisplayMode != 1) {
      lcd.clear();
      lcd.home();
      DisplayMode = 1;
    }
    TimeReturn = millis();
  }
  //main screen
  if (DisplayMode == 1 ) {
    now = rtc.now(); //get the current date-time
    uint32_t ts = now.getEpoch();
    //check second changed or not
    if (old_ts != ts) {
      scroll++;
      old_ts = ts;
      //Write time  on tm1367
      tm1637.display(0, now.hour() / 10);
      tm1637.display(1, now.hour() % 10);
      tm1637.display(2, now.minute() / 10);
      tm1637.display(3, now.minute() % 10);
      //blink dot
      tm1637.point(ts % 2 == 0 ? POINT_OFF : POINT_ON);
      //write current time and date on 20*4

      WriteTimeDT(now, 0, 0,false);
      WriteDateDT(now, 6, 0);
      //if hour changes store current sensor values to history
      if (LastRead != now.hour())
      {
        LastRead = now.hour();
        readSensors(rtc.now(), true,  true);
        for (byte i = 0; i < 19; i++) {
          PressureHistory[i] = PressureHistory[i + 1];
          TempHistoryIn[i] = TempHistoryIn[i + 1];
          TempHistoryOut[i] = TempHistoryOut[i + 1];
          HumHistory[i]=HumHistory[i+1];

        }
        TempHistoryIn[19] = InT;
        TempHistoryOut[19] = OutT;
        PressureHistory[19] = Pres;
        HumHistory[19]=Hum;
        //if date changes reset limit values
        if ( ResetVals != now.date()) {
          ResetVals = now.date();
          MaxTempO = -200;
          MinTempO = 200;
          MaxTempIn = -200;
          MinTempIn = 200;
          MaxPressure = 0;
          MinPressure = 65000;
          MaxHum = 0;
          MinHum = 101;
          readSensors(rtc.now(), true, true);
        }
      }
      //read sensors values
      //each sensor interrogated 1 time per 60 seconds
      //and 20 seconds delay between different sensors
      if (now.second() % 10 == 0 &&  now.second() > 0)
      {
        SetBrightness(analogRead(1));
        readSensors(now, false, true);
        lcd.setCursor(0, 3);
        lcd.print("               ");
        lcd.setCursor(0, 3);
        //try to forecast
        //this function wrute on 4 line forecast
        //lcd.print(Forecast(now.month()));
        Forecast(now.month());
        //serial write some data
        Serial.print("<h");
        Serial.print(now.hour());
        Serial.print("m");
        Serial.print(now.minute());
        Serial.print("s");
        Serial.print(now.second());
        Serial.print("D");
        Serial.print(now.date());
        Serial.print("M");
        Serial.print(now.month());
        Serial.print("Y");
        Serial.print(now.year());
        Serial.print("d");
        Serial.print(weekDay[now.dayOfWeek() - 1]);
        Serial.print("InT");
        Serial.print(InT);
        Serial.print("Out");
        Serial.print(OutT);
        Serial.print("Hum");
        Serial.print(Hum);
        Serial.print("Pres");
        Serial.print(Pres);
        Serial.print("F-t");
        Serial.print(buffer);
        Serial.println(">");
      }
    }

    //2 line
    lcd.setCursor(0, 1);
    //write in temp
    lcd.print("In");
    //write custom temp char
    lcd.print(char(0));
    lcd.print(InT);
    //write out temp
    lcd.print(" Out");
    //write custom temp char
    lcd.print(char(0));
    lcd.print(OutT);
    //3 line
    lcd.setCursor(0, 2);
    //write custom humidity char
    lcd.print(char(1));
    //write humidity
    lcd.print(Hum);
    lcd.print("% ");
    lcd.print(Pres);
    lcd.print("mmHg ");
    scrollInFromRight(3, buffer);
  }

  //show limit waluea for out temp
  if (DisplayMode == 2)
  {
    lcd.setCursor(0, 0);
    lcd.print("Max out t");
    WriteTimeDT(MaxTempOT, 0, 13,true);
    lcd.setCursor(0, 1);
    lcd.print(MaxTempO);
    lcd.setCursor(0, 2);
    lcd.print("Min out t");
    WriteTimeDT(MinTempOT, 2, 13,true);
    lcd.setCursor(0, 3);
    lcd.print(MinTempO);
  }
  //draw graph for out temp
  if (DisplayMode == 3)
  {
    lcd.setCursor(0, 0);
    lcd.print("Out t hist");
    drawGraphFullScreen(TempHistoryOut);
  }
  //show limit walues for in temp
  if (DisplayMode == 4)
  {
    lcd.setCursor(0, 0);
    lcd.print("Max in t");
    WriteTimeDT(MaxTempInT, 0, 13,true);
    lcd.setCursor(0, 1);
    lcd.print(MaxTempIn);
    lcd.setCursor(0, 2);
    lcd.print("Min in t");
    WriteTimeDT(MinTempInT, 2, 13,true);
    lcd.setCursor(0, 3);
    lcd.print(MinTempIn);
  }
  //draw graph for in temp
  if (DisplayMode == 5)
  {
    lcd.setCursor(0, 0);
    lcd.print("In t hist");
    drawGraphFullScreen(TempHistoryIn);
  }
  //show limit walues for pressure
  if (DisplayMode == 6)
  {
    lcd.setCursor(0, 0);
    lcd.print("Max pressure");
    WriteTimeDT(MaxPressureT, 0, 13,true);
    lcd.setCursor(0, 1);
    lcd.print(MaxPressure);
    lcd.setCursor(0, 2);
    lcd.print("Min pressure");
    WriteTimeDT(MinPressureT, 2, 13,true);
    lcd.setCursor(0, 3);
    lcd.print(MinPressure);
  }
  //draw graph for pressure
  if (DisplayMode == 7)
  {
    lcd.setCursor(0, 0);
    lcd.print("Pressure hist");
    drawGraphFullScreen(PressureHistory);
  }
  //show limit walues for humidity
  if (DisplayMode == 8)
  {
    lcd.setCursor(0, 0);
    lcd.print("Max humidity");
    WriteTimeDT(MaxHumT, 0, 13,true);
    lcd.setCursor(0, 1);
    lcd.print(MaxHum);
    lcd.setCursor(0, 2);
    lcd.print("Min humidity");
    WriteTimeDT(MinHumT, 2, 13,true);
    lcd.setCursor(0, 3);
    lcd.print(MinHum);
  }

if (DisplayMode == 9)
  {
    lcd.setCursor(0, 0);
    lcd.print("Humidity hist");
    drawGraphFullScreen(HumHistory);
  }

  //show Altitude, uptime and (c)
  if (DisplayMode == 10)
  {
    lcd.setCursor(0, 0);
    lcd.print("Altitude ");
    lcd.print(Altitude);
    lcd.print("m ");

    lcd.setCursor(0, 1);
    lcd.print("PowerOn");
    WriteTimeDT(PowerOn, 2, 0,true);
    WriteDateDT(PowerOn, 6, 2);
    lcd.setCursor(0, 3);
    lcd.print("(c)IvanchenkoAV 2017");
  }

  //if button up pressed
  if (!digitalRead(BTNUP) && DisplayMode < 100 && DisplayMode != 20)
  {
    DisplayMode++;
    lcd.clear();

  }
  //if button down pressed
  if (!digitalRead(BTNDOWN) && DisplayMode < 100 && DisplayMode != 20)
  {
    DisplayMode--;
    lcd.clear();

  }

  if (!digitalRead(BTNUP) && !digitalRead(BTNDOWN) && DisplayMode < 100)
  {
    DisplayMode = 20;
    lcd.clear();

  }

  if (DisplayMode == 20)
  {
    lcd.setCursor(0, 0);
    lcd.print("Altitude ");

    lcd.print(UserAltitude);
    lcd.print("m");
    lcd.setCursor(0, 1);
    lcd.print("press Set to save");


    if (!digitalRead(BTNUP))
      UserAltitude++;
    if (!digitalRead(BTNDOWN))
      UserAltitude--;

    if (!digitalRead(BTN))
    {
      EEPROMWriteInt(0, UserAltitude);
      lcd.clear();
      lcd.print("Saved");
      delay(1000);
      DisplayMode = 1;
    }

    if (UserAltitude > 800)
      UserAltitude = 0;
    if (UserAltitude < 0)
      UserAltitude = 800;
  }

  //display menu limits
  if (DisplayMode == 11)
  {
    DisplayMode = 1;
  }
  //display menu limits
  if (DisplayMode == 0)
  {
    DisplayMode = 10;
  }

  //set button pressed
  if (!digitalRead(BTN)) {
    TimeReturn = millis();
    //if set button pressed in main screen mode
    if (DisplayMode < 100)
    {
      DisplayMode = 100;
      //save current time to temp values
      TempTime = rtc.now();
      _h = TempTime.hour();
      _m = TempTime.minute();
      _day = TempTime.date();
      _mon = TempTime.month();
      _year = TempTime.year();
      _week = TempTime.dayOfWeek();
    }
    else
      //if button pressed in set mode
      DisplayMode++;
    //menu limit
    if (DisplayMode == 107) {
      lcd.setCursor(0, 1);
      lcd.print("Cancel");
      delay(3000);
      DisplayMode = 1;
      lcd.clear();
    }
    //delay(300);

  }
  delay(200);
  //disp.set(brightness / 64 + 1);

  //reset time return if any buton pressed
  if (!digitalRead(BTNUP) || !digitalRead(BTNDOWN)) {
    TimeReturn = millis();
  }
  //temp hour set
  if (DisplayMode == 100)
  {
    if (!digitalRead(BTNUP))
      _h++;
    if (!digitalRead(BTNDOWN))
      _h--;

    if (_h > 23)
      _h = 0;
    if (_h < 0)
      _h = 23;
    lcd.clear();
    lcd.home();
    lcd.print("Hour ");
    lcd.print(_h);
  }
  //temp minute set
  if (DisplayMode == 101)
  {

    if (!digitalRead(BTNUP))
      _m++;
    if (!digitalRead(BTNDOWN))
      _m--;

    if (_m >= 60)
      _m = 0;
    if (_m < 0)
      _m = 59;
    lcd.clear();
    lcd.home();
    lcd.print("Minute ");
    lcd.print(_m);
  }
  //temp date set
  if (DisplayMode == 102)
  {

    if (!digitalRead(BTNUP))
      _day++;
    if (!digitalRead(BTNDOWN))
      _day--;

    if (_day > 31)
      _day = 1;
    if (_day < 1)
      _day = 31;
    lcd.clear();
    lcd.home();
    lcd.print("Day ");
    lcd.print(_day);
  }
  //temp month set
  if (DisplayMode == 103)
  {
    if (!digitalRead(BTNUP))
      _mon++;
    if (!digitalRead(BTNDOWN))
      _mon--;

    if (_mon > 12)
      _mon = 1;
    if (_mon < 1)
      _mon = 12;
    lcd.clear();
    lcd.home();
    lcd.print("Month ");
    lcd.print(_mon);
  }
  //temp year set
  if (DisplayMode == 104)
  {

    if (!digitalRead(BTNUP))
      _year++;
    if (!digitalRead(BTNDOWN))
      _year--;

    if (_year > 3000)
      _year = 1;
    if (_year < 1)
      _year = 3000;

    lcd.clear();
    lcd.home();
    lcd.print("Year ");
    lcd.print(_year);
  }
  //temp weekday set
  if (DisplayMode == 105)
  {
    if (!digitalRead(BTNUP))
      _week++;
    if (!digitalRead(BTNDOWN))
      _week--;

    if (_week > 7)
      _week = 1;
    if (_week < 1)
      _week = 7;


    lcd.clear();
    lcd.home();
    lcd.print("WeekDay ");
    lcd.print(weekDay[_week - 1]);
  }
  // set new time?
  if (DisplayMode == 106)
  {
    lcd.clear();
    lcd.home();
    lcd.print("Save Y/N?");

    //if button up pressed save new time
    if (!digitalRead(BTNUP))
    {
      DateTime dt(_year, _mon, _day, _h, _m, 0, _week);
      rtc.setDateTime(dt);
      lcd.setCursor(0, 1);
      lcd.print("Ok");
      delay(3000);
      DisplayMode = 1;
      lcd.clear();
    }
    //if button down pressed - exit to main screen
    if (!digitalRead(BTNDOWN)) {
      lcd.setCursor(0, 1);
      lcd.print("Cancel");
      delay(3000);
      DisplayMode = 1;
      lcd.clear();
    }
  }
}
//write time in x,y of lcd
void WriteTimeDT(DateTime Time, byte y, byte x,boolean dot) {
  lcd.setCursor(x, y);
  if (Time.hour() < 10)
    lcd.print('0');
  lcd.print(Time.hour());
  lcd.print(Time.second() % 2 == 0||dot ? ':' : ' ');
  if (Time.minute() < 10)
    lcd.print('0');
  lcd.print(Time.minute());
}
//write date in x,y of lcd
void WriteDateDT(DateTime Time, int x, int y) {
  lcd.setCursor(x, y);
  if (Time.date() < 10)
    lcd.print('0');
  lcd.print(Time.date());
  lcd.print('/');
  if (Time.month() < 10)
    lcd.print('0');
  lcd.print(Time.month());
  lcd.print('/');
  lcd.print(Time.year());
  lcd.print(' ');
  lcd.print(weekDay[Time.dayOfWeek() - 1]);
}



//draw graph
void drawGraphFullScreen(float x[20]) {
  //
  float maxp = -30000, minp = 30000;
  float divider;
  byte curVal;
  //saerch max and min values in history
  for (byte i = 0; i < 20; i++)
  {
    if ( x[i] > maxp)
      maxp =  x[i];
    if ( x[i] < minp)
      minp =  x[i];
  }
  //graph draw in 3 lines, so we have 24 pixels height graph
  //Do not deny yourself anything =)
  //  divider - value of division of 1 pixel +0.01 to prevert division by 0
  divider = (maxp - minp) / 24 + 0.01;
  //write value of division
  lcd.setCursor(14, 0);
  lcd.print(divider);

  for (byte i = 0; i < 20; i++)
  {

    //draw 4 line, bottom of graph
    curVal = byte((x[i] - minp) / divider);
    lcd.setCursor(i, 3);
    //if current value of graph catch in value 0 to 8*divider
    //we draw chart
    if (curVal <= 8)
    {
      //seach appropriate char in array of custom chars
      if (curVal > 0)
        lcd.print(char(ArrCharIndex[curVal]));
      else
        //if current val = min
        lcd.print(char(2));
    }
    else
      //if chart line upper than current line print blank char
      lcd.print(char(ArrCharIndex[0]));
    //draw 3 line - middle of graph
    lcd.setCursor(i, 2);
    if (curVal <= 16 && curVal > 8)
      //if current value of graph catch in value  8*divider to 16*divider
      //we draw chart
      //seach appropriate char in array of custom chars
      lcd.print(char(ArrCharIndex[curVal - 8]));
    else
      //if chart line upper or lover than current line print blank char
      lcd.print(char(ArrCharIndex[0]));

    lcd.setCursor(i, 1);
    //draw 4 line, bottom of graph
    if (curVal <= 24 && curVal > 16)
      //if current value of graph catch in value  16*divider to 24*divider
      lcd.print(char(ArrCharIndex[curVal - 16]));
    else
      //if chart line lover than current line print blank char
      lcd.print(char(ArrCharIndex[0]));
  }
}

//read data from sensors depending on currend second
//bool Now means read all data immideatly
//bool store mean save limiting values data or not
void readSensors (DateTime Time, boolean Now, boolean store)
{
  if (!Now) {
    switch  ( Time.second()) {

      case 20:
        //out temp dht18d20
        sensors.requestTemperatures();
        OutT = sensors.getTempCByIndex(0);
        //store limiting values and time when they arrived
        if (store) {
          if (OutT > MaxTempO) {
            MaxTempO = OutT;
            MaxTempOT = Time;
          }
          if (OutT < MinTempO) {
            MinTempO = OutT;
            MinTempOT = Time;
          }
        }

        break;
      case 30:

        dht11.read(pinDHT11, &DHT11temperature, &Hum, NULL);
        //store limiting values and time when they arrived
        if (store) {
          if (Hum > MaxHum) {
            MaxHum = Hum;
            MaxHumT = Time;
          }
          if (Hum < MinHum) {
            MinHum = Hum;
            MinHumT = Time;
          }

        }
        break;
      case 40:

        float  hum(NAN);
        uint8_t pressureUnit(0);                                           // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
        bme.read(Pres, InT, hum, true, pressureUnit);
        hPa = Pres / 100+ float(UserAltitude* 12.502 / 100);
        Pres = Pres * 0.00750063755419211;
        Altitude = bme.alt(true);
        //store limiting values and time when they arrived
        if (store) {
          if (Pres > MaxPressure) {
            MaxPressure = Pres;
            MaxPressureT = Time;
          }
          if (Pres < MinPressure) {
            MinPressure = Pres;
            MinPressureT = Time;
          }

          if (InT > MaxTempIn) {
            MaxTempIn = InT;
            MaxTempInT = Time;
          }
          if (InT < MinTempIn) {
            MinTempIn = InT;
            MinTempInT = Time;
          }

        }
        break;


    }
  }
  else {

    if (store) {

    }
    //out temp dht18d20
    sensors.requestTemperatures();
    OutT = sensors.getTempCByIndex(0);
    //read humidity
    dht11.read(pinDHT11, &DHT11temperature, &Hum, NULL);
    //reap pressure and temp
    float  hum(NAN);
    uint8_t pressureUnit(0);                                           // unit: B000 = Pa, B001 = hPa, B010 = Hg, B011 = atm, B100 = bar, B101 = torr, B110 = N/m^2, B111 = psi
    bme.read(Pres, InT, hum, true, pressureUnit);
    hPa = Pres / 100+ float(UserAltitude* 12.502 / 100) ;
    //convert hPa to mmHh
    Pres = Pres * 0.00750063755419211;
    Altitude = bme.alt(true);
    //store limiting values and time when they arrived
    if (store) {
      if (Pres > MaxPressure) {
        MaxPressure = Pres;
        MaxPressureT = Time;
      }
      if (Pres < MinPressure) {
        MinPressure = Pres;
        MinPressureT = Time;
      }
      if (InT > MaxTempIn) {
        MaxTempIn = InT;
        MaxTempInT = Time;
      }
      if (InT < MinTempIn) {
        MinTempIn = InT;
        MinTempInT = Time;
      }
      if (Hum > MaxHum) {
        MaxHum = Hum;
        MaxHumT = Time;
      }
      if (Hum < MinHum) {
        MinHum = Hum;
        MinHumT = Time;
      }
      if (OutT > MaxTempO) {
        MaxTempO = OutT;
        MaxTempOT = Time;
      }
      if (OutT < MinTempO) {
        MinTempO = OutT;
        MinTempOT = Time;
      }

    }


  }

}


// Select weather index Zambretti
byte Forecast(byte Mon)
{
  float z = 0;
  char a;
  //Pressure is up
  if ((PressureHistory[19] >= PressureHistory[18] || PressureHistory[18] >= PressureHistory[17]  ) && (PressureHistory[19] - PressureHistory[17] > 0.3 || PressureHistory[19] - PressureHistory[16] > 0.2))
  {
    z = 179 - 2 * hPa / 12.9;
    if (Mon >= 5 && Mon <= 9)
      z -= 2;
    if (Mon < 5 || Mon > 9)
      z -= 1;
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[pgm_read_byte(&Zarr[int(z)])])));
    UpDownStable = 1;
  }
  else
    // Pressure is down
    if ((PressureHistory[19] - PressureHistory[17] <= -0.3 || PressureHistory[19] - PressureHistory[16] <= -0.2) && ( PressureHistory[19] <= PressureHistory[18] || PressureHistory[18] <= PressureHistory[17]))
    {
      z = 130 - hPa / 8.1;
      strcpy_P(buffer, (char*)pgm_read_word(&(string_table[pgm_read_byte(&Zarr[int(z)])])));

      //return "-_" + ForecastText[Zarr[int(z)]];
      if (Mon >= 5 && Mon <= 9)
        z += 2;
      if (Mon < 5 || Mon > 9)
        z += 1;
      UpDownStable = 2;
    } else {
      //stable pressure
      z = 147 - 5 * hPa / 37.6;
      strcpy_P(buffer, (char*)pgm_read_word(&(string_table[pgm_read_byte(&Zarr[int(z)])])));
      UpDownStable = 3;
    }
}

//write scroll text
void scrollInFromRight (byte line, char str1[]) {
  String s = buffer;
  byte  len = strlen(str1);
  lcd.setCursor(0, line);
  //15 instead 20 to see, that line ends
  if (len - scroll < 15)
    scroll = 0;
  lcd.print(s.substring(scroll, scroll + 20 > len ? len : scroll + 20));
  if (len - scroll < 20)
    lcd.print(" ");

}
void SetBrightness(int brightness)
{

  analogWrite(3, constrain( map(brightness / 4, 0, 255, 70, 255), 70, 255));
}

void EEPROMWriteInt(int p_address, int p_value)
{
  byte lowByte = ((p_value >> 0) & 0xFF);
  byte highByte = ((p_value >> 8) & 0xFF);

  EEPROM.write(p_address, lowByte);
  EEPROM.write(p_address + 1, highByte);
}

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
{
  byte lowByte = EEPROM.read(p_address);
  byte highByte = EEPROM.read(p_address + 1);

  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

 

 

Qanatoz
Offline
Зарегистрирован: 24.05.2017

Кстати, сейчас на eBay активно продаются аналоги (судя по маркировке) BMP280  и фейковые BME280 с прямоугольным а не квадратным чипом. В конце июня получил свой BMP280 датчик, так не смог заставить его работать ни по SPI ни по I2C. Продавец вернул деньги и только сегодня я заметил, что чип впаян вверх ногами. Сдул и перепаял - работает отлично. Обратите внимание, что отверстие чипа должно быть направлено к резисторам а не к конденсатору. На фото неправильно впаянный чип.

besteugen
Offline
Зарегистрирован: 03.12.2015

у меня получилось вот это...

#include <Wire.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#define BMP_CS 10

LiquidCrystal_I2C lcd(0x3f,20,4);
static byte addon_letters[16];
void init_rus(const char* letters_use )
{
  static byte letters[][8]   = {
        { B11110, B10000, B10000, B11110, B10001, B10001, B11110, B00000 },//Б
        { B11111, B10000, B10000, B10000, B10000, B10000, B10000, B00000 },//Г
        { B00110, B01010, B01010, B01010, B01010, B11111, B10001, B00000 },//Д
        { B10001, B10101, B10101, B01110, B10101, B10101, B10001, B00000 },//Ж
        { B01110, B10001, B00001, B00110, B00001, B10001, B01110, B00000 },//З
        { B10001, B10001, B10001, B10011, B10101, B11001, B10001, B00000 },//И
        { B10101, B10001, B10001, B10011, B10101, B11001, B10001, B00000 },//Й
        { B00110, B01001, B01001, B01001, B01001, B01001, B11001, B00000 },//Л
        { B11111, B10001, B10001, B10001, B10001, B10001, B10001, B00000 },//П
        { B10001, B10001, B10001, B01111, B00001, B10001, B01110, B00000 },//У
        { B01110, B10101, B10101, B10101, B01110, B00100, B00100, B00000 },//Ф
        { B10010, B10010, B10010, B10010, B10010, B10010, B11111, B00001 },//Ц
        { B10001, B10001, B10001, B01111, B00001, B00001, B00001, B00000 },//Ч
        { B10101, B10101, B10101, B10101, B10101, B10101, B11111, B00000 },//Ш
        { B10101, B10101, B10101, B10101, B10101, B10101, B11111, B00001 },//Щ
        { B10000, B10000, B10000, B11110, B10001, B10001, B11110, B00000 },//Ь
        { B11000, B01000, B01000, B01110, B01001, B01001, B01110, B00000 },//Ъ
        { B10001, B10001, B10001, B11001, B10101, B10101, B11001, B00000 },//Ы
        { B01110, B10001, B00001, B00111, B00001, B10001, B01110, B00000 },//Э
        { B10010, B10101, B10101, B11101, B10101, B10101, B10010, B00000 },//Ю
        { B01111, B10001, B10001, B01111, B00101, B01001, B10001, B00000 },//Я
        { B00110, B01001, B01001, B00110, B00000, B00000, B00000, B00000 },//г
  };
  static char chars[] = {'Б','Г','Д','Ж','З','И','Й','Л','П','У','Ф','Ц','Ч','Ш','Щ','Ь','Ъ','Ы','Э','Ю','Я','г'};
  static byte empty[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  int index = 0, cl = sizeof(chars)/sizeof(char),i,j,symb;
  memset(addon_letters,0,sizeof(addon_letters));
  for( j = 0; j < strlen(letters_use) && j < 16; j++ )
          lcd.createChar(j, empty);

  for( j = 0; j < strlen(letters_use) && j < 16; j++ )
  {
          symb = -1;
          for( i=0; i < cl; i++ ) if( chars[i] == letters_use[j] ) { symb = i; addon_letters[index] = letters_use[j]; break; }
          if( symb != -1 ) { lcd.createChar(index, letters[symb]); index++; }
  }
}
void print_rus(char *str) {
  static char rus_letters[] = {'А','В','Е','Ё','К','М','Н','О','Р','С','Т','Х'};
  static char trans_letters[] = {'A','B','E','E','K','M','H','O','P','C','T','X'};
  int lcount = sizeof(rus_letters)/sizeof(char), i, j;
  for( i=0; i<strlen(str); i++ )
  { 
        if( byte(str[i]) == 208 ) continue; // 208 ignore
        int found = 0;
        for(j=0; j < 16; j++) if( addon_letters[j] != 0 && byte(str[i]) == byte(addon_letters[j]) ) { lcd.write(j); found = 1; break; }
        if(!found) for(j=0; j < lcount; j++) if( byte(str[i]) == byte(rus_letters[j]) ) { lcd.write(trans_letters[j]); found = 1; break; }
        if(!found) lcd.write(byte(str[i]));
  }  
}
void print_rus(int x, int y, char *str) {
  lcd.setCursor(x, y);
  print_rus(str);
}
Adafruit_BMP280 bmp(BMP_CS);
void setup()
{
bmp.begin(9600);
lcd.init();
lcd.begin(20, 4);
lcd.backlight();
init_rus("ПУДЛИГЯг");
}
void loop()
{
tmElements_t tm;
RTC.read(tm);
lcd.setCursor(2, 1);
print_rus("ВРЕМЯ - ");
print2digits(tm.Hour);
lcd.print(":");
print2digits(tm.Minute);
lcd.print(":");
print2digits(tm.Second);
lcd.print(" ");
lcd.setCursor(0, 0);
print_rus("СЕГОДНЯ-");
print2digits(tm.Day);
lcd.print(".");
print2digits(tm.Month);
lcd.print(".");
lcd.print(tmYearToCalendar(tm.Year));
print_rus(" Г");
lcd.setCursor(0, 2);
print_rus("ТЕМПЕРАТУРА-");
lcd.print(bmp.readTemperature());
print_rus("г С");
lcd.setCursor(1, 3);
print_rus("ДАВЛЕНИЕ-");
lcd.print(bmp.readPressure()/133.322);
print_rus(" ММ");
delay(1000);
}
void print2digits(int number) {
if (number >= 0 && number < 10) {
lcd.print('0');
}
lcd.print(number);
}

 

besteugen
Offline
Зарегистрирован: 03.12.2015

kost2003
Offline
Зарегистрирован: 26.05.2017

Всем доброго дня! Товарищи подскажите приобрел BME280 на али подключил по i2c первые показания выдает нормальные но секунд через 5 сваливаеться в крайние значения мин темпиратура -144 макс влажность 100 процентов и давление тож самое в чем может быть проблема?

besteugen
Offline
Зарегистрирован: 03.12.2015

попрубуй посадить cs на 3,3v

sadman41
Offline
Зарегистрирован: 19.10.2016

На али есть BMP280 с level converter + ldo для работы с 5V МК, а есть чисто 3.3v. Вы там не втыкаете в 5V ардуину "облегченный" модуль?

kost2003
Offline
Зарегистрирован: 26.05.2017

В описании модуля в магазине написано "Поставка Напряжение: 1.8-5 В DC" 

Подключено к питанию 3,3V Но пробовал и 5V давать ничего не меняется. Только я к модулю ESP12N подключаю без ардуины но думаю это не важно суть не в этом.

sadman41
Offline
Зарегистрирован: 19.10.2016

Ну, а такой вариант допустим: модуль с LDO (на что описание намекает), вы его в 3.3V суете, на датчике получаете 2.1, в лучшем случае. Любая просадка напряжения и сенсор клинит. На модуль посмотрите - есть там кроме самого сенсора трехногие и более детальки или нет.

kost2003
Offline
Зарегистрирован: 26.05.2017

Вроде есть. Если не сложно посмотрите детальку.... сылка

sadman41
Offline
Зарегистрирован: 19.10.2016

kost2003 пишет:

Вроде есть. Если не сложно посмотрите детальку.... сылка

У BME, конечно, минимальное напряжение питание 1.2V заявлено, но черт его знает, что там за LDO. Я бы такой подключил к обычной 5V ардуине (и подключал вполне успешно) и посмотрел на поведение. Если будет работать устойчиво - значит, скорее всего, какие-то провалы по питанию при работе с ESP.

kost2003
Offline
Зарегистрирован: 26.05.2017

Спасибо! Попробую так сделать.

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Пытаюсь скомпилировать скетч - выдает море ошибок. 
Посему вопрос: какие у Вас библиотеки стоят?

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Не компилируется скетч. Выдает кучу ошибок. Библиотеки качал с Гита. В чем может быть проблема?
 

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:1:0:

D:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM\src/EEPROM.h:43:30: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]

     operator const uint8_t() const       { return **this; }

                              ^

D:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\EEPROM\src/EEPROM.h:92:26: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]

     operator const int() const          { return index; }

                          ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino: In function 'void setup()':

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:330:26: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

   lcd.createChar (0, Temp);

                          ^

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:3:0:

D:\Program Files (x86)\Arduino\libraries\LiquidCrystal_PCF8574-master\src/LiquidCrystal_PCF8574.h:89:8: note: initializing argument 2 of 'void LiquidCrystal_PCF8574::createChar(uint8_t, uint8_t*)'

   void createChar(uint8_t, uint8_t[]);

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:331:28: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

   lcd.createChar (1, HumCHR);

                            ^

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:3:0:

D:\Program Files (x86)\Arduino\libraries\LiquidCrystal_PCF8574-master\src/LiquidCrystal_PCF8574.h:89:8: note: initializing argument 2 of 'void LiquidCrystal_PCF8574::createChar(uint8_t, uint8_t*)'

   void createChar(uint8_t, uint8_t[]);

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:332:25: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

   lcd.createChar (2, ch1);

                         ^

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:3:0:

D:\Program Files (x86)\Arduino\libraries\LiquidCrystal_PCF8574-master\src/LiquidCrystal_PCF8574.h:89:8: note: initializing argument 2 of 'void LiquidCrystal_PCF8574::createChar(uint8_t, uint8_t*)'

   void createChar(uint8_t, uint8_t[]);

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:333:25: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

   lcd.createChar (3, ch3);

                         ^

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:3:0:

D:\Program Files (x86)\Arduino\libraries\LiquidCrystal_PCF8574-master\src/LiquidCrystal_PCF8574.h:89:8: note: initializing argument 2 of 'void LiquidCrystal_PCF8574::createChar(uint8_t, uint8_t*)'

   void createChar(uint8_t, uint8_t[]);

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:334:25: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

   lcd.createChar (4, ch4);

                         ^

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:3:0:

D:\Program Files (x86)\Arduino\libraries\LiquidCrystal_PCF8574-master\src/LiquidCrystal_PCF8574.h:89:8: note: initializing argument 2 of 'void LiquidCrystal_PCF8574::createChar(uint8_t, uint8_t*)'

   void createChar(uint8_t, uint8_t[]);

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:335:25: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

   lcd.createChar (5, ch6);

                         ^

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:3:0:

D:\Program Files (x86)\Arduino\libraries\LiquidCrystal_PCF8574-master\src/LiquidCrystal_PCF8574.h:89:8: note: initializing argument 2 of 'void LiquidCrystal_PCF8574::createChar(uint8_t, uint8_t*)'

   void createChar(uint8_t, uint8_t[]);

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:336:25: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

   lcd.createChar (6, ch7);

                         ^

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:3:0:

D:\Program Files (x86)\Arduino\libraries\LiquidCrystal_PCF8574-master\src/LiquidCrystal_PCF8574.h:89:8: note: initializing argument 2 of 'void LiquidCrystal_PCF8574::createChar(uint8_t, uint8_t*)'

   void createChar(uint8_t, uint8_t[]);

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:337:25: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

   lcd.createChar (7, ch8);

                         ^

In file included from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:3:0:

D:\Program Files (x86)\Arduino\libraries\LiquidCrystal_PCF8574-master\src/LiquidCrystal_PCF8574.h:89:8: note: initializing argument 2 of 'void LiquidCrystal_PCF8574::createChar(uint8_t, uint8_t*)'

   void createChar(uint8_t, uint8_t[]);

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino: In function 'void readSensors(DateTime, boolean, boolean)':

weatherstation:994: error: no matching function for call to 'BME280I2C::read(float&, float&, float&, bool, uint8_t&)'

         bme.read(Pres, InT, hum, true, pressureUnit);

                                                    ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:994:52: note: candidate is:

In file included from D:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280I2C.h:33:0,

                 from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:15:

D:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280.h:166:11: note: void BME280::read(float&, float&, float&, BME280::TempUnit, BME280::PresUnit)

    void   read(

           ^

D:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280.h:166:11: note:   no known conversion for argument 4 from 'bool' to 'BME280::TempUnit'

weatherstation:997: error: 'class BME280I2C' has no member named 'alt'

         Altitude = bme.alt(true);

                        ^

weatherstation:1037: error: no matching function for call to 'BME280I2C::read(float&, float&, float&, bool, uint8_t&)'

     bme.read(Pres, InT, hum, true, pressureUnit);

                                                ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:1037:48: note: candidate is:

In file included from D:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280I2C.h:33:0,

                 from C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:15:

D:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280.h:166:11: note: void BME280::read(float&, float&, float&, BME280::TempUnit, BME280::PresUnit)

    void   read(

           ^

D:\Program Files (x86)\Arduino\libraries\BME280-master\src/BME280.h:166:11: note:   no known conversion for argument 4 from 'bool' to 'BME280::TempUnit'

weatherstation:1041: error: 'class BME280I2C' has no member named 'alt'

     Altitude = bme.alt(true);

                    ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino: In function 'byte Forecast(byte)':

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:1089:8: warning: unused variable 'a' [-Wunused-variable]

   char a;

        ^

C:\Users\Nikolay\Documents\Arduino\weatherstation\weatherstation.ino:1120:1: warning: no return statement in function returning non-void [-Wreturn-type]

 }

 ^

Несколько библиотек найдено для "OneWire.h"
 Используется: C:\Users\Nikolay\Documents\Arduino\libraries\OneWire
Не используется: D:\Program Files (x86)\Arduino\libraries\OneWire-master
Не используется: D:\Program Files (x86)\Arduino\libraries\OneWire
exit status 1
no matching function for call to 'BME280I2C::read(float&, float&, float&, bool, uint8_t&)'

 

_zerabot_
Offline
Зарегистрирован: 26.05.2017

если речь о моем скетче то  у меня используется http://www.mathertel.de/Arduino/LiquidCrystal_PCF8574.aspx

Она отилчно ищется в подключении библиотек по фразе LiquidCrystal_PCF8574.

Обращаю внимание, что у меня экран подключен через i2c адаптер.

 

 

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Да, именно о Вашем скетче. Он мне очень понравился, но компилятор что то не компилирует. Очень желаю вашу схему повторить. Больше, конечно, компилятор ругается на bme280i2c библиотеку. Поиски ведут в тупик.

_zerabot_
Offline
Зарегистрирован: 26.05.2017

Библиотека отсюда. https://github.com/finitespace/BME280 Инсталится ручками.

Это кстати единственная библиотека, которая на моем китайском клоне выдает результаты похожие на правду.

PS у меня версия arduino 1.8.2

 

Genri5
Offline
Зарегистрирован: 31.05.2016

_zerabot_ пишет:

Библиотека отсюда. https://github.com/finitespace/BME280 Инсталится ручками.

Это кстати единственная библиотека, которая на моем китайском клоне выдает результаты похожие на правду.

PS у меня версия arduino 1.8.2

 

А чем хуже : "cactus_io_BME280_I2C.h" ?

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Кто может скомпилировать скетч _zerabot_ из поста #120 под nano v3 и выложит здесь?

_zerabot_
Offline
Зарегистрирован: 26.05.2017

Xer0x_king пишет:

Кто может скомпилировать скетч _zerabot_ из поста #120 под nano v3 и выложит здесь?


После работы сделаю.

Xer0x_king
Offline
Зарегистрирован: 22.06.2017
Подскажите еще по подключению периферии к ардуино:
Дисплей lcd2004 с bme280 садится на а4/а5 (sdl/sda),
dht11 садится на a9,
кнопки на d4...6,
Ds1820 садится на а8,
Куда садить фоторезистор, на какой пин?
И маааааленькая просьба, в скетче, когда будете компилировать, замените dht11 на dht22.
_zerabot_
Offline
Зарегистрирован: 26.05.2017

Xer0x_king пишет:

Подскажите еще по подключению периферии к ардуино:
Дисплей lcd2004 с bme280 садится на а4/а5 (sdl/sda),
кнопки на d4...6,
Да,
dht11 садится на d9,
Ds18d20 садится на d8,
фоторезистор на пин a1
на i2c переходнике для дисплея снимается перемычка отвечающая за подсветку и на ногу, на которой нет потенциала относительно земли цепляется вывод d3 для управления яркостью. Но честно, плавное изменение делать не захотел (памяти не хватает уже) а без нее выглядит очень убого, потому в последней версии я автояркость отключил. Да и жене ночник хороший получился. =)
 
У меня есть предложение, я как доберусь домой, настрою эти библиотеки, и выложу настроенную среду сразу.

Обращаю внимание у меня еще подключен сегментный экран на d12 и d13

0029 //LedDisplay
0030 #include "TM1637.h" // Подключаем библиотеку
0031 #define CLK 13 // К этому пину подключаем CLK
0032 #define DIO 12 // К этому пину подключаем DIO
0033 TM1637 tm1637(CLK, DIO);

 

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Конечно, буду ждать.Премного буду благодарен.
Только пока у меня TM1637 нет. Буду покупать.

_zerabot_
Offline
Зарегистрирован: 26.05.2017

Вот ссылка на архив с библиотеками. https://cloud.mail.ru/public/L4vX/UFrvfkHat

Содержимое заархивированной папки libraries\ распаковать в папку libraries\ в среде разработки и перезапустить.

Вроде библиотеки те же, завтра заберу с работы станцию попробую прошить.

Проблема была в том, что я писал используя версию от февраля 2017, а со последними версиями не компилируется.

Из замеченных багов за полгода:

*В строке 459 нужно добавить еще 1 пробел, стало заметно при минусовой температуре.

*константы определяющие динамику изменения погоды в функции byte Forecast(byte Mon)

(0,2 и 0,3) однозначно нужно увеличивать минимум в 2 раза, везде где встречаются. А вообще их нужно подбирать экспереминтально для вашего региона. У нас срань, а не погода в межсезонье.

Давление в течении дня на 5-8 мм прыгает за 2-3 часа, утром солнце и +15, в обед 0 и снежная крупа и легкий ветер нежно обрывает плитку со зданий и ласково прикладывает птичек к стенам домов и вечером снова ясно и +15. А зимой 4 месяца сракопада. Ну а  летом датчик на солнце показывает до +60, а воздух прогревается до 35 и ниодного дождя за 4 месяца. Если где и приукрасил, то слегка, а кое где даже приуменьшил =)

 

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Спасибо большое за помощь. Константы изменил, пробел добавил. На 2 компах компилировалось с ошибкой, на третьем пошло... Залил в ардуинку.Теперь проверить не могу. I2C дисплей не могу завести. Ничего не показывает.Будем тужиться завести на дисплей без I2C.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Xer0x_king пишет:

Спасибо большое за помощь. Константы изменил, пробел добавил. На 2 компах компилировалось с ошибкой, на третьем пошло... Залил в ардуинку.Теперь проверить не могу. I2C дисплей не могу завести. Ничего не показывает.Будем тужиться завести на дисплей без I2C.

а сканер I2C дисплей находит?

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Виктор Николаевич, не пробовал.Это идея. Заливал тестовый скетч из библиотеки liquid cristal pf8574. Загружал - в мониторе порта была какая то кракозября и не более того.О том, что нету дисплея - порт не сообщал

 

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Сканер показал 0x3f. Как всегда, или лодка дырявая или акула глухая

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Xer0x_king пишет:

Сканер показал 0x3f. Как всегда, или лодка дырявая или акула глухая

В оригинале: LiquidCrystal_PCF8574 lcd(0x27)

Придется просить компилировать с вашим 0x3f. Потому как PCF8574A не переключится на 0x3F, насколько я помню. А, судя по адресу, именно он у вас, а не обычный простой PCF8574 без индекса.

Xer0x_king
Offline
Зарегистрирован: 22.06.2017

Всем спрасибо за помощь. Проект пошел, только почему то атмосферное давление и другие параметры не обновляются автоматически. В скетче заменил адрес. Все показывает. Подсветка не работает, хоть и закинул на в3.но это мелочи.Проект начал хоть что то показывать.

 

_zerabot_
Offline
Зарегистрирован: 26.05.2017

Xer0x_king пишет:

Всем спрасибо за помощь. Проект пошел, только почему то атмосферное давление и другие параметры не обновляются автоматически. В скетче заменил адрес. Все показывает. Подсветка не работает, хоть и закинул на в3.но это мелочи.Проект начал хоть что то показывать.

Все показания с датчиков обновляются раз в минуту. Каждые 20 секунд обновляется значение 1 из датчиков. Чаще просто не вижу смысла, температура, давление и влажность крайне инертные велечины.

За установку яркости отвечает процедура

void SetBrightness(int brightness)

1136 {
1137  
1138   analogWrite(3, constrain( map(brightness / 4, 0, 255, 70, 255), 70, 255));
1139 }

Она устанавливает значение PWM от 70 до 255 на пине 3 в зависимости от напряжения на входе А1. Этот вход замеряет напряжение на делителе 10кОм+фоторезистор. Маркировка последнего неизвестна, но эксперементально он меняет сопротивление примерно от 4кОм до 12кОм.