Примерно год назад я начал разрабатывать блок управления автомобильным двигателем с нуля.
Позвольте рассказать, почему эта идея до сих пор кажется мне реалистичной.
Итак, старенькая Киа Прайд. Под капотом у неё есть вот такая штука, к которой подходит десяток проводов — это распределитель зажигания, в корпус которого заодно встроены датчики положения распредвала и катушка зажигания.
Нас для начала интересуют датчики положения вала. Если мы начнём этот распределитель немного разбирать, внутри мы увидим:
Если поразбирать еще немного, ты мы увидим и внутреннее колесо, и сами датчики.
Эти два жестяных колеса сидят на валу, вращаются вместе с ним — и, о чудо, формируют в двух торчащих наружу проводах вот такой очень простой сигнал:
На этом наше везение не заканчивается: хотя мы и знаем, что аккумулятор в автомобиле обычно двенадцативольтовый — сигнальная электроника работает обычно на пяти вольтах! А это значит, что этот сигнал можно вот абсолютно как он есть подключить к например stm32f4discovery — это такая плата с микроконтроллером, в которой цена менее тысячи рублей сочетается с 32ых битным процессором частотой 168 МГц и даже арифметическим сопроцессором.
Если решить программировать это чудо с использованием ChibiOS/RT, хотя бы для упрощения интерфейсов работы с периферией, то вот таким несложным кодом мы получим в консоль работающий тахометр.
volatile int rpm = 0; int lastInputEventTime = -10 * CH_FREQUENCY; void icuWidthCallback(ICUDriver *driver) { int now = chTimeNow(); int diff = now - lastInputEventTime; rpm = 60000 * TICKS_IN_MS * 2 / 4 / diff; lastInputEventTime = now; } ICUConfig wave_icucfg = { ICU_INPUT_ACTIVE_LOW, 100000, icuWidthCallback, NULL }; int main(void) { halInit(); chSysInit(); // this thread would blink one of the LEDs, that would look cool chThdCreateStatic(blinkingThreadStack, sizeof(blinkingThreadStack), NORMALPRIO, blinkingThread, NULL); // serial-over-usb initialization usb_serial_start(); // configure input signal pin palSetPadMode(CRANK_INPUT_PORT, CRANK_INPUT_PIN, PAL_MODE_ALTERNATE(GPIO_AF_TIM2)); // start input capture - we will handle input events and calculate RPM based on the timestamps icuStart(&CRANK_DRIVER, &wave_icucfg); icuEnable(&CRANK_DRIVER); while (TRUE) { // RPM value is updated by the input event handler chprintf(&SDU1, "rpm: %drn", rpm); chThdSleep(100); } return 0; } |
По-моему, достаточно просто. Но, всё-таки одно дело — считать что-то с датчиков, и совсем другое дело — сгенерировать какой-то управляющий сигнал.
Давайте разберёмся, как же управляются форсунки?
Чтоб не экспериментировать сразу же с большим и железным двигателем, продолжим пока только с оригинальным блоком управления — даже если мы его хотим заменить на свою плату со своим кодом, всё равно будет полезно собрать побольше информации. Например, будет полезно
собрать информацию о ширине управляющего форсунками сигнала в зависимости от оборотов двигателя.
Итак, берём блок управления и кладём его на стол.
Аккумулятор у нас в машине на 12 вольт? так и старый ATX блок питания — тоже на 12 вольт, его и используем для питания блока управления на время экспериментов.
Когда мы подключались к автомобильной проводке, мы видели там пятивольтовый сигнал — но сам датчик положения коленвала работает как открытый коллектор — т.е. провод датчика либо заземлён, либо ни к чему не подключён. Чтоб эмулировать такой датчик, нам будет нужен транзистор.
И немного кода для генерации сигнала.
static PWMConfig pwmcfg_slow = { 10000, 1000, NULL, { { PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_ACTIVE_LOW, NULL }, { PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL } }, /* HW dependent part.*/ 0 }; int main(void) { halInit(); chSysInit(); // this thread would blink one of the LEDs, that would look cool chThdCreateStatic(blinkingThreadStack, sizeof(blinkingThreadStack), NORMALPRIO, blinkingThread, NULL); // serial-over-usb initialization usb_serial_start(); pwmStart(PWM_SLOW, &pwmcfg_slow); palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(2)); pwmEnableChannel(PWM_SLOW, 1, 600); while (TRUE) chThdSleep(100); return 0; }
|
Форсунки впрыска топлива управляются заземлением идущего к ним от блока управления провода. Чтоб интерпретировать такой сигнал от лежащего на столе блока, нам понадобятся один диод и один резистор:
Соберём это всё и запустим. И, опять чудо! Стандартный блок управления нам поверил, и на основании всего лишь одного эмулированного датчика — датчика положения распредвала — начал пытаться управлять форсунками!
На самом деле, для получения осмысленной таблицы подачи топлива нам нужно будет начать эмулировать еще и датчик расхода воздуха. Когда мы начнём управлять настоящими форсунками, нам уже не хватит простого транзистора для заземления этого примерно одноамперного соленоида — но всё это детали. Главное — сделать блок управления двигателем с нуля кажется реальным — так что я продолжаю этим заниматься.
www.youtube.com/watch?v=GcxLY697WwM
Автор: andrey239
Полностью с Вами согласен – реально. Сам буду делать на базе Arduino или его аналога. Закажу в ближайшие дни, может дааже сегодня.