Включить светодиодный индикатор, если значение датчика влажности >= MaxDryness в течение более 20 минут.

Привет, я делаю самополивающийся цветочный горшок с датчиком влажности и перистальтическим насосом, код следующий:

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

Как мне изменить код, чтобы сделать это?

, 👍-2

Обсуждение

зачем ты выложил фото кода? ... вы действительно думаете, что кто-то будет тратить время на его ввод, чтобы его можно было добавить и опубликовать в качестве ответа?, @jsotola

Откажитесь от вызовов delay() и изучите неблокирующий стиль кодирования на примере BlinkWithoutDelay. Он использует функцию millis(), которая возвращает миллисекунды с момента запуска. Вы можете использовать их как часы, чтобы отмерить 20 минут. Стиль кодирования много раз объяснялся в Интернете., @chrisl

@jyc43, пожалуйста, замените изображение исходного кода на [блок кода](https://arduino.stackexchange.com/editing-help#code), это позволит нам вставить строки кода, которые вы ищете., @Roberto Lo Giacco

Пожалуйста, закодируйте текст как текст, @Greenonline


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


0

Вот небольшой пример, как это сделать. Адаптируйтесь таким образом (если хотите) самостоятельно.

// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
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