Расчет УОЗ и включение катушки

Раз/два в секунду отображать информацию и пытаться отображать информацию на каждый оборот - ЭТО БОЛЬШАЯ РАЗНИЦА !!!

Прямой путь к переполнению micros и всем сопутствующим весёлостям.

А есть другие варианты? Из меня программист-то так себе…

Это не касается Вашей текущей проблемы, просто, над чем ещё поработать. А варианты, конечно, есть, они есть всегда. Вот, изучите.

@denis_22rus , вам указали на кучу ошибок
Если вы их исправили - выложите обновленный код новым сообщением

#define hall 2                       // пин датчика холла (прерывание)
#define spark 16                     // пин управляющий катушкой зажигания
uint32_t rpmTime;           // время 1го оборота коленвала мксек
uint32_t vmtTime;           // текущее время прохождения ВМТ (датчика холла)
uint16_t flashTime;                  // время работы катушки зажигания
uint32_t on;                         // время включения катушки зажигания
uint32_t off;                   // время выключения катушки зажигания
uint32_t onTime;
int16_t massign[14] = {30, 30, 30, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40}; // массив значений УОЗ

void setup() 
{ Serial.begin(115200);
  attachInterrupt(hall, taho, RISING); // пин на прерывания
  pinMode(spark, OUTPUT);              // пин катушки как выход
  flashTime = 1500;                    // настройка времени работы катушки
}
void taho() // подсчет времени оборота
{
  if (micros()-vmtTime > 8570)      // если это убрать, то при прохождении ВМТ rpmTime выдает 3-4 мксек и иногда случайные значения
  {
    rpmTime = micros()-vmtTime;     // время оборота
    vmtTime = micros();             // время прохождения ВМТ
  }
}
void loop()
{ 
  off = on + flashTime;                             // считаем время отключения катушки
  if (micros() >= on && micros() <= off) {onTime = micros(); digitalWrite(spark, HIGH); Serial.println(vmtTime); Serial.println(rpmTime); Serial.println(on); Serial.println(onTime);}   // включить катушку если время от on до off
  else {digitalWrite(spark, LOW);}                  // в остальное время выкл катушку
  switch (rpmTime)                                  // здесь считаем время включеия  в зависимости от оборотов и УОЗ
  {
     case 120001 ... 900000 : on = vmtTime + rpmTime - massign[0] * rpmTime/360 ; break;
     case 60001  ... 120000 : on = vmtTime + rpmTime - massign[1] * rpmTime/360; break;
     case 40001  ... 60000  : on = vmtTime + rpmTime - massign[2] * rpmTime/360; break;
     case 30001  ... 40000  : on = vmtTime + rpmTime - massign[3] * rpmTime/360; break;
     case 24001  ... 30000  : on = vmtTime + rpmTime - massign[4] * rpmTime/360; break;
     case 20001  ... 24000  : on = vmtTime + rpmTime - massign[5] * rpmTime/360; break;
     case 17144  ... 20000  : on = vmtTime + rpmTime - massign[6] * rpmTime/360; break;
     case 15001  ... 17143  : on = vmtTime + rpmTime - massign[7] * rpmTime/360; break;
     case 13334  ... 15000  : on = vmtTime + rpmTime - massign[8] * rpmTime/360; break;
     case 12001  ... 13333  : on = vmtTime + rpmTime - massign[9] * rpmTime/360; break;
     case 10910  ... 12000  : on = vmtTime + rpmTime - massign[10] * rpmTime/360; break;
     case 10001  ... 10909  : on = vmtTime + rpmTime - massign[11] * rpmTime/360; break;
     case 9232   ... 10000  : on = vmtTime + rpmTime - massign[12] * rpmTime/360; break;
     case 8571   ... 9231   : on = vmtTime + rpmTime - massign[13] * rpmTime/360; break;
  }
}

пока мучаю вот так.

Вам же сказали. что это неверно. Нужно использовать вычитание, а не сложение.

я может не верно понял, сделал сначала умножение, а затем деление. Про вычитание ничего не было. Сейчас попробую…

Какие пределы по оборотам у двигателя ?

7000 об/мин в программе максимум, по ттх конкретного моего мотора 6000

мозг сломался в трех местах… как это можно вычислить путем только вычитания?
может вообще формула не верна? Я знаю время прохождения ВМТ, время между двумя ВМТ это время одного оборота. свечу мне надо зажечь за время до третьей и последующих ВМТ, определяемое углом опережения…

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

ваш вариант(неправильный):

newTime = oldTime + interval;
if (micros() > newTime) { //момент настал

правильный:

if (micros() - oldTime > interval) { //момент настал

подробнее - ссылка в комменте 24

Отчего же не смогут? Смогут, если по уму написать.

От библиотеки это не зависит. Никакая библиотека не способна исправить кривизну рук программиста.

Арифметику в школе учил?
При наличии некоторой сообразительности этого вполне достаточно.

Собственно, любой проект начинается с проектирования (а не с написания кода). Неожиданно, правда?
И при проектировании устройства на МК во многих случаях требуется особенно тщательно проектировать распределение времени, чтобы все успевало и ничего не пропускалось.

1 лайк

Ну не по зубам работа, не по зубам.

Конечно нет. Ошибка в строках 1-61.

  1. Зачем измерять время, переводить его в градусы и потом обратно?
  2. Нет контроля допустимых оборотов. Что будет при запуске или когда заглох? Т.е. ниже 100-500 об в мин.
  3. Катушка программно включается и выключается. Бред. Там лучше "железный одновибратор.
    Алгоритм подсчёта, который использовал я:
  4. Замерить период вращения от ВМТ до ВМТ.
  5. Вычислить момент искры Х мс после ВМТ.
  6. Через X мс после ВМТ дать искру.

Вычисляется просто:
Взять период вращения, от него вычесть константу. Константа в миллисекундах не зависит от скорости вращения, да. Физически константа это время от искры до максимального горения смеси. Там порядка 4 мс вроде, не помню.
Допустим 10мс.
Обороты: период: поджиг через Х после ВМТ
600. 100 мс. 96 мс
6000. 10 мс. 6 мс

Даже на глазок видно, что УОЗ меняется в правильном ключе. И никаких “тугодумных” вычислений, только сложение и вычитание.

Конечно нет. Ошибка в строках 1-61.

  1. Зачем измерять время, переводить его в градусы и потом обратно?
  2. Нет контроля допустимых оборотов. Что будет при запуске или когда заглох? Т.е. ниже 100-500 об в мин.
  3. Катушка программно включается и выключается. Бред. Там лучше "железный одновибратор.
    Алгоритм подсчёта, который использовал я:
  4. Замерить период вращения от ВМТ до ВМТ.
  5. Вычислить момент искры Х мс после ВМТ.
  6. Через X мс после ВМТ дать искру.

Вычисляется просто:
Взять период вращения, от него вычесть константу. Константа в миллисекундах не зависит от скорости вращения, да. Физически константа это время от искры до максимального горения смеси. Там порядка 4 мс вроде, не помню.
Допустим 10мс.
Обороты: период: поджиг через Х после ВМТ
600. 100 мс. 96 мс
6000. 10 мс. 6 мс

Даже на глазок видно, что УОЗ меняется в правильном ключе. И никаких “тугодумных” вычислений, только сложение и вычитание.
[/quote]

  1. за тем, чтобы вычислить время УОЗ в зависимости от оборотов.
  2. нет контроля? потому, что пока еще не добрался.
  3. как работает автомобильная катушка? подано питание - есть искра, снято питание - нет искры. поправьте, если я не прав.
  4. константа не такая уж и константа. Постройте график исходя из Ваших исходных данных и сравните его со среднестатистическим графиком уоз.
    Время горения смеси не постоянно и зависит от наполняемости цилиндра, степени сжатия(читай оборотов) температуры двс, стехиометрического состава ТВС, нагрузки на ДВС…
    Я когда только задумал эту штуковину, тоже думал вычитать константу. Только нет ее там.
    В автомобильных ЭБУ заложены топливные карты. ЭБУ там ничего не считает.
    Я пошел таким путем, чтобы можно было регулировать УОЗ в процессе обкатки. Потому, что рабочих графиков или карт УОЗ на мой мотор просто нет.
#define hall 2                       // пин датчика холла (прерывание)
#define spark 16                     // пин управляющий катушкой зажигания
uint32_t rpmTime;           // время 1го оборота коленвала мксек
uint32_t vmtTime;           // текущее время прохождения ВМТ (датчика холла)
uint16_t flashTime;                  // время работы катушки зажигания
uint32_t off;                   // время выключения катушки зажигания
uint32_t onTime;
int16_t massign[14] = {45, 45, 45, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40}; // массив значений УОЗ
uint32_t uoz;

void setup() 
{ Serial.begin(115200);
  attachInterrupt(hall, taho, RISING); // пин на прерывания
  pinMode(spark, OUTPUT);              // пин катушки как выход
  flashTime = 1500;                    // настройка времени работы катушки
}
void taho() // подсчет времени оборота
{
  if (micros()-vmtTime > 50000)      // если это убрать, то при прохождении ВМТ rpmTime выдает 3-4 мксек и иногда случайные значения
  {
    rpmTime = micros()-vmtTime;     // время оборота
    vmtTime = micros();             // время прохождения ВМТ
  }
}
void loop()
{ 
  off = uoz - flashTime;                             // считаем время отключения катушки
  if (micros() - vmtTime < uoz && micros() - vmtTime > off) {onTime = micros(); digitalWrite(spark, HIGH); Serial.println(vmtTime); Serial.println(rpmTime); Serial.println(uoz); Serial.println(onTime);}   // включить катушку если время от on до off
  else {digitalWrite(spark, LOW);}                  // в остальное время выкл катушку
  switch (rpmTime)                                  // здесь считаем время включеия  в зависимости от оборотов и УОЗ
  {
     case 120001 ... 99999999 : uoz = rpmTime - massign[0] * rpmTime/360; break;
     case 60001  ... 120000 : uoz = rpmTime - massign[1] * rpmTime/360; break;
     case 40001  ... 60000  : uoz = rpmTime - massign[2] * rpmTime/360; break;
     case 30001  ... 40000  : uoz = rpmTime - massign[3] * rpmTime/360; break;
     case 24001  ... 30000  : uoz = rpmTime - massign[4] * rpmTime/360; break;
     case 20001  ... 24000  : uoz = rpmTime - massign[5] * rpmTime/360; break;
     case 17144  ... 20000  : uoz = rpmTime - massign[6] * rpmTime/360; break;
     case 15001  ... 17143  : uoz = rpmTime - massign[7] * rpmTime/360; break;
     case 13334  ... 15000  : uoz = rpmTime - massign[8] * rpmTime/360; break;
     case 12001  ... 13333  : uoz = rpmTime - massign[9] * rpmTime/360; break;
     case 10910  ... 12000  : uoz = rpmTime - massign[10] * rpmTime/360; break;
     case 10001  ... 10909  : uoz = rpmTime - massign[11] * rpmTime/360; break;
     case 9232   ... 10000  : uoz = rpmTime - massign[12] * rpmTime/360; break;
     case 8571   ... 9231   : uoz = rpmTime - massign[13] * rpmTime/360; break;
  }
}

если я правильно понял, то это должно выглядить так?

Вообще-то наоборот.

Не то, чтобы прямо наоборот)) во время снятия напряжения с катушки происходит разряд… Но суть ясна, необходимо выключать пин на время разряда. Спасибо.

Осталось понять как победить дребезг датчика холла, которого вроде бы и не должно было быть…