Автозапуск двигателя на Arduino для Chevrolet Niva

На днях задумался реализовать систему автозапуска для автомобиля Chevrolet Niva оборудованного стандартной сигнализацией с дополнительным каналом. Он и будет задействован для подачи сигнала автозапуска с сигнализации в первой реализации. В дальнейшем планирую прикрутить GSM-шлюз для управления автозапуском и получения статуса и отчетов с помощью смс.

Быстро нагуглил несколько реализаций: раз, два, три, четыре и ещё несколько. Но, воспользовавшись теми идеями, решил писать свой вариант программы, так как в тех не всё устраивало, особенно отсутствие датчика нейтрали на автомобиле. Ручник тоже может глючить, да и не удержит ниву. Поэтому решил ещё задействовать датчик движения автомобиля, подключившись к штатному датчику скорости.

Получившаяся программа постоянно опрашивает все датчики (скорости, ручник, датчик нейтрали, заведённого двигателя) и в случае изменения какого-то сигнала (например, автомобиль начинает двигаться) процесс автозапуска прекращается и всё отключается.

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

На данный момент программа написана, основные реле подключены, осталось сообразить как прицепить датчики, установить это всё на автомобиле и отладить. На столе всё работает отлично)

Текущий код программы (скетча):

const int handBrakeIn =        2; // ручной тормоз  D2
const int neutralGearIn =      3; // датчик нейтрали D3
const int speedIn =            4; // сигнал с датчика скорости D4
const int chargeIn =           5; // наличие напряжения заряда D5
const int startSIn =           6; // сигнал автозапуска от сигнализации D6
const int startGIn =           7; // сигнал автозапуска от GSM-модуля D7

const int starterOut =         8; // стартер D8
const int coolingOut =         9; // охлаждение (кондиционер) D9
const int powerOut =          10; // зажигание D10
const int immoOut =           11; // обход иммобилизатора D11
const int heatingOut =        12; // отопление (печка, сиденья, стекла) D12
const int startModeOut =      13; // сигнализация режима автозапуска D13

const int handBrakeSignal   =  0; // сигнал, если ручник поднят
const int neutralGearSignal =  0; // сигнал, если включена нейтралка

const int maxTryesCount =      5; // максимальное число попыток запуска
const int powerDelayTime =     5; // задержка включения питания (перерыв между попытками), секунд
const int starterDelayTime =   5; // задержка включения стартера, секунд
const int maxStartTime =      10; // время работы стартера, секунд
const int secondaryDelayTime = 5; // задержка включения обогрева или охлаждения, секунд
const int maxRunTime =        1; // время работы двигателя после запуска, минут

int           engineState    = 0; // состояние двигателя 0 - выключен / 1 - работает
int           needStart      = 0; // наличие запроса на запуск двигателя
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long timeStart      = 0; // время с момента запуска двигателя
unsigned long tryStartTime   = 0; // время с момента запуска двигателя
int           tryesCount     = 0; // число попыток запуска
int           startMode      = 0; // режим автозапуска, 0 - нет / 1 - да
int           tryCurrent     = 0; // текущая попытка запуска
int           powerOn        = 0; // подали питание
int           starterOn      = 0; // включили стартер
int           secondaryOn    = 0; // включили вторичные устройства (охлаждение или обогрев салона)
int           speedSignal    = 0; // значение сигнала датчика скорости

void setup() {
  pinMode(handBrakeIn, INPUT);
  pinMode(neutralGearIn, INPUT);
  pinMode(speedIn, INPUT);
  pinMode(chargeIn, INPUT);
  pinMode(startSIn, INPUT);
  pinMode(startGIn, INPUT);

  pinMode(powerOut, OUTPUT);
  pinMode(immoOut, OUTPUT);
  pinMode(starterOut, OUTPUT);
  pinMode(heatingOut, OUTPUT);
  pinMode(coolingOut, OUTPUT);
  pinMode(startModeOut, OUTPUT);

  digitalWrite(powerOut, HIGH);
  digitalWrite(immoOut, HIGH);
  digitalWrite(starterOut, HIGH);
  digitalWrite(heatingOut, HIGH);
  digitalWrite(coolingOut, HIGH);
  digitalWrite(startModeOut, LOW);

  Serial.begin(9600);

}

void loop() {

  // получаем состояние двигателя
  if (digitalRead(chargeIn) == 1) {
    engineState = 1;
  } else {
    engineState = 0;
  }

  unsigned long timeFromStart = 0;
  unsigned long currentMillis = millis(); // текущее время

  // проверяем, включали ли что-то и если да - вырубаем в любом случае через заданное время, т.к. двигатель мог и заглохнуть
  if (powerOn == 1 && secondaryOn == 1) {
    timeFromStart = (currentMillis - timeStart) / 60000; // время работы в минутах
  }

//Serial.println(timeFromStart);

  // получаем сигнал с датчика скорости, ручника и датчика нейтрали, а так же проверяем время прошедшее с момента запуска двигателя
  // если что-то не так - глушим всё и ничего не делаем
  if (digitalRead(speedIn) != speedSignal || // датчик скорости изменил значение
      digitalRead(handBrakeIn) != handBrakeSignal || // ручник
      digitalRead(neutralGearIn) != neutralGearSignal || // нейтралка
      tryesCount >= maxTryesCount || // число попыток запуска
      timeFromStart >= maxRunTime // время работы
  ) {
    digitalWrite(powerOut, HIGH);
    digitalWrite(immoOut, HIGH);
    digitalWrite(starterOut, HIGH);
    digitalWrite(heatingOut, HIGH);
    digitalWrite(coolingOut, HIGH);
    digitalWrite(startModeOut, LOW);
    timeStart = 0;
    startMode = 0;
    tryCurrent = 0;
    powerOn = 0;
    starterOn = 0;
    secondaryOn = 0;
  } else if (startMode == 1) {

    // автозапуск двигателя

    if (tryCurrent != tryesCount) { // новая попытка

      tryStartTime = millis(); // время начала очередной попытки
      tryesCount = tryCurrent;
      digitalWrite(powerOut, HIGH);
      digitalWrite(immoOut, HIGH);
      digitalWrite(starterOut, HIGH);
      digitalWrite(heatingOut, HIGH);
      digitalWrite(coolingOut, HIGH);
      powerOn = 0;
      starterOn = 0;
      secondaryOn = 0;

    } else {

      // сколько секунд прошло с начала процедуры
      unsigned int timePassed =  (currentMillis - tryStartTime) / 1000;

      // задержка автозапуска, включаем питание
      if (timePassed > powerDelayTime && powerOn == 0) {
        digitalWrite(powerOut, LOW);
        digitalWrite(immoOut, LOW);
        powerOn = 1;

      }

      // задержка, включаем стартер если двигатель не запущен
      if (engineState == 0 && starterOn == 0 && timePassed > powerDelayTime + starterDelayTime) { //
        digitalWrite(starterOut, LOW);
        starterOn = 1;
      }

      // завелась, выключаем стартер
      if (engineState == 1 && starterOn == 1) {
        digitalWrite(starterOut, HIGH);
        starterOn = 0;
      }

      // не завелась, а время вышло - выключаем стартер, запускаем новую попытку
      if (engineState == 0 && starterOn == 1 && timePassed > powerDelayTime + starterDelayTime + maxStartTime) { //
        digitalWrite(starterOut, HIGH);
        starterOn = 0;
        tryCurrent += 1;
      }

      // машина заведена, прошло время задержки для включения дополнительного оборудования, включаем его и прекращаем процедуру автозапуска.
      if (engineState == 1 && timePassed > powerDelayTime + starterDelayTime + maxStartTime + secondaryDelayTime) {
        digitalWrite(heatingOut, LOW);
        startMode = 0;
        tryCurrent = 0;
        tryesCount = 0;
        secondaryOn = 1;
        timeStart = currentMillis; // запоминаем время
        speedSignal = digitalRead(speedIn); // запоминаем сигнал датчика скорости
      }

    }

    // конец автозапук двигателя

  } else {

    // получаем наличие сигналов на запуск двигателя
    if (digitalRead(startSIn) == 1 || digitalRead(startGIn) == 1 ) {
      needStart = 1;
    } else {
      needStart = 0;
    }

    if (engineState == 0) {  // если двигатель не заведён
      if (needStart == 1) {  // и есть сигнал на его запуск
        startMode = 1;       // переходим в режим запуска двигателя
        tryesCount = 0;
        tryCurrent = 1;
        digitalWrite(startModeOut, HIGH);
      }
    }
  }
}

Предложения, советы, рекомендации принимаются.

Читайте также:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *