Обнаружение, когда прерывание таймера не выполняется

Я имею дело с полученным кодом, который сильно зависит от прерываний таймера. я использую Arduino Mega (Funduino)

В частности, когда на вывод поступает сигнал, запускается прерывание, запускающее таймер. Другое прерывание запускается изнутри первого прерывания, когда таймер переполняется.

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

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

Мой код застрял в функции loop(). Он не может выполняться, так как требует установки флага, начиная с момента, когда прерывание завершает выполнение (прерывание устанавливает этот флаг в конце).

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

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

Но использование другого таймера (мое прерывание уже использует два таймера) может еще больше усложнить ситуацию. Есть идеи?

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

Это код:

/***** CONSTANTS *****/
const int BAUD_RATE = 9600;

const int INTERRUPT_PIN = 3;

const int S0_PIN = 4;
const int S1_PIN = 5;
const int S2_PIN = 6;
const int OE_BAR_PIN = 22;

const int NUM_OF_SENSORS = 8;

/***** ANALOG CIRCUIT CONSTANTS *****/
const double CAPACITOR_VALUE = 400; //пф
const double GAIN_VALUE = 3.5222672065;
const double R_BIAS_VALUE = 98.7; //кОм

/***** GLOBAL VARIABLES *****/
int number_of_samples = 10;

int pulse_counter = 0;
byte measurement_counter = 0;

unsigned long overflows = 0;
unsigned long ticks = 0;
double period = 0;

boolean interrupts_enabled = false;
boolean measurement_finished = false;

int sensor_coord;

boolean full_mode = false;

void setup() {
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), count_time_of_k_pulses, RISING);

  pinMode(OE_BAR_PIN, OUTPUT);
  pinMode(S0_PIN, OUTPUT);
  pinMode(S1_PIN, OUTPUT);
  pinMode(S2_PIN, OUTPUT);

  TIMER1_init();

  Serial.begin(BAUD_RATE);
  while (! Serial);
}

void loop() {
  if (Serial.available()) {
    /***** DEFINE MEASUREMENT MODE *****/
    String input = Serial.readString();
    if (input[0] == 'r' && interrupts_enabled == false) {
      if (input[1] == 'f') {
        full_mode = true;
        sensor_coord = 0;
      } else
        sensor_coord = input[2] - '0';

      select_sensor();

      /***** SET VARIABLES FOR DUMMY MEASUREMENT *****/
      number_of_samples = 10;

      pulse_counter = 0;
      measurement_counter = 0;

      TIMER1_clear();

      interrupts_enabled = true;
    }
  }


// ЭТО ГДЕ, Я ВЕРЮ, ДОЛЖНА ПРОИЗОЙТИ ПРОВЕРКА, ОТСУТСТВУЕТ ЛИ ПРЕРЫВАНИЕ. ИЛИ ПОЛУЧАЕТ ЛИ PIN 3 НУЛЕВОЙ СИГНАЛ В ТЕЧЕНИЕ НЕКОТОРОГО ВРЕМЕНИ


  if (measurement_finished) {
    measurement_counter++;

    ticks = (overflows * 65536) + TCNT1;
    period = (ticks * 0.0625) / (number_of_samples - 1);

    if (measurement_counter == 1) {
      /***** SET VARIABLES FOR MEASUREMENT *****/
      number_of_samples = 500;

      pulse_counter = 0;

      TIMER1_clear();

      interrupts_enabled = true;
    }
    else {
      TIMER1_print_results();

      if (full_mode) {
        sensor_coord++;

        select_sensor();

        /***** SET VARIABLES FOR DUMMY MEASUREMENT *****/
        number_of_samples = 10;

        pulse_counter = 0;
        measurement_counter = 0;

        TIMER1_clear();

        interrupts_enabled = true;

        if (sensor_coord == NUM_OF_SENSORS) {
          full_mode = false;
          interrupts_enabled = false;
        }
      }
    }
    measurement_finished = false;
  }
}

/***** INTERRUPT ROUTINES *****/

void count_time_of_k_pulses() {
  if (interrupts_enabled) {
    pulse_counter++;

    if (pulse_counter == 1)
      TIMER1_start();

    if (pulse_counter == number_of_samples) {
      TIMER1_stop();

      measurement_finished = true;
      interrupts_enabled = false;
    }
  }
}

ISR (TIMER1_OVF_vect) {
  overflows++;
}

/***** FUNCTION FOR SENSOR SELECTION *****/

void select_sensor() {
  digitalWrite(OE_BAR_PIN, LOW);
  digitalWrite(S2_PIN, ((sensor_coord & 4) == 4) ? HIGH : LOW );
  digitalWrite(S1_PIN, ((sensor_coord & 2) == 2) ? HIGH : LOW );
  digitalWrite(S0_PIN, ((sensor_coord & 1) == 1) ? HIGH : LOW );
}

/***** TIMER1 FUNCTIONS *****/

void TIMER1_init() {
  TCCR1A  = 0;
  TCCR1B  = 0;
  TIMSK1  = 0;
  TCCR1B |= (0 << CS12) | (0 << CS11) | (1 << CS10);
}

void TIMER1_start() {
  TIMSK1 |= (1 << TOIE1);
}

void TIMER1_stop() {
  TIMSK1 = 0;
}

void TIMER1_clear() {
  TCNT1     = 0;
  overflows = 0;
}

void TIMER1_print_results() {
  Serial.println("----------------------------------------");
  Serial.print("SENSOR COORDINATE         = ");
  Serial.println(sensor_coord);

  Serial.print("NUMBER OF PULSES MEASURED = ");
  Serial.println(pulse_counter);

  Serial.print("TIMER1 VALUE              = ");
  Serial.println(TCNT1);

  Serial.print("TIMER1 OVERFLOWS          = ");
  Serial.println(overflows);

  Serial.print("TICKS                     = ");
  Serial.println(ticks);

  Serial.print("MEASURED PERIOD           = ");
  Serial.print(period);
  Serial.println(" US");

  Serial.print("MEASURED RESISTANCE       = ");

  double resistanse = ((period * GAIN_VALUE * 1000) / (4 * CAPACITOR_VALUE)) - R_BIAS_VALUE; //кОм
  Serial.print(resistanse);

  Serial.println(" kΩ");

  Serial.println("----------------------------------------");
}

EDIT: это обновленный код с помощью chrisl. Только строки или блоки кода с '!!!!!!!!!!!' являются новыми, поэтому нового кода не так много.

/***** CONSTANTS *****/
const int BAUD_RATE = 9600;

const int INTERRUPT_PIN = 3;

const int S0_PIN = 4;
const int S1_PIN = 5;
const int S2_PIN = 6;
const int OE_BAR_PIN = 22;

const int NUM_OF_SENSORS = 8;

/***** ANALOG CIRCUIT CONSTANTS *****/
const double CAPACITOR_VALUE = 400; //пф
const double GAIN_VALUE = 3.5222672065;
const double R_BIAS_VALUE = 98.7; //кОм

/***** GLOBAL VARIABLES *****/
int number_of_samples = 10;


byte measurement_counter = 0;

unsigned long overflows = 0;
unsigned long ticks = 0;
double period = 0;

//переменные для определения невозможности измерения сопротивления !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!
unsigned long timestamp = 0;
unsigned long measurement_timeout = 5000;  //5 секунд - время тайм-аута
boolean sensor_corruption[7]; //каждый элемент массива - информация о датчике. Если false, сопротивление работает. Если это правда, сопротивление открыто.
boolean ISR_unavailable = false; //этот флаг поднимается, когда ISR не работает, потому что сигнал не поступает из цепи, потому что сопротивление разомкнуто
boolean setup_finished = false;


//переменные, которые изменяются внутри ISR - поэтому объявляются изменчивыми!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!
volatile int pulse_counter = 0;
volatile boolean interrupts_enabled = false;
volatile boolean measurement_finished = false;



int sensor_coord;

boolean full_mode = false;

void setup() {
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), count_time_of_k_pulses, RISING);

  pinMode(OE_BAR_PIN, OUTPUT);
  pinMode(S0_PIN, OUTPUT);
  pinMode(S1_PIN, OUTPUT);
  pinMode(S2_PIN, OUTPUT);

  TIMER1_init();

  Serial.begin(BAUD_RATE);
  while (! Serial);

  //Инициализация всех элементов массива в false!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  for (int i=0; i<=7; i++)
  {
    sensor_corruption[i] = false; // false означает, что все работает нормально. true означает, что он поврежден
  }

  setup_finished = true; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

}

void loop()
{
  if (Serial.available())
  {
    /***** DEFINE MEASUREMENT MODE *****/
    String input = Serial.readString();
    if (input[0] == 'r' && interrupts_enabled == false)
    {
      if (input[1] == 'f')
      {
        full_mode = true;
        sensor_coord = 0;
      } else
        sensor_coord = input[2] - '0';

      select_sensor();

      /***** SET VARIABLES FOR DUMMY MEASUREMENT *****/
      number_of_samples = 10;

      pulse_counter = 0;
      measurement_counter = 0;

      TIMER1_clear();

      interrupts_enabled = true;
    }
  }

// ЗДЕСЬ КОД ТАЙМ-АУТА. ДЛЯ ОПРЕДЕЛЕНИЯ РАЗОМКНУТОГО СОПРОТИВЛЕНИЯ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!
  if(setup_finished && millis() - timestamp > measurement_timeout)
  {
    sensor_corruption[sensor_coord] = true; // пометить сопротивление (обозначенное как sensor_coord) как истинное в логическом массиве. это означает, что он разомкнут (нет сигнала от цепи)
    measurement_finished = true;
    interrupts_enabled = false;
    ISR_unavailable = true;
  }




  if (measurement_finished)
  {
    // Это не выполняется, когда сопротивление разомкнуто
    if (!ISR_unavailable) //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! это оператор if - единственное, что я добавил сюда
    {
      measurement_counter++;

      ticks = (overflows * 65536) + TCNT1;
      period = (ticks * 0.0625) / (number_of_samples - 1);

      if (measurement_counter == 1)
      {
         /***** SET VARIABLES FOR MEASUREMENT *****/
        number_of_samples = 500;

        pulse_counter = 0;

        TIMER1_clear();

        interrupts_enabled = true;
       }
    }
    else
    {
      TIMER1_print_results();

      if (full_mode)
      {
        sensor_coord++;

        select_sensor();

        /***** SET VARIABLES FOR DUMMY MEASUREMENT *****/
        number_of_samples = 10;

        pulse_counter = 0;
        measurement_counter = 0;

        TIMER1_clear();

        interrupts_enabled = true;

        if (sensor_coord == NUM_OF_SENSORS)
        {
          full_mode = false;
          interrupts_enabled = false;
        }
      }
    }
    measurement_finished = false;
    ISR_unavailable = false; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!
    timestamp = millis();  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!
  }
}

/***** INTERRUPT ROUTINES *****/

void count_time_of_k_pulses() {
  if (interrupts_enabled) {
    pulse_counter++;

    if (pulse_counter == 1)
      TIMER1_start();

    if (pulse_counter == number_of_samples) {
      TIMER1_stop();

      measurement_finished = true;
      interrupts_enabled = false;
    }
  }
}

ISR (TIMER1_OVF_vect) {
  overflows++;
}

/***** FUNCTION FOR SENSOR SELECTION *****/

void select_sensor() {
  digitalWrite(OE_BAR_PIN, LOW);
  digitalWrite(S2_PIN, ((sensor_coord & 4) == 4) ? HIGH : LOW );
  digitalWrite(S1_PIN, ((sensor_coord & 2) == 2) ? HIGH : LOW );
  digitalWrite(S0_PIN, ((sensor_coord & 1) == 1) ? HIGH : LOW );
}

/***** TIMER1 FUNCTIONS *****/

void TIMER1_init() {
  TCCR1A  = 0;
  TCCR1B  = 0;
  TIMSK1  = 0;
  TCCR1B |= (0 << CS12) | (0 << CS11) | (1 << CS10);
}

void TIMER1_start() {
  TIMSK1 |= (1 << TOIE1);
}

void TIMER1_stop() {
  TIMSK1 = 0;
}

void TIMER1_clear() {
  TCNT1     = 0;
  overflows = 0;
}

void TIMER1_print_results() {
  Serial.println("----------------------------------------");
  Serial.print("SENSOR COORDINATE         = ");
  Serial.println(sensor_coord);

  //Добавлен оператор if-else, чтобы покрыть возможность сопротивления разомкнутой цепи !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!
  if (sensor_corruption[sensor_coord])
  {
  Serial.println("This resistance is open circuited!!!");
  }
  else
  {
  Serial.print("NUMBER OF PULSES MEASURED = ");
  Serial.println(pulse_counter);

  Serial.print("TIMER1 VALUE              = ");
  Serial.println(TCNT1);

  Serial.print("TIMER1 OVERFLOWS          = ");
  Serial.println(overflows);

  Serial.print("TICKS                     = ");
  Serial.println(ticks);

  Serial.print("MEASURED PERIOD           = ");
  Serial.print(period);
  Serial.println(" US");

  Serial.print("MEASURED RESISTANCE       = ");

  double resistanse = ((period * GAIN_VALUE * 1000) / (4 * CAPACITOR_VALUE)) - R_BIAS_VALUE; //кОм
  Serial.print(resistanse);

  Serial.println(" kΩ");
  }

  Serial.println("----------------------------------------");
}

И вот что я получаю:

----------------------------------------
SENSOR COORDINATE         = 0
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 1
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 2
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 3
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 4
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 5
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 6
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 7
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 8
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 8
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 8
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 8
This resistance is open circuited!!!
----------------------------------------
----------------------------------------
SENSOR COORDINATE         = 8
This resistance is open circuited!!!
----------------------------------------

Как видите, все сопротивления ошибочно помечены как разомкнутые. Не только это, но и по какой-то причине он измеряет несуществующее сопротивление 8 несколько раз. На самом деле, тогда он вечно зацикливается на сопротивлении 8 (нормальная работа останавливается на сопротивлении 7)

, 👍-1

Обсуждение

Комментарии не для расширенного обсуждения; этот разговор был [перемещен в чат](https://chat.stackexchange.com/rooms/102616/discussion-on-question-by-user1584421-detecting-when-a-timer-interrupt-not)., @VE7JRO


2 ответа


Лучший ответ:

1

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

Основная проблема заключается в том, что логика loop() довольно запутана и сложна. следить. Я предполагаю, что проблема, с которой вы сталкиваетесь, является прямым следствием этой единственной проблемы. Я не буду предлагать исправление, потому что я действительно не могу понять, что эта логика должна выполнить. я думаю это проблема коренится в том, что логика имеет слишком много «состояний», т.е. слишком много глобальные переменные, влияющие на его поведение.

Возможно, логика функции станет намного понятнее, если вы объединить различные переменные, определяющие состояние, в одно enum переменную с именем state и напишите логику, как в обычном finite конечный автомат. Это должно облегчить понимание, что, в свою очередь, должно заставить жуков испаряться как по волшебству.

Теперь некоторые детали кода.

Я не понимаю назначение measurement_counter. Он используется только в тесте if (measurement_counter == 1). Логическое имя Здесь больше подходит first_measurement. Еще лучше, если вы можете объединить его с уникальной переменной state.

Переменная setup_finished не имеет никакого смысла. Он используется только в loop() для проверки выполнения setup(). Однако только loop() начинает работать после завершения setup(), поэтому тест бессмыслен.

Обработка OE_BAR_PIN выглядит неправильно: контакт становится LOW в setup() и никогда больше не становится HIGH. Казалось бы, разумнее инициализировать HIGH, держите его HIGH при переключении контактов выбора датчика и только поверните его LOW, как только датчик будет правильно выбран. Таким образом:

void setup() {
  ...
  digitalWrite(OE_BAR_PIN, HIGH);
  pinMode(OE_BAR_PIN, OUTPUT);
  ...
}

void select_sensor() {
  digitalWrite(OE_BAR_PIN, HIGH);
  digitalWrite(S2_PIN, ((sensor_coord & 4) == 4) ? HIGH : LOW );
  digitalWrite(S1_PIN, ((sensor_coord & 2) == 2) ? HIGH : LOW );
  digitalWrite(S0_PIN, ((sensor_coord & 1) == 1) ? HIGH : LOW );
  digitalWrite(OE_BAR_PIN, LOW);
}

Обратите внимание, что setup() переводит контакт на HIGH перед тем, как установить его как ВЫХОД: это предотвращает нежелательный короткий импульс LOW.

Обработка таймера 1 также ненадежна: он работает непрерывно. TIMER1_start() и TIMER1_stop() запускают и останавливают переполнение подсчет, а не сам таймер. Это означает, что измеренное количество тиков может отклоняться на целых ±65 535 тиков. Разумнее было бы действительно запускать и останавливать таймер по мере необходимости:

void TIMER1_init() {
  TCCR1A  = 0;
  TCCR1B  = 0;
  TIMSK1 |= (1 << TOIE1);
}

void TIMER1_start() {
  TCCR1B |= (0 << CS12) | (0 << CS11) | (1 << CS10);
}

void TIMER1_stop() {
  TCCR1B  = 0;
}

Возможно, вы захотите вызвать TIMER1_stop(), когда обнаружите тайм-аут.

,

О счетчике измерений. При первом измерении данные ложны. Вот почему мы делаем первое измерение с 10 образцами, просто чтобы избавиться от него. Во второй раз, когда мы проводим измерение, мы делаем это правильно с 500 образцами. Счетчик измерений — это переключатель между этими двумя параметрами. б) Я удалил setup_finished и все связанные с ним вещи. c) Что касается OE_BAR_PIN и обработки Timer1, я не совсем понял вашу точку зрения, но я проверил ваш код, и результаты аналогичны, так что я думаю, вы, вероятно, правы. г) Мой код все еще застрял в скобке, где я обнаружил тайм-аут, и я, @user1584421

Не знаю, почему. Он просто не может покинуть эту область, независимо от того, получает он импульсы или нет. Вы также сказали: «Возможно, вы захотите вызвать TIMER1_stop(), когда обнаружите тайм-аут». Как это отразится на моем коде для обнаружения тайм-аута?, @user1584421

Большое спасибо за вклад. Воспользовавшись вашим советом, мне удалось заставить скетч работать с одним набором измерений, а не использовать два набора для измерений, потому что первый всегда давал неверные результаты. Вероятно, это как-то связано с таймерами, которые ваша реализация полностью решила. Я не понимаю, что вы сделали с таймерами, но это сработало., @user1584421


1

В вашем коде вы используете переменную measurement_finished в качестве флага того, что новое измерение было завершено внутри ISR, чтобы его можно было обработать внутри loop() функция. Это очень полезно. Как я понял, разомкнутая цепь означает, что никакого измерения произойти не может, так как импульсы не создаются. Поэтому вам нужно проверить, сколько времени прошло с момента последнего измерения.

Кроме того, ядро Arduino настраивает Timer0 для общего хронометража. Например, его использует функция delay(), а также такие функции, как micros() и millis(), которые возвращают количество микро /миллисекунд, прошедших с момента запуска. Таким образом, если вы используете эти функции, вы на самом деле используете аппаратный таймер, но вам не нужно настраивать его самостоятельно. Это уже сделано ядром Arduino.

Поэтому я предлагаю принцип, аналогичный примеру BlinkWithoutDelay из Arduino IDE. Сначала вы определяете глобальную переменную временной метки и значение времени ожидания (здесь 1 с или 1000 мс):

unsigned long timestamp=0;
unsigned long measurement_timeout=1000;

Затем внутри вашей функции loop() (на самом деле вы можете сделать это именно там, где разместили соответствующий комментарий для проверки) вы проверяете разницу между текущим временем и отметкой времени:

if(millis() - timestamp > measurement_timeout){

Это срабатывает, когда метка времени последний раз обновлялась 1 с назад. Внутри этого измерения вы делаете все, что вам нужно, если происходит тайм-аут измерения (например, печать соответствующего сообщения в Serial). И теперь мы хотим начать новый тайм-аут, обновив переменную timestamp до текущего времени, заданного millis(). Мы могли бы сделать это внутри соответствующего ISR, но это создало бы проблему. ISR может сработать прямо между вычислениями нашего оператора if. Этого не может произойти для однобайтовых переменных (поскольку для 8-битного контроллера текущее 8-битное действие будет выполнено за один шаг), но unsigned long имеет 4 байта. Нам нужно будет отключить прерывания при доступе к нему, чтобы он не был поврежден.

Поэтому мы можем просто установить метку времени внутри

if (measurement_finished) {

оператор в функции цикла. Там мы просто делаем

timestamp = millis();

для обновления отметки времени. Пока оператор if выполняется достаточно часто (по крайней мере, 1 раз за время ожидания), он будет работать.

Итак, что происходит в измененном коде? Когда вы запускаете код, он может подумать, что было сделано нулевое измерение (если вашей функции setup() требуется больше времени ожидания), но как только приходит первое измерение, if (measurement_finished) выполнит и обновит метку времени. Теперь оператор millis() if отключен на время тайм-аута, каждое новое законченное измерение будет сбрасывать этот тайм-аут. Это как выключатель мертвеца. Тайм-аут сработает, когда некому (или не будет кода) снова сбросить тайм-аут.


Кстати: поскольку вы используете процедуры обработки прерываний, вы должны объявить все переменные, которые изменяются в ISR, как изменчивые следующим образом:

volatile int pulse_counter = 0;

Если вы этого не сделаете, компилятор может оптимизировать переменную для использования кэшированного значения вместо реального значения. Также подумайте о том, что я писал выше о переменных, изменяемых ISR в середине расчета. Вы должны быть осторожны, чтобы не работать в сложных для отладки ситуациях, если вы не защитите свои переменные в основном коде от изменений из ISR.

,

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

Эти персонажи (!!!!!!!!!!!), @user1584421

После дальнейшего тестирования ваше решение не работает, так как оно всегда остается в этом блоке. Вместо того, чтобы оставаться только тогда, когда прерывание не выполняется., @user1584421

Почему вы делаете interrupts_enabled = false; по тайм-ауту? Насколько я понимаю ваш код, это предотвратит измерение любых новых импульсов. Также вы устанавливаете для measurement_finished значение true, несмотря на то, что у вас нет готового измерения. Это сбрасывает отметку времени в следующем операторе if, но вы не включаете прерывания через эту переменную. Без фактического измерения импульсов ISR вы снова сталкиваетесь с тайм-аутом. Таким образом, прерывание повторно активируется только в том случае, если вы отправляете соответствующие последовательные данные. И я не знаю, почему у вас есть переменная ISR_unavailable. Не вижу, где вам это нужно, @chrisl

Также я согласен с Эдгаром в том, что переписывание вашего кода с помощью FSM с 1 переменной состояния приведет к более простому, чистому и намного более легкому для отладки коду., @chrisl

Я исправил interrupts_enabled = false; на тайм-ауте. Я установил для Measurement_finished значение true, чтобы ввести следующий блок кода (который необходим). Затем он сбрасывает временные метки, как вы сказали, но прерывания отключены, так как я исправил файл interrupts_enabled. ISR_unavailable гарантирует, что скобка кода не запускается, а вместо этого перемещается вперед. Тем не менее со всеми этими изменениями код застревает в скобке if(millis() - timestamp > Measurement_Timeout){, помечая все сопротивления как разомкнутые. Другими словами, выйти из этой скобки невозможно., @user1584421

Если все работает правильно, почему он вообще входит в этот блок кода?, @user1584421