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

С чего начать создание спортивного секундомера (1 сенсор запускает секундомер, 2 останавливает)

pvvx

Активный участник сообщества
Начните с реализации секундомера на ESP
Прикручиваете кнопку к ESP
По нажатию кнопки первый раз запоминаете системное время
Какая задержка от фронта внешнего сигнала до считывания "системное время"?
при нажатии второй раз вычитаете из системного времени первое значение.
А тут какая задержка от фронта внешнего сигнала до считывания "системного времени"?

Результат пересылаете на комп
Как, когда и каким интерфейсом переслать?
Сто пятьсот финишировавших устройств одновременно подключатся к одной AP и скопом передадут по UDP? :)
рассуждение о мгновенной стабильности частоты кварца не является ответом на конкретный вопрос о погрешности измерения интервала в 1000 секунд.
Стабильность кварца на стационарной AP гораздо больше, чем "системное время" от стекляшки у ESP. Минимум на десятичный порядок и перепаивать в самом модуле WiFi ничего не требуется.
Вы об этом хотели сказать, но стесняетесь?
Но и главные вопросы:
1 Где в ваших предложениях единая синхронная система времени от которой можно оттолкнуться и привязаться любому устройству?
2 Куда там у вас прикручивать супер стабильный абсолютный источник времени?
3 Вам сложно загрузить Arduino и скинутые "либы" для собственной проверки?
Тогда так и пишите - помогите и обучите установке Arduino для ESP8266.
 

pvvx

Активный участник сообщества
С какой погрешностью можно измерить интервал времени в 1000 секунд на AP?
C точностью к +-50 nc если к стационарной AP на OpenWRT прикрутить PTP (IEEE 1588)
Но зачем там WiFi AP, если функция всего-то = измерение интервала?
Если кому требуется точность (джиттер) к 20 ns, то можно прикрутить многое из специализированного хлама с GPS.
А мне не нужна точность более времени прохождения радиоволны в радиусе работы WiFi 802.11n/a AP. Ну не хочу я вычислять на это расстояние поправку. Просто лень, но возможность есть, особенно при при много-антенном роутере... :p
Аналогично не хочу и лень разрабатывать новый аналог TCP и 802.11n/a из недо-кусков ESP-NOW и UDP.
Проще передавать дровам WiFi на linux дополнительную переменную со своим супер пупер timestamp для вставки в маяк (beacon), так как стандарт это уже предусмотрел на заре появления WiFi...
Напомню вам "скорость света" :) :)
 

pvvx

Активный участник сообщества
судя по продаваемому оборудованию погрешность в 0.1 0.01 секунды вполне хватает.
Дык купите это оборудование и не мешайтесь сдеся :p
Так зачем что-то городить если такую погрешность можно достигнуть за 2-5 долларов на ардуине без особых заморочек
А мы хотим что-то новое и лучшее, и уже имеем точность измерения периода в +-1.7 см от скорости распространения звука на 100 рублевом модуле c одним вызовом готовой функции в прерывании по пину. :p
 

pvvx

Активный участник сообщества
Бедные спортсмены - тот кто дальше от стартового пистолета, тот гарантированно проиграет... :) :)
Импульс старта к нему придет с громадной задержкой во много-много единиц нашего счетчика !!!
 

pvvx

Активный участник сообщества
Вчера я презагрузил роутер – “был старт спортсменов ESP8266 с TSF”.
Вписал в пример на Arduino SSID и пароль сети, нажал капу upload_2019-5-20_16-17-3.png и ...
В порт 12345 TCP от “бегущей” ESP8266 приходят посылки, что она в пути уже 67482553918 мкс:

Receive from 192.168.1.225 : 50404: 67352451289
Receive from 192.168.1.225 : 52285: 67365463277
Receive from 192.168.1.225 : 55954: 67378471779
Receive from 192.168.1.225 : 50157: 67391490348
Receive from 192.168.1.225 : 57272: 67404497941
Receive from 192.168.1.225 : 50414: 67417508051
Receive from 192.168.1.225 : 49701: 67430518140
Receive from 192.168.1.225 : 62911: 67443526721
Receive from 192.168.1.225 : 52881: 67456536491
Receive from 192.168.1.225 : 50605: 67469546451
Receive from 192.168.1.225 : 50022: 67482553918


Роутер говорит, что спортсмены в пути уже 18ч 44м:

upload_2019-5-20_16-15-17.png

А где обещанное nicolz отклонение?
 

pvvx

Активный участник сообщества
Извиняюсь что на тут, где я ныне, нет генератора со стабильностью в 6 дес.знаков… но есть USB осел и старенький AG4151 DDS генератор. У него в спеках для Square: Jitter (rms) 300ps + 100ppm of period (typical). Будем считать что 5 дес.знаков.
Ставим на нем меандр 100 mHz (10 сек) и на пин 13 ESP12E Devkit со скетчем:
Код:
#include <ESP8266WiFi.h>
#include <WiFiTSF.h>
#include <inttypes.h>

#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK  "your-password"
#endif

const char* ssid     = STASSID;
const char* password = STAPSK;

const char* host = "192.168.1.6";
const uint16_t port = 12345;

const byte interruptPin = 13;
int numberOfInterrupts = 0;

volatile byte writecount = 0;
byte readcount = 0;
#define MAX_COUNT_TSF 32
uint64_t pin_tsf[MAX_COUNT_TSF];

void ICACHE_RAM_ATTR handleInterrupt() {
  if (++writecount >= MAX_COUNT_TSF) writecount = 0;
  pin_tsf[writecount] = get_tsf_station();
}

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

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  /* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
     would try to act as both a client and an access-point and could cause
     network-issues with your other WiFi-devices on your WiFi-network. */
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
}

char buf[128];

void loop() {
  if ( writecount != readcount ) {
    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    if (!client.connect(host, port)) {
      Serial.println("connection failed");
      delay(1000);
      return;
    }
    // This will send a string to the server
    if (client.connected()) {
      while ( writecount != readcount ) {
        uint64_t old_tsf = pin_tsf[readcount];
        if (++readcount >= MAX_COUNT_TSF) readcount = 0;
        uint64_t new_tsf = pin_tsf[readcount];
        sprintf(buf, "%" PRId64 ";%" PRId64, new_tsf, new_tsf - old_tsf);
        client.println(buf);
        Serial.println(buf);
      }
    }
    // Close the connection
    client.stop();
  }
  delay(555); // execute once every 555 ms, don't flood remote service
}
Уходим гулять… Приходим и на ноуте получаем:

Connecting to xxxxx
.......
WiFi connected
IP address:
192.168.1.225
// первый импульс от страта
74288313045;74288313045
// время срабатывания TSF AP в us; период в us
74298312561;9999516
74308312833;10000272
74318312814;9999981
74328312752;9999938
74338312347;9999595
74348312604;10000257
74358312554;9999950
74368312450;9999896
… и далее
Копируем в tsf.csv и травим на него Exel для наглядности:
upload_2019-5-20_18-49-1.png
Видим, что необходимая точность в 5-ть дес. знаков полностью достигнута несмотря на примитивность алго и дикие лаги-джиттеры в Arduino.

Попробуем уточнить расхождение времени на 1000 сек замере. Для этого возьмем разницу меток TSF через 100.
upload_2019-5-20_18-50-34.png
Видим, что различие частоты генератора от частоты AP находится в 7-м дес. знаке... На 1000 сек менее +- 0.5 ms.
Т.е., если мы введем поправку (0.9999935) в генератор или к TSF в AP, то получим стабильность при измерении периодов в 1000 сек при некой известной температуре к 1 ppm :p
(безусловно нужен более точный источник для калибровки)
И это без каких-либо фильтров, ФАПЧ, и прочих доп. протоколов и алгоритмов!
@nicolz полностью в попе :p
 

pvvx

Активный участник сообщества
Пока был занят другими делами накопилось ещё замерчиков…
Теперь для лучшего понимания происходящих процессов приведем всё к единому знаменателю. Т.е. поглядим возникающие дисперсии, джиттер и лаги в Arduino:
upload_2019-5-20_20-8-21.png
Т.е. при использовании Arduino имеем лаги и джиттеры для любого замера в +- 400 мкс, а при чистом СИ и правленых либах SDK + минимальная коррекция, выходим к показателю +-5 us. Привет Arduino-писателям :p
 

Сергей_Ф

Moderator
Команда форума
@pvvx да ладно вам. Для региональных соревнований точность 800 мкс для скалолазанья - выше крыши, имхо. Даже для лёгкой атлетики сойдёт. :)
Отличная работа, Виктор!
 

pvvx

Активный участник сообщества
если AP будет реализован на одном из ESP то ошибки измерения времени составят мс а не мкс.
Попробуем это узнать.
Сравним метод измерения TSF и через функцию millis().
В процедуру прерывания по спаду импульса добавим получение времени функций millis().
Код:
#include <ESP8266WiFi.h>
#include <WiFiTSF.h>
#include <inttypes.h>

#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK  "your-password"
#endif

const char* ssid     = STASSID;
const char* password = STAPSK;

const char* host = "192.168.1.6";
const uint16_t port = 12345;

const byte interruptPin = 13;
int numberOfInterrupts = 0;

volatile byte writecount = 0;
byte readcount = 0;
#define MAX_COUNT_TSF 64
uint64_t pin_tsf[MAX_COUNT_TSF];
uint32_t pin_ms[MAX_COUNT_TSF];

void ICACHE_RAM_ATTR handleInterrupt() {
  if (++writecount >= MAX_COUNT_TSF) writecount = 0;
  pin_tsf[writecount] = get_tsf_station();
  pin_ms[writecount] = millis();
}

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

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  /* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
     would try to act as both a client and an access-point and could cause
     network-issues with your other WiFi-devices on your WiFi-network. */
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
}

char buf[128];

void loop() {
  if ( writecount != readcount ) {
    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    if (!client.connect(host, port)) {
      Serial.println("connection failed");
      delay(1000);
      return;
    }
    // This will send a string to the server
    if (client.connected()) {
      while ( writecount != readcount ) {
        uint64_t old_tsf = pin_tsf[readcount];
        uint32_t old_ms = pin_ms[readcount];
        if (++readcount >= MAX_COUNT_TSF) readcount = 0;
        uint64_t new_tsf = pin_tsf[readcount];
        uint32_t new_ms = pin_ms[readcount];
        sprintf(buf, "%" PRIu64 ";%" PRIu64 ";%" PRIu32 ";%" PRIu32, new_tsf, new_tsf - old_tsf, new_ms, new_ms - old_ms);
        client.println(buf);
        Serial.println(buf);
      }
    }
    // Close the connection
    client.stop();
  }
  delay(555); // execute once every 555 ms, don't flood remote service
}

* Счетчик синхронизации с TSF и таймера millis() тактируются от единого стекла-кварца ESP8266.
* Счетчик синхронизации TSF на ESP8266 обновляется каждые 0.1 сек от AP. Т.е. уход стекла ESP8266 подправляется каждые 0.1 сек на значение счета таймера в AP, а он тактируется своим кварцем.
* На ногу пигна 13 идет меандр в 10 сек с дешевого и старого DDS генератора AG4151.
* Обстановка в сети роутера ужасна. К его WiFi 2.4 и 5 ГГц подключено к десятку устройств + десяток 1 ГБ сетевых, включая телевизор у детей...

В итоге имеем 3 таймера, каждый из них тактируется от своего кварца.
Получаем лог:
Connecting to xxxx
........
WiFi connected
IP address:
192.168.1.225
// TSF время старта; ; millis() время старта;
85085610010;85085610010;10078;10078
// TSF время события; период в us; millis() время события; период в ms
85095609950;9999940;20078;10000
85105609870;9999920;30078;10000
85115609453;9999583;40078;10000
85125609764;10000311;50078;10000
85135609331;9999567;60078;10000
85145609342;10000011;70078;10000
85155609568;10000226;80078;10000
85165609493;9999925;90079;10001
85175609062;9999569;100079;10000
85185609382;10000320;110079;10000
85195609299;9999917;120079;10000
…. и далее
за время накопления два раза ESP8266 не смогла создать коннект с компом...

В итоге имеем 500 замеров 10 сек меандра на GPIO:
upload_2019-5-20_23-19-6.png

Т.к. пока нет точного абсолютного таймера, тогда, если принять что генератор имеет уход равный среднему значению TSF и millis(), то расхождение таймера miilis() и кварца AP за период в 5000 сек составит:
upload_2019-5-20_23-19-21.png
Но это если взять среднее... AP наверняка более точная.
И итог: работа с TSF имеет большую точность и полностью заменяет локальный millis(), и самое главное имеет полную синхронизацию на всех станциях.
 

pvvx

Активный участник сообщества
Для региональных соревнований точность 800 мкс для скалолазанья - выше крыши, имхо. Даже для лёгкой атлетики сойдёт. :)
Если требуется измерять больший период чем 100000 сек с 1 ppm, то на любом роутере с OpenWRT стоит "ntpd — он корректирует время постоянно и «плавно» (без резких рывков, «размазывая» замедление/ускорение времени)". Коррекция хода внутреннего счетчика осуществляется прибавкой до нескольких nc через определенный вычисляемый период или ещё сложнее - в Linux этим управляет громадная структура с толпой данных... Этот счетчик и участвует в формировании TSF (как показали исходники). Т.е. если роутер имеет доступ к NTP серверам, то делать ничего не надо, в отличии от предложений nicolz.
 

pvvx

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

nikolz

Well-known member
pvvx,
В целом я доволен Вашими результатами.
Вы хорошо справились с поставленной задачей и провели удовлетворительные исследования данного вопроса.
и результат уже более правдоподобен - перешли от единиц мкс к единицам ms и получили правдоподобный результат.
================
Однако, Вы спорите сам с собой, хотя и постоянно обращаясь к кому-то третьему, называете всуе мой ник.
----------------
Если внимательно посмотрите на постановку мною данной задачи,
то я рассматривал соревнование в чистом поле или в горах, где нет инфраструктуры Wi-fi,
так как автор изначально не уточнял условия проведения соревнований,
В эксперименте я тоже рассматривал работу исключительно ESP без роутеров и уж тем более без переделанных OpenWRT.
----------------------
Причем я изначально сказал, что есть два варианта.
Один - это ваш - на основе имеющейся инфраструктуры WiFi,реализация которого требует активации Вашей деятельности.
второй -это мой - на основе лишь двух либо трех ESP, реализация которого может быть исполнена любым любителем.
-----------------
Вариант с браслетом - вообще не требует никакой синхронизации.
Он применяется при марафоне с забегом сотен и тысяч участников.
 

Сергей_Ф

Moderator
Команда форума
@nikolz а что в вашем предложении будет источником опорного сигнала времени? Одна из esp? О какой точности можно говорить в этом случае?
 

nikolz

Well-known member
@nikolz а что в вашем предложении будет источником опорного сигнала времени? Одна из esp? О какой точности можно говорить в этом случае?
уточню терминологию.
говорим о погрешности.
Вроде бы все написал, посмотрите там где картинка, там где я говорю о параметрах существующих систем (причем это не поделки а профессиональные системы, но в них нет заявления о точности измерения времени с погрешностью в мкс)
 

Сергей_Ф

Moderator
Команда форума
@nikolz Николай, согласитесь, что вариант предложенный Виктором позволяет оперировать точностью относительно опорного времени из интернета. Таким образом результат соревнований будет однозначно кореллироваться с результатами других соревнований, где бы они не проходили.
Ваш вариант привязан к локальному генератору мастер-esp. Какая у него точность мы не знаем и даже не знаем как она будет плавать при разной температуре. Профессиональные варианты, которые вы нашли в интернете, наверняка имеют сертификаты для использования в международных соревнованиях. Потому там и такая стоимость. Это должно как то описываться.
Ваш вариант, даже в случае проведения соревнований при разной температуре с одним набором esp, даст результаты с непредсказуемой погрешностью. Что уж говорить про разные наборы esp.
Не согласны?
 

nikolz

Well-known member
@nikolz Николай, согласитесь, что вариант предложенный Виктором позволяет оперировать точностью относительно опорного времени из интернета. Таким образом результат соревнований будет однозначно кореллироваться с результатами других соревнований, где бы они не проходили.
Ваш вариант привязан к локальному генератору мастер-esp. Какая у него точность мы не знаем и даже не знаем как она будет плавать при разной температуре. Профессиональные варианты, которые вы нашли в интернете, наверняка имеют сертификаты для использования в международных соревнованиях. Потому там и такая стоимость. Это должно как то описываться.
Ваш вариант, даже в случае проведения соревнований при разной температуре с одним набором esp, даст результаты с непредсказуемой погрешностью. Что уж говорить про разные наборы esp.
Не согласны?
Почему Вы полагаете, что я против варианта Виктора?
Мне нравится , что делает Виктор , что нельзя сказать о том, что он говорит.
На форуме он единственный, кто сделал действительно много и выложил свои решения. Это факт.
=============================
Полагаю, что я достаточно четко написал выше о разнице в его и моем решении задачи данной темы.
Повторю ...надцатый раз.
-------------------
Начну от печки.
Задача состоит в том, чтобы измерить отрезки времени с привязкой к единой шкале (общему началу координат)
Решить задачу можно разными способами
--------------------------
первый состоит в том, что используется эталонный стабильный источник времени и его показания передаются в точки измерения
Эти показания и используются как метки времени для замера интервала.
Вариант маяка WiFi, который благодаря патчу от Виктора доступен в ESP8266,
основан на передачи меток времени с шагом 100 мс
а интервал 100 мс квантуется локальным генератором.
В результате мы получаем время с шагом 100 мс с погрешностью эталона и более мелкий шаг с погрешностью таймера ESP8266.
--------------------
Очевидно, что если используем базовую станцию WiFi, то привязка будет к точности ее часов.
В интернете есть эталонные маяки - сервера времени. Можно привязываться к ним.
--------------------
Но такой метод можно реализовать на любом протоколе.
Например на BLE есть специальный режим маяка, в котором можно передавать эталонное время с любым шагом,
например те же 100 мс или 10 мс.
========================
Таким образом, если есть инфраструктура WiFi и доступ к счетчику TSF то метод реализуем.
Но не для всех чипов есть Виктор и следовательно доступ к счетчику TSF
----------------------------------------
Еще раз подчеркну, что этот метод реализуется на любом диапазоне и на любых протоколах.
==========================
Теперь перейдем к задаче измерения интервала времени в чистом поле или в горах.
-------------------------------
Когда wifi кирдык, нет базовых станций или, когда Виктор не написал, патч для TSF.
Что делать?
-------------------------------
Есть несколько вариантов (мои варианты в данной теме)
1) Создать базовый эталон времени и передавать метки времени в точки измерения
В качестве базы может быть ESP как AP Wifi или ESP-NOW.либо другой чип с BLE протоколом
-----------------
2) Не создавать специально базу, а передавать сигнал старта с одной точки на другую.
Этот вариант более универсальный и проще так как не требует привлечения Виктора и наличия инфраструктуры Wifi.
В этом варианте на один чип меньше.
----------------
3) устройства синхронизируются в начальном пункте. После этого используются автономно для измерения момента времени событий.
Это время ими передается асинхронно в точку обработки данных.
Т е в этом случае мы фактически делаем электронные часы, которые отсчитывают абсолютное время например по гринвичу и передают его в точку сбора информации
======================================
Очевидно, что Варианты без использования инфраструктуры WiFi априори менее точны,
так как в них менее точное железо,
но они существенно проще.
Вопрос какой вариант выбрать в том или ином случае решается с учетом конкретных условий и требований к точности.
=====================
Для оценки точности в своих вариантах я и сделал тест
усе.
 

pvvx

Активный участник сообщества
перешли от единиц мкс к единицам ms и получили правдоподобный результат.
Я ещё не дошел до границ в мс. Как было, так и осталось в +-5 мкс для моей сборки SDK и описанию указанному в начальной теме.
Не приписывайте методу лаги в +-400 мкс возникающие из-за писателей Arduino системы и её пользователей- это их беда, а не моя и не данного метода.
Эти лаги возникают в ней при любом методе, даже при чтении внутреннего аппаратного таймера по прерыванию :p
Причем я изначально сказал, что есть два варианта.
Где второй? Ждем измерений и демку, для возможности перепроверить... Да поленивее - ни у кого тут нет желания писать более десятка строк СИ/С++ - "вкалывают роботы" .
 

pvvx

Активный участник сообщества
Но не для всех чипов есть Виктор и следовательно доступ к счетчику TSF
Тут у вас выходит ошибочка.
Во всех нормальных модулях с SDK/DDK есть доступ к TSF. У некоторых для этого необходимо NDA, т.к. некоторые корпорации (не все!) по неясным причинам считают исходники своих драйверов WiFi "сикретными".
Этого нет исключительно у Exsperssif (походу и с NDA) и на основе имеющихся у меня данных за период с даты старта продаж ESP8266, по сей день, я могу только предполагать причины... На первое место выходит предположение о том, что у них или нет исходников или нарушены (c). Другого вроде не дано.
У многих, в базе SDK для простых смертных, существует API с функцией получения beacon фрейма и разными реализациями. У Realtek это иногда реализуется калбаком...
Для оценки точности в своих вариантах я и сделал тест
А нам можно тоже "потестить" Ваш вариант?
Или ТС и другим надо сделать и предоставить для вас Ваш вариант? o_O
 

pvvx

Активный участник сообщества
И на счет “Что там моего в TSF”:

Для реализации потребовалось:
1. Прочитать чужие статьи как делается синхронизация в 802.11
2. Поиском google в инете найти несколько “открытых” исходники дров WiFi.
3. Выбрать наиболее соответствующие исходники по имена процедур с листингом GCC от сборки SDK Espressif.
4. С помощью утилиты GCC для работы с либами разобрать файл ‘libnet80211.a’ от Espressif на объектные файлы.
5. В бинарном виде найти строку символов “cnx_update_bss_more” (в файле ‘wl_cnx_new.o’) и исправить последний символ на “_” получив “cnx_update_bss_mor_”.
6. С помощью утилит GCC собрать обратно файл либы ‘libnet80211.a’ из объектных файлов.
Что тут было “моего” и не описано ранее кем-то другим? Выберите номер п.п. :)

Причина применения патча в том, что над данной локальной процедурой не сработал “wrapping a call” с помощью опции --wrap= cnx_update_bss_more компилятору.
Вот тут и появляются главные вопросы:
А нафига так было делать программерам Espressif?
Почему незя было это 'расшарить' для свободного стандартного доступа средствами GCC, если сами не могут в течении многих лет предоставить запрашиваемый многими пользователями функционал API? Ничего сИкретного, хулиганского или хакерского от наличия такой функции в API сделать невозможно.
Причины явно в другом :p
 
Сверху Снизу