Тактовый генератор с разрешением 1 мкс и меньше

petrovich
Offline
Зарегистрирован: 06.07.2016

Здравствуйте, уважаемые форумчане. Подскажите, пожалуйста, каким образом можно сделать тактовый генератор с разрешением 1 мкс и меньше? Как мне видится, нужно использовать внешний генератор 64МГц, т.к. судя по тому, что у генератора 16 МГц, встроенного в ардуино, разрешение 4 мкс. Как его подключить к ардуино? В даташите ATmega328 нашел такую схему, это то, что мне нужно?

Соответственно, для разрешения меньше 1 мкс нужно использовать генератор больше 64МГц. Скажите, пожалуйста, мои рассуждения верны или нет?

a5021
Offline
Зарегистрирован: 07.07.2013

Я не очень понимаю, что такое разрешение 1мкс, но для периода 1мкс, частота такого генератора будет 1мгц. Частота стандартного ардуины = 16мгц, т.е. период будет 1/16 = 62.5 наносекунды.

petrovich
Offline
Зарегистрирован: 06.07.2016

Кажется я намудрил немного:) Да, мне нужен период 1 мкс и меньше, спасибо что прояснили.

Arduino_New
Offline
Зарегистрирован: 02.07.2016

думаю, так себе нихрена себе, ему 16Мгц не хватает для 1мкс

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

petrovich пишет:

Как мне видится, нужно использовать внешний генератор 64МГц,

Надеюсь Вы в курсе, что на такой частоте придётся охлаждать жидким азотом?

https://geektimes.ru/post/258086/

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

petrovich пишет:

у генератора 16 МГц, встроенного в ардуино, разрешение 4 мкс.

Не знаю, что Вы понимаете под "разрешением", но при частоте 16МГц длительность такта равна 1/16 (0,0625) микросекунды. Где Вы взяли 4 микросекунды могу только догадываться - наверное из точности millis. Если так, то не забудьте, что там делитель частоты 64 используется.

petrovich
Offline
Зарегистрирован: 06.07.2016

ЕвгенийП пишет:

petrovich пишет:

у генератора 16 МГц, встроенного в ардуино, разрешение 4 мкс.

Не знаю, что Вы понимаете под "разрешением", но при частоте 16МГц длительность такта равна 1/16 (0,0625) микросекунды. Где Вы взяли 4 микросекунды могу только догадываться - наверное из точности millis. Если так, то не забудьте, что там делитель частоты 64 используется.

Точно, я совсем запутался, я хотел спросить про millis, как добиться точности этой функции в 1 мкс и меньше?

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

petrovich пишет:

Точно, я совсем запутался, я хотел спросить про millis, как добиться точности этой функции в 1 мкс и меньше?

Переписать её под себя. Не столько саму миллис, сколько оснастку вокруг неё. Она "живёт" в файле wiring.c, если мне память не изменяет.

Если же Вы предпочитаете пользоваться той, что поставляется с IDE, то никак.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

В принципе можно ничего не переписывать, а использовать счётный регистр таймера1 как замену микрос, без прерываний разумеется. Тем более в отличие от миллисов и микросов его можно будет обнулять :)  С единичным прескалером один шаг такого счёта будет 0,0625µS, максимум сможет измерить до 4mS   A c прескалером==8  шаг станет 0,5µS  и считать сможет до  32mS. Судя по всему именно этого хотел ТС, хотя скорость исполнения команд ставит под сомнение необходимость такого мелкого разрешения :)

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

может ему STM будет проще использовать?

petrovich
Offline
Зарегистрирован: 06.07.2016

Спасибо за ответы, сейчас пытаюсь разобраться. Вообще мне необходимо посчитать время между импульсами с энкодера, чтобы затем измерить скорость. Теоретически подсчитано, что для того, чтобы можно было измерять скорость в 1 м/с с погрешностью 1% нужно  подсчитывать время с точностью до 1 мкс, для этого предполагается использовать функцию micros(), но у неё разрешение 4 мкс. Значит выходит, что нужно либо писать свою собственную функцию, либо, что я еще не совсем понял, использовать регистр таймера1, правильно?

Logik
Offline
Зарегистрирован: 05.08.2014

Вот так. Из-за кривой идеи надо всю систему переписать. А померить период не для одного импульса а для 4-х и поделить на 4 для достижения той же точности не проще?

a5021
Offline
Зарегистрирован: 07.07.2013

А если пользовать таймер в режиме захвата, то разрешение будет вплоть до упоминавшихся 62.5 наносекунд.

Logik
Offline
Зарегистрирован: 05.08.2014

Так тут ещё вопрос, а нужна ли там точность. Кажется я знаю следующий поворот сюжета, окажется, что ТС хочет интегрировать скорость для получения координаты ))) 

a5021
Offline
Зарегистрирован: 07.07.2013

Великовата скорость. Мож просто обороты меряет?

petrovich
Offline
Зарегистрирован: 06.07.2016

Logik пишет:

Так тут ещё вопрос, а нужна ли там точность. Кажется я знаю следующий поворот сюжета, окажется, что ТС хочет интегрировать скорость для получения координаты ))) 

Нет, мне нужно просто точно измерять скорость, так что бы до 1.5 м/с погрешность измерения была меньше процента, при чем как на малых (около 0.1 м/с), так и около 1.5 м/с.

Logik
Offline
Зарегистрирован: 05.08.2014

А зачем такая точность, на авто спидометр врет больше и ничё катаемся?

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

1% от 1.5м/сек = 0.01 * 1500 = 15мм/сек. .. точность времени определения при такой погрешности как раз и составит 0.01 .. СЕКУНДЫ, т.е. 10 миллисекунд.

При точности измерения интервала в 1 МИКРОСЕКУНДУ на скоростях 1.5м/с можно ожидать точность в 0.000001 или 0.0001 ПРОЦЕНТА .. Вы нигде не ошиблись? :)

P.S. Или спрошу иначе: с какой точностью измеряет ошибку скорости (расстояния или угла поворота) Ваш энкодер?

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

Logik пишет:

А зачем такая точность ...?

«Недостатки математического образования с наибольшей отчётливостью проявляются в чрезмерной точности численных расчётов» (Карл Фридрих Гаусс)

petrovich
Offline
Зарегистрирован: 06.07.2016

Arhat109-2 пишет:

1% от 1.5м/сек = 0.01 * 1500 = 15мм/сек. .. точность времени определения при такой погрешности как раз и составит 0.01 .. СЕКУНДЫ, т.е. 10 миллисекунд.

При точности измерения интервала в 1 МИКРОСЕКУНДУ на скоростях 1.5м/с можно ожидать точность в 0.000001 или 0.0001 ПРОЦЕНТА .. Вы нигде не ошиблись? :)

P.S. Или спрошу иначе: с какой точностью измеряет ошибку скорости (расстояния или угла поворота) Ваш энкодер?

Длина окружности = 15.7 см, Z = 600, т.е. длина одного деления = 0.0002616 м.

По поводу погрешности в 10 миллисекунд: я только что протестировал программу с помощью генератора импульсов, и получается что на частоте в 750 Гц (что примерно 196 мм/с) разбежка в скорости, измеренной с помощью указанного выше расстояния / разницу времени, измеренного с помощью micros() составляет около 100 мм/с. И это только на такой малой скорости, дальше погрешность будет еще больше.

Что касается измерения 4 импульсов и деления на 4, то происходит примерно то же самое, только погрешность меньше. Напрашивается решение сделать выборку импульсов еще больше, т.е. тогда на большой скорости всё будет нормально, но на малой будет обратная ситуация, или я ошибаюсь?

Я думаю нет смысла вдаваться в подробности, для чего нужен этот прибор, просто такое ТЗ:) Нужно каким-то образом считать импульсы с энкодера так, чтобы и на малых, и на больших скоростях ошибка была процент и меньше.

Вот код программы для 4/4

 


int pin8 = 8;
int k = 0;


int  pinState;
int  Sec_pinState;
unsigned long timeBefore;
unsigned long timeAfter;
double difference;
float L = 261666.6;
float U;


void setup() {

  Serial.begin(9600);

  pinMode(pin8, INPUT);

 
}

void loop() {

  //подсчет скорости
  pinState = digitalRead(pin8);

  if (pinState !=  Sec_pinState)
  {
    timeBefore = micros();
    /////////////////////////////////////   1   ///////////////////////////////////
    
    Sec_pinState = pinState;          //0 -> 1
    
    while (pinState == Sec_pinState) // 0 ... T/2     
    {
      pinState = digitalRead(pin8);
    }
    Sec_pinState = pinState;        // T/2    1 -> 0

   
    while (pinState == Sec_pinState) // T/2 ... T
    {
      pinState = digitalRead(pin8);
    }

        /////////////////////////////////////   2   ///////////////////////////////////
    
    Sec_pinState = pinState;          //0 -> 1
    
    while (pinState == Sec_pinState) // 0 ... T/2     
    {
      pinState = digitalRead(pin8);
    }


    Sec_pinState = pinState;        // T/2
   
    while (pinState == Sec_pinState) // T/2 ... T
    {
      pinState = digitalRead(pin8);
    }


        ///////////////////////////////////////////////////////////   3   ///////////////////////////////////
    
    Sec_pinState = pinState;          //0 -> 1
    
    while (pinState == Sec_pinState) // 0 ... T/2     
    {
      pinState = digitalRead(pin8);
    }


    Sec_pinState = pinState;        // T/2
   
    while (pinState == Sec_pinState) // T/2 ... T
    {
      pinState = digitalRead(pin8);
    }

        ///////////////////////////////////////////////////////////   4   ///////////////////////////////////
    
    Sec_pinState = pinState;          //0 -> 1
    
    while (pinState == Sec_pinState) // 0 ... T/2     
    {
      pinState = digitalRead(pin8);
    }


    Sec_pinState = pinState;        // T/2
   
    while (pinState == Sec_pinState) // T/2 ... T
    {
      pinState = digitalRead(pin8);
    }

    //----------------------------------------------------------------------------
    timeAfter = micros();         // T
    difference = (timeAfter - timeBefore)/4;
    //Serial.print("  difference: ");
    //Serial.println(difference);
    
    U = L / difference;
    Sec_pinState = pinState;

    Serial.print("  speed: ");
    Serial.println(U);
  }


}

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

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

Logik
Offline
Зарегистрирован: 05.08.2014

petrovich пишет:

Что касается измерения 4 импульсов и деления на 4, то происходит примерно то же самое, только погрешность меньше. Напрашивается решение сделать выборку импульсов еще больше, т.е. тогда на большой скорости всё будет нормально, но на малой будет обратная ситуация, или я ошибаюсь?
 

Про большую выборку верно.  

На малой погрешность не выростит. Просто длительность измерения может стать слишком большой. 

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

petrovich
Offline
Зарегистрирован: 06.07.2016

dimax, спасибо, буду разбираться.

Logik пишет:

Про большую выборку верно.  

На малой погрешность не выростит. Просто длительность измерения может стать слишком большой. 

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

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

petrovich
Offline
Зарегистрирован: 06.07.2016

Dimax, не подскажите в какую сторону копать? Я просмотрел наверное с десяток тем и как-то всё мутновато.. Вы говорили нужно без прерываний, а они везде. Еще вот нашел библиотеку Timer One, она мне поможет? Просветите:)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013
petrovich
Offline
Зарегистрирован: 06.07.2016

Dimax, вы просто мегамозг, спасибо вам большое:)