Требуется ввод: дождитесь ввода напряжения, чтобы начать сценарий, и когда напряжение будет оставаться на уровне 0 В в течение X времени, выполните сброс и дождитесь ввода напряжения.

Сейчас я работаю над автомобильной установкой.

Я использую таймер 555 для эмуляции импульса переменного напряжения сигнала поворота (от 12 В до 0 В и повторения) в целях отладки, который выводится на turnPin/A1.

Вот цель: когда напряжение больше 1 В, Arduino должна подавать постоянное питание на выходной контакт (контакт 13) до тех пор, пока входное напряжение не вернется к постоянному значению 0 (или к концу сигнала поворота) в течение x-времени или, как я буду называть, тайм-аута.

Кажется, мне удалось подать постоянную мощность при подаче входного сигнала и отключить постоянный выходной сигнал, когда напряжение падает до 0 В. Однако у меня возникли трудности с правильной работой функции тайм-аута, поскольку светодиод по-прежнему остается ВЫСОКИМ.

ПРАВКА: Я переработал код, чтобы использовать millis(); вместо чистого использования входных данных датчиков. Я также добавил комментарии, чтобы помочь вам разобраться в том, что, по моему мнению, произошло/что я хочу, чтобы произошло.

// Константы не изменятся
const int ledPin = LED_BUILTIN; //используем встроенный светодиод + pin13
const int turnPin = A1;         // входной контакт (сигнал поворота, чередующийся 5В/0В/5В/0В и т. д.)

// Переменные изменятся
int ledState = LOW;             // текущее состояние выходного контакта
int prevLed = ledState;
int lastVoltage = 1;            // предыдущее показание источника напряжения
int state = 1;                      // текущее "состояние" (см. ниже)
                                // Состояние = 1++: светодиод выключен -- Состояние = 0: светодиод включен

// Следующие переменные являются длинными, поскольку время измеряется в миллисекундах,
// быстро станет большим числом, чем может быть сохранено в int.

long previousMillis = 0;    //последний раз, когда напряжение достигало 0
long waitTime = 100;    // время ожидания

void setup()
{
  pinMode(ledState, OUTPUT);        //установить выходной контакт
  pinMode(turnPin, INPUT);          //установить входной контакт ПРИМЕЧАНИЕ: СИГНАЛ ИЗМЕНЯЕТСЯ
5V/0V/5V/0V & so forth to emulate a turn signal for this application
  Serial.begin(9600);               //начать серийный номер
}

void loop()
{
  int sensorValue = analogRead(turnPin);        // Считать напряжение на входном контакте
  float voltage = sensorValue * (5.0/1023.0);   // Преобразовать
  unsigned long currentMillis = millis();    // устанавливаем currentMillis как текущий
 time


  if (voltage > 1)      //если напряжение больше 1 В
  {
    ledState = HIGH;    //включить светодиод
    state = 0;          //установить состояние на 0
  }

  if (voltage < 1)      //если напряжение меньше 1 В
  {   
    currentMillis;      //установить currentMillis как текущее время

    if ((millis() - currentMillis) > waitTime) // если (текущее время минус время, когда напряжение было меньше 1) больше времени ожидания
    {
        ledState = LOW;     //выключить светодиод
        Serial.print("OFF - TIMED OUT - WAITING FOR INPUT: ");  //вывод сообщения для отладки
        Serial.println(state);//текущее состояние
        state++;              //увеличить состояние (прошло время)
    }
        else if ((millis() - currentMillis) < waitTime) // если (текущее время минус время, когда напряжение было меньше 1) меньше времени ожидания
        {
            ledState = HIGH;    //включить светодиод
        }
  }
  digitalWrite(ledPin, ledState);   //отправляем состояние светодиода на выход
}

, 👍1


2 ответа


Лучший ответ:

1

Спасибо всем за вклад. Я нашел решение.

Используя функцию while, я смог создать два "состояния" для кода. Состояние с истекшим временем ожидания и не истекшее время ожидания соответственно. В состоянии с истекшим временем ожидания выход будет равен 0, и наоборот для последнего, и ждать, пока напряжение не достигнет 0 в течение "X" времени.

Я также интегрировал функцию "learn", чтобы при необходимости установить задержку на основе переменного входного напряжения. В противном случае по умолчанию будет установлено значение в переменной timeoutWait.

Код ниже. Пожалуйста, дайте мне знать, если у вас есть какие-либо замечания/предложения.

НАЗНАЧЕНИЕ: Это приложение было создано для автомобильного применения. Клиент заменил OEM-сигналы поворота на многоцветные фонари стороннего рынка
Светодиодные ленты, управляемые неизвестным контроллером. Для того, чтобы функция поворотника светодиодных лент работала,
контроллер должен был быть включен. Было нежелательно запускать светодиоды каждый раз, когда автомобиль ехал. Поэтому,
Контроллер должен был получать постоянное питание при подаче входного сигнала от заводской проводки указателя поворота (которая чередует 16 В/0 В/16 В/0 В...
и так далее.

ОБЗОР: В двух словах: это приложение будет подавать постоянный выходной сигнал на любой указанный выход (в данном случае на контакт 13) при напряжении 5 Вольт.
применяется к любому указанному аналоговому входу (в данном случае к контакту A1). Когда напряжение на входном контакте прекращается через 250 миллисекунд
постоянный выход будет прекращен. Затем приложение будет ждать повторной подачи напряжения на входной контакт.

Это приложение также будет поддерживать альтернативный источник входного сигнала (в данном случае сигнал поворота). Время ожидания перед возвратом
Перевод выходного контакта в состояние ВЫКЛ определяется одним из двух методов.

МЕТОД 1: Установка значения по умолчанию путем изменения переменной timeoutWait.
МЕТОД 2: Использование кнопки обучения для определения времени падения напряжения и соответствующей регулировки времени ожидания (+ 50 миллисекунд для любых изменений во времени)

ИСПОЛЬЗОВАНИЕ КНОПКИ ОБУЧЕНИЯ: В любой момент времени нажмите и удерживайте кнопку примерно 6 секунд (в реальном времени, а не в режиме моделирования). Это позволит
замерьте разницу во времени между Voltage > 1 и Voltage < 1 и установите ее как время timeoutWait. ПРИМЕЧАНИЕ: переменная timeoutWait не обновляется!
Переменная blinkRate обновляется этими данными.

СХЕМА: Для целей эмуляции была построена схема с использованием источника питания 5 В, подключенного к микропроцессору ATTINY (для эмуляции переменного тока).
сигнал поворота с чередованием 5В/0В/5В/0В каждые 250 миллисекунд) подключен к контакту A1 на Arduino UNO R3. Светодиод с резистором 1 кОм подключен к контакту 13.
Кнопка обучения питается и заземляется от платы Arduino с помощью резистора 10 кОм и подключается к цифровому выводу 2 на плате Arduino.*/

// Константы не изменятся
int output = 13;            // Контакт для выходного напряжения
int input = A1;             // Контакт для получения напряжения
int learnButton = 2;        // Контакт для приема сигнала для режима обучения
int waitTime = 500;         // Время ожидания в миллисекундах
int timeoutWait = 250;      // Время ожидания в миллисекундах

// Эти переменные изменятся
int relayState = LOW;       // Отслеживаем, в каком состоянии находится реле
bool timeout = false;       // Отслеживаем, истекло ли время ожидания или нет
bool learnMode = false;     // Отслеживаем, должны ли мы находиться в режиме обучения или нет
int blinkRate = 0;          // Сохраняем интервал моргания в миллисекундах (полученный из режима обучения)
int lastButtonState = 0;    // Отслеживаем последнее состояние кнопки обучения
int buttonState = 0;        // Отслеживаем текущее состояние кнопки обучения

// Следующие переменные являются длинными, поскольку время измеряется в миллисекундах,
// быстро станет большим числом, чем может быть сохранено в int.
long timerStart = 0;        // Отслеживаем, когда таймер был запущен
long timerStop = 0;         // Отслеживаем момент остановки таймера
long passedTime = 0;        // Отслеживаем прошедшее время =(timerStop - timerStart)
long blinkStart = 0;        // Отслеживать, когда мигает HIGH (режим обучения)
long blinkStop = 0;         // Отслеживать, когда мигает LOW (режим обучения)

void setup()
{
  pinMode(relayState, OUTPUT); // Установить выходной контакт
  pinMode(input, INPUT);       // Установить входной пин
  pinMode(learnButton, INPUT); // Установить входной контакт (режим обучения)
}

void loop()
{
  int sensorValue = analogRead(input);          // Считать напряжение на входном контакте
  float voltage = sensorValue * (5.0 / 1023.0); // Преобразовать
  buttonState = digitalRead(learnButton);       // Считать пин learnButton
  Serial.begin(9600);                           // Начать последовательную связь

  if (buttonState == HIGH)  // Если нажата кнопка learnButton
  {
    learnMode = true;   // Вход в режим обучения
  }
  delay(50);        // Отказ

      if (voltage > 1)    // Если напряжение больше 1 Вольта
  {
    timeout = false;  // Устанавливаем состояние тайм-аута в FALSE, поскольку нет причин для тайм-аута
    passedTime = 0;   // Сбросить переменную passedTime
    timerStart = 0;   // Сброс переменной timerStart
    timerStop = 0;    // Сброс переменной timerStop
  }

  if (voltage < 1)  //Если напряжение меньше 1 Вольта
  {
    timerStart = millis();                 // Запустить таймер тайм-аута
    delay(waitTime);                       // Как долго нам ждать, пока не истечет время ожидания?
    timerStop = millis();                  // Остановка таймера тайм-аута
    passedTime = (timerStop - timerStart); // Рассчитываем, сколько времени мы ждали

    if (passedTime >= waitTime) //Если вычисленное время больше или равно нашему времени ожидания
    {
      sensorValue;      // Сначала перепроверьте напряжение

      if (voltage < 1)  // Если напряжение все еще меньше 1 Вольта
      {
        timeout = true; // Устанавливаем состояние тайм-аута в TRUE, так как напряжение было меньше 1 Вольта в течение >= нашего времени ожидания
        timerStart = 0; // Сбросить переменную timerStart
        timerStop = 0;  // Сброс переменной timerStop
        passedTime = 0; // Сбросить переменную passedTime
      }
    }
  }

  while (timeout == true)                    // Если TIMEOUT = TRUE
  {
    relayState = LOW;                        // Установить состояние реле на LOW/OFF
    sensorValue = analogRead(input);         // Считать напряжение на входном контакте
    voltage = sensorValue * (5.0 / 1023.0);  // Преобразовать
    digitalWrite(output, relayState);        // Сообщаем реле выключиться

    if (voltage > 1)    // если напряжение больше 1 Вольта
    {
      timeout = false;  // Устанавливаем состояние тайм-аута в FALSE, поскольку нет причин для тайм-аута
      timerStart = 0;   // Сбросить переменную timerStart
      timerStop = 0;    // Сброс переменной timerStop
      passedTime = 0;   // Сбросить переменную passedTime

    }

    if (voltage < 1)
    {
      timeout = true; // Устанавливаем состояние тайм-аута на TRUE, так как напряжение стало меньше 1 Вольта
      timerStart = 0; // Сбросить переменную timerStart
      timerStop = 0;  // Сброс переменной timerStop
      passedTime = 0; // Сбросить переменную passedTime
    }
  }

  while (timeout == false)  // Если TIMEOUT = FALSE
  {
    sensorValue = analogRead(input);        // Считать напряжение на входном контакте
    voltage = sensorValue * (5.0 / 1023.0); // Преобразовать
    relayState = HIGH;                      // Устанавливаем реле в положение ON/HIGH, поскольку время ожидания не истекло
    digitalWrite(output, relayState);       // Реле, которое нужно включить
    buttonState = digitalRead(learnButton); // Считать пин learnButton

    if (buttonState == HIGH)  // Если нажата кнопка learnButton
    {
      learnMode = true; // Вход в режим обучения
    }
    delay(50);        // Отказ

    if (voltage < 1)  // Если напряжение меньше 1 Вольта
    {
      timerStart = millis();                // Запустить таймер тайм-аута

      if (blinkRate > 100)          // Если blinkRate больше 100
      {
        timeoutWait = blinkRate + 50; // Установите timeoutWait на значение blinkRate + 50 миллисекунд для любых изменений во времени
      }
      else                // Если blinkRate не больше 100
      {
        timeoutWait = timeoutWait; // Оставьте значение по умолчанию без изменений
      }

      delay(timeoutWait);                     // Сколько времени нам следует ждать до тайм-аута в этом состоянии?
      timerStop = millis();                   // Остановка таймера тайм-аута
      passedTime = (timerStop - timerStart);  // Рассчитываем, сколько времени мы ждали

      if (passedTime >= timeoutWait)  //Если вычисленное время больше или равно назначенному нам времени ожидания
      {
        sensorValue;        //Сначала перепроверьте датчик

        if (voltage < 1)    //Если показания датчика меньше 1 Вольта
        {
          relayState = LOW; //Установить состояние реле на OFF/LOW.
          timeout = true;   //Оставить нас в состоянии истечения времени ожидания.
          timerStart = 0;   //Сброс переменной timerStart.
          timerStop = 0;    //Сброс переменной timerStop.
          passedTime = 0;   //Сброс переменной passedTime.
        }
      }
    }
  }
  while (learnMode == true)  // Если LEARNMODE = TRUE
  {
    sensorValue = analogRead(input);        // Считать напряжение на входном контакте
    voltage = sensorValue * (5.0 / 1023.0); // Преобразовать
    Serial.println("LEARN MODE ACTIVE");  // Печать на последовательный монитор

    while (voltage > 1)
    {
      sensorValue = analogRead(input);        // Считать напряжение на входном контакте
      voltage = sensorValue * (5.0 / 1023.0); // Преобразовать
      blinkStart = millis();          // Устанавливаем blinkStart как запущенный millis();
      Serial.print("Start: ");          // Печать на последовательном мониторе
      Serial.println(blinkStart);       // Печать на последовательном мониторе
      delay(50);                // Отказ
    }
    while (voltage < 1)
    {
      sensorValue = analogRead(input);        // Считать напряжение на входном контакте
      voltage = sensorValue * (5.0 / 1023.0); // Преобразовать
      blinkStop = millis();           // Устанавливаем blinkStop как работающий millis();
      Serial.print("Stop: ");         // Печать на последовательном мониторе
      Serial.println(blinkStop);        // Печать на последовательном мониторе
      delay(50);                // Отказ
    }

    blinkRate = (blinkStop - blinkStart);   // Рассчитать blinkRate
    Serial.print("Blink Interval: ");     // Печать на последовательном мониторе
    Serial.println(blinkRate);          // Печать на последовательном мониторе
    delay(50);                  // Отказ
    learnMode = false;              // Выход из режима обучения
  }
  digitalWrite(output, relayState);       // Отправить relayState
}
,

1

Трудно решить, с чего начать. :)


 if (currentMillis + 500)

Хорошо, что это делает? Это добавляет 500 к currentMillis, так что это будет верно почти все время.


if (status = 3)

Это присвоение 3 статусу и последующая проверка, является ли он ненулевым, что и будет (будет равно 3).


int turnPin = A1;
...

  int sensorValue = analogRead(A1);

Почему бы не написать:

  int sensorValue = analogRead(turnPin);

float voltage = sensorValue * (5.0 / 1023.0);

Вы вычисляете напряжение, но никогда им не пользуетесь. Зачем беспокоиться?


Что касается вашего вопроса относительно (currentMillis + 500), я хотел, чтобы этот оператор брал текущее время и прибавлял к нему 500, а затем проверял...

Хорошо, тогда вот как это сделать:

// смотрим, прошло ли 1/2 секунды
if (currentMillis - previousMillis >= 500)
   {
   previousMillis = currentMillis;  // сбросить previousMillis
   ... do something ...
   }

Кстати, previousMillis — это также переменная, которую вы больше нигде не использовали.

,