реклама на сайте
подробности

 
 
> Усреднение значений энкодера, Как посчитать среднее около нуля?
Corvus
сообщение Jun 14 2013, 17:33
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 24-04-08
Из: Зеленоград
Пользователь №: 37 056



Добрый день!

Есть инкрементный энкодер - разрядность 14 бит. Из-за несовершенства механики значения немного дрожат. Примерно на 1-3 значения. Чтобы избавиться от этого вычисляю арифметическое среднее для нескольких измерений. И всё бы хорошо, но в окрестности нуля такой путь не работает. Т.е. имеем набор значений 0, 0, 1, 16383, 0. После усреднения получим 3277 sad.gif

Собственно, вопрос: как лучше всего обойти эту ситуацию?
Пока вижу единственный путь - считать обороты и использовать их как старшие биты для значения текущего положения. А потом усреднять.

Но может быть есть способ проще? Задача выглядит стандартной, но что-то ничего путного не нагуглилось. Может не так ищу...

Заранее спасибо.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
toweroff
сообщение Jun 14 2013, 18:18
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Я бы поступил так. Если значение от предыдущего усредненного (или просто предыдущего) "скачет" гораздо больше, чем величина "люфта", то ее вообще не воспринимать
Go to the top of the page
 
+Quote Post
BvDV
сообщение Jun 14 2013, 18:50
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 80
Регистрация: 8-12-12
Из: Б.М.
Пользователь №: 74 760



может быть что то типа этого

код содран от сюда
Код
#include<math.h>
#include<stdio.h>

double
meanAngle (double *angles, int size)
{
  double y_part = 0, x_part = 0;
  int i;

  for (i = 0; i < size; i++)
    {
      x_part += cos (angles[i] * M_PI / 180);
      y_part += sin (angles[i] * M_PI / 180);
    }

  return atan2 (y_part / size, x_part / size) * 180 / M_PI;
}

int
main ()
{
  double angleSet1[] = { 350, 10 };
  double angleSet2[] = { 90, 180, 270, 360};
  double angleSet3[] = { 10, 20, 30};

  printf ("\nMean Angle for 1st set : %lf degrees", meanAngle (angleSet1, 2));
  printf ("\nMean Angle for 2nd set : %lf degrees", meanAngle (angleSet2, 4));
  printf ("\nMean Angle for 3rd set : %lf degrees\n", meanAngle (angleSet3, 3));
  return 0;
}
Output:
Mean Angle for 1st set : -0.000000 degrees
Mean Angle for 2nd set : -90.000000 degrees
Mean Angle for 3rd set : 20.000000 degrees
Go to the top of the page
 
+Quote Post
toweroff
сообщение Jun 14 2013, 19:17
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(BvDV @ Jun 14 2013, 22:50) *
может быть что то типа этого

круто!

однако, у ТС целочисленные значения, дабл ему не уперся ни в куда (да еще cos с sin, да еще деление...), да и копипастить тут все могут
осмыслите, что пишет человек - значения от 0 до 16384. Логический 0 - это около 16384 и 0. Т.е. 3-2-1-0-16384-16383-16382

кстати.. я тут тоже маху дал.
не будет моя идея работать.. надо еще подумать sm.gif

ТС, объясните задачу по-конкретнее. Есть у устройства этот самый "0" или нет, должен ли счет остановиться на этом "0" или спокойно может идти в одну или другую сторону
Go to the top of the page
 
+Quote Post
Corvus
сообщение Jun 15 2013, 06:43
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 24-04-08
Из: Зеленоград
Пользователь №: 37 056



Цитата(toweroff @ Jun 14 2013, 23:17) *
ТС, объясните задачу по-конкретнее. Есть у устройства этот самый "0" или нет, должен ли счет остановиться на этом "0" или спокойно может идти в одну или другую сторону


Устройство - это энкодер. Ноль, разумеется, есть. Крутиться может в любую сторону. Значение считывается в любой произвольный момент.

BvDV
Вот это близко к тому, что нужно. a14.gif Но сложность вычисления убивает. Попробую поискать в этом направлении, может есть более простые способы.

Про знаковые-беззнаковые была идея, но это, действительно, только перемещает проблему по оси в другую точку.

Про медианную фильтрацию - можно, конечно. Но, неужели, нет более элегантного и простого решения? wacko.gif
Go to the top of the page
 
+Quote Post
adnega
сообщение Jun 15 2013, 07:46
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Ввод цифр от 0 до 9 при помощи энкодера (по типу сейфового замка: "5 по часовой, 3 против часовой").
Может, идея Вам поможет.
CODE

pos = TIM3->CNT; // считываем положение энкодера

if((pos > (encoder_position + (1<<ENCODER_SENCE) - 1))
&&((pos - encoder_position)<((ENCODER_MAX<<ENCODER_SENCE)>>1)))
{
//pos
if(enc_dir == -1)
{
#ifdef ENCODER_DEBUG
tx0_push('#');
tx0_push(' ');
#endif //ENCODER_DEBUG

tx0_dec(enc_num);

#ifdef ENCODER_DEBUG
tx0_push(' ');
tx0_push('#');
#endif //ENCODER_DEBUG

tx0_start();
enc_num = 0;
}
enc_time = 0;
enc_dir = 1;

enc_num += (pos - encoder_position)>>ENCODER_SENCE;

if(enc_num >= 10)
{
enc_num = 0;
}

#ifdef ENCODER_DEBUG
tx0_push('[');
tx0_dec(enc_num);
tx0_push(']');
tx0_start();
#endif //ENCODER_DEBUG

encoder_position = pos;
}else if((pos < (encoder_position - (1<<ENCODER_SENCE) + 1))
&&((encoder_position - pos)>((ENCODER_MAX<<ENCODER_SENCE)>>1)))
{
//pos
if(enc_dir == -1)
{
#ifdef ENCODER_DEBUG
tx0_push('#');
tx0_push(' ');
#endif //ENCODER_DEBUG

tx0_dec(enc_num);

#ifdef ENCODER_DEBUG
tx0_push(' ');
tx0_push('#');
#endif //ENCODER_DEBUG

tx0_start();
enc_num = 0;
}
enc_time = 0;
enc_dir = 1;

enc_num += (pos + (ENCODER_MAX<<ENCODER_SENCE) - encoder_position)>>ENCODER_SENCE;

if(enc_num >= 10)
{
enc_num = 0;
}

#ifdef ENCODER_DEBUG
tx0_push('<');
tx0_dec(enc_num);
tx0_push('>');
tx0_start();
#endif //ENCODER_DEBUG

encoder_position = pos;
}else if((pos < (encoder_position - (1<<ENCODER_SENCE) + 1))
&&((encoder_position - pos)<((ENCODER_MAX<<ENCODER_SENCE)>>1)))
{
//neg
if(enc_dir == 1)
{
#ifdef ENCODER_DEBUG
tx0_push('#');
tx0_push(' ');
#endif //ENCODER_DEBUG

tx0_dec(enc_num);

#ifdef ENCODER_DEBUG
tx0_push(' ');
tx0_push('#');
#endif //ENCODER_DEBUG

tx0_start();
enc_num = 0;
}
enc_time = 0;
enc_dir = -1;

enc_num += (encoder_position - pos)>>ENCODER_SENCE;

if(enc_num >= 10)
{
enc_num = 0;
}

#ifdef ENCODER_DEBUG
tx0_push('(');
tx0_dec(enc_num);
tx0_push(')');
tx0_start();
#endif //ENCODER_DEBUG

encoder_position = pos;
}else if((pos < (encoder_position + (ENCODER_MAX<<ENCODER_SENCE) - (1<<ENCODER_SENCE) + 1))
&&((pos - encoder_position)>((ENCODER_MAX<<ENCODER_SENCE)>>1)))
{
//neg
if(enc_dir == 1)
{
#ifdef ENCODER_DEBUG
tx0_push('#');
tx0_push(' ');
#endif //ENCODER_DEBUG

tx0_dec(enc_num);

#ifdef ENCODER_DEBUG
tx0_push(' ');
tx0_push('#');
#endif //ENCODER_DEBUG

tx0_start();
enc_num = 0;
}
enc_time = 0;
enc_dir = -1;

enc_num += (encoder_position + (ENCODER_MAX<<ENCODER_SENCE) - pos)>>ENCODER_SENCE;

if(enc_num >= 10)
{
enc_num = 0;
}

#ifdef ENCODER_DEBUG
tx0_push('{');
tx0_dec(enc_num);
tx0_push('}');
tx0_start();
#endif //ENCODER_DEBUG

encoder_position = pos;
}

if(enc_time < (TO_SEC * 2))
{
enc_time++;
if(enc_time == ((TO_SEC * 2)))
{
#ifdef ENCODER_DEBUG
tx0_push('#');
tx0_push(' ');
#endif //ENCODER_DEBUG

tx0_dec(enc_num);

#ifdef ENCODER_DEBUG
tx0_push(' ');
tx0_push('#');
#endif //ENCODER_DEBUG

tx0_str("\n\r");
tx0_start();
enc_dir = 0;
enc_num = 0;
}
}

Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Corvus   Усреднение значений энкодера   Jun 14 2013, 17:33
- - cant   наиболее просто сделать исключение и принять 2-1-0...   Jun 14 2013, 19:21
|- - toweroff   Цитата(cant @ Jun 14 2013, 23:21) наиболе...   Jun 14 2013, 20:00
- - RabidRabbit   Может медианная фильтрация подойдёт?   Jun 14 2013, 22:22
|- - MaslovVG   В промышленных CNC Для определения положения по да...   Jun 17 2013, 05:18
- - ar__systems   КодMixedSigns = (V1 | V2 | V3 | V4) ^ ...   Jun 15 2013, 05:54
- - Iptash   У вас же не на большую велечину прыгают, если посл...   Jun 15 2013, 07:44
- - Alex11   А если по-простому? У Вас же не бывает скачков на ...   Jun 15 2013, 09:15
|- - Corvus   adnega Спасибо. Сейчас попробую разобраться. Цита...   Jun 15 2013, 11:44
- - Fujitser   Просто используйте числа со знаком. Тогда 16384 пр...   Jun 16 2013, 10:14
|- - ae_   Цитата(Fujitser @ Jun 16 2013, 19:14) Про...   Jun 16 2013, 12:19
- - АНТОН КОЗЛОВ   Обрабатывая сигналы от ветряка, аналогичные эконде...   Jun 16 2013, 17:37
- - ViKo   Весь диапазон значений энкодера 0...16384 разбивае...   Jun 17 2013, 08:29
- - maksimp   Код#define N 5 uint16_t x[N]; // их будем ...   Jun 20 2013, 18:55


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th July 2025 - 09:13
Рейтинг@Mail.ru


Страница сгенерированна за 0.01461 секунд с 7
ELECTRONIX ©2004-2016