Надо по импульсу защелкивать значение таймера - тогда будет точность на уровне выбранной скорости счёта таймера (input capture mode) …
Какая длительность импульсов предполагается ? Если частота 9 герц, как и 9 килогерц, то и 328p справится !!!
У меня начало подсчета импульсов реализовано в строке 16. а защелкивание реализовано в строке17. Так вот время с момента прихода импульса до момента вызова прерывания в строке 9 меняется случайным образом в диапазоне от 1 до 500 тактов процессора. Мне это надо победить.
А это нужно?
Насколько я понял, 300 тактов - это 2 мкс. Если возникает потребность, чтобы программное решение обеспечивало более высокую точность, то на 99.9% у Вас неверно поставлена задача.
Постарайтесь переформулировать ее так, чтобы подобная точность не требовалась. В конце концов, специально для этого есть такие вещи как таймеры, DMA и т.п.
А зачем Вам такая точность?
И, кстати, точность принято указывать относительную. Сколько это будет в процентах?
Отнюдь.
Этот форум создан довольно давно, просто пару лет назад он переехал на другой движок.
Это, кстати, пример сделанного Вами неверного вывода. Подозреваю, что и с требуемой Вами точностью дело обстоит примерно так же.
Вы продолжаете нагонять туману. Скорее всего потому что сами понимаете, что ваша ловля тактов - глупость. Вы не хотите раскрывать задачу, потому что тогда это станет очевидным.
- Если бы мне была нужна точность в 2 мкс я бы использовал функцию микрос - она обеспечивает лучшую точность. И кстати я согласен на таймер если скажете как посчитать текущее состояние регистра таймера. Потому что обычно обычно таймер используется для вызова прерывания через заданный интервал времени.
- Ну так речь о новом форуме. Поскольку когда переходил со старого форума на новый просил регистрацию ввести, а автоматом логин со старого не прошел.
- Ну и последнее, зачем мне это надо. Есть аналоговый прибор - он имеет двухполярный выходной ток с переменной частотой. Напряжение на измеряемой цепи зависит от величины измеряемого сопротивления и данное сопротивление нелинейно зависит от тока. Чем сопротивление измеряемой цепи меньше - тем длительность импульса больше. В итоге произведение входного напряжение на длительность импульса есть величина постоянная. Если входное сопротивление постоянно и не зависит от знака приложенного напряжения то скважность импульсов равна двум. если скважность изменилась - значит изменилось среднее сопротивление измеряемой цепи и его соотношение для различной полярности. Необходимо по длительности импульсов различной полярности определить асимметрию сопротивлений. Посчитать среднее значение, скорость изменения и знак изменения и асимметрию считывать с точностью 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;
}
}
}