ARDUINO Блок опережения зажигания ДВС

PiratFox

★★★★★✩✩
13 Фев 2020
1,706
474
Вот именно из-за этого чаще всего выходят из строя кнопки во всяких мышках, особенно если инженеры поставили подобный конденсатор для уменьшения дребезга.
Начнём с того, что главная причина износа контактов - деформация и трение при замыкании/размыкании. И конденсатор ёмкостью сотню-другую нанофарад, да ещё при 5 вольтах, особо не ускорит износ. Если вообще повлияет. Слишком мизерная энергия для заметной электроэррозии. :)
@Эдуард Анисимов, камрад, ты пропустил важный фактор :) . В контактном зажигании конденсатор на контактах существенно увеличивает энергию искры.;) Потому без него плохо едет: топливо не всегда поджигается по причине слабой искры.
 
Изменено:

user314

★✩✩✩✩✩✩
26 Апр 2022
38
28
@Геннадий П,
А если комаров миллион, значит чтобы контакт их "почувствовал" их нужно три миллиарда. :) Я ещё раз вам повторяю, не сравнивайте микропереключатели и прерыватели предназначенные для коммутации катушек зажигания, это вещи, мягко говоря, разных весовых категорий. С таким же успехом мы можем докопаться до того, что вход микроконтроллера тоже имеет входную ёмкость, которая убивает контакт, а ещё линия от прерывателя до входа тоже имеет свою ёмкость.

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

Главное то, что причина ложных срабатываний подавляется программным алгоритмом, остальное уже маловажно.
 
  • Лойс +1
Реакции: UJV 5901

PiratFox

★★★★★✩✩
13 Фев 2020
1,706
474
думаю теперь её даже можно убрать как возможно, бесполезную вещь
Ну, почему же прям бесполезную. Ёмкость эта давит наводки на входе. Насколько хорошо - другой вопрос, но всё жеж какая-то польза есть. :)
 

Artip

✩✩✩✩✩✩✩
19 Сен 2023
6
3
@user314, добрый день! Не подскажете, что нужно изменить в коде, чтобы заработало с платой Digispark по схеме с custom cult? Исходник с их сайта у меня не заработал, к тому же заметил, что формирователь их скетча не меняет углы при внесении изменений на сайте. С коммутатором и платой всё в порядке, мот даже заводится с ними, хоть и с трудом и нет опережения
 

user314

★✩✩✩✩✩✩
26 Апр 2022
38
28
@Artip,
Причин там может быть много и они могут быть индивидуальные. В их скетче я не разобрался до конца поэтому написал свой. У меня условия для состояния "нуля" и "единицы" разделены в коде для большей читабельности.

Вы вполне можете использовать мой скетч, но так как скорее всего у вас БСЗ, вам нужно убрать строки "антидребезга", подставить команды на вкл/выкл порта специфичные для процессоров atmega (они есть в комментариях) и выяснить, нужно ли инвертировать сигнал с датчика или нет.

Осмелюсь предположить, что вам не нужно инвертировать сигнал и скорее всего получается что-то типа вот этого:

C++:
#define IN 0
#define OUT 1

bool interruptor;
bool oldInterruptor;
bool advanceGranted;

unsigned long fuseTime;
unsigned long newTime;
unsigned long oldTime;
unsigned long midTime;
unsigned long periodTime;
unsigned long chargeTime;
unsigned long ignitionAdvance;

int ignitionDegree;
long int rpm;

void setup() {
  Serial.begin(115200);         // Start the Serial communication to send messages to the computer
  Serial.println("\n");

  oldTime = micros(); // сразу нужно установить, чтобы readAll() не споткнулся
  fuseTime = micros(); // устанавливается время до выключения катушки

  pinMode(IN, INPUT); // от БСЗ
  pinMode(OUT, OUTPUT); // к коммутатору
}

void readAll() {
  newTime = micros();
  periodTime = newTime-oldTime; // длительность всего периода (от размыкания до размыкания)
  chargeTime = newTime-midTime; // отрезок цикла от замыкания контакта до размыкания (зарядка катушки)
  rpm = 60000000/periodTime; // число оборотов
  oldTime = micros();
}

void loop() {
  interruptor = digitalRead(IN);

  if(interruptor == LOW && oldInterruptor == HIGH) { // шторка открылась
    digitalWrite(OUT, LOW); // отключаем катушку в любом случае (ИСКРА) LOW;
    oldInterruptor = interruptor; // oldInterruptor = LOW
    readAll(); // подсчёт всех параметров цикла
    // калькулятор положения коленвала на всякий случай: http://www.torqsoft.net/piston-position.html#gudgeon
    // примерный расчёт коэфициентов взят отсюда: https://customcult.netlify.app/
    if(rpm >= 0 && rpm <= 700) {
      ignitionDegree = 0;
      goto bailout;
    }
    if(rpm >= 700 && rpm <= 1000) { // 0 - 2.2
      ignitionDegree = 0.007 * rpm + (-4.800);
      goto bailout;
    }
    if(rpm >= 1000 && rpm <= 2000) { // 2.2 - 15
      ignitionDegree = 0.013 * rpm + (-10.800);
      goto bailout;
    }
    if(rpm >= 2000 && rpm <= 3000) { // 15 - 30
      ignitionDegree = 0.015 * rpm + (-15.000);
      goto bailout;
    }
    if(rpm >= 3000 && rpm <= 4000) { // 30 - 40
      ignitionDegree = 0.010 * rpm + (0.000);
      goto bailout;
    }
    if(rpm > 4000) {
      ignitionDegree = 40;
    }
    bailout:
    ignitionAdvance = chargeTime - ((periodTime / 360) * ignitionDegree);
    fuseTime = micros(); // начало отсчёта для предохранителя (отключение катушки зажигания при простое)
  }

  if(interruptor == HIGH && oldInterruptor == LOW) { // шторка закрылась
    digitalWrite(OUT, HIGH); // включаем катушку (ЗАРЯДКА) HIGH;
    oldInterruptor = interruptor; // oldInterruptor = HIGH
    midTime = micros(); // отметка начала зарядки катушки (середина цикла)
    advanceGranted = 1; // блок опережения разрешён
  }

  if(micros() - midTime >= ignitionAdvance && advanceGranted == 1) { // собственно само опережение
    digitalWrite(OUT, LOW); // отключаем катушку (ИСКРА) LOW;
    advanceGranted = 0; // больше сюда не возвращаемся до следующего цикла.
  }

  if(micros() - fuseTime >= 1000000) { // предохранитель, если катушка заряжается больше 1 секунды
    digitalWrite(OUT, LOW); // отключаем катушку LOW;
  }
}
 
  • Лойс +1
Реакции: UJV 5901 и Artip

Artip

✩✩✩✩✩✩✩
19 Сен 2023
6
3
@user314, да, всё верно, у меня установлена БСЗ по "классической схеме", то есть коммутатор от 2108, только с оптическим датчиком, который работает так же, как и датчик Холла - подает на минус на сигнальный вход при выходе модулятора из зоны свечения светодиода. Большое спасибо за скетч, попробую в нем разобраться и протестировать. Считаю, что данная тема очень интересна для наших довольно древних двигателей.
 
  • Лойс +1
Реакции: UJV 5901

Artip

✩✩✩✩✩✩✩
19 Сен 2023
6
3
@user314, не заработало. Точнее - сначала получилось запустить двигатель, но с нескольких попыток, хоть он и был прогрет и без ФУОЗ заводился "с полпинка". Пару раз так запускал, потом решил проверить, что же получается с искроподачей в первые попытки запуска и далее. А ничего - искры просто не было, как я ни крутил двигатель киком. После проверки двигатель перестал запускаться вообще. Без ФУОЗ всё работает штатно. Возможно, какой-нибудь счетчик не даёт плате подавать сигнал на выход? Что-то я не разобрался в Вашем скетче - не хватает знаний в программировании. Похоже, что надо досмотреть курсы)
 
  • Лойс +1
Реакции: UJV 5901

user314

★✩✩✩✩✩✩
26 Апр 2022
38
28
@Artip,

Тогда после сброса платы искра снова должна появиться. Можно попробовать убрать последний абзац:

C++:
  if(micros() - fuseTime >= 1000000) { // предохранитель, если катушка заряжается больше 1 секунды
    digitalWrite(OUT, LOW); // отключаем катушку LOW;
  }
Он вам всё равно ни к чему. Но вряд ли дело в нём. Если сначало было, а потом пропало - значит что-то где-то отвалилось.

Думаю, пытаться накодить рабочий скетч без опыта - почти невозможная задача, сам с этим столкнулся.
Поэтому рекомендую вооружиться симуляторами, например tinkercad . com

2023-11-05_19_38_36.png

На вход 2 arduino подаётся меандр с частотой 100 герц (что соответствует 6000 оборотов), на выходе 4 видим тоже меандр, но с большей скважностью, что говорит о работе ФУОЗ.

В заключительных тестах воспроизводил всю обвязку на стенде, на вход цеплял генератор сигналов, а на выход к коммутатору лампочку и осциллограф, меняя частоту контролировал чтобы небыло никаких явных пропусков и затупов.

Заводиться хуже может по той простой причине что на первых оборотах алгоритм только определяет длительность входного импульса, а на выход подаётся случайная абракадабра, иногда может даже чихать по понятным причинам, в симуляторе proteus это очень хорошо видно, так как там можно сравнить входные и выходные данные с самых первых моментов. Я пока с этим никак не боролся, потому что на работу саму по себе оно никак не влияет.
 
Изменено:
  • Лойс +1
Реакции: UJV 5901

Artip

✩✩✩✩✩✩✩
19 Сен 2023
6
3
@user314, ооо, Тинкеркад, знаком с сайтом по пробам 3d моделирования (даже успешным). Попробую потестить там, спасибо. Возможно, будь стартер на мотаке электрическим а не киком, двигатель бы и дальше запускался. Может, у меня просто нога устала, хоть и очень старался. Плату перезагружал несколько раз, в перерывах подключая и запуская двигатель с коммутатором без платы. В любом случае спасибо за ответ)
 

Artip

✩✩✩✩✩✩✩
19 Сен 2023
6
3
@user314, Попробовал смодулировать в Тинкеркад, опять засада - пишет, что есть некая ошибка в коде
 

Вложения

  • Ахах! +1
Реакции: Wan-Derer

Artip

✩✩✩✩✩✩✩
19 Сен 2023
6
3
@Брякомякс, :unsure:, точно, ночью и не понял, что браузер автоматически переводит код)) Отключил, запустилось
 

user314

★✩✩✩✩✩✩
26 Апр 2022
38
28
Пришло время поделиться своими наработками в области зажигания. В этот раз суть вся таже, только вместо контакта используется оптодатчик. Вся логика схемы и прошивки при этом сохраняется как на контактном.
esp8266_ignition_BSZ.GIF

В качестве датчика используется датчик отражения TCRT5000

PART-TCRT5000_1-1024x768.jpg

Отражатель выпилен под 120 градусов.

reflector_t200m.JPG

Плата датчика и коммутатора (превью, ничего зеркалить не надо, оригиналы sprint layout во вложении в zip архиве)

BSZ_T200m.JPGcommutator_T200M.JPG

Внешний вид мотоцикла и всего этого в мотоцикле:

IMG_20240928_122716.jpgIMG_20240928_122738.jpgIMG_20240928_122830.jpgIMG_20240928_123031.jpgIMG_20240928_123042.jpg

Ну и наконец, прошивка ESP8266 с функцией ФУОЗ:

C++:
#define IN 4
#define OUT 5

bool detector;
bool oldDetector;
bool advanceGranted;

unsigned long fuseTime;
unsigned long newTime;
unsigned long oldTime;
unsigned long midTime;
unsigned long periodTime;
unsigned long chargeTime;
unsigned long ignitionAdvance;

int ignitionDegree;
long int rpm;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);         // Start the Serial communication to send messages to the computer
  Serial.println("\n");

  oldTime = micros(); // сразу нужно установить, чтобы readAll() не споткнулся
  fuseTime = micros(); // устанавливается время до выключения катушки

  pinMode(IN, INPUT); // D2 от прерывателя
  pinMode(OUT, OUTPUT); // D1 к драйверу
  pinMode(2, OUTPUT); // LED
  digitalWrite(2, LOW); // LED ENABLED
}

void readAll() {
  newTime = micros();
  periodTime = newTime-oldTime; // длительность всего периода (от закрытия до закрытия)
  chargeTime = newTime-midTime; // отрезок цикла от открытия шторки до закрытия (зарядка катушки)
  rpm = 60000000/periodTime; // число оборотов
  oldTime = micros();
}


/* Схема оптодатчика https://www.drive2.ru/b/481766688824492718/
* Если светодиод светится, на выходе с датчика - 0
* Если светодиод не светится, на выходе с датчика - 1
* Логика инверсная: на входе коммутатора - 0, на выходе коммутатора - 1.
* Роль отражателя выполняет сектор 120 градусов.
        x---------x------------------------------x-----------x---------> + 12V от батареи
        |         |                              |           |
        |         |      к входу ардуино/esp     |           |
        |         |          *                  | | 10kOm    |
       | | 1kOm  | | 63kOm   |                  | |          |
       | |       | |         |                   |           |
        |         |         \ / D1              \ / Led1     |
        |         |         ---                 ---         ---  C1 100nf
        |оптопара |          |                   |          ---
        |         |----.     |-------------------x           |
       \ /  ->  |/     |__ |/                                |
       ---  ->  |\         |\  Q1                            |
        |         |          |                               |
        |         |          |                               |
        |         |          |                               |
        x---------x----------x-------------------------------x---------* GND
*/


/*
* Все измерения производятся относительно состояния датчика.
* Логика инверсная: если на входе контроллера 0, то на выходе 1.
* Когда шторка открыта (Led1 горит), на входе контроллера 0.
* chargeTime - период зарядки КЗ, если нет опережения.
* ignitionAdvance - период зарядки КЗ, если есть опережение.
* под delay подразумевается delayMicroseconds(periodTime/5);
             oldTime                   midTime             newTime
                \                         |                  /
                 \                        |                 /
                  x===================x   |                x
                  #                   #   |                #
                  #                   #   |                #
                  #       HIGH        #   |     LOW        #
                  #                   #  /                 #
                  #                   # /                  #
                  #                   #/                   #
                  x                   x====================x
                                 
                                      <-ignitionAdvance->
                               
                                      <-----chargeTime----->
                             
                  <-delay->           <-delay->
               
                  <---------------periodTime--------------->
*/

void loop() {
  detector = digitalRead(IN);

  if(detector == HIGH && oldDetector == LOW) { // момент когда шторка закрылась
    GPOC = (1 << OUT); // отключаем катушку в любом случае (ИСКРА) LOW; digitalWrite(OUT, LOW);
    oldDetector = detector; // oldDetector = HIGH
    readAll(); // подсчёт всех параметров цикла
    // калькулятор положения коленвала на всякий случай: http://www.torqsoft.net/piston-position.html#gudgeon
    // примерный расчёт коэфициентов взят отсюда: https://customcult.netlify.app/
    if(rpm >= 0 && rpm <= 700) {
      ignitionDegree = 0;
      goto bailout;
    }
    if(rpm >= 700 && rpm <= 1000) { // 0 - 2.2
      ignitionDegree = 0.007 * rpm + (-4.800);
      goto bailout;
    }
    if(rpm >= 1000 && rpm <= 2000) { // 2.2 - 15
      ignitionDegree = 0.013 * rpm + (-10.800);
      goto bailout;
    }
    if(rpm >= 2000 && rpm <= 3000) { // 15 - 30
      ignitionDegree = 0.015 * rpm + (-15.000);
      goto bailout;
    }
    if(rpm >= 3000 && rpm <= 4000) { // 30 - 40
      ignitionDegree = 0.010 * rpm + (0.000);
      goto bailout;
    }
    if(rpm > 4000) {
      ignitionDegree = 40;
    }
    bailout:
    ignitionAdvance = chargeTime - ((periodTime / 360) * ignitionDegree);
    fuseTime = micros(); // начало отсчёта для предохранителя (отключение катушки зажигания при простое)
    // антисбой датчика
    delayMicroseconds(periodTime/5);
  }

  if(detector == LOW && oldDetector == HIGH) { // момент когда шторка открылась
    GPOS = (1 << OUT); // включаем катушку (ЗАРЯДКА) HIGH; digitalWrite(OUT, HIGH);
    oldDetector = detector; // oldDetector = LOW
    midTime = micros(); // отметка начала зарядки катушки (середина цикла)
    advanceGranted = 1; // блок опережения разрешён
    // антисбой датчика
    delayMicroseconds(periodTime/5);
  }

  if(micros() - midTime >= ignitionAdvance && advanceGranted == 1) { // собственно само опережение
    GPOC = (1 << OUT); // отключаем катушку (ИСКРА) LOW; digitalWrite(OUT, LOW);
    advanceGranted = 0; // больше сюда не возвращаемся до следующего цикла.
  }

  if(micros() - fuseTime >= 1000000) { // предохранитель, если катушка заряжается больше 1 секунды
    GPOC = (1 << OUT); // отключаем катушку LOW; digitalWrite(OUT, LOW);
  }
}
Датчик выставлен на 0 градусов.
 

Вложения

Изменено:
  • Лойс +1
Реакции: UJV 5901

UJV 5901

✩✩✩✩✩✩✩
25 Мар 2024
16
0
@user314,здравствуйте!,уважаемый!,спасибо!,Вам!,большое!,за Вашу,разработку!.В zip архиве только отражатель,платы датчика и коммутатора в zip архиве нет.С уважением.
 

UJV 5901

✩✩✩✩✩✩✩
25 Мар 2024
16
0
@user314,Здравствуйте!,многоуважаемый!,спасибо!,Вам,за подсказку,теперь я разобрался,да,вкладки я нашёл.Вопрос,ещё к Вам,на АРДУИНО НАНО можно такое реализовать?,просто плата АРДУИНО НАНО у меня имеется,такой платы как у Вас у меня нет.И,ещё вопрос:отражатель можно на 60 градусов применить?,если можно,то что в коде надо изменить?.У меня мотороллер муравей.Заранее,Вам спасибо,за Ваш ответ.С уважением.
 

user314

★✩✩✩✩✩✩
26 Апр 2022
38
28
@UJV 5901,

Чтобы запустить прошивку на arduino nano нужно поменять строки 1 и 2 на свои значения, в зависимости от пинов входа и выхода с платы.

C++:
#define IN 4
#define OUT 5
Далее заменить строки 98, 134, 143 и 148 на "digitalWrite(OUT, LOW);" в зависимости от того что указано в комментарии.

И ещё пин для светодиода в строке 29, если нужно чтобы показывал индикацию питания.

По поводу модулятора, у меня используется датчик отражения. Когда "модулятор" входит в режим отражения, КЗ отключается и происходит искра. В этот момент на выходе датчика у нас логическая единица.

Если у вас после предполагаемого момента искры на выходе датчика 1, то в коде ничего менять не нужно, если же у вас 0, то нужно в тех же строках 98, 134, 143 и 148 поменять состояния на обратные.

Касательно конструкции модулятора, думаю 60 градусов должно хватать чтобы успевать полностью разряжать КЗ.
 
  • Лойс +1
Реакции: UJV 5901

UJV 5901

✩✩✩✩✩✩✩
25 Мар 2024
16
0
@user314,здравствуйте!,спасибо!,Вам!,огромное!,за Ваш ответ!.У меня сейчас БСЗ установлено на мотороллере муравей,оптический датчик на отражение,и коммутатор ВАЗ 2108,шторка-модулятор на 60 градусов,и ещё один вопрос:к коммутатору ВАЗ 2108 можно применить,Ваш ФУОЗ?,будет эта связка работать?,или может под эту связку Ваш ФУОЗ и коммутатор ВАЗ 2108,необходимо,что-то в коде поменять?,если это надо,то что именно в коде надо изменить?.Заранее Вам спасибо,за Ваш ответ,и прошу прощения у Вас,за то что вопросами я,своими Вам докучаю.Ещё раз,спасибо!,Вам огромное!,за Ваши ответы.С уважением.
 

user314

★✩✩✩✩✩✩
26 Апр 2022
38
28
@UJV 5901,
Чтобы что-то изменить, нужно понимать логику работы схемы. Вам нужно на вашем рабочем зажигании определить когда происходит искра, в момент когда свет попадает на фототранзистор, или наоборот, модулятор открывает лопасть.
 
  • Лойс +1
Реакции: UJV 5901

UJV 5901

✩✩✩✩✩✩✩
25 Мар 2024
16
0
@user314,Искра происходит в момент когда свет прекращается.
 

UJV 5901

✩✩✩✩✩✩✩
25 Мар 2024
16
0
@user314,Искра происходит,при выходе модулятора,из оптопары.
 

user314

★✩✩✩✩✩✩
26 Апр 2022
38
28
@UJV 5901,
На выходе с датчика логический 0 или 1 после искры? Замерять нужно напряжение непосредственно с выхода датчика, так чтобы коммутатор был подключен.
 
  • Лойс +1
Реакции: UJV 5901

UJV 5901

✩✩✩✩✩✩✩
25 Мар 2024
16
0
@user314,После искры,на выходе оптодатчика логический 0.Опишу точнее,если на выходе оптодатчика логическая 1,то катушка зажигания подключена к электропитанию,и она накапливает энергию,когда на выходе оптодатчика появляется логический 0,то катушка зажигания,мгновенно отключается от электропитания,и ровно в этот момент её отключения,происходит искра,в свече зажигания.