Оптимизация алгоритма обработки ДПКВ
Posted: Mon Jan 16, 2012 4:32 pm
				
				(Optimization of CKP sensor processing)
Посвящаю эту тему вопросам оптимизации существующего алгоритма обработки датчика положения коленвала (ДПКВ). Смотреть файл ckps.c
Первая часть алгоритма, которая требует оптимизации это 32-х битное деление, добавляющее к времени обработки прерывания 25...40мкс.
Тут viewtopic.php?f=52&t=1238&start=50 участник по имени teuer предложил замену:
- OCR1A = GetICR() + ((uint32_t)diff * (ckps.period_curr)) / ANGLE_MAGNITUDE(CKPS_DEGREES_PER_COG);
+ OCR1A = GetICR() + (((((uint32_t)diff * (ckps.period_curr))>>8) * 0x15556)>>16);
Чтобы проверить его версию, я написал специальную программку на С. Ее я компилировал и запускал на настольном компьютере. Программка перебирает все возможные комбинации входных параметров и строит гистограмму ошибок.
Предложенный вариант непригоден к использованию, так как дает очень много ошибок.
Код программы:
			Посвящаю эту тему вопросам оптимизации существующего алгоритма обработки датчика положения коленвала (ДПКВ). Смотреть файл ckps.c
Первая часть алгоритма, которая требует оптимизации это 32-х битное деление, добавляющее к времени обработки прерывания 25...40мкс.
Тут viewtopic.php?f=52&t=1238&start=50 участник по имени teuer предложил замену:
- OCR1A = GetICR() + ((uint32_t)diff * (ckps.period_curr)) / ANGLE_MAGNITUDE(CKPS_DEGREES_PER_COG);
+ OCR1A = GetICR() + (((((uint32_t)diff * (ckps.period_curr))>>8) * 0x15556)>>16);
Чтобы проверить его версию, я написал специальную программку на С. Ее я компилировал и запускал на настольном компьютере. Программка перебирает все возможные комбинации входных параметров и строит гистограмму ошибок.
Предложенный вариант непригоден к использованию, так как дает очень много ошибок.
Код программы:
Code: Select all
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main(void)
{
  uint16_t value_1;
  uint16_t value_2;
  uint16_t ICR = 1024;
  uint16_t p_c = 5076;
  uint16_t diff = 8234;
  #define ERR_MAX 256
  uint32_t errors[ERR_MAX+2];
  memset(errors, 0, sizeof(int)*(ERR_MAX+2));
  int i,j;
  uint32_t max_error = 0;
  //collect statistics
  for(i = 0; i < 65536; ++i)
  {
    for(j = 0; j < 65536; ++j)
    {
      diff = i, p_c = j;
      //-------------------------------------------------------------------
      value_1 = ICR + ((uint32_t)diff * p_c) / (32*6);
      value_2 = ICR + (((((uint32_t)diff * p_c)>>8) * 0x15556)>>16);
      //-------------------------------------------------------------------
      if (value_1 != value_2)
      {
        uint32_t error = abs((int32_t)value_1 - (int32_t)value_2);
        if (error > max_error)
          max_error = error;
//      printf("%u ", (int)error);
        if (error > ERR_MAX)
          error = ERR_MAX;
        errors[error]++;
      }
    }
  }
  //print statistics
  printf("\nerrors flow:\n");
  for(i = 1; i < ERR_MAX+1; ++i)
    printf("%u ", (int)errors[i]);
  printf("\n");
  printf("max. detected error = %u\n", max_error);
}