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

У меня есть код, который создает последовательный сигнал с 4 светодиодами. Она ниспадает каскадом вправо. Это работает, когда я удерживаю нажатой кнопку ввода. В чем мне нужна помощь, так это в том, чтобы код выполнялся точно так же при наличии входного сигнала .5s HIGH -> .5s LOW (повтор). Итак, что я имею в виду в терминах псевдокода, так это код, который продолжает считывать ВЫСОКИЙ сигнал до тех пор, пока сигнал не будет низким более 5 секунд.

// Светодиодные выходы
int LED_5 = 6;
int LED_6 = 7;
int LED_7 = 8;
int LED_8 = 9;

//правый указатель поворота
int RTS_IN  = A0;




//переменная состояния для операторов switch case
int stateRightTurn = 0;

//временная переменная
unsigned long t = 0;
//интервал - это интервал времени между операторами case
unsigned long interval = 100;
//время отключения кода
unsigned long off = 600;



void setup() 
{
  Serial.begin(9600);
  
  //вводит
  pinMode(RTS_IN,  INPUT);


  //вывод сигнала правого поворота из левого в правый
  pinMode(LED_5, OUTPUT);
  pinMode(LED_6, OUTPUT);
  pinMode(LED_7, OUTPUT);
  pinMode(LED_8, OUTPUT);

}

void loop() 
{
  StateRight();

}

//последовательные сигналы поворота
void StateRight()
{

   switch (stateRightTurn)
    {
      
    case 0: //холостой ход
          if (digitalRead(RTS_IN) == HIGH)
          {
              Serial.println("0000");
              t = millis();
              SwitchRightLedsOff();
              stateRightTurn = 1;
          }
          break;
          
      case 1: // Один светодиод горит
          if (digitalRead(RTS_IN) == LOW)
          {
              Serial.println("1111-LOWLOWLOW");
              SwitchRightLedsOff();
              stateRightTurn = 0;
          }
          else if (millis() > t + interval)
          {
              Serial.println("1111-HHHHHHHH");
              t = millis();
              digitalWrite(LED_5, HIGH);
              stateRightTurn = 2;
          }
          break;
          
      case 2: // Два светодиода горят
          if (digitalRead(RTS_IN) == LOW)
              {
                  Serial.println("2222-LOWLOWLOW");
                  SwitchRightLedsOff();
                  stateRightTurn = 0;
              }
              else if (millis() > t + interval)
              {
                  Serial.println("2222-HHHHHHHH");
                  t = millis();
                  digitalWrite(LED_6, HIGH);
                  stateRightTurn = 3;
              }
          break;
          
      case 3: // Три светодиода включены
          if (digitalRead(RTS_IN) == LOW)
          {
              Serial.println("3333-LOWLOWLOW");
              SwitchRightLedsOff();
              stateRightTurn = 0;
          }
          else if (millis() > t + interval)
          {
              Serial.println("3333-HHHHHHHH");
              t = millis();
              digitalWrite(LED_7, HIGH);
              stateRightTurn = 4;
          }
          break;
          
      case 4: // Четыре светодиода включены
          if (digitalRead(RTS_IN) == LOW)
          {
              Serial.println("4444-LOWLOWLOW");
              SwitchRightLedsOff();
              stateRightTurn = 0;
          }
          else if (millis() > t + interval)
          {
              Serial.println("4444-HHHHHHHH");
              t = millis();
              digitalWrite(LED_8, HIGH);
              stateRightTurn = 5;
          }
          break;
          
      case 5: // Светодиоды не горят
          if (digitalRead(RTS_IN) == LOW)
          {
              Serial.println("5555-LOWLOWLOW");
              SwitchRightLedsOff();
              stateRightTurn = 0;
          }
          else if (millis() > t + interval)
          {
              Serial.println("55555-HHHHHHHH");
              SwitchRightLedsOff();
              stateRightTurn = 0;
          }
          break;
    } 
}


//способ отключения светодиодов
void SwitchRightLedsOff()
{ 
  digitalWrite(LED_5, LOW);
  digitalWrite(LED_6, LOW);
  digitalWrite(LED_7, LOW);
  digitalWrite(LED_8, LOW);
}

, 👍2

Обсуждение

И каков ваш фактический вопрос? Ты ни о чем таком не спрашивал. И ваше описание мне кажется непонятным. Пожалуйста, выделите одну проблему в вашем коде, опишите только эту проблему, что произошло, когда вы попробовали ее, и что вы ожидали, что произойдет., @chrisl

@chrisl Я обновил основное описание. Дайте мне знать, если в этом будет больше смысла., @Myles

Если вы действительно собираетесь использовать это в реальном автомобиле, пожалуйста, подумайте, что должно произойти с вашими "последовательными сигналами поворота", когда аварийные огни автомобиля мигают одновременно. Что должны делать указатели поворота, если одновременно горит стоп-сигнал?, @VE7JRO

@VE7JRO У меня весь этот код работает одновременно с приведенным выше кодом. Я удалил все это и сегментировал только этот код для простоты., @Myles

Это не ваша проблема, но вы должны переместить t на другую сторону знака > в выражениях, подобных этому: (millis ()> t + интервал), чтобы вы всегда сравнивали интервалы, а не временные метки. // Предлагаемое вами решение - это отключение или блокировка низких входных сигналов в течение 0,5 с после последнего наблюдаемого максимума., @Dave X

millis ()-t - это правильный способ обработки ролловера часов, если millis () и t имеют один и тот же тип, а интервал меньше значения ролловера, @Abel


2 ответа


1

Если я правильно понимаю ваши требования, вы могли бы использовать переменную, чтобы определить, должны ли ваши последовательные индикаторы мигать или нет. Если входной сигнал НИЗКИЙ более 1/2 секунды, переменная должна измениться на НИЗКИЙ, сообщая Arduino прекратить мигание последовательных индикаторов.

Давайте представим, что ваш входной сигнал имеет правильное напряжение и очень точен с учетом времени. На отметке 501 мс, при отсутствии высокого входного сигнала, ваши индикаторы должны перестать мигать.

Может работать простой таймер и переменная состояния. Вот тестовый набросок.

// Sketch использует 1144 байта (3%) дискового пространства программы.
// Глобальные переменные используют 19 байт (0%) динамической памяти.
class MillisTimer{

  private:

    unsigned long m_timeInMilliSeconds;
    unsigned long m_previousMillis;
    byte m_timerActive;

  public:

    MillisTimer(unsigned long timeInMilliSeconds):
      m_timeInMilliSeconds(timeInMilliSeconds),
      m_timerActive(0),
      m_previousMillis(0){
    }

    bool Update(){
      if(m_timerActive && (millis() - m_previousMillis >= m_timeInMilliSeconds)){
        m_previousMillis += m_timeInMilliSeconds;
        return 1;
      }
      else{
        return 0;
      }
    }

    void Start(){
      m_timerActive = 1;
    }

    void Stop(){
      m_timerActive = 0;
    }

    void ReStart(){
      m_timerActive = 1;
      m_previousMillis = millis();
    }

    byte IsActive(){
      return m_timerActive;
    }

};

// Создайте копию объекта для работы.
MillisTimer MyTimer(501);

byte inputPin = 2;
byte signalActive = 0;

void setup(){

  // ПРИМЕЧАНИЕ: Если вход плавающий, требуется понижающий резистор.
  pinMode(inputPin, INPUT);
  MyTimer.Start();

  // Индикатор состояния таймера для целей тестирования.
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

}

void loop(){

  if(digitalRead(inputPin) == HIGH){
    signalActive = 1;
    MyTimer.ReStart();
  }

  if(MyTimer.Update()){
    signalActive = 0;
  }

  // Протестируйте вывод переменной "signalActive" с помощью встроенного светодиода на Uno.
  if(signalActive == 1){
    digitalWrite(LED_BUILTIN, HIGH);
  }
  else{
    digitalWrite(LED_BUILTIN, LOW);
  }
  
}

,

Я пытаюсь получить эту работу. Я дам вам знать., @Myles


1

Предполагая, что digitalRead(RTS_IN) является входным сигналом, я бы прочитал его один раз в верхней части цикла и сохранил временную метку, если она высока, а затем использовал условие millis() - timestamp <= 500 в качестве фиксированной входной переменной.

Я бы также выполнил остальную часть ввода (т. Е. millis()) в верхней части функции, преобразовал сравнения времени из абсолютных значений в интервалы и рассмотрел возможность учета не включенного регистра из регистров коммутатора.

Непроверенный код:

// Светодиодные выходы
int LED_5 = 6;
int LED_6 = 7;
int LED_7 = 8;
int LED_8 = 9;

//правый указатель поворота
int RTS_IN  = A0;

//переменная состояния для операторов switch case
int stateRightTurn = 0;

//временная переменная
unsigned long t = 0;
//интервал - это интервал времени между операторами case
unsigned long interval = 100;
//время отключения кода
unsigned long off = 600;

void setup()
{
  Serial.begin(9600);

  //вводит
  pinMode(RTS_IN,  INPUT);

  //вывод сигнала правого поворота из левого в правый
  pinMode(LED_5, OUTPUT);
  pinMode(LED_6, OUTPUT);
  pinMode(LED_7, OUTPUT);
  pinMode(LED_8, OUTPUT);

}

void loop()
{
  StateRight();

}

//последовательные сигналы поворота
void StateRight()
{
  const int latchInterval = 500; // ms
  static unsigned long lastHigh = -latchInterval; // инициализировать в перенесенное прошлое
  unsigned long now = millis();
  int inState = digitalRead(RTS_IN);
  if (inState == HIGH) { //таймер обновления
    lastHigh = now;
  }
  bool enabled = (now - lastHigh <= latchInterval) ; // включен в течение 500 мс после выключения

  switch (stateRightTurn)
  {
    case 0: //холостой ход
      if (enabled)
      {
        Serial.println("0000");
        t = now;
        SwitchRightLedsOff();
        stateRightTurn = 1;
      }
      break;

    case 1: // Один светодиод горит
      if (!enabled)
      {
        Serial.println("1111-LOWLOWLOW");
        SwitchRightLedsOff();
        stateRightTurn = 0;
      }
      else if (now - t > interval)
      {
        Serial.println("1111-HHHHHHHH");
        t = now;
        digitalWrite(LED_5, HIGH);
        stateRightTurn = 2;
      }
      break;

    case 2: // Два светодиода горят
      if (!enabled)
      {
        Serial.println("2222-LOWLOWLOW");
        SwitchRightLedsOff();
        stateRightTurn = 0;
      }
      else if (now - t >  interval)
      {
        Serial.println("2222-HHHHHHHH");
        t = now;
        digitalWrite(LED_6, HIGH);
        stateRightTurn = 3;
      }
      break;

    case 3: // Три светодиода горят
      if (!enabled)
      {
        Serial.println("3333-LOWLOWLOW");
        SwitchRightLedsOff();
        stateRightTurn = 0;
      }
      else if (now - t > interval)
      {
        Serial.println("3333-HHHHHHHH");
        t = now;
        digitalWrite(LED_7, HIGH);
        stateRightTurn = 4;
      }
      break;

    case 4: // Четыре светодиода горят
      if (!enabled)
      {
        Serial.println("4444-LOWLOWLOW");
        SwitchRightLedsOff();
        stateRightTurn = 0;
      }
      else if (now - t > interval)
      {
        Serial.println("4444-HHHHHHHH");
        t = now;
        digitalWrite(LED_8, HIGH);
        stateRightTurn = 5;
      }
      break;

    case 5: // Светодиоды не горят
      if (!enabled)
      {
        Serial.println("5555-LOWLOWLOW");
        SwitchRightLedsOff();
        stateRightTurn = 0;
      }
      else if (now - t > interval)
      {
        Serial.println("55555-HHHHHHHH");
        SwitchRightLedsOff();
        stateRightTurn = 0;
      }
      break;
  }
}


//способ отключения светодиодов
void SwitchRightLedsOff()
{
  digitalWrite(LED_5, LOW);
  digitalWrite(LED_6, LOW);
  digitalWrite(LED_7, LOW);
  digitalWrite(LED_8, LOW);
}

,

Это сработало отлично! Я тоже это понимаю. Я пытался сделать что-то с тем же мыслительным процессом, @Myles

Хитрость заключается в том, чтобы превратить ваши входные данные в полезную переменную состояния на основе таймера "ввод НИЗКИЙ в течение определенного промежутка времени", которую может использовать ваш код., @Dave X