Как узнать время испонения функций Библиотеки Liquid crystal I2c ?

sanekru
Offline
Зарегистрирован: 05.12.2017

Доброго дня !!!

Пошелестил форум и вразумительного ответа для себя не нашёл.

Требуется узнать время выполнения нескольких функци в библиотеке LyquidCrystal_I2C, а именно:

   clear(); я так понимаю она самая ресурсоёмкая по времени, т.к. в её реализации задержка в 2000 мкс

   print(); тут я думаю время зависит от количества переданных символов

   setCursor(); здесь могу предположить что время исполнения зависит от сдвига курсора

На просторах интернета на  форуме http://mypractic-forum.ru/viewtopic.php?t=17 Эдуард написал программу для данной цели, но при отключении прерывания прогрпмма у меня не выводит данные в сериал, и соответственно на дисплее тоже пусто, предпологаю что прерывания нужны библиотеке. так же в ветке Эдуард приводит данные для библиотеки LiqudCristal, но я так понимаю что эти данные даже близко не соответствуют для библиотеки с I2C.

Попробывал измерить на пустом исследуемом блоке и результат измерений показал 0.00mks, что вполне логично

#include <Arduino.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C disp (0x27, 20, 4);

// определение времени выполнения программного блока Ардуино

unsigned int  timerValue; // значение таймера
 
void setup() {
  Serial.begin(9600);  // инициализируем последовательный порт, скорость 9600
  // установки таймера 1
  TCCR1A = 0;
  TCCR1B = 0; 
  disp.init();
  disp.backlight();
}

void loop() {
  noInterrupts(); // запрет прерываний
  TCNT1H = 0; // сброс таймера
  TCNT1L = 0;
  TCCR1B = 1; // разрешение работы таймера
  // ---------- исследуемый программный блок ---------
  
    

  // -------------------------------------------------
  TCCR1B = 0; // остановка таймера
  timerValue = (unsigned int)TCNT1L | ((unsigned int)TCNT1H << 8); // чтение таймера
  interrupts(); // разрешение прерываний
     
  // вывод на компьютер
  Serial.print( (float)(timerValue - 2) * 0.0625);
  Serial.println(" mks");
  
  delay(500);
}

далее уже перед входом в исследуемый блок добавил разрешение прерываний а после выключение, соответственно результат измерения уже был 0.12mks, что тоже вполне логично т.к. затрачивается время на исполнение функий

#include <Arduino.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C disp (0x27, 20, 4); 

// определение времени выполнения программного блока Ардуино

unsigned int  timerValue; // значение таймера
 
void setup() {
  Serial.begin(9600);  // инициализируем последовательный порт, скорость 9600
  // установки таймера 1
  TCCR1A = 0;
  TCCR1B = 0; 
  disp.init();
  disp.backlight();
}

void loop() {
  noInterrupts(); // запрет прерываний
  TCNT1H = 0; // сброс таймера
  TCNT1L = 0;
  TCCR1B = 1; // разрешение работы таймера
  interrupts();
  // ---------- исследуемый программный блок ---------

    

  // -------------------------------------------------
  noInterrupts();
  TCCR1B = 0; // остановка таймера
  timerValue = (unsigned int)TCNT1L | ((unsigned int)TCNT1H << 8); // чтение таймера
  interrupts(); // разрешение прерываний
     
  // вывод на компьютер
  Serial.print( (float)(timerValue - 2) * 0.0625);
  Serial.println(" mks");
  
  delay(500);
}

После в исследуемый програмный блок добавил фунцию clear(); и время исполнения показало от 3487 до 3505 mks

#include <Arduino.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C disp (0x27, 20, 4); //

// определение времени выполнения программного блока Ардуино

unsigned int  timerValue; // значение таймера
 
void setup() {
  Serial.begin(9600);  // инициализируем последовательный порт, скорость 9600
  // установки таймера 1
  TCCR1A = 0;
  TCCR1B = 0; 
  disp.init();
  disp.backlight();
}

void loop() {
  noInterrupts(); // запрет прерываний
  TCNT1H = 0; // сброс таймера
  TCNT1L = 0;
  TCCR1B = 1; // разрешение работы таймера
  interrupts();
  // ---------- исследуемый программный блок ---------
    disp.clear();
    

  // -------------------------------------------------
  noInterrupts();
  TCCR1B = 0; // остановка таймера
  timerValue = (unsigned int)TCNT1L | ((unsigned int)TCNT1H << 8); // чтение таймера
  interrupts(); // разрешение прерываний
     
  // вывод на компьютер
  Serial.print( (float)(timerValue - 2) * 0.0625);
  Serial.println(" mks");
  
  delay(500);
}

После добавил ещё одну функию print ("a"); (один символ) и время снизилось от 883 до 903 мкс, в данном случае предпологаю что произошло переполнение счётчика и данные уже пишет после переполнения (поправьте если не прав)

#include <Arduino.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C disp (0x27, 20, 4);

// определение времени выполнения программного блока Ардуино

unsigned int  timerValue; // значение таймера
 
void setup() {
  Serial.begin(9600);  // инициализируем последовательный порт, скорость 9600
  // установки таймера 1
  TCCR1A = 0;
  TCCR1B = 0; 
  disp.init();
  disp.backlight();
}

void loop() {
  noInterrupts(); // запрет прерываний
  TCNT1H = 0; // сброс таймера
  TCNT1L = 0;
  TCCR1B = 1; // разрешение работы таймера
  interrupts();
  // ---------- исследуемый программный блок ---------
    disp.clear();
    disp.print("a");
    

  // -------------------------------------------------
  noInterrupts();
  TCCR1B = 0; // остановка таймера
  timerValue = (unsigned int)TCNT1L | ((unsigned int)TCNT1H << 8); // чтение таймера
  interrupts(); // разрешение прерываний
     
  // вывод на компьютер
  Serial.print( (float)(timerValue - 2) * 0.0625);
  Serial.println(" mks");
  
  delay(500);
}

потом убрал clear(); и время показало 1485-1503 mks

далее попробывал print("ab"); (два символа) 2965-2994 mks

после print("abc"); (три символа) 355-381 mks (снова переполнение)

и третья функция setCursor(1, 1); 1481-1498 mks

Вопросы:

1. Насколько достоверным можно считать такой анализ ?

2. Почему время исполнения одной функции разнится? Ведь действие идет в цикле а время каждуй раз разное, хоть и вне большом интервале.

3. Может быть есть какой то универсальный код для высчитывания времени исполнения, например нескольких функций для прорисовки всего дисплея или чего либо с временем большим чем 4095 мкс и относительно точным, например с точностью от 10мкс и до 100 мс в прогоне и чтобы без отключеня прерываний, так сказать есть шаблон и можно испытать часть кода запихнув его в этот шаблон.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Микросы чем не устраивают ?

uint32_t time=micros();
//Функция которую замеряем
Serial.print(micros()-time);

b707
Offline
Зарегистрирован: 26.05.2017

sanekru. уже писал в другой ветке - самый простой и точный спсоб измерения длительности процедур на МК - аппаратный. В начле процедуры, которую хочешь измерить - добавляетшь вывод HIGH на любой свободный пин, в конце процедуры - LOW на тот же пин. Потом садишься на этот вывод осцилом или логиканализером и замеряешь время.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

b707 пишет:

sanekru. уже писал в другой ветке - самый простой и точный спсоб измерения длительности процедур на МК - аппаратный. В начле процедуры, которую хочешь измерить - добавляетшь вывод HIGH на любой свободный пин, в конце процедуры - LOW на тот же пин. Потом садишься на этот вывод осцилом или логиканализером и замеряешь время.

О какой аппаратной точности идёт речь, если ТС нужно +/-10мкс ?

sanekru
Offline
Зарегистрирован: 05.12.2017

Спасибо!

Оказалось всё проще чем думал, те же показания, один символ ~ 1500 мкс, три символа ~4500 мкс вроде всё сходиться, я так понимаю что через таймер с точностью до сотых микросекунд, а мне такая точность не нужна, ещё раз спасибо!

#include <Arduino.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C disp (0x27, 20, 4);  

uint32_t time;
 
void setup() {
  Serial.begin(9600);
  disp.init();
  disp.backlight();
}

void loop() {

  time = micros();
  disp.print("a");
  Serial.println (micros() - time);
  delay(500);
}

 

b707
Offline
Зарегистрирован: 26.05.2017

Kakmyc пишет:
О какой аппаратной точности идёт речь, если ТС нужно +/-10мкс ?

а что такого? у Салеае, например, 24 Мегасемплов в сек, то есть разрешение порядка 40нс. 10мкс им можно измерить весьма точно

sanekru
Offline
Зарегистрирован: 05.12.2017

Не, мне такая точность точно в ближайшее время не понадобиться!

А так спасибо за метод, может когда нибудь пригодиться

Kakmyc
Offline
Зарегистрирован: 15.01.2018

b707 пишет:

Kakmyc пишет:
О какой аппаратной точности идёт речь, если ТС нужно +/-10мкс ?

а что такого? у Салеае, например, 24 Мегасемплов в сек, то есть разрешение порядка 40нс. 10мкс им можно измерить весьма точно

Это все понятно.
В данном случае оно зачем ?

b707
Offline
Зарегистрирован: 26.05.2017

Kakmyc пишет:
Это все понятно. В данном случае оно зачем ?

ну как по мне - это проще, чем вывод в Сериал. Особенно когда Сериал чем-то занят :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

Kakmyc пишет:
Это все понятно. В данном случае оно зачем ?

ну как по мне - это проще, чем вывод в Сериал. Особенно когда Сериал чем-то занят :)

а особенно когда его (ATtiny) нет...

nik182
Offline
Зарегистрирован: 04.05.2015

Если посмотреть в список команд дисплея , то можно увидеть команду Read busy flag and address counter которую игнорируют большинство библиотек. Сделано это не просто так, а потому что. Проверка занятости занимает время и ресурсы. В своё время столкнулся с ситуацией, когда очередной китайский дисплей делал clear больше секунды, что было больше времени задержки в библиотеке и соответственно при попытке писать в него раньше приводило к глюкам. Тогда написал программку, которая измеряла реальные цифры времени выполнения команд конкретного дисплея через busy flag и вставлял задержки выполнения команд в библиотеку. Последнее время на китайских дисплеях быстрее оказывается прописать две строки пробелов, чем сделать clear. 

Что я хотел сказать - измерять задержки не надо. Их можно посмотреть в библиотеке. А вот если надо максимально быстро и без глюков выводить на дисплей, то лучше проверить реально необходимые задержки или вообще убрать задержки и дописать проверку busy flag. Мой опыт говорит, что почти все команды, корме clear, успевают проверить busy flag не более 2 раз.     

nik182
Offline
Зарегистрирован: 04.05.2015

ua6em пишет:

а особенно когда его (ATtiny) нет...

А софт сериал никто не отменял, особенно учитывая что на вывод нужна только одна нога и без прерываний. В теме про тиньку я приводил вывод всего пару десятков байт.

Green
Offline
Зарегистрирован: 01.10.2015

А ещё есть некие плоттеры (не обязательно ардуино), которые позволяют отображать/фиксировать длительности вплоть до 100 мкс.