Форум обсуждения систем  

Вернуться   Форум обсуждения систем "Умный дом", проектов Ардуино, OpenWRT и других DIY устройств > Форум умного дома > Сделай сам

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
Старый 14.06.2014, 18:22   #101
Bulatovor
Senior Member
 
Регистрация: 20.01.2013
Адрес: Уфа
Сообщений: 444
Вес репутации: 799
Bulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond repute
По умолчанию Re: Ускоряем работу Arduino

Собрал в кучу оригинал и для 32u4 и 2560. ДЛя последних двух все так же работает только управление пинами и оба delay. Хочу извиниться за поспешность выводов что с Duo все просто и так же - архитектура совершенно другая и управлять пинами нужно по другому -потихоньку разбираюсь

ЗЫ. Ну и блинк как к всякой приличной библиотеке
Вложения
Тип файла: rar CyberLib.rar (9.2 Кб, 435 просмотров)

Последний раз редактировалось Bulatovor; 14.06.2014 в 18:41.
Bulatovor вне форума   Ответить с цитированием
Старый 14.06.2014, 20:28   #102
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,618
Вес репутации: 9823
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Ускоряем работу Arduino

Для Atmega328 либа взята из шапки?
Admin вне форума   Ответить с цитированием
Старый 14.06.2014, 21:16   #103
Bulatovor
Senior Member
 
Регистрация: 20.01.2013
Адрес: Уфа
Сообщений: 444
Вес репутации: 799
Bulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond repute
По умолчанию Re: Ускоряем работу Arduino

да, сегодня скачанная
Вот вопрос. почему при компилировании для 328 размер скетча Blink 598 байт, для 2560 - 628, а для Leonardo сразу 4,2к, я так понимаю из-за плохих библиотек к леонарду в самой среде arduino -у меня версия 1.0.5 r2

Последний раз редактировалось Bulatovor; 14.06.2014 в 21:25.
Bulatovor вне форума   Ответить с цитированием
Старый 14.06.2014, 21:53   #104
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,618
Вес репутации: 9823
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Ускоряем работу Arduino

Леонардо компилирует код вместе с загрузчиком, поддержка USB неявно подключается к каждому компилируемому под Leonardo скетчу, для поддержания возможности программного сброса через USB.
Admin вне форума   Ответить с цитированием
Старый 14.06.2014, 22:05   #105
Bulatovor
Senior Member
 
Регистрация: 20.01.2013
Адрес: Уфа
Сообщений: 444
Вес репутации: 799
Bulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond repute
По умолчанию Re: Ускоряем работу Arduino

Понятно, т.е. если с местом начнутся проблемы, путем небольших махинаций сию поддержку можно отключить. Из прочитанного приятно то, что у людей обычный блинк занимает за 5к, а с библиотекой CyberLib - уже почти на 800 байт меньше
Bulatovor вне форума   Ответить с цитированием
Старый 14.06.2014, 22:15   #106
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,618
Вес репутации: 9823
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Ускоряем работу Arduino

Спасибо за проделанную работу!!!
Залил библиотеку в шапку темы
Admin вне форума   Ответить с цитированием
Старый 14.06.2014, 23:35   #107
Bulatovor
Senior Member
 
Регистрация: 20.01.2013
Адрес: Уфа
Сообщений: 444
Вес репутации: 799
Bulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond repute
По умолчанию Re: Ускоряем работу Arduino

Пожалуйста. Но два спасибо в шапке темы уже пожалуй излишне - все равно основная причина -это собственная нужда.
Так вот едем дальше - столкнулся с такой проблемой, что одна уникальная и нужная мне библиотека использует другую библиотеку быстрого управления пинами digitalWriteFast.h/ Однако последняя поддерживает только 328 и 2560 процессоры - Леонардо не поддерживает. Я быстренько допилил её под Леонардо - поюзал и потерял . В принципе снова допилить недолго, но мы не ищем простых путей -зачем мне две! Засада в том, что номера портов и состояние переменные. Попробовал в CyberLib решить вопрос в лоб для начала с переменными номерами портов
PHP код:
void D_High(uint16_t Pin)
{switch (
Pin) {
case 
0:PORTD |=B00000100; break;
case 
1:PORTD |=B00001000; break;
case 
2:PORTD |=B00000010; break;
case 
3:PORTD |=B00000001; break;
case 
4:PORTD |=B00010000; break;
case 
5:PORTC |=B01000000; break;
case 
6:PORTD |=B10000000; break;
case 
7:PORTE |=B01000000; break;
case 
8:PORTB |=B00010000; break;
case 
9:PORTB |=B00100000; break;
case 
10:PORTB |=B01000000; break;
case 
11:PORTB |=B10000000; break;
case 
12:PORTD |=B01000000; break;
case 
13:PORTC |=B10000000; break;
case 
14:PORTF |=B10000000; break;
case 
15:PORTF |=B01000000; break;
case 
16:PORTF |=B00100000; break;
case 
17:PORTF |=B00010000; break;
case 
18:PORTF |=B00000010; break;
case 
19:PORTF |=B00000001; break;}
};


void D_Low(uint16_t Pin)
{switch (
Pin
{
case 
0:PORTD &=B11111011; break;
case 
1:PORTD &=B11110111; break;
case 
2:PORTD &=B11111101; break;
case 
3:PORTD &=B11111110; break;
case 
4:PORTD &=B11101111; break;
case 
5:PORTC &=B10111111; break;
case 
6:PORTD &=B01111111; break;
case 
7:PORTE &=B10111111; break;
case 
8:PORTB &=B11101111; break;
case 
9:PORTB &=B11011111; break;
case 
11:PORTB &=B01111111; break;
case 
12:PORTD &=B10111111; break;
case 
13:PORTC &=B01111111; break;
case 
14:PORTF &=B01111111; break;
case 
15:PORTF &=B10111111; break;
case 
16:PORTF &=B11011111; break;
case 
17:PORTF &=B11101111; break;
case 
18:PORTF &=B11111101; break;
case 
19:PORTF &=B11111110; break;}
}; 
Тест разочаровал-

Тест проведенный на следующем скетче разочаровал
PHP код:
#include "CyberLib.h"
uint16_t Pin=13;
uint16_t Time;

void setup()
Serial.begin(57600);
D13_Out//Настраиваем пин D13 на выход
}
     
-    
void loop()
Serial.println("Hello "); Time=millis();

for (
int i=0<= 10000i++)
{
// 1Стандартная Arduino 127-128 миллисекунд
// digitalWrite(13, HIGH);
// digitalWrite(13, LOW);

// // 2 Через инвентирование 8-9 миллисекунд
// D13_Inv;
// D13_Inv;
// 
// // 3 Через включение выключение портов 7-8 миллисекунд
// D13_High;
// D13_Low;
// 
// // 4порт задан переменной 43-44 миллисекунд
D_High(Pin);
D_Low(Pin);
}
Serial.print("Time: "); Serial.println((millis()-Time),DEC);


как видно при использовании старых функции скорость выросла по сравнению с родной Arduino почти в 20 раз, то в моем варианте только в три - маловато будет. Какие еще варианты кода мона попробовать?при использовании старых функции скорость выросла по сравнению с родной Arduino почти в 20 раз, то в моем варианте только в три - маловато будет. Какие еще варианты кода мона попробовать?
Вот это для меня пока сложновато - надо конкретненее пример куда впихать
Цитата:
Сообщение от ys1797 Посмотреть сообщение
Чтобы использовать Конструкцию вида:
D_in(<предопределенный номер пина>)

А не менять все, например, D2_Read, на D3_Read, если пин поменялся
Можно задействовать препроцессор:
Код:
#define _D_In(x) D##x##_In
#define D_In(x) _D_In(x)

#define _D_Out(x) D##x##_Out
#define D_Out(x) _D_Out(x)

#define _D_High(x) D##x##_High
#define D_High(x) _D_High(x)

#define _D_Low(x) D##x##_Low
#define D_Low(x) _D_Low(x)

#define _D_Inv(x) D##x##_Inv
#define D_Inv(x) _D_Inv(x)

#define _D_Read(x) D##x##_Read
#define D_Read(x) _D_Read(x)

Последний раз редактировалось Bulatovor; 15.06.2014 в 00:12.
Bulatovor вне форума   Ответить с цитированием
Старый 15.06.2014, 10:35   #108
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,618
Вес репутации: 9823
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Ускоряем работу Arduino

Если использовать например D_High(2); то будет быстрее, а D_High(19); будет самым медленно выполняемым, так как в цикле он последний
Можно попробовать замутить решение на ассемблере
Производить переходы по номеру пина умноженному на смещение плюс базовый адрес
Admin вне форума   Ответить с цитированием
Старый 15.06.2014, 18:05   #109
Bulatovor
Senior Member
 
Регистрация: 20.01.2013
Адрес: Уфа
Сообщений: 444
Вес репутации: 799
Bulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond repute
По умолчанию Re: Ускоряем работу Arduino

Цитата:
Сообщение от Admin Посмотреть сообщение
Если использовать например D_High(2); то будет быстрее, а D_High(19); будет самым медленно выполняемым, так как в цикле он последний
Эксперименты показывают что это не совсем верно. Нужна помощь в анализе результатов теста. Итак -в качестве исходного родной язык Ардуино. Потом на библиотеке digitalWriteFast.h с явным указанием пина и с переменной в качестве номера пина. К CyberLib написал 4 функции переключения с переменной в качестве пина и с переменными на пин и значение, причем в двух вариантах
PHP код:
//**************Прямое управление с переменной порта**********************
void D_High(uint16_t Pin)
{
(((
Pin) == ) ?  PORTD|=B00000100 : \
(((
Pin) == ) ?  PORTD|=B00001000 : \
(((
Pin) == ) ?  PORTD|=B00000010 : \
(((
Pin) == ) ?  PORTD|=B00000001 : \
(((
Pin) == ) ?  PORTD|=B00010000 : \
(((
Pin) == ) ?  PORTC|=B01000000 : \
(((
Pin) == ) ?  PORTD|=B10000000 : \
(((
Pin) == ) ?  PORTE|=B01000000 : \
(((
Pin) == ) ?  PORTB|=B00010000 : \
(((
Pin) == ) ?  PORTB|=B00100000 : \
(((
Pin) == 10 ) ? PORTB|=B01000000 : \
(((
Pin) == 11 ) ? PORTB|=B10000000 : \
(((
Pin) == 12 ) ? PORTD|=B01000000 : \
(((
Pin) == 13 ) ? PORTC|=B10000000 : \
(((
Pin) == 14 ) ? PORTF|=B10000000 : \
(((
Pin) == 15 ) ? PORTF|=B01000000 : \
(((
Pin) == 16 ) ? PORTF|=B00100000 : \
(((
Pin) == 17 ) ? PORTF|=B00010000 : \
(((
Pin) == 18 ) ? PORTF|=B00000010 PORTF |=B00000001)))))))))))))))))));
}

void D_Low(uint16_t Pin)
{
(((
Pin) == ) ? PORTD&=B11111011 : \
(((
Pin) == ) ? PORTD&=B11110111 : \
(((
Pin) == ) ? PORTD&=B11111101 : \
(((
Pin) == ) ? PORTD&=B11111110 : \
(((
Pin) == ) ? PORTD&=B11101111 : \
(((
Pin) == ) ? PORTC&=B10111111 : \
(((
Pin) == ) ? PORTD&=B01111111 : \
(((
Pin) == ) ? PORTE&=B10111111 : \
(((
Pin) == ) ? PORTB&=B11101111 : \
(((
Pin) == ) ? PORTB&=B11011111 : \
(((
Pin) == 10 ) ? PORTB&=B10111111 : \
(((
Pin) == 11 ) ? PORTB&=B01111111 : \
(((
Pin) == 12 ) ? PORTD&=B10111111 : \
(((
Pin) == 13 ) ? PORTC&=B01111111 : \
(((
Pin) == 14 ) ? PORTF&=B01111111 : \
(((
Pin) == 15 ) ? PORTF&=B10111111 : \
(((
Pin) == 16 ) ? PORTF&=B11011111 : \
(((
Pin) == 17 ) ? PORTF&=B11101111 : \
(((
Pin) == 18 ) ? PORTF&=B11111101 PORTF&=B11111110)))))))))))))))))));
}

void D_High2(uint16_t Pin)
{switch (
Pin) {
case 
0:PORTD |=B00000100; break;
case 
1:PORTD |=B00001000; break;
case 
2:PORTD |=B00000010; break;
case 
3:PORTD |=B00000001; break;
case 
4:PORTD |=B00010000; break;
case 
5:PORTC |=B01000000; break;
case 
6:PORTD |=B10000000; break;
case 
7:PORTE |=B01000000; break;
case 
8:PORTB |=B00010000; break;
case 
9:PORTB |=B00100000; break;
case 
10:PORTB |=B01000000; break;
case 
11:PORTB |=B10000000; break;
case 
12:PORTD |=B01000000; break;
case 
13:PORTC |=B10000000; break;
case 
14:PORTF |=B10000000; break;
case 
15:PORTF |=B01000000; break;
case 
16:PORTF |=B00100000; break;
case 
17:PORTF |=B00010000; break;
case 
18:PORTF |=B00000010; break;
case 
19:PORTF |=B00000001; break;}
};


void D_Low2(uint16_t Pin)
{switch (
Pin
{
case 
0:PORTD &=B11111011; break;
case 
1:PORTD &=B11110111; break;
case 
2:PORTD &=B11111101; break;
case 
3:PORTD &=B11111110; break;
case 
4:PORTD &=B11101111; break;
case 
5:PORTC &=B10111111; break;
case 
6:PORTD &=B01111111; break;
case 
7:PORTE &=B10111111; break;
case 
8:PORTB &=B11101111; break;
case 
9:PORTB &=B11011111; break;
case 
11:PORTB &=B01111111; break;
case 
12:PORTD &=B10111111; break;
case 
13:PORTC &=B01111111; break;
case 
14:PORTF &=B01111111; break;
case 
15:PORTF &=B10111111; break;
case 
16:PORTF &=B11011111; break;
case 
17:PORTF &=B11101111; break;
case 
18:PORTF &=B11111101; break;
case 
19:PORTF &=B11111110; break;}
};  

void D_Pin2(uint16_t Pinuint16_t Status)
{if(
Status==0){D_Low2(Pin);} else {D_High2(Pin);};
};

void D_Pin(uint16_t Pinuint16_t Status)
{if(
Status==0){D_Low(Pin);} else {D_High(Pin);};
}; 
написал вот такой скетч для проверки скорости
PHP код:
#include <digitalIOPerformance.h>
#include "CyberLib.h"

uint16_t led=19;
unsigned long Time;
uint16_t Sig1=0;
uint16_t Sig2=1;

void setup()

  
Serial.begin(57600);
  
pinMode(ledOUTPUT); //Настраиваем пин  на выход
}

void loop()

  
delay(10000);
  
Serial.print("*********Port Nomer - "); Serial.println(led,DEC); 

  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
digitalWrite(ledHIGH); digitalWrite(ledLOW);};
  
Serial.print("1 Standart arduino -  "); 
  
Serial.println((millis()-Time),DEC);
  
  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
digitalWriteFast(191); digitalWriteFast(190);};
  
Serial.print("2 digitalIOPerformance port constanta  -  "); 
  
Serial.println((millis()-Time),DEC);
  
  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
digitalWriteFast(led1); digitalWriteFast(led0);};
  
Serial.print("3 digitalIOPerformance port peremennaya  -  "); 
  
Serial.println((millis()-Time),DEC);
  
  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
D19_InvD19_Inv;};
  
Serial.print("4 CyberLib from Dx_Inv -  "); 
  
Serial.println((millis()-Time),DEC);
  
  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
D19_HighD19_Low;};
  
Serial.print("5 CyberLib from Dx_High and Low -  "); 
  
Serial.println((millis()-Time),DEC);
  
  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
D_High(led); D_Low(led);};
  
Serial.print("6 CyberLib port peremennaya variant 1  -  "); 
  
Serial.println((millis()-Time),DEC);
  
  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
D_High2(led); D_Low2(led);};
  
Serial.print("7 CyberLib port peremennaya variant 2  -  "); 
  
Serial.println((millis()-Time),DEC);
  
  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
D_Pin(ledSig1); D_Pin(ledSig2);};
  
Serial.print("8 CyberLib port i znachenie peremennaya variant 1  -  "); 
  
Serial.println((millis()-Time),DEC);
  
  
Time=millis();
  for (
long i=0<= 1000000i++)
  {
D_Pin2(ledSig1); D_Pin2(ledSig2);};
  
Serial.print("8 CyberLib port i znachenie peremennaya variant 2  -  "); 
  
Serial.println((millis()-Time),DEC);
  


Попробовал на разных портах и получил такие результаты
PHP код:
*********Port Nomer 0
1 Standart arduino 
-  10449
2 digitalIOPerformance port constanta  
-  1077
3 digitalIOPerformance port peremennaya  
-  10450
4 CyberLib from Dx_Inv 
-  1204
5 CyberLib from Dx_High 
and Low -  1077
6 CyberLib port peremennaya variant 1  
-  3104
7 CyberLib port peremennaya variant 2  
-  4876
8 CyberLib port i znachenie peremennaya variant 1  
-  4941
8 CyberLib port i znachenie peremennaya variant 2  
-  6713 
*********Port Nomer 9
1 Standart arduino 
-  13868
2 digitalIOPerformance port constanta  
-  1077
3 digitalIOPerformance port peremennaya  
-  13868
4 CyberLib from Dx_Inv 
-  1205
5 CyberLib from Dx_High 
and Low -  1077
6 CyberLib port peremennaya variant 1  
-  7662
7 CyberLib port peremennaya variant 2  
-  4877
8 CyberLib port i znachenie peremennaya variant 1  
-  9499
8 CyberLib port i znachenie peremennaya variant 2  
-  6714 
*********Port Nomer 19
1 Standart arduino 
-  10448
2 digitalIOPerformance port constanta  
-  1078
3 digitalIOPerformance port peremennaya  
-  10448
4 CyberLib from Dx_Inv 
-  1205
5 CyberLib from Dx_High 
and Low -  1077
6 CyberLib port peremennaya variant 1  
-  12349
7 CyberLib port peremennaya variant 2  
-  4877
8 CyberLib port i znachenie peremennaya variant 1  
-  14185
8 CyberLib port i znachenie peremennaya variant 2  
-  6712 
Bulatovor вне форума   Ответить с цитированием
Старый 15.06.2014, 18:21   #110
Bulatovor
Senior Member
 
Регистрация: 20.01.2013
Адрес: Уфа
Сообщений: 444
Вес репутации: 799
Bulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond reputeBulatovor has a reputation beyond repute
По умолчанию Re: Ускоряем работу Arduino

Итак, что у нас получилось:
digitalIOPerformance при явном указании пина работает точно с такой же скоростью как CyberLib, а при указании пина переменной падает до скорости Ардуины, т.е. меняем шило на мыло, а нужного результата не добились. почему в CiberLib Inv работает чуть-чуть, но медленнее High и Low интересно, но особенно не важно.
Из мною написанного самый лучший вариант это первый -написанный вчера -обозначенный как вариант два, да на первых 3 пинах он чуть чуть проигрывает варианту 1, но он стабилен- на всех портах одинаковая скорость, а у варианта 1 растет и в конце концов становиться медленнее родной ардуино. Так что вот так. На данном этапе получили скорость почти в два раза выше чем arduino, до новых чужих идей остановлюсь на этом.
Bulatovor вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 19 (пользователей: 0 , гостей: 19)
 

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Текущее время: 01:53. Часовой пояс GMT +3.


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Яндекс.Метрика