программирование Arduino

встраиваемые модели

Модераторы: Olej, vikos

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

программирование Arduino

Непрочитанное сообщение Olej » 21 мар 2018, 20:39

Уже много по этому поводу написано в разных темах: Arduino (отчасти) и Arduino + Processing.
Но всё-таки там - это специфические вопросы ... и темы перегружены.
Поэтому вот такая отдельная тема.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: программирование Arduino

Непрочитанное сообщение Olej » 21 мар 2018, 20:44

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

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

Код: Выделить всё

#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;  
}
И вот что он даёт...
m2.png
Вот как это происходит по умолчанию (если не влазить в этот процесс): коррекция производится чаще через 43, реже через 42 последовательных вызовов millis().

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

программирование Arduino

Непрочитанное сообщение Olej » 22 мар 2018, 00:10

Интересный вопрос: продолжительность пустого цикла опроса 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;
  }
}
В итоге имеем:
Изображение
Вложения
l2.png
(18.92 КБ) 1584 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: программирование Arduino

Непрочитанное сообщение Olej » 22 мар 2018, 00:29

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

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: программирование Arduino

Непрочитанное сообщение Olej » 22 июл 2022, 14:08

В проекте TinyGo - A Go Compiler For Small Places на их GIT-репозитории в перечислении таргет-платформ появилось:

Код: Выделить всё

...
Arduino Mega 1280
Arduino Mega 2560
Arduino MKR1000
Arduino MKR WiFi 1010
Arduino Nano
Arduino Nano 33 BLE
Arduino Nano 33 BLE Sense
Arduino Nano 33 IoT
Arduino Nano RP2040 Connect
Arduino Uno
Arduino Zero
...
TinyGo — это проект по переносу Go на микроконтроллеры и небольшие системы с одним процессорным ядром. Он похож на emgo, но основное отличие состоит в том, что мы хотим сохранить модель памяти Go (что подразумевает некую сборку мусора). Еще одно отличие состоит в том, что TinyGo использует LLVM внутри, а не генерирует C, что, как мы надеемся, приведет к меньшему и более эффективному коду и, безусловно, к большей гибкости.

Ответить

Вернуться в «Одноплатные компьютеры»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя