Проблема в коде для метеостанции
- Войдите на сайт для отправки комментариев
Здравствуйте! Просьба помочь с кодом для метеостанции. Он работает исправно, но в некоторых частях (продублированы внизу) почему-то не хочет работать по задумке. Вместо того, чтобы через определённый промежуток времени (t_pres) производить замер и сдвигать массив, после чего выводить последние 4 значения давления на дисплей, выводится только значение в левом краю дисплея (ячейка [3]), причём оно всегда равно нулевой ячейке массива. В самом начале работы станции также выводится только ячейка [3], тоже равная нулевой. Миллис поделён на тысячу, чтобы время было в секундах.
Немного не работает также функция Pressure, но там код похож, поэтому думаю, проблема там та же.
Код метеостанции:
//--------------БИБЛИОТЕКИ---------------- #include <Wire.h> // Библиотека для работы по i2c #include <LiquidCrystal_I2C.h>// Библиотека для дисплея #include <Adafruit_BMP280.h> // Библиотека для работы барометра #include "DHT.h" // Библиотека для датчика влажности #include "GyverPower.h" // Библиотека для пониженного энергопотребления // --------------НАСТРОЙКИ---------------- const int16_t typedht = DHT22;// Тип датчика (DHT22, DHT11) const int8_t zhdat = 30; // Время между замерами (в секундах), не более 255 секунд const bool pres_sign = 1; // Показывать ли запись давления (0 - нет, 1 - да) const int8_t zhdat_pres = 4; // Время показа данных с давлением (если в предыдущем пункте 1) const uint16_t t_pres = 1800; // Раз во сколько замерять давление для вывода показаний на дисплей (если в предпредпоследнем пункте 1) const bool prep_type = 1; // Тип подготовки системы (0 - лампочки вкл. по-очереди, 1 - лампочки все вкл., потом все выкл.) const uint16_t zhdat_pogoda = 1800; // Раз во сколько замерять давление для предсказания погоды (в секундах) //-------------ПЕРЕМЕННЫЕ----------------- // Даём названия пинам датчиков: #define mq A0 // Газов, #define svet A1 // света, #define vl 2 // влажности. // Светодиоды: #define r_rain 9 // РГБ осадков, #define g_rain 8 #define b_rain 7 #define led A2 // Меняющий яркость от света светодиод, #define lamp 10 // Лампочка, показывающая превышение нормы, #define r 4 // РГБ газа. #define g 5 #define b 6 // Переменные, хранящие показания датчиков: int16_t pressure = 0; // Переменная давления, int16_t gaz = 0; // Газов(газоанализатор), int16_t temperature = 0;// Температуры, int8_t h = 0; // Влажности, int16_t altitude = 0; // Абсолютной высоты int16_t weather [] = {0, 0}; // Массив для записи давления int16_t pres [] = {111, 222, 333, 444}; // Массив для записи 2 давления // Дополнительные переменные: boolean lamp_indicator = 0; // Индикатор лампочки int8_t gaz_b = 0; // Уровень газа(степень опасности), int16_t dvl_b = 0; // Степень погоды для включения лампочек разного цвета uint64_t pogoda_zapis = 0; // Переменная для записи времени последнего замера давления uint64_t pres_zapis = 0; // Переменная для записи времени последнего замера 2 давления LiquidCrystal_I2C lcd(0x27, 16, 2); // Установка дисплея DHT dht(vl, typedht);// Настройка датчика влажности Adafruit_BMP280 bmp280; // Настройка датчика давления //------------SETUP-------------------- void setup() { lcd.init(); // Настройка дисплея lcd.backlight();// Включаем подсветку дисплея dht.begin(); // Подготовка датчика влажности while (!bmp280.begin(BMP280_ADDRESS - 1)) { // Подготовка датчика давления Serial.println(F("Could not find a valid BMP280 sensor, check wiring!")); delay(2000); } delay(100); pinMode(vl, INPUT); // Настраиваем пины pinMode(mq, INPUT); pinMode(svet, INPUT); pinMode(lamp, OUTPUT); pinMode(r, OUTPUT); pinMode(g, OUTPUT); pinMode(b, OUTPUT); pinMode(r_rain, OUTPUT); pinMode(g_rain, OUTPUT); pinMode(b_rain, OUTPUT); pinMode(led, OUTPUT); lcd.setCursor(0, 0); // Пишем, что идет подготовка системы lcd.print(" Preparing of "); lcd.setCursor(0, 1); lcd.print(" system... "); for (byte q = 0; q < 11; q++) { // Мигаем светодиодами для проверки и нагрева системы (2 режима) if (prep_type == true) { digitalWrite(lamp, 1); analogWrite(led, 255); digitalWrite(r, 1); delay(500); digitalWrite(g, 1); delay(500); digitalWrite(b, 1); delay(500); digitalWrite(r_rain, 1); delay(500); digitalWrite(g_rain, 1); delay(500); digitalWrite(b_rain, 1); delay(1000); digitalWrite(r, 0); digitalWrite(g, 0); digitalWrite(b, 0); digitalWrite(r_rain, 0); digitalWrite(g_rain, 0); digitalWrite(b_rain, 0); digitalWrite(lamp, 0); for (int i = 0; i <= 255; i++) { analogWrite(led, i); delay(10); } } else if (prep_type == false) { digitalWrite(lamp, 1); analogWrite(led, 255); digitalWrite(r, 1); delay(500); digitalWrite(r, 0); digitalWrite(g, 1); delay(500); digitalWrite(g, 0); digitalWrite(b, 1); delay(500); digitalWrite(b, 0); digitalWrite(r_rain, 1); delay(500); digitalWrite(r_rain, 0); digitalWrite(g_rain, 1); delay(500); digitalWrite(g_rain, 0); digitalWrite(b_rain, 1); delay(500); digitalWrite(b_rain, 0); digitalWrite(lamp, 0); for (int i = 0; i <= 255; i++) { analogWrite(led, i); delay(10); } } } analogWrite(led, 0); // Выключаем аналоговый светодиод lcd.setCursor(0, 0); // Пишем, что подготовка завершена lcd.print("Preparation was"); lcd.setCursor(0, 1); lcd.print(" completed "); digitalWrite(lamp, 1); // Мигаем лампочкой, извещая о выходе на обычный режим работы delay(2000); digitalWrite(lamp, 0); lcd.setCursor(0, 0); // Стираем все, что писали, освобождая место для вывода показаний lcd.print(" "); lcd.setCursor(0, 1); lcd.print(" "); power.hardwareDisable(PWR_UART0 | PWR_UART1 | PWR_UART2 | PWR_UART3 | PWR_SPI); } //---------------LOOP--------------- void loop() { float temperature = bmp280.readTemperature(); // Опрос датчиков float pressure = bmp280.readPressure() / 133.3224; gaz = analogRead(mq); h = round(dht.readHumidity()); if (millis() / 1000 <= zhdat_pogoda * 2) { analogWrite(led, 255); } else { analogWrite(led, 0); } Gaz(); // Определяем газ(функция внизу) Pressure(); // Определяем давление(функция внизу) // Другие показания: if (h > 60 || h < 40 && lamp_indicator == 0) { // Если показатели влажности не в норме, то digitalWrite(lamp, HIGH); // Зажечь сигнал lamp_indicator = 1; } else if (h >= 40 && h <= 60 && lamp_indicator == 1) { // А если в норме, digitalWrite(lamp, LOW); // Убрать сигнал lamp_indicator = 0; } if (pres_sign == true) { //Если хотим показывать давление if (pres_zapis > millis()) { pres_zapis = 0; } if (millis() / 1000 - pres_zapis >= t_pres) { pres[3] = pres[2]; pres[2] = pres[1]; pres[1] = pres[0]; pres[0] = round(pressure); pres_zapis = millis() / 1000; } lcd.setCursor(0, 0); // Стираем все, что писали, освобождая место для вывода показаний lcd.print(" "); lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 0); // Выводим показания с давлением lcd.print(" 4 3 2 1"); lcd.setCursor(1, 1); lcd.print(pres[3]); lcd.setCursor(1, 5); lcd.print(pres[2]); lcd.setCursor(1, 9); lcd.print(pres[1]); lcd.setCursor(1, 14); lcd.print(pres[0]); delay(zhdat_pres * 1000); // Ждём время, указанное в настройках } lcd.setCursor(0, 0); // Стираем все, что писали, освобождая место для вывода показаний lcd.print(" "); lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 0); // Вывод показаний на дисплей lcd.print("Dv: "); lcd.print(round(pressure)); lcd.print(" Vl: "); lcd.print(h); lcd.print("%"); lcd.setCursor(0, 1); lcd.print("Gz: "); lcd.print(gaz); lcd.print(" Temp: "); lcd.print(round(temperature - 3)); lcd.print("C"); delay(zhdat * 1000); } //-----------ФУНКЦИИ----------------- void Gaz() { // Функция определения газов if (gaz > 52 && gaz_b != 1) { gaz_b = 1; // Первый, т. е. высший уровень опасности } if (gaz > 45 && gaz < 53 && gaz_b != 2) { gaz_b = 2; // Второй уровень опасности } if (gaz < 46 && gaz > 38 && gaz_b != 3) { gaz_b = 3; // Третий уровень опасности } else if (gaz < 37 && gaz_b != 4) { gaz_b = 4; // Совсем мало угл. газа } // Вывод показаний газа на лампочку: if (gaz_b == 1) { // Если газа много, нужно зажечь красный свет и забыть digitalWrite(r, HIGH); digitalWrite(g, LOW); digitalWrite(b, LOW); } if (gaz_b == 2) { // Если второй уровень, нужно включить зеленый цвет и забыть digitalWrite(g, HIGH); digitalWrite(r, LOW); digitalWrite(b, LOW); } if (gaz_b == 3) { // Если третий, включить сине-зелёный и забыть digitalWrite(b, HIGH); digitalWrite(g, HIGH); digitalWrite(r, LOW); } if (gaz_b == 4) { //Если 4, включить фиолетовый digitalWrite(r, HIGH); digitalWrite(b, HIGH); digitalWrite(g, LOW); } delay(10); } void Pressure() { //Функция определения давления if (pogoda_zapis > millis()) { pogoda_zapis = 0; } if (millis() / 1000 - pogoda_zapis >= zhdat_pogoda) { // Если прошло zhdat_pogoda weather[1] = weather[0]; // То свежее показание теперь старое weather[0] = round(pressure); // А свежим будет новое pogoda_zapis = millis() / 1000; } if (weather[0] - weather[1] == 0 && dvl_b != 1) { // Если давление не менялось и переменная не знает об этом dvl_b = 1; // Сказать ей } if (weather[0] - weather[1] >= 2 && dvl_b != 2) { // Если давление стало ниже и переменная не знает об этом dvl_b = 2; // Сказать ей } if (weather[0] - weather [1] <= (-2) && dvl_b != 3) { // Если давление стало больше и переменная не знает об этом dvl_b = 3; // Сказать ей } if (dvl_b == 1) { // При неизменной погоде вкл. зелёный цвет digitalWrite(g_rain, HIGH); digitalWrite(b_rain, LOW); digitalWrite(r_rain, LOW); } if (dvl_b == 2) { // При ухудшении погоды - вкл. синюю лампочку digitalWrite(b_rain, HIGH); digitalWrite(g_rain, LOW); digitalWrite(r_rain, LOW); } if (dvl_b == 3) { // При улучшении погоды - вкл. красный цвет digitalWrite(r_rain, HIGH); digitalWrite(b_rain, LOW); digitalWrite(g_rain, LOW); } delay(10); }
Код проблемного места:
if (pres_sign == true) { //Если хотим показывать давление (указано в настройках) if (pres_zapis > millis()) { //сброс если переполнение переменной pres_zapis = 0; } if (millis() / 1000 - pres_zapis >= t_pres) { //если прошло t_pres (указано в настройках в секундах), pres[3] = pres[2]; //перезаписать массив pres[2] = pres[1]; pres[1] = pres[0]; pres[0] = round(pressure); pres_zapis = millis() / 1000; } lcd.setCursor(0, 0); // Стираем все, что писали, освобождая место для вывода показаний lcd.print(" "); lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 0); // Выводим показания с давлением lcd.print(" 4 3 2 1"); lcd.setCursor(1, 1); lcd.print(pres[3]); lcd.setCursor(1, 5); lcd.print(pres[2]); lcd.setCursor(1, 9); lcd.print(pres[1]); lcd.setCursor(1, 14); lcd.print(pres[0]); delay(zhdat_pres * 1000); // Ждём время, указанное в настройках }
Код функции Pressure():
void Pressure() { //Функция определения давления if (pogoda_zapis > millis()) { //защита от переполнения pogoda_zapis = 0; } if (millis() / 1000 - pogoda_zapis >= zhdat_pogoda) { // Если прошло zhdat_pogoda weather[1] = weather[0]; // То свежее показание теперь старое weather[0] = round(pressure); // А свежим будет новое pogoda_zapis = millis() / 1000; } if (weather[0] - weather[1] == 0 && dvl_b != 1) { // Если давление не менялось и переменная не знает об этом dvl_b = 1; // Сказать ей } if (weather[0] - weather[1] >= 2 && dvl_b != 2) { // Если давление стало ниже и переменная не знает об этом dvl_b = 2; // Сказать ей } if (weather[0] - weather [1] <= (-2) && dvl_b != 3) { // Если давление стало больше и переменная не знает об этом dvl_b = 3; // Сказать ей } if (dvl_b == 1) { // При неизменной погоде вкл. зелёный цвет digitalWrite(g_rain, HIGH); digitalWrite(b_rain, LOW); digitalWrite(r_rain, LOW); } if (dvl_b == 2) { // При ухудшении погоды - вкл. синюю лампочку digitalWrite(b_rain, HIGH); digitalWrite(g_rain, LOW); digitalWrite(r_rain, LOW); } if (dvl_b == 3) { // При улучшении погоды - вкл. красный цвет digitalWrite(r_rain, HIGH); digitalWrite(b_rain, LOW); digitalWrite(g_rain, LOW); } delay(10); }
Переменные:
t_pres - раз во сколько делать замер
pres_zapis – записанное время с последнего замера
zhdat_pres – сколько времени выводить показатели на дисплей
pres[*] – массив давления
Может стоит к автору кода обратится?
Так я и автор этого кода
loop надо переписать полностью
Что нужно исправить?
Мне просто интересно - почему любители считают, что отладку их кода нужно производить коллективно?
Любишь кататься, люби и саночки возить. Написал - отлаживай. Это неотъемлемая часть процесса.
Я уже пробовал. Если у меня не вышло, я вообще не вижу проблему, почему я не могу спросить? Не для этого ли форумы нужны?
Не для этого ли форумы нужны?
Нет.
А для чего же, интересно?
http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/pesochnitsa-dl...
2й пост
Так там и написано: "Чтобы получить помощь"
Дальше читайте: "...чтобы возникло желание помочь".
Пока что его нет, так как я лично не вижу никаких следов отладки, просто исходник с запросом "где проблема, ткните пальцем где поправить".
Я бы не стал выкладывать код, не проверив его. Думаете, зачем мне задавать вопрос сразу? Во-первых, я в первый раз задаю его тут, не знаю, как быстро ответят. Во-вторых, зачем мне кого-то спрашивать, если там была бы простейшая проблема, которую я могу решить сам за 5 минут? В-третьих, если вы не заметили этих следов, это не значит, что я не пробовал исправить проблему сам, верно?
Деление на 1000 выкинь - ужасная идея. И "сброс" твой не нужен. От него только вред.
Спасибо, сейчас попробую
Что нужно исправить?
например, очевидный косяк кода - перерисовка экрана каждую миллисекунду. Обновляйте экран либо по расписанию - например раз в секунду, либо, что правильнее - только тогда, когда информация на экране меняется.
Глубоко не вглядывался. уверен. в коде еще тыщи :) ошибок, но это видно с первого взгляда