Проблема в коде для метеостанции
- Войдите на сайт для отправки комментариев
Здравствуйте! Просьба помочь с кодом для метеостанции. Он работает исправно, но в некоторых частях (продублированы внизу) почему-то не хочет работать по задумке. Вместо того, чтобы через определённый промежуток времени (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 выкинь - ужасная идея. И "сброс" твой не нужен. От него только вред.
Спасибо, сейчас попробую
Что нужно исправить?
например, очевидный косяк кода - перерисовка экрана каждую миллисекунду. Обновляйте экран либо по расписанию - например раз в секунду, либо, что правильнее - только тогда, когда информация на экране меняется.
Глубоко не вглядывался. уверен. в коде еще тыщи :) ошибок, но это видно с первого взгляда