Управление выдвижными фарами

У меня машина 90-х годов с выдвижными фарами, но у меня нет оригинального модуля фары. Поэтому я пытаюсь сделать его сам.

Идея проста

1. У меня есть главный выключатель, который держит фары в поднятом положении, когда он включен.

2. Я считываю аналоговое значение сигнала ближнего света автомобиля, и когда он достигает определённого порога, фары должны включиться. Когда сигнал опускается ниже порога, фары должны подождать 5 секунд. Если за это время сигнал не поступает, фары должны включиться.

3. Я считываю аналоговое значение сигнала дальнего света автомобиля (мигающего сигнала), и когда он достигает определённого порога, фары должны включиться. Когда сигнал опускается ниже порога, начинается обратный отсчёт на 5 секунд. Если за это время мигание не повторяется, фары должны выключиться. Если за это время мигание повторяется, обратный отсчёт сбрасывается.

Фары включаются, но когда сигнал равен 0, они немедленно закрываются.

https://wokwi.com/projects/422074392400440321

#define relayRight 8
#define relayLeft 9

#define lightSignal A2
#define flashSignal A3
#define masterSignal 13


int relayStatus = 0;
int Lights = 0;
int Flash = 0;
int Master = 0;
unsigned int lightThreshold = 10;
unsigned int flashThreshold = 2;
unsigned long lightOffTime = 0;
unsigned long flashOffTime = 0;
bool signalTimerActive = false;

void setup() {

  pinMode(relayLeft, OUTPUT);
  pinMode(relayRight, OUTPUT);
  pinMode(masterSignal, INPUT_PULLUP);

  digitalWrite(relayLeft, HIGH);
  digitalWrite(relayRight, HIGH);

  Serial.begin(9600);
}

void loop() {
  Lights = analogRead(lightSignal);
  Flash = analogRead(flashSignal);
  Master = digitalRead(masterSignal);

  unsigned long currentTime = millis();

  if (Master == LOW) {
    relayStatus = 1;
    HeadsUp();
  } else {
    // Логика светового сигнала
    if (Lights >= lightThreshold) {
      relayStatus = 1;
      HeadsUp();
      signalTimerActive = false;
    } else if (Lights < lightThreshold && relayStatus == 1) {
      if (!signalTimerActive) {
        lightOffTime = currentTime;
        signalTimerActive = true;
      }
      if (currentTime - lightOffTime >= 4000) {
        relayStatus = 0;
        HeadsDown();
        signalTimerActive = false;
      }
    }

     if (relayStatus == 0 && Flash >= flashThreshold) {
      relayStatus = 1;
      HeadsUp();
      flashOffTime = currentTime;
      signalTimerActive = true;
    }

    if (signalTimerActive && (currentTime - flashOffTime >= 4000)) {
      relayStatus = 0;
      HeadsDown();
      signalTimerActive = false;
    }
  }

  Serial.print("Master: ");
  Serial.println(Master);
  Serial.print("Light: ");
  Serial.println(Lights);
  Serial.print("Flash: ");
  Serial.println(Flash);

  delay(200);
}

void HeadsUp() {
  digitalWrite(relayLeft, LOW);
  digitalWrite(relayRight, LOW);
  Serial.println("HeadsUp");
}

void HeadsDown() {
  digitalWrite(relayLeft, HIGH);
  digitalWrite(relayRight, HIGH);
  Serial.println("HeadsDown");
}

, 👍-1

Обсуждение

почему вы используете аналоговое считывание вместо цифрового?, @jsotola

Вы забыли подтягивающие резисторы на контактах A2 и A3?, @Edgar Bonet

Оригинальные автомобильные линии выдают аналоговые сигналы, и тогда я не знал, как преобразовать их в цифровые сигналы, поэтому настроил систему таким образом. Я не добавлял никаких подтягивающих или стягивающих резисторов. На данный момент чтение сигналов не является основной заботой, но необходимо держать фары включенными еще 5 секунд перед закрытием без использования «задержки»., @afmek

На этой схеме вам **определенно** необходимо подтягивание на каждом из A2 и A3., @Edgar Bonet


1 ответ


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

0

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

Когда я сталкиваюсь с подобной проблемой программирования, я склонен думать Условия конечного автомата: какие существуют состояния Система может быть включена? При каких условиях она должна быть включена в каждом штате? Изменение состояния? Для вашего конкретного проекта я бы перефразировал требования такие:

  • Когда фары включены: если главный выключатель выключен и он прошло не менее пяти секунд с тех пор, как в последний раз горел какой-то свет, затем Фары должны быть выключены.
  • Когда фары опущены: если главный выключатель включен или какой-либо Если горит свет, то фары должны подняться.

Это облегчает перевод требований в код. Я бы Обычно для переменной состояния используют enum, но когда есть только два состояния (фары либо включены, либо нет), логическое значение хорошо.

void loop() {
    static bool headlightsAreUp = false;    // текущее состояние
    static unsigned long lastTimeLightsOn;  // для отсчета времени

    // Считываем входные данные и текущее время.
    bool masterSwitchIsOn = digitalRead(masterSignal) == LOW;
    bool lightsAreOn = analogRead(lightSignal) >= lightThreshold
            || analogRead(flashSignal) >= flashThreshold;
    unsigned long now = millis();
    if (lightsAreOn) {
        lastTimeLightsOn = now;
    }

    // При необходимости переместите фары вверх или вниз.
    if (headlightsAreUp) {
        if (!masterSwitchIsOn && now - lastTimeLightsOn >= 5000) {
            HeadsDown();
            headlightsAreUp = false;
        }
    } else {  // фары опущены
        if (masterSwitchIsOn || lightsAreOn) {
            HeadsUp();
            headlightsAreUp = true;
        }
    }
}
,

Сэр, вы потрясающий, и не верьте никому, кто утверждает обратное. Я просто добавляю вашу часть в симуляцию, и всё работает как надо. Вы меня спасли и многому научили. Огромное спасибо!, @afmek