Как узнать время испонения функций Библиотеки Liquid crystal I2c ?
- Войдите на сайт для отправки комментариев
Доброго дня !!!
Пошелестил форум и вразумительного ответа для себя не нашёл.
Требуется узнать время выполнения нескольких функци в библиотеке 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 мс в прогоне и чтобы без отключеня прерываний, так сказать есть шаблон и можно испытать часть кода запихнув его в этот шаблон.
Микросы чем не устраивают ?
uint32_t time=micros();
//Функция которую замеряем
Serial.print(micros()-time);
sanekru. уже писал в другой ветке - самый простой и точный спсоб измерения длительности процедур на МК - аппаратный. В начле процедуры, которую хочешь измерить - добавляетшь вывод HIGH на любой свободный пин, в конце процедуры - LOW на тот же пин. Потом садишься на этот вывод осцилом или логиканализером и замеряешь время.
sanekru. уже писал в другой ветке - самый простой и точный спсоб измерения длительности процедур на МК - аппаратный. В начле процедуры, которую хочешь измерить - добавляетшь вывод HIGH на любой свободный пин, в конце процедуры - LOW на тот же пин. Потом садишься на этот вывод осцилом или логиканализером и замеряешь время.
О какой аппаратной точности идёт речь, если ТС нужно +/-10мкс ?
Спасибо!
Оказалось всё проще чем думал, те же показания, один символ ~ 1500 мкс, три символа ~4500 мкс вроде всё сходиться, я так понимаю что через таймер с точностью до сотых микросекунд, а мне такая точность не нужна, ещё раз спасибо!
а что такого? у Салеае, например, 24 Мегасемплов в сек, то есть разрешение порядка 40нс. 10мкс им можно измерить весьма точно
Не, мне такая точность точно в ближайшее время не понадобиться!
А так спасибо за метод, может когда нибудь пригодиться
а что такого? у Салеае, например, 24 Мегасемплов в сек, то есть разрешение порядка 40нс. 10мкс им можно измерить весьма точно
Это все понятно.
В данном случае оно зачем ?
ну как по мне - это проще, чем вывод в Сериал. Особенно когда Сериал чем-то занят :)
ну как по мне - это проще, чем вывод в Сериал. Особенно когда Сериал чем-то занят :)
а особенно когда его (ATtiny) нет...
Если посмотреть в список команд дисплея , то можно увидеть команду Read busy flag and address counter которую игнорируют большинство библиотек. Сделано это не просто так, а потому что. Проверка занятости занимает время и ресурсы. В своё время столкнулся с ситуацией, когда очередной китайский дисплей делал clear больше секунды, что было больше времени задержки в библиотеке и соответственно при попытке писать в него раньше приводило к глюкам. Тогда написал программку, которая измеряла реальные цифры времени выполнения команд конкретного дисплея через busy flag и вставлял задержки выполнения команд в библиотеку. Последнее время на китайских дисплеях быстрее оказывается прописать две строки пробелов, чем сделать clear.
Что я хотел сказать - измерять задержки не надо. Их можно посмотреть в библиотеке. А вот если надо максимально быстро и без глюков выводить на дисплей, то лучше проверить реально необходимые задержки или вообще убрать задержки и дописать проверку busy flag. Мой опыт говорит, что почти все команды, корме clear, успевают проверить busy flag не более 2 раз.
а особенно когда его (ATtiny) нет...
А софт сериал никто не отменял, особенно учитывая что на вывод нужна только одна нога и без прерываний. В теме про тиньку я приводил вывод всего пару десятков байт.
А ещё есть некие плоттеры (не обязательно ардуино), которые позволяют отображать/фиксировать длительности вплоть до 100 мкс.