• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Реально ли считать длительность импульса с шагом 0.1мкс ?

pvvx

Активный участник сообщества
Уход кварца-стекла ESP8266 от температуры в мкс уже был показан тут https://esp8266.ru/forum/threads/sinxronizacija-chasov.1951/page-12#post-28692
"Строим график расхождения с учетом данной погрешности хода часов:

Ага – видим открытие окна и смену температуры"

Фиксация в лигрылы (литр грам на рыло), т.е. сколько на одын градус не производилась. На том графике разница была не более 3-х градусов...
 

pvvx

Активный участник сообщества
за интервал 450 секунд время по системным часам и этому счетчику разошлось на 6.4 мс причем в одну сторону
без заменой случайной составляющей (наверное в эфире никого нет)
т е относительное отклонение 1.4*10-5
А у системных часов какое абсолютное отклонение?
И кто же врет? Счетчик с таймера с делителем и разной установкой счета на прерывания или счетчик тактируемый от того-же источника (кварц->PLL)?
Переизмеряйте в тактах CPU:
extern unsigned xthal_get_ccount(void); // { return rsr.ccount}
или
#define GET_CCOUNT(x) __asm__ __volatile__("rsr.ccount %0" : "=r"(x))
 

nikolz

Well-known member
А у системных часов какое абсолютное отклонение?
И кто же врет? Счетчик с таймера с делителем и разной установкой счета на прерывания или счетчик тактируемый от того-же источника (кварц->PLL)?
Переизмеряйте в тактах CPU:
extern unsigned xthal_get_ccount(void); // { return rsr.ccount}
или
#define GET_CCOUNT(x) __asm__ __volatile__("rsr.ccount %0" : "=r"(x))
объясняю еще раз вашу ошибку
--------------------------------
берем аппаратный таймер
он работает на частоте 80 Мггц
#define APB_CLK_FREQ 80*100000
используем SDK
аппаратный таймер
может работать с интервалами до 200 мс
если мы возьмем интервал 100 mc в таймер будет загружена константа 500000
рассчитывается в SDK
#define US_TO_RTC_TIMER_TICKS(t)
т е погрешность ПРОГРАММНОГО таймера составит 0.000001.
т е погрешность считается не на один разряд как Вы написали а на число загруженное в таймер
---------------------
так вот берем этот таймер
и в колбеке считаем прошедший интервал системным счетчиком
получаем погрешность 1 мкс
а вот ваш счетчик дает все те же 12 тысяч мкс. что составляет ошибку в 1000 раз больше чем возможная ошибка таймера
и в 1000 раз больше чем возможная ошибка из за неточности кварца
-------------------------
факт есть факт.
почему таk? я не знаю, а ВЫ?
 

nikolz

Well-known member
теперь немного разгребем лапшу которую pvvx навешал на данном форуме про суперточность его счетчика времени (далее назовем его супертаймер).
-------------------
Сначала рассуждение дилетанта.
Чтобы измерить время с погрешностью 0.1 мкс или как ранее рассказывал нам pvvx даже с погрешностью в 0.005 мкс(5 нс)
нам надо иметь инструмент у которого минимальное деление хотя бы равно этой величине
Но вот что прикольно
супертаймер это же не какой-то новый таймер
это тот же китайский таймер который pvvx тут выше обкакал со всех сторон
но к значению этого таймера просто прибавляется некоторая константа, которая изменяется с шагом не менее 100 мс.
и с какой же погрешностью мы может измерить эту константу?
правильно ,
все с той же самой -погрешностью китайского таймера.
А какая погрешность этого китайского таймера
Неужели 5 наносекунд? или может 100 нс?
Нет pvvx сказал что 3 мкс. А мы ему верим
------------------------------------------------
Полагаю что лапшу с ушей посетителей так усердно развешанную pvvx я немного стряхнул.
=======================
А теперь любознательным кулибиным я предлагаю провести тест.
берем таймер и в его колбеке делаем запись 8 значений времени в массив
для супертаймера и обычного программного китайского таймера
потом вычисляет разность этих значений в массиве и между собой
-----------------
вопрос любознательным что мы увидим в результате?
----------------
правильно
в массиве значения отличаются на мкс
а разность между значениями супертаймера и китайского таймера равна нулю
так как это один и тот же китайский таймер.
--------------------
жаль что чудо не получилось и не удалось за 100 копеек получить суперточные часы.
А так хочется чудо и халявы.
 

nikolz

Well-known member
отвечаю на вопрос автора темы:
НЕЗЯ!!!
-----------
для выяснения данного вопроса
предлагаю вам сделать простейший тест
включаем обработку сигнала с пина по прерывниям
на пине устанавливаем постоянный уровень например High
прерывание разрешаем по уровню High на данном пине
в колбеке делаем так
читаем статус регистра состояния пинов
считаем счетчик вызова колбека
если вызвали мюльон раз то считаем время на эти вызовы и печатаем результат
сбрасываем регистр состояния.
--------------------------
фактически это ваш возможный алгоритм работы
в итоге получаем что минимальное время вызова и выхода из колбека составляет 1.5 мкс.
что в 15 раз больше желаемого.
--------------------
конечно это не предел
можно на ассемблере все это делать и будет быстрее
Но Вы то это осилите сделать, вот в чем вопрос.
 

pvvx

Активный участник сообщества
теперь немного разгребем лапшу которую pvvx навешал на данном форуме про суперточность его счетчика времени (далее назовем его супертаймер).
-------------------
Сначала рассуждение дилетанта.
Чтобы измерить время с погрешностью 0.1 мкс или как ранее рассказывал нам pvvx даже с погрешностью в 0.005 мкс(5 нс)
нам надо иметь инструмент у которого минимальное деление хотя бы равно этой величине
Но вот что прикольно
супертаймер это же не какой-то новый таймер
это тот же китайский таймер который pvvx тут выше обкакал со всех сторон
но к значению этого таймера просто прибавляется некоторая константа, которая изменяется с шагом не менее 100 мс.
и с какой же погрешностью мы может измерить эту константу?
правильно ,
все с той же самой -погрешностью китайского таймера.
А какая погрешность этого китайского таймера
Неужели 5 наносекунд? или может 100 нс?
Нет pvvx сказал что 3 мкс. А мы ему верим
------------------------------------------------
Полагаю что лапшу с ушей посетителей так усердно развешанную pvvx я немного стряхнул.
=======================
А теперь любознательным кулибиным я предлагаю провести тест.
берем таймер и в его колбеке делаем запись 8 значений времени в массив
для супертаймера и обычного программного китайского таймера
потом вычисляет разность этих значений в массиве и между собой
-----------------
вопрос любознательным что мы увидим в результате?
----------------
правильно
в массиве значения отличаются на мкс
а разность между значениями супертаймера и китайского таймера равна нулю
так как это один и тот же китайский таймер.
--------------------
жаль что чудо не получилось и не удалось за 100 копеек получить суперточные часы.
А так хочется чудо и халявы.
:) :) Вы бы по началу изучили, как работает программный таймер :p
Потом бы почитали, что написано ТС и чем рекомендовано измерять :p
 

nikolz

Well-known member
путем прямого контроля пина можно уменьшить квант до 0.47 мкс.
 

nikolz

Well-known member
pvvx,
может расскажите как вы на ESP умудряетесь работать с квантами времени в 5 нс или хотя бы 100 нс
и какое время уходит чтобы просто прочитать это время не говоря о том чтобы что-то сделать с этими значениями
и все это в реальном времени
рекомендовать вам что-то читать не буду, вам не поможет.
 

pvvx

Активный участник сообщества
А по существу вашего супертаймера что-то есть сказать?
Какого моего супер таймера? Моих таймеров в ESP8266 нет и не было.
Про 64-х битный таймер в блоке WiFi чипа ESP8266 имеющего шаг в 1 мкс? Что про него сказать - он необходим в чипе для обеспечения работы WiFi по протоколам 802.11.
 

pvvx

Активный участник сообщества
pvvx,
может расскажите как вы на ESP умудряетесь работать с квантами времени в 5 нс или хотя бы 100 нс
и какое время уходит чтобы просто прочитать это время не говоря о том чтобы что-то сделать с этими значениями
и все это в реальном времени
рекомендовать вам что-то читать не буду, вам не поможет.
Где вы прочитали про кванты в 5 нс?
32-х битный счетчик тактов CPU имеет квант 1/80000000 или при x2 1/160000000. Но можно настроить PLL и на большие частоты, разогнав квант этого счетчика до 1/320000000.
Кратности к 5 нс не наблюдается.
 

pvvx

Активный участник сообщества
Вот тут есть некоторые протестированные частоты разгона CPU ESP8266 с помощью коэф. PLL cnlohr/nosdk8266
 

pvvx

Активный участник сообщества
Нет pvvx сказал что 3 мкс. А мы ему верим
Вы когда нибудь разбирали модели аппаратных таймеров?
Посмотрите делитель данного таймера. Он равен 256 и тактируется от PLL с выхода 80МГц (по установкам из инициализации в SDK).
И не выходит 3 мкс, а выходит 256/80 мкс :p
 

pvvx

Активный участник сообщества
рекомендовать вам что-то читать не буду, вам не поможет.
Гуру @nikolz - это вам ничего уже не поможет.
Вы даже примерчик теста правильно написать не можете. А нужен всего-то скопипастить и дописать несколько строк для тесту:
Код:
#include <Ticker.h>
#define GET_CCOUNT(x) __asm__ __volatile__("rsr.ccount %0" : "=r"(x))
extern "C" unsigned xthal_get_ccount(void);

extern "C" {
#include <c_types.h>
#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"
#define MAC_TIMER64BIT_COUNT_ADDR 0x3ff21048
uint64_t ICACHE_FLASH_ATTR get_mac_time(void)
{
  union {
    volatile uint32_t dw[2];
    uint64_t dd;
  }ux;
  ets_intr_lock();
  volatile uint32_t * ptr = (volatile uint32_t *)MAC_TIMER64BIT_COUNT_ADDR;
  ux.dw[1] = ptr[1];
  ux.dw[0] = ptr[0];
  if(ux.dw[1] != ptr[1]) {
    ux.dw[0] = ptr[0];
    ux.dw[1] = ptr[1];
  }
  ets_intr_unlock();
  return ux.dd;
}
};

Ticker flipper;

uint64_t mt1, mt2; // timestamp MAC_TIMER64BIT
uint32_t st1, st2; // timestamp
uint32_t ct1, ct2; // timestamp CPU clk
char buf[256];
int count = 0;
int old_count = 0;

void mytick(int x) {
  (void) x;
  ct1 = xthal_get_ccount();
  mt1 = get_mac_time();
  st1 = system_get_time();
  ++count;
}

void setup() {
  Serial.begin(115200);
  // every 1 sec, call mytick(0)
  flipper.attach_ms(1000, mytick, 0);
}

void loop() {
    if(old_count != count) {
      old_count = count;
      sprintf(buf, "CT: %u, ST: %u, MT: %" PRId64, ct1-ct2, st1-st2, mt1-mt2);
      mt2 = mt1;
      st2 = st1;
      ct2 = ct1;
      Serial.println(buf);
    }
}
и получить лог:
CT: 79999800, ST: 999995, MT: 999995
CT: 80000161, ST: 1000004, MT: 1000005
CT: 80000211, ST: 1000003, MT: 1000002
CT: 79999502, ST: 999994, MT: 999994
CT: 80000337, ST: 1000002, MT: 1000002
CT: 79999793, ST: 999999, MT: 1000000
CT: 80000189, ST: 1000000, MT: 1000000
CT: 79999917, ST: 1000002, MT: 1000001
CT: 79999899, ST: 999998, MT: 999999
CT: 79999978, ST: 999998, MT: 999997
CT: 80000341, ST: 1000006, MT: 1000007
CT: 80000005, ST: 1000001, MT: 1000000
CT: 79999970, ST: 999996, MT: 999996
CT: 80000029, ST: 1000004, MT: 1000004
CT: 79999658, ST: 999995, MT: 999995
CT: 79999881, ST: 999995, MT: 999995
CT: 80000227, ST: 1000007, MT: 1000007
CT: 80000079, ST: 1000001, MT: 1000001
CT: 79999891, ST: 999995, MT: 999995
CT: 80000156, ST: 1000005, MT: 1000005
CT: 79999698, ST: 999996, MT: 999997
CT: 80000086, ST: 999998, MT: 999997
CT: 80000036, ST: 1000004, MT: 1000004
CT: 80000156, ST: 1000002, MT: 1000002
CT: 80000056, ST: 999997, MT: 999997
CT: 79999924, ST: 1000003, MT: 1000003
CT: 80000079, ST: 1000001, MT: 1000001
CT: 80036891, ST: 1000457, MT: 1000457
CT: 79996995, ST: 999966, MT: 999966
CT: 79966184, ST: 999577, MT: 999578
CT: 79999534, ST: 999992, MT: 999992
CT: 80000393, ST: 1000008, MT: 1000007
CT: 79999869, ST: 999998, MT: 999998
CT: 79999907, ST: 999996, MT: 999997
CT: 79999949, ST: 1000002, MT: 1000001
CT: 80000051, ST: 1000001, MT: 1000001
CT: 80000232, ST: 1000000, MT: 1000001
CT: 79999643, ST: 999998, MT: 999997
CT: 80000010, ST: 999998, MT: 999998
CT: 80000038, ST: 1000000, MT: 1000001
CT: 80000304, ST: 1000007, MT: 1000006
CT: 79999793, ST: 999995, MT: 999995
CT: 79999915, ST: 999999, MT: 999999
CT: 79999904, ST: 1000001, MT: 1000001
CT: 80000072, ST: 1000001, MT: 1000001
CT: 79999928, ST: 999999, MT: 999999
...

Где:
СT - счет между прерываниями софт-таймера на 1 сек в тактах CPU (xthal_get_ccount())
ST - счет между прерываниями софт-таймера на 1 сек в тиках system_get_time() по 1 us
MT - счет между прерываниями софт-таймера на 1 сек в тиках get_mac_time() по 1 us
И различий указанных Гуру nicolz не наблюдается :p
Пора заканчивать объяснять что-то идиоту ...
 

pvvx

Активный участник сообщества
Если да, то как, я пока решений не нашел, только 1мкс через готовые функции.
Простейшее решение, если надо считать длительность именно путем опроса GPIO, а не битами SPI или I2S.
Запускает окно опроса GPIO на 2048 замеров с шагом 0.15004 мкс (при 160 МГц CPU).
Код:
#define GET_CCOUNT(x) __asm__ __volatile__("rsr.ccount %0" : "=r"(x))
#define TEST_CNT 2048 // размер буфера
uint32_t mio[TEST_CNT];
uint32_t kt;
float fkt;

void ICACHE_RAM_ATTR get_samples(uint32_t * ptr, int count) {
  volatile uint32_t * ptr_inport = (volatile uint32_t *)0x60000318;
  volatile uint32_t * vptr = (volatile uint32_t *)ptr;
  uint32_t ts,te;
  ets_intr_lock();
  GET_CCOUNT(ts);
  while(count--)
    *vptr++= *ptr_inport;
  GET_CCOUNT(te);
  ets_intr_unlock();
  kt = te - ts;
}

float get_impulse_count(uint32_t bit_mask) {
  int count = TEST_CNT;
  uint32_t * ptr = mio;
  int i = 0;
  if((*ptr & bit_mask) != 0) while(count--) {
    if((*ptr++ & bit_mask) != 0) {
      if(i)
        return i * fkt;
    }
    else
      i++;
  }
  return NAN;
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  get_samples(mio, TEST_CNT);
  fkt = kt/(160.0*TEST_CNT);
  printf("Sample Step = %.5f us\n", fkt);
  printf("Low pulse (-_-) duration in us on\n");
  printf("GPIO0\tGPIO1\tGPIO2\tGPIO4\tGPIO5\tGPIO6\tGPIO7\tGPIO8\tGPIO9\tGPIO10\tGPIO11\tGPIO12\n");
}

void loop() {
  get_samples(mio, TEST_CNT);
  printf("%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\n",
    get_impulse_count(1<<0),get_impulse_count(1<<2),get_impulse_count(1<<3),get_impulse_count(1<<4),
    get_impulse_count(1<<5),get_impulse_count(1<<6),get_impulse_count(1<<7),get_impulse_count(1<<8),
    get_impulse_count(1<<9),get_impulse_count(1<<10),get_impulse_count(1<<11),get_impulse_count(1<<12));
  delay(1000);
}
Набирает массив значения всех GPIO с шагом 0.15004 мкс, а затем находит и распечатывает первый найденный импульс (нулевого уровня) из окна замеров для каждого GPIO. И через паузу на повтор.
Проверить на точность не смог, т.к. не в городе... Подключил на измерение к GPIO0 выход COM порта с 112500 baud, передающий в цикле байты 0xAA. В этом потоке должны быть найдены импульсы 1/115200 и 2/115200 сек (8.68 и 17.361 us)...
Вышел такой лог:
Код:
Sample Step = 0.15004 us
Low pulse (-_-) duration in us on
GPIO0    GPIO1    GPIO2    GPIO4    GPIO5    GPIO6    GPIO7    GPIO8    GPIO9    GPIO10    GPIO11    GPIO12
nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
17.254    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
17.404    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
8.702    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
8.552    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
17.404    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
8.702    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
17.404    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
17.254    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan    nan
...
nan - это значит, что на данном GPIO нет импульса...
Всё ради прикола, т.е. чтобы объяснить принцип и низкую скорость шин и контроллера GPIO ESP8266. :)
 

pvvx

Активный участник сообщества
Канаву для кабеля откопал, кабель уложил, закопал... Теперь надо разобраться c Гуру nikolz :)
Беру Ваше значение как вы его называете: "принятый TSF от внешней AP"
*((volatile uint32 *)MAC_TIMER64BIT_COUNT_ADDR);
и беру значение системного времени функцией
system_get_time();
и тут не понятно что берет Гуру nikolz - значение аппаратный счетчика mac_timer (get_mac_time()) или TSF принятый от внешней AP с поправкой от mac_timer (get_tsf_station())? Соединена ли ESP к AP? Wifi вообще включен? Но похоже что нет. Значит расхождения не должно быть.
Далее это подтверждается:
за интервал 450 секунд время по системным часам и этому счетчику разошлось на 6.4 мс причем в одну сторону
без заменой случайной составляющей (наверное в эфире никого нет)
т е относительное отклонение 1.4*10-5
что ESP8266 никуда не соединена и "(наверное в эфире никого нет)". А это значит, что TSF не принимается и get_mac_time() и счет get_tsf_station() идет синхронно c какой-то константой начального смещения назначенной по старту или с константой от последнего приема beacon. Никаких расхождений...

И далее опять, что там у nikolz твориться он не говорит, но получает нормальный уход кривого кварца-стекла у ESP от кварца внешней AP, путем сравнения их хода времени через TSF (по разнице хода get_mac_time() и get_tsf_station()):
и вашей функции get_tsf_station()
зафиксируйте их в первый вызов колбека
после этого вычисляйте разницу всех последующих и зафиксированного значения
получается следующее:
10000000,10013399
20000000,20025182
30000000,30037821
Цифры намекают, что ESP8266 у nikolz соединена с какой-то AP и он наблюдает расхождение счета времени ESP и AP.
 

nikolz

Well-known member
Канаву для кабеля откопал, кабель уложил, закопал... Теперь надо разобраться c Гуру nikolz :)

и тут не понятно что берет Гуру nikolz - значение аппаратный счетчика mac_timer (get_mac_time()) или TSF принятый от внешней AP с поправкой от mac_timer (get_tsf_station())? Соединена ли ESP к AP? Wifi вообще включен? Но похоже что нет. Значит расхождения не должно быть.
Далее это подтверждается:

что ESP8266 никуда не соединена и "(наверное в эфире никого нет)". А это значит, что TSF не принимается и get_mac_time() и счет get_tsf_station() идет синхронно c какой-то константой начального смещения назначенной по старту или с константой от последнего приема beacon. Никаких расхождений...

И далее опять, что там у nikolz твориться он не говорит, но получает нормальный уход кривого кварца-стекла у ESP от кварца внешней AP, путем сравнения их хода времени через TSF (по разнице хода get_mac_time() и get_tsf_station()):

Цифры намекают, что ESP8266 у nikolz соединена с какой-то AP и он наблюдает расхождение счета времени ESP и AP.
написали много как всегда нахамили но на вас грех обижаться.
Но вы как всегда, вместо повторения теста один к одному и доказательства что я не прав нагородили еще кучу г..на в которой никто не будет разбираться.
Но вы так и не показали как измерить таймером импульс 0.1 мкс.
Слабо без хамства сделать?
-------------
помню как Вы злились когда вам приклеили ярлык гуру
мне нравится что и для вас я гуру. Хотя Вы и злитесь но делаете то что я сказал
-------------------------------------
Часто шаг вперед есть результат пинка под зад
 

nikolz

Well-known member
Вы не доказали что таймером можно измерить интервал 0.1 мкс
тем более Вашим супертаймером.
ну признайтесь, что немного приврали.
 

pvvx

Активный участник сообщества
Вы не доказали что таймером можно измерить интервал 0.1 мкс
тем более Вашим супертаймером.
ну признайтесь, что немного приврали.
Вы о чем?
А - как всегда. Что-то выдумали, наворотили ошибок и вместо извинения навязываете свою дурь другим?
По поводу запроса ТС перечитайте мои ответы ему и не путайте с вашими вымыслами:
В итого, без ОС, линейным опросом ножки в порту IO, на ASM, вы достигните максимального шага измерения не выше 0.04 мкс (1/26МГц).
:p
 
Сверху Снизу