Всем привет. Начал с нуля делать минимальную автоматизацию теплицы. Организовал простое меню состоящее из трёх пунктов. Программист из меня ну никакой. Лепил из того что было, библиотеки от AlexGyver. Все почти работает. Но в память не сохраняет значения. Может кто объяснит, что делать
хотел посмотреть код - а во вложении файл "программа txt". На всякий случай открывать не стал...
Я не знаю, что у вас там - но выкладывать надо скетч для ардуино с расширением .ino , а не какие-то тексты...
В скетче реализовано только чтение настроек из памяти и сброс настроек если зажать кнопку энкодера при подачи питания.
Чтобы сохранить настройки при их изменении, надо использовать функцию EEPROM.writeLong в нужном месте.
void update_EEPROM() {
EEPROM.updateLong(8 * current_pump, period_time[current_pump]);
EEPROM.updateLong(8 * current_pump + 4, pumping_time[current_pump]);
}
Вот эта функция для записи в память. Почему умножаем на 8 переменную выбора насоса
Она же итак меняет своё значение когда мы делаем настройки
@RamasTex, почему на 8? Всё легко Для одного канала у нас 2 настройки типа long, то есть 4 байта, 2 умножаем на 4 получаем 8 байтов на один канал.
Этот множитель на 8 это сдвиг по байтам, первый канал имеет индекс 0, умножая на 8 получаем адрес 0 и 4, именно то что нам надо
СпасибоНу теперь я понял. Ок, тогда настройки освещения можно записать на 6 канал допустим, или 5. просто вместо переменной current_pump поставим число. Но всё равно не сохраняет. Да еще и подсветку дисплея отключает
Всем привет. Я поправил программу. Подсветку не отключает. Решил заносить в память настройки температуры через адреса. Но почему-то Тmin и Tmax становятся одинаковыми. А настройки освещения не заносит в память. Вот последняя версия. Может кто объяснит в чем может быть дело
Привет, открыл скетч и сразу заметил одну вещь из-за которой всё может не работать.
Смотри, вот твой код setup:
C++:
for (byte i = 0; i < PUPM_AMOUNT; i++) { // пробегаем по всем помпам
period_time[i] = EEPROM.readLong(8 * i); // читаем данные из памяти. На чётных - период (ч)
pumping_time[i] = EEPROM.readLong(8 * i + 4); // на нечётных - полив (с)
}
for (byte i = 4; i <= 4; i++) { // читаем данные записанные по адресу 5 канала
period_timel[i] = EEPROM.readLong(8 * i); // читаем данные из памяти. На чётных - период освещения(ч)
pumping_timel[i] = EEPROM.readLong(8 * i + 4); // на нечётных - работа освещения (с)
}
val1 = EEPROM.read(40);
val2 = EEPROM.read(45);
}
В нём я выделил пару строк, в чём же дело спросишь ты? Смотри, в програмировании есть некоторые типы данных, отличаются они тем, сколько место в байтах выдаётся каждому типу.
Есть переменные типа byte, которые как следует из названия, занимают ровно один байт, есть тип int, он занимает два байта.
Для наглядности вот таблица примитивных типов и сколько места они занимают в памяти:
Тип
Описание
Размер
bool
Имеет два значения, true или false, да или нет, 1 или 0 и т.д
1 байт
byte, char, uint8_t
Может принимать значение от 0 до 255 (включая), годится для сохранения буквы (у каждой буквы по таблице ASCII значение от 0 до 255), яркости если яркость управляется в диапазоне от 0 до 255 и т.д
1 байт
short, int, int16_t
Используется когда надо сохранить значения чуть который не входят в диапазон 0 до 255.
Валидный диапазон значений: -32768 до 32767
2 байта
unsigned short, unsigned int, uint16_t
То же самое как и short и int, разница в том что переменные этого типа не могут иметь отрицательные значения.
То есть, диапазон значений: 0 до 65535
2 байта
long, int32_t
В переменную такого типа можно записывать большие числа, но и занимают они не мало так памяти.
Валидный диапазон значений: -2147483648 до 2147483647
4 байта
unsigned long, uint32_t
Тот же long только без отрицательных значений.
0 до 4294967295
4 байта
Найдя у тебя в коде переменную val1, я сразу пошёл смотреть какой у неё тип, оказалось что это int.
Открыл документацию к библиотеки EEPROMEx которая используется в скетче, функция read возвращает тип данных byte, то есть большинство значений ты просто не можешь получить из-за того что читаешь из памяти только часть данных.
Чтобы прочитать тип данных int, надо использовать функцию readInt (учти, что функция возвращает значения типа uint16_t, то есть значения типа unsigned int, отрицательные значения прочитать этой функцией ты не сможешь).
Вот список функций библиотеки:
Тоже самое и при изменении данных в памяти, увидел что ты обновляешь данные функцией update, которая также принимает byte, полагаю что туда просто сохраняется первый байт из числа, надо также update заменить на updateInt, и ещё раз заметь что функция принимает тип uint16_t и отрицательные значения ты записать не сможешь.
Вернёмся в функцию setup и посмотрим уже на другие строки
C++:
for (byte i = 4; i <= 4; i++) { // читаем данные записанные по адресу 5 канала
period_timel[i] = EEPROM.readLong(8 * i); // читаем данные из памяти. На чётных - период освещения(ч)
pumping_timel[i] = EEPROM.readLong(8 * i + 4); // на нечётных - работа освещения (с)
}
Мы тут видим цикл, который выполняется один раз с значением i = 4, цикл тут не нужен и просто так будет тратить время микроконтроллера на выполнение ненужного кода.
Куда проще заменить цикл на две строки:
C++:
period_timel[4] = EEPROM.readLong(8 * 4); // читаем данные из памяти. На чётных - период освещения(ч)
pumping_timel[4] = EEPROM.readLong(8 * 4 + 4); // на нечётных - работа освещения (с)
Спасибо вам за помощь Замена функций действительно необходима. Теперь настройки температуры сохраняются в памяти. А мне отрицательные значения и не пригодятся) теплица же. Убрал цикл for. Но данные по освещению все равно не сохраняет. Менял номер с 4 на 5. тоже самое. После перезагрузки одни нули. Может память закончилась)Менял положение вызова функции void changeSetLIGHT()
Попробуйте перед изменением данных в память выывести их в порт, посмотрите через компьютер, какое значение должно сохраниться, а также после загрузки этих данных из памяти желательно вывести в порт.
Всем привет Продолжаю работать над программой небольшой автоматизации теплицы. Получилось полностью организовать меню. Данные заносятся в память при обновлении. Только остались некоторые моменты. Во вложении "Настройка температуры" и"Настройка свет" некорректно отображаются числа. Данное условие не помогло. Может кто знает решение
C++:
if (val3<10)
{
lcd.setCursor(4, 1);
lcd.print(0);
lcd.print(val3);
}
if (val4<10)
{
lcd.setCursor(12, 1);
lcd.print(0);
lcd.print(val4);
}
Всем привет. После долгих мучений и бессонных ночей. Мне наконец-то удалось поправить программу. Всё более менее работает как надо. И думал уже финиш. Данные сохраняются в память, клапаны открываются по таймеру. Проект завершён, круть. Но есть проблемка, когда находишься во вложении меню, то все работает. Как только выходишь в основное меню, перестают срабатывать клапаны по времени. И все останавливается. Как решить данную проблему? Я знаю, что нужно поставить функцию которая отвечает за включение клапанов по таймерам в цикл void loop() но как правильно это сделать не знаю. Вот скетч
Привет
Конструкция меню не совсем удобная и правильная,опрос клапанов происходит только на одном экране, в идеале надо было бы избавиться от цикла while, а так думаю что можно просто добавить вызов функций periodTickWAT и flowTickWAT в каждую функцию экрана (drawM....)
Спасибо вам огроменное за помощь. Все начало работать как надо. Даже если электричество пропадет, и снова появится все сразу заработает. Не только в каждой функции, но и нужно drawMWAT(); дописать в void setup. А как иначе делать меню? Если не через wihile. Неужели есть решения проще
На данном сайте используются файлы cookie, чтобы персонализировать контент и сохранить Ваш вход в систему, если Вы зарегистрируетесь.
Продолжая использовать этот сайт, Вы соглашаетесь на использование наших файлов cookie.