Как начать делать блок управления двигателем с нуля

от автора

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

Итак, старенькая Киа Прайд. Под капотом у неё есть вот такая штука, к которой подходит десяток проводов — это распределитель зажигания, в корпус которого заодно встроены датчики положения распредвала и катушка зажигания.

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

Если поразбирать еще немного, ты мы увидим и внутреннее колесо, и сами датчики.

Эти два жестяных колеса сидят на валу, вращаются вместе с ним — и, о чудо, формируют в двух торчащих наружу проводах вот такой очень простой сигнал:

На этом наше везение не заканчивается: хотя мы и знаем, что аккумулятор в автомобиле обычно двенадцативольтовый — сигнальная электроника работает обычно на пяти вольтах! А это значит, что этот сигнал можно вот абсолютно как он есть подключить к например 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: %d\r\n", 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

ссылка на оригинал статьи http://habrahabr.ru/post/198672/


Комментарии

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

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