#1 2018-03-21 21:25:55

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

служба времени Arduino

Вот любопытные вещи относительно хронометража в Arduino:

При использовании millis() нужно помнить об одной особенности - millis() "тикает" не равномерно.
Возвращаемое значение увеличивается на единицу каждые 1024 мсек. Затем, когда миллис отстанет на 1 мсек, она "подводится" на единицу, т.е.  возвращаемое значение перескакивает через один.
При измерении длительных интервалов это не страшно, но при интервалах в несколько мсек это заметно.

Так же (время системного тика чуть меньше 1mc) имеет место во всех процессорных семействах и всех операционных системах (или средах выполнения). Но это в точности соответствует представлениям реального времени и требованиям стандарта POSIX 1003b для реального времени: "фактические значения временных интервалов может быть сколь угодно больше заказанных, но никогда не может оказаться меньше". Или то же самое: единица шкалы измерения времени (1мс.) может быть меньше, но не смеет быть больше.

В вашем изложении период 1mc фактически соответствует 0,9765625mks. Тогда процесс коррекции millis() строго детерминированный, и можно точно вычислить период, с которым ошибка millis() будет накапливать 1ms и будет подлежать коррекции.

Неактивний

#2 2018-03-21 21:27:21

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

В связи с чем сделал такое тестовое приложение:

#include <stdio.h>
int serial_fputchar( const char ch, FILE *stream ) { Serial.write( ch ); return ch; }
static FILE *serial_stream = fdevopen( serial_fputchar, NULL );

void setup() {
  stdout = serial_stream;
  Serial.begin( 115200 ); 
}

void loop() {
  while( !Serial.available() );
  unsigned len = 0;
  while( Serial.available() ) {
    int r = Serial.read();
    if( r >= '0' && r <='9' ) 
      len = len * 10 + ( r - '0' );
    delay( 1 );
  }
  Serial.println( len, DEC );
  printf( "вычисление... ожидайте...\n" );
  unsigned long *prev = new unsigned long [ len ],
                *next = new unsigned long [ len ];
  int i = 0;
  do {
    prev[ i ] = millis();
    while( prev[ i ] == ( next[ i ] = millis() ) );
    if( next[ i ] - prev[ i ] > 1 ) i++;
  } while( i < len );
  for( i = 0; i < len; i++ ) {
    printf( "%lu:%lu:%2u", prev[ i ], next[ i ], i ? prev[ i ] - prev[ i - 1 ] : 0 );    
    printf( "%s", ( 9 == ( i % 10 ) ) ? "\n" : " | " );
  }
  printf( "\n" );
  delete [] prev;
  delete [] next;  
}

Неактивний

#3 2018-03-21 21:28:21

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Olej пише:

В связи с чем сделал такое тестовое приложение:

А вот как оно выполняется:
file.php?id=2900

Остання редакція Olej (2018-03-22 00:15:03)

Неактивний

#4 2018-03-22 00:23:56

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Интересный вопрос: продолжительность пустого цикла опроса loop()?
Часто пишут: что мы, мол, точно не знаем задержек повторения loop() ... поэтому сложно судить ... о скважности, например delay() ...

Проверяем!

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

unsigned long rep, i, s1, s2, prev, next;
bool cont = true; 

void loop() {
  if( cont ) {                       // ввод числа повторений
    while( !Serial.available() );
    rep = 0;
    while( Serial.available() ) {
      int r = Serial.read();
      if( r >= '0' && r <='9' ) 
        rep = rep * 10 + ( r - '0' );
      delay( 3 );
    }
    cont = false;
    s1 = s2 = prev = next = i = 0;
  }    
  next = micros();
  if( i <= rep ) {                     // посчёт задержек
    if( i > 0 ) {
      uint32_t inter = next - prev;
      s1 += inter;
      s2 += inter * inter; 
    }
    i++;
  }
  prev = next;
  if( i == rep + 1 ) {                 // вычисление результатов
    Serial.print( i - 1, DEC );
    Serial.print( " : " );  
    double m = (double)s1 / rep,
           d = (double)s2 / rep - m * m;
    Serial.print( m, 2 );
    Serial.print( " +/-" );
    Serial.println( sqrt( d ) ); 
    cont = true;
  }
}

В итоге имеем:
file.php?id=2901
Итог:
- период повторения "пустых" loop() в среднем 17.61 мкс.
- со среднеквадратичным разбросом (СКО) 2.09 мкс. (11.87% от среднего)

Остання редакція Olej (2018-03-22 00:27:33)

Неактивний

#5 2018-03-22 11:36:54

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

время системного тика чуть меньше 1mc

Поделись телефоном дилера. Тоже хочу эту траву попробовать.

Неактивний

#6 2018-03-22 11:42:57

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

- период повторения "пустых" loop() в среднем 17.61 мкс.

А если бы ты туда ко всему ещё и delay впихнул, то время было бы ещё больше.

Частота вызова пустого loop - 1.136МГц, стало быть период - 880 наносекунд.

Источник - http://arduino.ru/forum/programmirovanie/chastota-vyzovov-loop

Остання редакція Kaka (2018-03-22 11:55:31)

Неактивний

#7 2018-03-22 12:09:13

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:
Olej пише:

время системного тика чуть меньше 1mc

Поделись телефоном дилера. Тоже хочу эту траву попробовать.

Попробуй ... если годишься хоть что-то в этом понимать big_smile

Посмотрим что ты за Сухов...

Вот тебе телефон дилера - http://arduino.ru/forum/programmirovani … ent-354224:

Возвращаемое значение увеличивается на единицу каждые 1024 мсек. Затем, когда миллис отстанет на 1 мсек, она "подводится" на единицу, т.е.  возвращаемое значение перескакивает через один.

Разницу между 1024 и 1000 уловишь? wink
+ фактический результат теста выше - где хорошо видно неравномерный инкремент последовательных millis(): на 1, но иногда, каждый 42-43-й раз, на 2.

Остання редакція Olej (2018-03-22 12:11:16)

Неактивний

#8 2018-03-22 12:25:09

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:
Olej пише:

- период повторения "пустых" loop() в среднем 17.61 мкс.

А если бы ты туда ко всему ещё и delay впихнул, то время было бы ещё больше.

При чём здесь delay(), если интерес состоял именно в максимальной частоте loop(), которая в слабеньком Arduino совсем не так высока, и часто недостаточная в реальной обработке уже в звуковом диапазоне. Т.е. частота "быстрого" цикла без пассивных ожиданий и активно нагружающих операций в цикле.

Kaka пише:

Частота вызова пустого loop - 1.136МГц, стало быть период - 880 наносекунд.

Источник - http://arduino.ru/forum/programmirovanie/chastota-vyzovov-loop

Если бы ты читал до конца то, на что ссылаешься ... да ещё давал себе труд понимать то, что читаешь - то заметил бы такую простую вещь, что "стало быть" - это при запрещённых прерываниях процессора, когда служба времени не работает и недоступна для использования - это граничный режим, который на практике никому и никогда не понадобится.
P.S. Хотя ссылка сама по себе интересная ... дальше там, а не с начала - я её как-то пропустил.

Остання редакція Olej (2018-03-22 12:26:43)

Неактивний

#9 2018-03-22 13:17:09

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Olej пише:

P.S. Хотя ссылка сама по себе интересная ... дальше там, а не с начала - я её как-то пропустил.

Там же показывают как loop() встраивает в функцию main() Arduino IDE:

for (;;) {
	loop();
	if (serialEventRun) serialEventRun();
}

Вот то обслуживание ("системное"), которое за: if (serialEventRun) serialEventRun(); и тем, что может оттуда вызываться по цепочке, и добавляет к периоду тупого вызова loop() в цикле.
Там же, кстати, утверждается:

Предлагаю автору провести эксперимент с таким циклом:

while (1) {
	loop();
	if (serialEventRun) serialEventRun();
}

и убедиться, что цикл выполняется в 4 раза быстрее.

Если это действительно так (мне в облом это проверять), то это полный идиотизм ... кого? компилятора AVR? разработчиков IDE? и т.д.

Неактивний

#10 2018-03-22 15:09:16

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

это при запрещённых прерываниях процессора,

А теперь возьми примпер оттуда, убери запрет прерываний и получи свои 17,6 мкс, бла-блабол.

Неактивний

#11 2018-03-22 15:10:49

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

Разницу между 1024 и 1000 уловишь? wink

А ты разницу между системным тиком и тиком миллис уловишь? Или тебе это всё едино?

Неактивний

#12 2018-03-22 15:18:37

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:
Olej пише:

это при запрещённых прерываниях процессора,

А теперь возьми примпер оттуда, убери запрет прерываний и получи свои 17,6 мкс, бла-блабол.

А вот это значение, в реальной работе, с разрешёнными прерываниями и хотелось получить.
Только это ещё вопрос: получится или нет "свои 17,6 мкс" или нет? Потому как в их примере это можно только осциллографом видеть ... а мне такие эксперименты проделывать в облом. А я себе определял выше "свои 17,6 мкс" чисто программным путём, без шнурков и обвязки.

Так что про "возьми примпер оттуда" - это как-раз и есть бла-бла-бла: языком оно совсем просто ворочать, не камни, чай yikes
Так-то вот как-то ... , примпер.

Остання редакція Olej (2018-03-22 15:19:08)

Неактивний

#13 2018-03-22 15:40:56

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:
Olej пише:

Разницу между 1024 и 1000 уловишь? wink

А ты разницу между системным тиком и тиком миллис уловишь? Или тебе это всё едино?

В AVR обычно и в Arduino в частности таймер настроен на системный тик как-раз по 1024-й микросекунде (если не лазить к таймеру руками).
Что такое за термин "тик миллис" - это только ты один такие страшные слова знаешь. Но millis() как-раз и считает 1.024мс интервалы, и именно из-за этого отстаёт от течения физического времени, и его приходится корректировать, каждые 42/43 отсчёта millis() инкрементируется не на 1, а на 2. Это по дефаулту, хотя детальные параметры коррекции можно перенастроить (но вряд ли стоит это делать). А соотношение вот тех 42 и 43 в последовательности корректировок они выбрали, чтобы моделировать некоторое дробное приближение 42.xxx.

А если тебе как-то по-другому это известно, так изложи ... с ссылками  на источники и аргументами, а не бла-бла-бла:

Дабы глупость каждого была видна.

Остання редакція Olej (2018-03-24 11:08:59)

Неактивний

#14 2018-03-22 16:52:30

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

а мне такие эксперименты проделывать в облом

Так ты определись - или делай, или не болтай. Не пахнет там никакими 17,6 мкс и близко. Это твои тормоза. Так что измерял ты не скорость вызовов loop, а скорость твоих тормозов.

Неактивний

#15 2018-03-22 16:54:17

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

В AVR обычно и в Arduino в частности таймер настроен на системный тик как-раз по 1024-й микросекунде (если не лазить к таймеру руками).

Ты идиот? Частота в ардуино 16МГц, значит системный тик - 1/16 микросекунды. Не знаю, какие тебе нужны источники и пруфы, чтобы из частоты период получить, ну почитай учебник для 6-го класса.

Остання редакція Kaka (2018-03-22 16:55:49)

Неактивний

#16 2018-03-22 16:58:19

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:
Olej пише:

В AVR обычно и в Arduino в частности таймер настроен на системный тик как-раз по 1024-й микросекунде (если не лазить к таймеру руками).

Ты идиот? Частота в ардуино 16МГц, значит системный тик - 1/16 микросекунды.

Идиот - это ты, дружище.
А 1/16 микросекунды - это период частоты процессора, к системному тику никакого прямого отношения не имеет ... хотя системный тик и формируется из этой частоты.
Это только у недоумков-самоделкиных, безграмотных радиолюбителей - что частота процессора, что системный тик ... и всё по хер.

Неактивний

#17 2018-03-22 17:00:07

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Понятно. Диагноз ясен. Вопрос закрыт.

Неактивний

#18 2018-03-22 17:02:44

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:

Понятно. Диагноз ясен. Вопрос закрыт.

Вот и я подумал, что с самонадеянным ... радиомонтажником big_smile обсуждать дальше не стану.

Неактивний

#19 2018-03-24 11:36:42

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:

Так что измерял ты не скорость вызовов loop, а скорость твоих тормозов.

В принципе, да.
За счёт очень длинных (в сравнении с тактовой частотой) операций процессора +=, * + очень короткой задержки сверх цикла loop(), даже влияние 2-3 операций уже длиннее 1-го цикла loop(). Но это можно компенсировать, сделав калибровку на выполнение точно тех же операций (не заисанных в коде по-другому), но во внутреннем пустом цикле не выходя за пределы 1-го прохода цикла loop().
Как-то вот так, например:

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

unsigned long rep, i, s1, prev, next;
bool cont = true; 

#define step()                    \
  next = micros();                \
  if( i++ > 0 )                   \
    s1 += (next - prev);          \
  prev = next;

void loop() {
  if( cont ) {                      // ввод числа повторений
    while( !Serial.available() );
    rep = 0;
    while( Serial.available() ) {
      int r = Serial.read();
      if( r >= '0' && r <='9' ) 
        rep = rep * 10 + ( r - '0' );
      delay( 3 );
    }
    cont = false;
    s1 = i = 0;
  }  
  step();                           // интервал в loop 
  if( i > rep ) {                   // вычисление результатов
    double m = (double)s1 / rep;
    s1 = i = 0;
  loop: step();                     // интервал во внутреннем цикле
    if( i <= rep ) goto loop;    
    double c = (double)s1 / rep;
    Serial.print( rep, DEC );
    Serial.print( " : " ); 
    Serial.print( m, 3 ); 
    Serial.print( " - " ); 
    Serial.print( c, 3 ); 
    Serial.print( " = " ); 
    Serial.println( m - c, 3 );     
    cont = true;
  }
}

В результате будет как-то так:

100 : 9.960 - 9.640 = 0.320
1000 : 9.992 - 9.684 = 0.308
10000 : 9.998 - 9.684 = 0.314
100000 : 9.998 - 9.684 = 0.314
1000000 : 9.998 - 9.684 = 0.315

1. видно хорошую сходимость в зависимости от числа усреднения
2. может, чуть заниженный итог из-за одной "лишней" операции goto (для цикла использовать for() и while() не хотелось, там зависимоть от того как компилятор распорядится, и вносимые искажения там ещё больше ... проверено)
3. дополнительная задержка, вносимая в цикл loop() исполняющей системой Arduino исчезающе мала, меньше 1мкс ... неважно сколько там точно.

P.S. (Это что не лазить и не смотреть период осциллографом... Хотя с осциллографом тоже есть вопрос: в цикле loop() должна быть хотя бы одна операция вывода ... даже если её записать операцией AVR как PIND |= (1 << 3); - без промежуточного вызова функций Arduino)

Неактивний

#20 2018-03-24 11:49:57

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Olej пише:

3. дополнительная задержка, вносимая в цикл loop() исполняющей системой Arduino исчезающе мала, меньше 1мкс ... неважно сколько там точно.

Это хорошая новость (для меня wink ). Потому что она опровергает описываемые на разных форумах Arduino утверждения о том, что простейший пример генерации меандра не будет иметь скважности 2:

void loop()
{
  digitalWrite( ledPin, HIGH );  
  delay( 1 );   
  digitalWrite( ledPin, LOW );
  delay( 1 );
}

Так что стоило повозиться с тестированием, чтобы лишний раз самому убедиться, что разговоры по дополнительные задержки, вносимые к циклу loop() - это пустое: цикл - он и в Африке цикл.

Неактивний

#21 2018-03-26 20:32:09

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

Так что стоило повозиться с тестированием,

Достаточно было почитать тему по той ссылке, что я давал. Там есть этот пример с осциллограммой.

Неактивний

#22 2018-03-26 21:09:29

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:
Olej пише:

Так что стоило повозиться с тестированием,

Достаточно было почитать тему по той ссылке, что я давал. Там есть этот пример с осциллограммой.

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

Неактивний

#23 2018-03-27 08:41:04

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

В-третьих, мне не хочется возиться с осциллографом.

Ну, как писал Высоцкий: "Стукнул раз - специалист - видно по нему! smile

Неактивний

#24 2018-03-27 09:50:44

Olej
Учасник
З Харьков
Зареєстрований: 2018-03-08
Повідомлень: 234

Re: служба времени Arduino

Kaka пише:
Olej пише:

В-третьих, мне не хочется возиться с осциллографом.

Ну, как писал Высоцкий: "Стукнул раз - специалист - видно по нему! smile

Я не понимаю что вас так развеселило? Я написал же как и почему способ аппаратного определения, с помощью осциллографа, тоже порочный логически: он будет давать заниженные значения частоты, или затянутый период одного цикла loop().
Хотя сама цифра длины периода и не так важна (разве любопытства ради). Если она мала (800нс или 300нс - не важно) то:
- рассыпается миф, пересказываемый во многих обсуждениях об Arduino, что цикли с 2-мя delay( 1 ) (и любыми другими delay()) будет иметь скважность не 2 ... т.е. что loop() ещё что-то куда-то добавляет;
- можно спокойно не учитывать какие бы ни было задержки, вносимые частями исполняющей системой, прикомпилируемой IDE;
- хотя можно, понятности и точности ради, вообще исключить из исполнимого скетча функции setup() и loop(), прописав туда собственную функцию main():

int main() {
    Serial.begin( 9600 ); 
    Serial.println( "++" ); 
}

- IDE замечательно, без ругани компилирует такой код (загружает и выполняет) ... хотя какие-то операции инициализации в библиотеках при этом выпадают из выполнения, есть некоторые отличия в поведении.

Остання редакція Olej (2018-03-27 09:51:22)

Неактивний

#25 2018-03-27 20:38:03

Kaka
Учасник
Зареєстрований: 2018-03-21
Повідомлень: 411

Re: служба времени Arduino

Olej пише:

рассыпается миф

Так там в теме именно так вопрос и ставился - проверить это. Проверили. Скважность, конечно не ровно 2, но близко к тому. Читать надо.

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму