Включить светодиодный индикатор, если значение датчика влажности >= MaxDryness в течение более 20 минут.
Привет, я делаю самополивающийся цветочный горшок с датчиком влажности и перистальтическим насосом, код следующий:
Я хочу добавить светодиодный индикатор, который загорается, если значение датчика равно или превышает значение MaxDryness в течение более двадцати минут.
Как мне изменить код, чтобы сделать это?
@jyc43, 👍-2
Обсуждение2 ответа
Ниже приведен пример того, как это можно закодировать.
Помните, что почва сухая, установив DrySoil = true
.
Зарегистрируйте время начала засушливого периода в DrySoilBegin.
Проверяйте при каждом «сухом» показателе, было ли значение DrySoil верным в течение более 20 минут.
Устанавливайте DrySoil = false
при каждом показании «не сухости».
ul
после константы 1200000
делает ее длинным значением без знака. Это потому, что millis()
возвращает результат unsigned long
. Я не уверен на 100%, что это необходимо (возможно, компилятор позаботится об этом автоматически).
Поскольку у меня нет системы полива растений, я не смог проверить ее работу.
#define WATERPIN 10
#define READSOILPIN A0
#define LEDPIN 13
// чем больше число, тем суше
#define MAXDRYNESS 700
#define WATERDELAY 10000
#define WATERPOSTDELAY 5000
bool DrySoil = false; // Состояние почвы
unsigned long DrySoilBegin; // Время, когда DrySoil стал правдой
void setup() {
Serial.begin(9600);
pinMode(READSOILPIN, INPUT);
pinMode(WATERPIN, OUTPUT);
pinMode(LEDPIN, OUTPUT);
}
void loop() {
int SensorValue = analogRead(READSOILPIN); //взять образец
Serial.print(SensorValue);
Serial.print(" ־ ");
if(SensorValue >= MAXDRYNESS) {
// Почва слишком сухая
// Проверяем, была ли почва уже в сухом состоянии
if(DrySoil){
// Если уже в сухом состоянии, проверьте продолжительность
if((millis()-DrySoilBegin) > 1200000ul){
// Если продолжительность превышает 20 минут, включаем светодиод
// или оставить светодиод включенным
digitalWrite(LEDPIN, HIGH);
}
}
else{
// Первый «сухой» результат после «мокрых» результатов
DrySoil = true; // Устанавливаем DrySoil в истинное состояние
DrySoilBegin = millis(); // Устанавливаем начало периода DrySoil
}
// начинаем поливать в течение 10 секунд, затем
// ждем 5 секунд перед повторным мониторингом
Serial.println("Soil dry start watering");
digitalWrite(WATERPIN, HIGH);
delay(WATERDELAY); // ждем, пока пройдет WATERDELAY миллисекунд
digitalWrite(WATERPIN, LOW);
delay(WATERPOSTDELAY); // ждем, пока пройдут миллисекунды WATERPOSTDELAY
}
else{
// Почва не слишком сухая
DrySoil = false; // Устанавливаем или сохраняем DrySoil в состоянии false
digitalWrite(LEDPIN, LOW); // Выключаем светодиод или оставляем его выключенным
delay(50); // Подождите 50 мс перед следующей выборкой
}
}
1. Вам следует переместить первое слово «else» вниз так, чтобы оно соответствовало «if(DrySoil)». 2. Вам следует заменить while((millis()-TimerStart)<...
на delay()
. Использование millis()
в этом стиле _blocking_ не имеет никакого преимущества перед delay()
и делает код сложнее читать., @Edgar Bonet
1. Спасибо, вы правы. Отредактировали соответственно. 2. Я предполагаю, что из-за этого осталось больше внутренних процессов. Но я понимаю, что это неправда. Тоже исправил соответственно., @PimV
Вот небольшой пример, как это сделать. Адаптируйтесь таким образом (если хотите) самостоятельно.
// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
unsigned long lowSensorTick = 0;
bool dry = false;
void loop()
{
if (analogRead(/* PIN */) > /* THRESHOLD VALUE */)
{
// СУХОЙ
if (dry == false)
{
lowSensorTick = millis();
dry = true;
}
else
{
if (millis() - lowSensorTick > 720000) // 720000мс = 12мин * 60000мс (1с = 1000мс)
{
digitalWrite(LED_PIN, HIGH); // СВЕТОДИОД ЗАГОРИТСЯ/ВКЛ.
}
}
}
else
{
// ВЛАЖНЫЙ
dry = false;
digitalWrite(LED_PIN, LOW); // СВЕТОДИОД ГОРИТ/ВЫКЛЮЧАЕТСЯ
}
}
Обратите внимание, что ноль — это совершенно допустимая временная метка. Вам следует использовать отдельную логическую переменную, как в ответе PimV, вместо того, чтобы lowSensorTick выполнял двойную функцию: сохранял временную метку и состояние «действительная временная метка»., @Edgar Bonet
Почему? millis() никогда не вернет ноль в качестве значения. Я использую этот способ в своих проектах, и он работает без проблем., @Pararera
millis()
возвращает ноль в начале выполнения программы, а затем снова каждые 49,7 дней., @Edgar Bonet
Вначале у вас есть функция pinMode. Ноль остается в течение 1/1000 с. Для переполнения это еще одна проблема., @Pararera
1. pinMode()
выполняется менее чем за миллисекунду. 2. lowSensorTick = 0
— это уловка, позволяющая запихнуть информацию о действительном/недействительном статусе в переменную, которая предназначена для хранения чего-то еще, и это может привести к неправильному поведению программы, хотя и очень редко. Кроме лени, нет причин не использовать отдельное логическое значение. Если вы хотите взять на себя (очень небольшой) риск в отношении своих собственных программ, это нормально. Но отвечая на вопросы, вам следует избегать обучения плохим практикам, особенно если учесть, что уже существует вполне обоснованный ответ., @Edgar Bonet
@EdgarBonet исправлено., @Pararera
- Количество мигающих светодиодов с датчиком LDR
- KY-022 ИК-приемник, светодиод всегда горит, нет выхода
- Проблемы с кнопками
- Как установить таймеры, используя миллисекунды на 3 датчиках PIR?
- Почему светодиоды влияют на аналоговый вход?
- Проблемы с управлением светодиодом с датчиком влажности почвы
- Игнорирование первого высокого выходного сигнала датчика
- Одновременное использование двух датчиков с задержкой
зачем ты выложил фото кода? ... вы действительно думаете, что кто-то будет тратить время на его ввод, чтобы его можно было добавить и опубликовать в качестве ответа?, @jsotola
Откажитесь от вызовов
delay()
и изучите неблокирующий стиль кодирования на примереBlinkWithoutDelay
. Он использует функцию millis(), которая возвращает миллисекунды с момента запуска. Вы можете использовать их как часы, чтобы отмерить 20 минут. Стиль кодирования много раз объяснялся в Интернете., @chrisl@jyc43, пожалуйста, замените изображение исходного кода на [блок кода](https://arduino.stackexchange.com/editing-help#code), это позволит нам вставить строки кода, которые вы ищете., @Roberto Lo Giacco
Пожалуйста, закодируйте текст как текст, @Greenonline