Отлавливание счетчика.

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

Всем привет. Данная тема уже обсуждалось много уже где. Поэтому прошу прощкния за повторения. Но немогу разобраться в таймерах. Очень много источников перелопатил. Но всеже решил спросить у месных гуру. Прошу снисхождения к малоопытному (или совсем безопытному, смотря с кем сравнить). Вопрос такой: имеется внешнее прерывание. В его функции счетчик. Есть также диод, который нужно зажеч на N мс при достижении этого счетчика значения M.

volatile int i=0;
 
void setup()
{
  pinMode(13, OUTPUT);
  attachInterrupt(0, Schet, RISING);
}
 
void loop()
{
  if(i=14)
{
digitalWrite(13, HIGH);
delay(2)//или ожидание через милис 
digitalWrite(13, LOW);
}
}
 
void Schet()
{
  i++;
if (i=68) {i=0;}
}

 

Очень важно не пропустить когда i=N так как диодов 9 штук. И у каждого свое N :) Можно ли сделать это не используя цикл loop или же есть какие то другие пути? Может где то неправильно изъяснился прошу меня извинить уже каша в голове путаться стал:)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Что по Вашему делает строка 22?

По-моему она ВСЕГДА обнуляет перемнную i. 

Исправьте опечатку и всё заработает.

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

Извиняюсь это тут опечатка код вручную писал не копипаст:) в 22 строке конешноже двойное равно:) 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А в 11-й?

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

Также двойное. Суть в том что 9 диодов при повышении частоты прерываний начинают пропускаться. Как побороть этот ньюанс? Диумал использовать может непосредственно таймеры. Но вопрос как...

faeton
faeton аватар
Offline
Зарегистрирован: 21.03.2016

TTpu3paK пишет:

Также двойное. Суть в том что 9 диодов при повышении частоты прерываний начинают пропускаться. Как побороть этот ньюанс? Диумал использовать может непосредственно таймеры. Но вопрос как...

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

Скорее всего, дребезг контактов крутит Ваши счётчики сильно быстро, а на каждом из 9-ти светодиодов у Вас по delay() тупит. Кстати, Вы думаете сверкнувший 2мс светодиод будет заметен?

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

Это малый пример моей програмки, показывающий алгоритм который я использую. Импульсы идут от индуктивного датчика и реперного диска на валу. На реперном диске 32 метки. При вращении вала свыше 2000 начинаются пропуски. Загружать прерывание тоже нельзя изза его частоты.

faeton
faeton аватар
Offline
Зарегистрирован: 21.03.2016

2000 чего? Оборотов в минуту? Так это мелочи. При такой скорости вращения 2000/60*32=1066 прерываний в секунду. 

Там у Вас показан не алгоритм, а, простите, неверный подход. :) Нельзя надеяться на асинрхронное (в одном месте меняем, в другом проверяем) отлавливание значения переменной в некоторой точке. Можно с дрейфом обнаружить завершение отсчёта, который останавливается. Там, где переменная изменяется, и надо проверять её значение. А далее либо выставлять флаг, либо генерировать событие, либо выполнять действие непосредственно.

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

именно оборотов в минуту:) согласен подход неверный - поэтому я здесь. Добрался наконец до компа вот полный код програмки.

float diamcyl = 82.0;  //Диаметр цилиндра
float hodcyl = 71.0;   //Ход поршня
float Vcyl = 1.0;      //Объем цидиндра
float Pvpusc = 0.1;        //Давление во впуске (преобразованый)
int SAPvpusc = 0;      //ЦАП давление во впуске, Па
int PvpuscPIN = 0;     //Пин давление во впуске-------------------А.П 0
float Tvpusc = 0;        //Температура во впуске, С
int SATvpusc = 0;      //ЦАП температуры во впуске
int TvpuscPIN = 1;     //Пин температуры во впуске----------------А.П 1
float Mvozduh = 0.1;   //Масса воздуха, г
float trebtopl = 0.1;  //Требуемое количество топлива, г
float Vsmes = 0.1;     //Коэфицент смеси 1/х
float Vfors = 166.0;     //Производительность форсунок см3/мин
int fors1PIN = 22;     //Пин форсунки1---------------------------Ц.П 22
int fors2PIN = 23;     //Пин форсунки2---------------------------Ц.П 23
int fors3PIN = 24;     //Пин форсунки3---------------------------Ц.П 24
int fors4PIN = 25;     //Пин форсунки4---------------------------Ц.П 25
int fors5PIN = 26;     //Пин форсунки5---------------------------Ц.П 26
int fors6PIN = 27;     //Пин форсунки6---------------------------Ц.П 27
int ign1PIN = 28;      //Пин катушки1----------------------------Ц.П 28
int ign2PIN = 29;      //Пин катушки2----------------------------Ц.П 29
int ign3PIN = 30;      //Пин катушки3----------------------------Ц.П 30
unsigned long T2 = 0;            //Время открытия форсунки, мс
float T = 0.1;         //Время открытия форсунки, мс
int droszaslPIN = 2;   //Пин дросельной заслонки------------------А.П 2
int SAdroszasl = 0;    //ЦАП дросельной заслонки
int cylinders = 6;     //Количество цилиндров
//int DPKV = 0;       //Пин ДПКВ---------------------------------Ц.П
//int DPKV2PIN = 2;      //Пин ДПКВ---------------------------------Ц.П
int SADPKV = 0;        //ЦАП ДПКВ
volatile int PKV1 = 0; //Вспомогательная 1
volatile unsigned long TIMEIMP1 = 0; //Вспомогательная 1 вычесления периода
volatile unsigned long TIMEIMP2 = 0; //Вспомогательная 2 вычесления периода
volatile unsigned long TIMEIMP3 = 0;      //Вспомогательная 3 вычесления периода
volatile unsigned long TIMEIMP4 = 0;      //Вспомогательная 4 вычесления периода
int PKV2 = 0;          //Вспомогательная 2
//int PKV3 = 0;          //Вспомогательная 3
//unsigned long shag ;   //Время импульсов ДПКВ
//int DFPIN = 7;         //Пин ДФ-----------------------------------Ц.П
//int DF = 0;            //ДФ
float UOZ = 0.1;        //УОЗ
float UOZOPT = 0.1;        //УОЗ оптимальный
int UOZUST = 15;       //УОЗ установочный
float UOZODV = 0.1;        //УОЗ по оборотам
float UOZNAGR = 0.1;       //УОЗ при нагрузке
float UOZOBR = 0.1;        //УОЗ обратный
unsigned long UOZINT = 0;            //УОЗ целый
float UOZOST = 0.1;        //УОЗ остаток
unsigned long UOZTIME = 0;           //УОЗ повремени
volatile int DFD = 0;           //переменная ДФ
unsigned long TFors1_1; //1 вспомогательная 1 форсунки
unsigned long TFors1_2; //2 вспомогательная 1 форсунки
unsigned long TFors2_1; //1 вспомогательная 2 форсунки
unsigned long TFors2_2; //2 вспомогательная 2 форсунки
unsigned long TFors3_1; //1 вспомогательная 3 форсунки
unsigned long TFors3_2; //2 вспомогательная 3 форсунки
unsigned long TFors4_1; //1 вспомогательная 4 форсунки
unsigned long TFors4_2; //2 вспомогательная 4 форсунки
unsigned long TFors5_1; //1 вспомогательная 5 форсунки
unsigned long TFors5_2; //2 вспомогательная 5 форсунки
unsigned long TFors6_1; //1 вспомогательная 6 форсунки
unsigned long TFors6_2; //2 вспомогательная 6 форсунки
unsigned long TIGN1_1; //1 вспомогательная 1 катушки
unsigned long TIGN1_2; //2 вспомогательная 1 катушки
unsigned long TIGN2_1; //1 вспомогательная 2 катушки
unsigned long TIGN2_2; //2 вспомогательная 2 катушки
unsigned long TIGN3_1; //1 вспомогательная 3 катушки
unsigned long TIGN3_2; //2 вспомогательная 3 катушки
volatile unsigned long tahometr = 0;      //Тахометр
volatile int knopka1 = 1;  //Кнопка
volatile unsigned long KN1 = 0;//вспомогательная кнопки
volatile unsigned long KN2 = 0;//вспомогательная кнопки
volatile unsigned long KN3 = 0;//вспомогательная кнопки
volatile unsigned long KN4 = 0;//вспомогательная кнопки

void setup() {
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(2), DPKV, FALLING);    //ДПКВ-----------------------Ц.П. 2
  attachInterrupt(digitalPinToInterrupt(21), DF, RISING);        //ДФ-------------------------Ц.П.21
  attachInterrupt(digitalPinToInterrupt(20), knopka, RISING);       //ДФ-------------------------Ц.П.20
  pinMode(fors1PIN, OUTPUT);
  pinMode(fors2PIN, OUTPUT);
  pinMode(fors3PIN, OUTPUT);
  pinMode(fors4PIN, OUTPUT);
  pinMode(fors5PIN, OUTPUT);
  pinMode(fors6PIN, OUTPUT);
  Vcyl = 3.14 * hodcyl * ((diamcyl / 2.0) * (diamcyl / 2.0));
  //  pinMode(DFPIN, INPUT);
  Serial.begin(9600);


void loop()
{




  SAPvpusc = analogRead(PvpuscPIN);
  Pvpusc = SAPvpusc * 0.68;
  SATvpusc = analogRead(TvpuscPIN);
  Tvpusc = (float)SATvpusc * 0.078 - 40;
  Mvozduh = (0.8 * Vcyl * 0.000000001 * 28.98 * (float)Pvpusc * 1000) / (8.31 * (273.0 + Tvpusc));
  SAdroszasl = analogRead(droszaslPIN);
  Vsmes = 12.965 + (0.003 * (float)SAdroszasl);
  trebtopl = Mvozduh / Vsmes;
  T = ((trebtopl / 0.71) / Vfors) * 60000000;
  T2 = (int)T;

  UOZODV = 1.5;
  UOZNAGR = 1.4;
  UOZOPT = (float)UOZUST + UOZODV + UOZNAGR;
  UOZOBR = (30.0 - UOZOPT);
  UOZINT = (int)UOZOBR / 6;
  UOZOST = UOZOBR - (float)UOZINT * 6;
  if (UOZOST != 0)
  {
    UOZTIME = (UOZOST / 0.06) * (TIMEIMP4 / 100);
  }
  else {
    UOZTIME = 0;
  }



marker1:

  switch (PKV1) {
    case 80:
      // ---------------------------------------------------------------------- 1 цилиндр впрыск
      digitalWrite(fors1PIN, HIGH);
      TFors1_1 = micros();
      for (TFors1_2 = TFors1_1; TFors1_2 - TFors1_1 < T2; TFors1_2 = micros())
      {
      }
      digitalWrite(fors1PIN, LOW);
      break;
    case 10:
      //-----------------------------------------------------------------------  1,2 цилиндр искра
      for (; PKV1 < 19 + UOZINT;)
      {
      }
      TIGN1_1 = micros();
      for (TIGN1_2 = TIGN1_1; TIGN1_2 - TIGN1_1 < UOZTIME; TIGN1_2 = micros())
      {
      }
      digitalWrite(ign1PIN, LOW);
      TIGN1_1 = micros();
      for (TIGN1_2 = TIGN1_1; TIGN1_2 - TIGN1_1 < 1000; TIGN1_2 = micros())
      {
      }
      digitalWrite(ign1PIN, HIGH);
      break;
    case 100:
      // ----------------------------------------------------------------------- 5 цилиндр впрыск
      digitalWrite(fors5PIN, HIGH);
      TFors5_1 = micros();
      for (TFors5_2 = TFors5_1; TFors5_2 - TFors5_1 < T2; TFors5_2 = micros())
      {
      }
      digitalWrite(fors5PIN, LOW);
      break;
    case 30:
      // -------------------------------------------------------------------------------- 5,6 цилиндр искра
      for (; PKV1 < 30 + UOZINT;)
      {
      }
      TIGN3_1 = micros();
      for (TIGN3_2 = TIGN3_1; TIGN3_2 - TIGN3_1 < UOZTIME; TIGN3_2 = micros())
      {
      }
      digitalWrite(ign3PIN, LOW);
      TIGN3_1 = micros();
      for (TIGN3_2 = TIGN3_1; TIGN3_2 - TIGN3_1 < 1000; TIGN3_2 = micros())
      {
      }
      digitalWrite(ign3PIN, HIGH);
      break;
    case 1:
      // ------------------------------------------------------------------------- 3 цилиндр впрыск
      digitalWrite(fors3PIN, HIGH);
      TFors3_1 = micros();
      for (TFors3_2 = TFors3_1; TFors3_2 - TFors3_1 < T2; TFors3_2 = micros())
      {
      }
      digitalWrite(fors3PIN, LOW);
      break;
    case 50:
      // ------------------------------------------------------------------------- 3,4 цилиндр искра
      for (; PKV1 < 50 + UOZINT;)
      {
      }
      TIGN2_1 = micros();
      for (TIGN2_2 = TIGN2_1; TIGN2_2 - TIGN2_1 < UOZTIME; TIGN2_2 = micros())
      {
      }
      digitalWrite(ign2PIN, LOW);
      TIGN2_1 = micros();
      for (TIGN2_2 = TIGN2_1; TIGN2_2 - TIGN2_1 < 1000; TIGN2_2 = micros())
      {
      }
      digitalWrite(ign2PIN, HIGH);
      break;
    case 20:
      // ------------------------------------------------------------------------ 6 цилиндр впрыск
      digitalWrite(fors6PIN, HIGH);
      TFors6_1 = micros();
      for (TFors6_2 = TFors6_1; TFors6_2 - TFors6_1 < T2; TFors6_2 = micros())
      {
      }
      digitalWrite(fors6PIN, LOW);
      break;
    case 70:
      //------------------------------------------------------------------------  5,6 цилиндр искра
      for (; PKV1 < 70 + UOZINT;)
      {
      }
      TIGN3_1 = micros();
      for (TIGN3_2 = TIGN3_1; TIGN3_2 - TIGN3_1 < UOZTIME; TIGN3_2 = micros())
      {
      }
      digitalWrite(ign3PIN, LOW);
      TIGN3_1 = micros();
      for (TIGN3_2 = TIGN3_1; TIGN3_2 - TIGN3_1 < 1000; TIGN3_2 = micros())
      {
      }
      digitalWrite(ign3PIN, HIGH);
      break;
    case 40:
      // ------------------------------------------------------------------------ 2 цилиндр впрыск
      digitalWrite(fors2PIN, HIGH);
      TFors2_1 = micros();
      for (TFors2_2 = TFors2_1; TFors2_2 - TFors2_1 < T2; TFors2_2 = micros())
      {
      }
      digitalWrite(fors2PIN, LOW);
      break;
    case 90:
      // ------------------------------------------------------------------------------ 1,2 цилиндр искра
      for (; PKV1 < 90 + UOZINT;)
      {
      }
      TIGN1_1 = micros();
      for (TIGN1_2 = TIGN1_1; TIGN1_2 - TIGN1_1 < UOZTIME; TIGN1_2 = micros())
      {
      }
      digitalWrite(ign1PIN, LOW);
      TIGN1_1 = micros();
      for (TIGN1_2 = TIGN1_1; TIGN1_2 - TIGN1_1 < 1000; TIGN1_2 = micros())
      {
      }
      digitalWrite(ign1PIN, HIGH);
      break;
    case 61:
      //----------------------------------------------------------------------------  4 цилиндр впрыск
      digitalWrite(fors4PIN, HIGH);
      TFors4_1 = micros();
      for (TFors4_2 = TFors4_1; TFors4_2 - TFors4_1 < T2; TFors4_2 = micros())
      {
      }
      digitalWrite(fors4PIN, LOW);
      break;
    case 110:
      // --------------------------------------------------------------------------- 3,4 цилиндр искра
      for (; PKV1 < 110 + UOZINT;)
      {
      }
      TIGN2_1 = micros();
      for (TIGN2_2 = TIGN2_1; TIGN2_2 - TIGN2_1 < UOZTIME; TIGN2_2 = micros())
      {
      }
      digitalWrite(ign2PIN, LOW);
      TIGN2_1 = micros();
      for (TIGN2_2 = TIGN2_1; TIGN2_2 - TIGN2_1 < 1000; TIGN2_2 = micros())
      {
      }
      digitalWrite(ign2PIN, HIGH);
      break;
    default:
      if (tahometr >= 10)
      {
        goto marker1;
      }
  }

//  display.clearDisplay();
//  display.display();

}


void DPKV ()
{
  if (PKV1 == 58)
  {
    PKV1 = 60;
  }
  PKV1++;
  TIMEIMP3 = TIMEIMP4;
  TIMEIMP1 = micros();
  TIMEIMP4 = TIMEIMP1 - TIMEIMP2;
  TIMEIMP2 = micros();
  tahometr = 1000000 / TIMEIMP4;
  if (DFD == 1 && TIMEIMP1 > TIMEIMP3 * 1.5  )
  {
    PKV1 = 0;
    DFD = 0;
  }
}

void DF()
{
  DFD = 1;
}

немного поподробней можно про ваши варианты? малость не уловил)

faeton
faeton аватар
Offline
Зарегистрирован: 21.03.2016

TTpu3paK пишет:

именно оборотов в минуту:) согласен подход неверный - поэтому я здесь. Добрался наконец до компа вот полный код програмки.

немного поподробней можно про ваши варианты? малость не уловил)

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

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

А не получится что проверка флага выйдет тож самое что и проверка переменной?

faeton
faeton аватар
Offline
Зарегистрирован: 21.03.2016

TTpu3paK пишет:

А не получится что проверка флага выйдет тож самое что и проверка переменной?

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

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

Видимо я думаю моленько о другом. Можно простенький пример с флагом?

faeton
faeton аватар
Offline
Зарегистрирован: 21.03.2016

В обработчике прерывания:

If (Counter==MaxCounter) {
   Counter=0;
   Flag=true;
} else {
   Counter++;
};

В теле программы:

if (Flag) {
   Flag=false;
   // сработало, надо что-то делать
};

 

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

faeton пишет:

В обработчике прерывания:

If (Counter==MaxCounter) {
   Counter=0;
   Flag=true;
} else {
   Counter++;
};

В теле программы:

if (Flag) {
   Flag=false;
   // сработало, надо что-то делать
};

 

 

Ну пропустить то он точно не пропустит согласен:) но он так же не успеет отработать в нужный момент.... какже быть то?

TTpu3paK
Offline
Зарегистрирован: 14.11.2014

faeton пишет:

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

Скорее всего, дребезг контактов крутит Ваши счётчики сильно быстро, а на каждом из 9-ти светодиодов у Вас по delay() тупит. Кстати, Вы думаете сверкнувший 2мс светодиод будет заметен?

А ведь действительно же лучше будет. Неправильно вас сначало понял:) Попробую таким методом. 

faeton
faeton аватар
Offline
Зарегистрирован: 21.03.2016

TTpu3paK пишет:

faeton пишет:

В обработчике прерывания:

If (Counter==MaxCounter) {
   Counter=0;
   Flag=true;
} else {
   Counter++;
};

В теле программы:

if (Flag) {
   Flag=false;
   // сработало, надо что-то делать
};

 

 

Ну пропустить то он точно не пропустит согласен:) но он так же не успеет отработать в нужный момент.... какже быть то?

Если это очень критично, тут же на месте в прерывании выполнять действия. Суть в том, что прерывания могут работать рекурсивно. Грубо говоря, если Вы зависли в прерывании и ходите в нём долго покуралесить, вполне допустимо разрешить прерывания внутри обработчика, но использовать флаг т.с. занятости чтобы до завершения некоторого действия прерываения работали, крутился счётчик и всё остальное внутри прерывания, но не вызывался обработчик рекурсивно.

В прерывании:

volatile boolean Flag = false;

void Interrup() {
   if (Counter==MaxCounter) {
      Counter=0;
      if (!BusyFlag) {
         BusyFlag=true;         
         sti;                        // разрешить прерывания, точно не знаю как оно в дуне
         RunAny();           // можете зависнуть в этой процедуре сколько пожелаете
         BusyFlag=false;
      };
   } else {
      Counter++;
   }
}

 

Yer
Offline
Зарегистрирован: 12.02.2016

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

faeton пишет:

прерывания могут работать рекурсивно. 

Ох, faeton, "не надо бы вслух, ох, не надо бы". Эта техника для профессионалов или хотя бы продвинутых любителей, но никак не для новичков. Парень сейчас нворотит чего-нибудь, что будет "вроде бы работать", а потом месяцами будет глюки ловить.