ESP32 Различное время вызова прерывания

Надо по импульсу защелкивать значение таймера - тогда будет точность на уровне выбранной скорости счёта таймера (input capture mode) …
Какая длительность импульсов предполагается ? Если частота 9 герц, как и 9 килогерц, то и 328p справится !!!

У меня начало подсчета импульсов реализовано в строке 16. а защелкивание реализовано в строке17. Так вот время с момента прихода импульса до момента вызова прерывания в строке 9 меняется случайным образом в диапазоне от 1 до 500 тактов процессора. Мне это надо победить.

А это нужно?
Насколько я понял, 300 тактов - это 2 мкс. Если возникает потребность, чтобы программное решение обеспечивало более высокую точность, то на 99.9% у Вас неверно поставлена задача.
Постарайтесь переформулировать ее так, чтобы подобная точность не требовалась. В конце концов, специально для этого есть такие вещи как таймеры, DMA и т.п.

А зачем Вам такая точность?
И, кстати, точность принято указывать относительную. Сколько это будет в процентах?

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

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

  1. Если бы мне была нужна точность в 2 мкс я бы использовал функцию микрос - она обеспечивает лучшую точность. И кстати я согласен на таймер если скажете как посчитать текущее состояние регистра таймера. Потому что обычно обычно таймер используется для вызова прерывания через заданный интервал времени.
  2. Ну так речь о новом форуме. Поскольку когда переходил со старого форума на новый просил регистрацию ввести, а автоматом логин со старого не прошел.
  3. Ну и последнее, зачем мне это надо. Есть аналоговый прибор - он имеет двухполярный выходной ток с переменной частотой. Напряжение на измеряемой цепи зависит от величины измеряемого сопротивления и данное сопротивление нелинейно зависит от тока. Чем сопротивление измеряемой цепи меньше - тем длительность импульса больше. В итоге произведение входного напряжение на длительность импульса есть величина постоянная. Если входное сопротивление постоянно и не зависит от знака приложенного напряжения то скважность импульсов равна двум. если скважность изменилась - значит изменилось среднее сопротивление измеряемой цепи и его соотношение для различной полярности. Необходимо по длительности импульсов различной полярности определить асимметрию сопротивлений. Посчитать среднее значение, скорость изменения и знак изменения и асимметрию считывать с точностью 0.01%. Ну и в итоге выводить среднее значение сопротивления, его асимметрию. минимальное значение сопротивления и максимальную асимметрию на индикатор. Ну и соответственно автоматически корректировать ноль программными методами, поскольку аналоговая часть меняет частоту в зависимости от температуры и надо это корректировать. Частота изменяется в диапазоне от 0.1 Гц до 300 Гц. Точность измерения асимметрии на частоте 300 Гц должна быть 0.01% .Да значение генератора измеряемого тока фиксированное и составляет 10 мкА. На Arduino Nano Это уже делал, там нехватало скорости выполнения математических операций.

Если при этом частота сигнала 9гц, как у вас в тесте - то точность 0.01% это 5 мкс. То есть примерно 200 тактов контроллера на частоте 40мгц

Счётчик таймера в любом МК - это регистр, который без проблем читается в любой момент.

Диапазон частот от 0.1 до 300 Гц. Берите для рачета 300 Гц.

Для особо одарённых - Точность достигается АППАРАТНЫМ захватом !!!

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

А где у вас аппаратный захват то ???

Это тот захват, про который Вы пишите.

А можно узнать, как до вашего проекта люди пользовались этим прибором? Каким образом в аналоговом приборе считали эти наносекундные интервалы? Или про точность в одну сотую вы сейчас просто выдумали, чтобы от вас отстали, а на практике прибор даёт данные плюс- минус 20 процентов?

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

А ты уверен что это не скачки длительности импульсов? Я не верю что можно получить наносекундные фронты импульсов на какой энергетике. Что бы их получить надо иметь ватты на выходе генератора.

Настраиваете таймер на нужный режим и скорость.
Ждёте события input capture и засекаете состояние счётчика таймера
Ждёте следующего события input capture ну или десять таких событий попутно в обработчике переполнений таймера подсчитывая сколько полных оборотов он сделал
Вычисляете длительность …

Что мешает сделать сейчас так же?

Можно и так. Только наш любимый таймер со стандартным примером не работает.

void setup() {
pinMode(LED, OUTPUT)
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &onTimer, true);
timerAlarmWrite(My_timer, 1000000, true);
timerAlarmEnable(My_timer);
}
void loop() {
}

А так бы без вопросов.

А это вообще аппаратный таймер то? Выглядит как софтовпая обёртка над миллис- микрос

Дурдом

Это настройка таймера.

У меня работает следующий таймер из примера. Но я понятия не имею чего в этом примере написано.

/*
 Repeat timer example

 This example shows how to use hardware timer in ESP32. The timer calls onTimer
 function every second. The timer can be stopped with button attached to PIN 0 (IO0).

 */

// Stop button is attached to PIN 0 (IO0)
#define BTN_STOP_ALARM 0

hw_timer_t *timer = NULL;
volatile SemaphoreHandle_t timerSemaphore;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

volatile uint32_t isrCounter = 0;
volatile uint32_t lastIsrAt = 0;

void ARDUINO_ISR_ATTR onTimer() {
  // Increment the counter and set the time of ISR
  portENTER_CRITICAL_ISR(&timerMux);
  isrCounter = isrCounter + 1;
  lastIsrAt = micros();
  portEXIT_CRITICAL_ISR(&timerMux);
  // Give a semaphore that we can check in the loop
  xSemaphoreGiveFromISR(timerSemaphore, NULL);
  // It is safe to use digitalRead/Write here if you want to toggle an output
}

void setup() {
  Serial.begin(115200);

  // Set BTN_STOP_ALARM to input mode
  pinMode(BTN_STOP_ALARM, INPUT);

  // Create semaphore to inform us when the timer has fired
  timerSemaphore = xSemaphoreCreateBinary();

  // Set timer frequency to 1Mhz
  timer = timerBegin(1000000);

  // Attach onTimer function to our timer.
  timerAttachInterrupt(timer, &onTimer);

  // Set alarm to call onTimer function every second (value in microseconds).
  // Repeat the alarm (third parameter) with unlimited count = 0 (fourth parameter).
  timerAlarm(timer,1000000, true, 0);
}

void loop() {
  // If Timer has fired
  if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE) {
    uint32_t isrCount = 0, isrTime = 0;
    // Read the interrupt count and time
    portENTER_CRITICAL(&timerMux);
    isrCount = isrCounter;
    isrTime = lastIsrAt;
    portEXIT_CRITICAL(&timerMux);
    // Print it
    Serial.print("onTimer no. ");Serial.print(isrCount);Serial.print(" at ");Serial.print(isrTime); Serial.println(" mks");
  }
  // If button is pressed
  if (digitalRead(BTN_STOP_ALARM) == LOW) {
    // If timer is still running
    if (timer) {
      // Stop and free timer
      timerEnd(timer);
      timer = NULL;
    }
  }
}