• В разделах «Гараж» и «Бортовые журналы» для того, чтобы отфильтровать темы по вашему индексу кузова, вы можете просто нажать на него в начале любой соответствующей темы.
    Ребята! Есть огромная просьба - если создаете тему с вопросом в "Гараже", не ленитесь отписаться, как именно решилась проблема, что сделали и т.д.
    Только тогда наш "Гараж" станет реальной базой знаний!!

Запуск приборки на столе + управление стрелками

mendezz

Пользователь
Реєстрація
03.08.2014
Повідомлення
49
Вік
32
Город
Смела
Привет всем.
Последнее время мне "понравилось" запускать все на столе - вот дошло время приборной панели.

Собственно получилось запустить приборку на "столе" (без машины) и чуток покрутить стрелками с помощью Arduino.


Теперь все по порядку:
1. Подключение приборки.
2. Управление стрелкой спидометра
2. Управление стрелкой тахометра
3. Управление стрелкой эконометра
4. Что дальше

Сразу оговорюсь что у меня хай приборка с машины 525i 1994.
Подключение приборки.
Как подключить приборку я нашел в этой статье
Х17 — High 26 пин, бежевый
Х17 — High Х17 6 пин, коричневый
Для этого нам требуется подать +12V в три места:
Х17: 15 (включено всегда если не ошибаюсь, соответствует положению ACC ключа)
Х16: 12 (включено всегда)
Х16: 7 (включено зажигание)
и минус:
Х17: 1 (Масса или минус)
После этого если все пошло хорошо то вы увидите пробег и несколько ошибок на экрана
Далее можно вытянуть 7 пин с X16, далее зажать правую кнопку на приборке, включить 7 пин с X16, отпустить кнопку — должен начаться тест приборки.
На котором вы увидите примерно это:
1 Номер партии (6 цифр)
2 Серийный номер кодера приборки.
3 K NUMBER (4 digits) — (количество ипульсов для одометра/спидометра означает сколько раз датчик посылает сигнал по прохождению 1 км).
4 VIN кузова. (5 последних цифр)
5 Версия программного обеспечения.
6 Версия платы приборки.
* очень важен 4 параметр с помощью него можно рассчитать сколько импульсов нужно что б спидометр показал 100 км в час — Х = K * 100 (км) / 60 (минут) / 60 (сек) (Х — количество импульсов в 1 сек.)

Управление стрелкой спидометра
Распиновка приборки
Для управление спидометром нам нужно передавать количество импульсов на X271 пин 8.
Рассчитываем его по формуле Х = K * 100 (км) / 60 (минут) / 60 (сек) (Х — количество импульсов в 1 сек.)
Далее подключаем arduino и с помощью функции tone задает количество импульсов, в свою очередь пин который выдает сигнал подключен к базе полевого транзистора который подает и убирает напряжение с X271 пин 8. (Транзистор нам нужен поскольку сигнал должен приходить на приборку 12в, а arduino выдает 5в, как подключать транзистор легко найти в интернете описывать не буду).
Если все получилось то вы сможете задавать любое значение для спидометра с программы, которое выше 40 км — это связано с тем что функция tone выдает квадратный сигнал (50% времени сигнал есть 50% его нет), а реальный датчик выдает сигнал примерно 75% есть и 25% нет.
Если хотите что б и до 40км работало красиво надо написать реализацию на таймерах (библиотеки я не нашел :( )

Управление стрелкой тахометра
Для управление спидометром нам нужно передавать количество импульсов на X16 пин 18.
Тут примерно 50 импульсов (hz) в секунду равно 1000 оборотов, но работает как то странно… я подобрал вот такое соотношение (сначала выставил стрелку по центру, а потом калибровал что б на 1к и 6к тоже правильно показывало)
X = (engineRPM — (engineRPM — 3500) / 19.7) / 19.4; (X — количество импульсов в секунду).
Тут сигнал тоже не квадратный а 66% в high (есть сигнал) и 34 в low (нет сигнала).

Управление стрелкой эконометра
Для управление эконометром нам нужно передавать количество импульсов на X16 пин 17.
По этой стрелке вообще очень мало инфы в инете… пришлось что то выдумывать получилось что то сложное но работает ))
Проблема в том что машина получает импульсы с DME (предположительно количество впрысков и их длина) дальше как то преобразует его в литры на 100км учитывая текущую скорость и обороты.
Методом "тыка" вывел такую формулу
X = engineRPM / 20; (X — количество импульсов в секунду)
Но тут еще влияет длина сигнала (впрыска).
1 / Х — длина одного импульса
litersPer100km — сколько мы хотим увидеть на эконометре
currentSpeed — текущая скорость авто
далее нужно посчитать длину high фазы (есть сигнал)
Y = (1 / X) * litersPer100km * currentSpeed / 3000 (Y — длина high фазы, длина low фазы — (1 / Х — Y))
Теперь при изменение скорости или оборотов надо пересчитывать и текущий расход на 100 км.

Что дальше
Дальше хотел еще добить бак и температуру
По баку знаю что он работает от сопротивления 87 Ом — пустой, 2 Ом — полный. Но по какой то причине стрелка не двигается… если кто то знает почему напишите.
По температуре еще ничего не смотрел но думаю должно быть легко (если у кого то есть инфа напишите)
Нашел тему где люди выводят свой текст вместо ошибок — тоже интересно попробовать но пока не знаю зачем ))
Ах да, еще одно для тестов, когда все будет спаяно попробую подключить все к жуку (vw new beetle) — надеюсь приборка заработает (должна дублировать основную приборку машины)
P.S.
Все это делается что б подружить новые двигателя которые работают по can шине с оригинальной приборкой.


Видео работы.
[video=youtube;zGW9lw26zVs]https://www.youtube.com/watch?time_continue=6&v=zGW9lw26zVs[/video]
 

bumer_ANG

Moderator
Реєстрація
30.03.2013
Повідомлення
11,754
Город
Счастье
По баку знаю что он работает от сопротивления 87 Ом — пустой, 2 Ом — полный. Но по какой то причине стрелка не двигается… если кто то знает почему напишите.
может приборка неисправна? кз на массу провода датчика бака ложит стрелку на максимум. Я в свое время тупо резистор подобрал, чтобы посередине стрелка была (после снятия стрел, чтобы позицию не профукать).
По температуре еще ничего не смотрел но думаю должно быть легко (если у кого то есть инфа напишите)
Там все просто, чем ниже сопротивление, тем дальше стрелка вправо. КЗ на массу - ложит стрелку.

Показания эконометра, кроме всего прочего (скорости и оборотов) еще от значений, зашитых в кодере, зависят.
 

mendezz

Пользователь
Реєстрація
03.08.2014
Повідомлення
49
Вік
32
Город
Смела
Спасибо, по датчику бака посмотрю.
Приборка работала (все стрелки показывали правильно), до того как я ее снял... дальше не знаю))
 

mendezz

Пользователь
Реєстрація
03.08.2014
Повідомлення
49
Вік
32
Город
Смела
Код для Arduino Uno (sketch)

PHP:
#include <FrequencyTimer2.h>

const int kMinSpeed = 0;
const int kMaxSpeed = 100;

const int kSpeedPin = 3;
const int kTachoPin = 2;
const int kEconomPin = 5;

unsigned long speedSignalHighDuration = 0;
unsigned long speedSignalLowDuration = 0;
unsigned long speedSignalChangeTime = 0;
bool isCurrentSpeedSignalHigh = false;

unsigned long tachoSignalHighDuration = 0;
unsigned long tachoSignalLowDuration = 0;
unsigned long tachoSignalChangeTime = 0;
bool isCurrentTachoSignalHigh = false;

unsigned long economSignalHighDuration = 0;
unsigned long economSignalLowDuration = 0;
unsigned long economSignalChangeTime = 0;
bool isCurrentEconomSignalHigh = false;

unsigned int currentTacho = 0;
unsigned int currentSpeed = 0;
unsigned int currentEconom = 0;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  delay(2);

  pinMode(kSpeedPin, OUTPUT);
  pinMode(kTachoPin, OUTPUT);
  pinMode(kEconomPin, OUTPUT);
  changeEcomometer(0);
  changeSpeed(100);
  changeEngineRPM(2800);
  
  FrequencyTimer2::setPeriod(90);
  FrequencyTimer2::enable();
  FrequencyTimer2::setOnOverflow(checkTime);
}

void loop() {
//  for (int i = 600; i < 4800; i= i + 10) {
//    changeEngineRPM(i);
//    delay(3);
//  }
//
//  for (int i = 4700; i > 2000; i= i - 10) {
//    changeEngineRPM(i);
//    delay(4);
//  }
//  
//  for (int i = 2200; i < 7200; i= i + 10) {
//    changeEngineRPM(i);
//    changeSpeed(i / 120);
//    delay(5);
//  }
//  changeEngineRPM(5500);
//  delay(90);
//
//  for (int i = 4200; i < 8000; i= i + 10) {
//    changeEngineRPM(i);
//    changeSpeed(60 + (i - 4200) / 70);
//    delay(7);
//  }

    if (Serial.available() > 0) {  //если есть доступные данные
        changeEngineRPM(Serial.parseInt());
//        changeSpeed(Serial.parseInt());
//        changeEcomometer(Serial.parseInt());
    }
}

void changeSpeed(long speed) {
  currentSpeed = speed;
  float signalPerSecond = speed * 1.25944444444;

  speedSignalHighDuration  = 10000 / signalPerSecond * 75;
  speedSignalLowDuration  = 10000 / signalPerSecond * 25;
  changeEcomometer(10);
}

void changeEngineRPM(long engineRPM) {
  currentTacho = engineRPM;
  float signalPerSecond = (engineRPM - (engineRPM - 3500) / 19.7) / 19.4;

  tachoSignalHighDuration = 10000 / signalPerSecond * 66;
  tachoSignalLowDuration = 10000 / signalPerSecond * 34;
  changeEcomometer(10);
}

void changeEcomometer(float litersPer100km) {
  float signalPerSecond = currentTacho / 20;
 float signalLengthMilisec = 1000000 / signalPerSecond;
  economSignalHighDuration = signalLengthMilisec * litersPer100km * currentSpeed / 3000;
   
 economSignalLowDuration = signalLengthMilisec  - economSignalHighDuration;
}

extern "C" void checkTime(void) {
  unsigned long currentMicroTime = micros();
  if (isCurrentSpeedSignalHigh) {
    if ((speedSignalChangeTime + speedSignalHighDuration) <= currentMicroTime) {
      digitalWrite(kSpeedPin, LOW);
      speedSignalChangeTime = currentMicroTime;
      isCurrentSpeedSignalHigh = false;
    }
  } else {
    if ((speedSignalChangeTime + speedSignalLowDuration) <= currentMicroTime) {
      digitalWrite(kSpeedPin, HIGH);
      speedSignalChangeTime = currentMicroTime;
      isCurrentSpeedSignalHigh = true;
    }
  }

  if (currentMicroTime < speedSignalChangeTime) {
    speedSignalChangeTime = currentMicroTime;
  }

  if (isCurrentTachoSignalHigh) {
    if ((tachoSignalChangeTime + tachoSignalHighDuration) <= currentMicroTime) {
      digitalWrite(kTachoPin, LOW);
      tachoSignalChangeTime = currentMicroTime;
      isCurrentTachoSignalHigh = false;
    }
  } else {
    if ((tachoSignalChangeTime + tachoSignalLowDuration) <= currentMicroTime) {
      digitalWrite(kTachoPin, HIGH);
      tachoSignalChangeTime = currentMicroTime;
      isCurrentTachoSignalHigh = true;
    }
  }

  if (currentMicroTime < tachoSignalChangeTime) {
    tachoSignalChangeTime = currentMicroTime;
  }

  if (isCurrentEconomSignalHigh) {
    if ((economSignalChangeTime + economSignalHighDuration) <= currentMicroTime) {
      digitalWrite(kEconomPin, LOW);
      economSignalChangeTime = currentMicroTime;
      isCurrentEconomSignalHigh = false;
    }
  } else {
    if ((economSignalChangeTime + economSignalLowDuration) <= currentMicroTime) {
      digitalWrite(kEconomPin, HIGH);
      economSignalChangeTime = currentMicroTime;
      isCurrentEconomSignalHigh = true;
    }
  }

  if (currentMicroTime < economSignalChangeTime) {
    economSignalChangeTime = currentMicroTime;
  }
}
 

mendezz

Пользователь
Реєстрація
03.08.2014
Повідомлення
49
Вік
32
Город
Смела
Выше написан код для Ардуино на С (не РНР :) )
Все стандартное, единственное что Вам нужно будет доставить это библиотеку FrequencyTimer2
Удачи всем.
 
Зверху