Управление выдвижными фарами
У меня машина 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");
}

@afmek, 👍-1
Обсуждение1 ответ
Лучший ответ:
Во-первых, вы можете упростить свою логику, не отслеживая, какие Включились огни (обычные или импульсные). Ваша программа следует беспокоиться только о том, загорелся ли какой-нибудь свет, а не о том, природа этого света.
Когда я сталкиваюсь с подобной проблемой программирования, я склонен думать Условия конечного автомата: какие существуют состояния Система может быть включена? При каких условиях она должна быть включена в каждом штате? Изменение состояния? Для вашего конкретного проекта я бы перефразировал требования такие:
- Когда фары включены: если главный выключатель выключен и он прошло не менее пяти секунд с тех пор, как в последний раз горел какой-то свет, затем Фары должны быть выключены.
- Когда фары опущены: если главный выключатель включен или какой-либо Если горит свет, то фары должны подняться.
Это облегчает перевод требований в код. Я бы
Обычно для переменной состояния используют 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
- управление 2 датчиками и 3 насосами с помощью millis
- Использование mills() вместо задержки() на реле, не обеспечивающих надежное переключение
- Использование millis вместо задержки перезагрузки реле
- Реле просто включаются и выключаются на delay(), а не на millis().
- Как справиться с rollover millis()?
- Как заставить 5-вольтовое реле работать с NodeMCU
- Использование millis() и micros() внутри процедуры прерывания
- Когда следует использовать транзистор, МОП-транзистор, а когда следует использовать реле?
почему вы используете аналоговое считывание вместо цифрового?, @jsotola
Вы забыли подтягивающие резисторы на контактах A2 и A3?, @Edgar Bonet
Оригинальные автомобильные линии выдают аналоговые сигналы, и тогда я не знал, как преобразовать их в цифровые сигналы, поэтому настроил систему таким образом. Я не добавлял никаких подтягивающих или стягивающих резисторов. На данный момент чтение сигналов не является основной заботой, но необходимо держать фары включенными еще 5 секунд перед закрытием без использования «задержки»., @afmek
На этой схеме вам **определенно** необходимо подтягивание на каждом из A2 и A3., @Edgar Bonet