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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Извлечение корня и возведение в квадрат в AVR, как быстрее
yanita
сообщение Jul 14 2008, 11:06
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 9-02-08
Из: Украина
Пользователь №: 34 891



Здравствуйте всем.
У меня возникла следующая задача. В цепи обратной связи мне надо произвести ряд арифметических преобразований, в том числе излечение корня и возведение в квадрат. Как это можно сделать максимально быстро на одном из микроконтроллеров AVR (извлечь корень и возвести в квадрат)?
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 14 2008, 11:28
Сообщение #2


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



#include <math.h>

корень - sqrt
квадрат x*x.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 14 2008, 11:30
Сообщение #3


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(yanita @ Jul 14 2008, 14:06) *
Здравствуйте всем.
У меня возникла следующая задача. В цепи обратной связи мне надо произвести ряд арифметических преобразований, в том числе излечение корня и возведение в квадрат. Как это можно сделать максимально быстро на одном из микроконтроллеров AVR (извлечь корень и возвести в квадрат)?

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


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
777777
сообщение Jul 14 2008, 11:36
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(yanita @ Jul 14 2008, 15:06) *
У меня возникла следующая задача. В цепи обратной связи мне надо произвести ряд арифметических преобразований, в том числе излечение корня и возведение в квадрат. Как это можно сделать максимально быстро на одном из микроконтроллеров AVR (извлечь корень и возвести в квадрат)?


А числа целые или с плавающей точкой? Если с плавающей, то написать на Си, а если целые (или с фиксированной точкой), то искать "алгорим Ньютона" для извлечения корня.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 14 2008, 11:59
Сообщение #5


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(777777 @ Jul 14 2008, 14:36) *
А числа целые или с плавающей точкой? Если с плавающей, то написать на Си, а если целые (или с фиксированной точкой), то искать "алгорим Ньютона" для извлечения корня.
У AVR нет аппаратного деления. Оно реализовано через вычитания и сдвиги. И корень можно вычислять через вычитания и сдвиги.
Только при этом для деления число проходов цикла равно числу разрядов числа, а для корня - в два раза меньше. Правда, там ещё другие расходы есть (дополнительные операции ИЛИ, ещё один сдвиг), да и сдвиг на два у AVR реализуется как два сдвига на 1, итого вычисление корня по времени будет не в два раза быстрее программного деления, а близко к нему.
А "по Ньютону" нужно будет несколько делений, что будет в несколько раз дольше.
Обратите внимание на обсуждение по первой приведенной мной ссылке - там корень через вычитания/сдвиги оказался не медленнее "Ньютона" даже на 80386, который имеет аппаратное деление (впрочем, не слишком быстрое, но всё равно быстрее, чем программное через вычитания и сдвиги).

p.s. Александр Труш когда-то публиковал корень именно для AVR именно на асме. И где-то его недавно цитировали. Надо поискать.

Нашёл в своих завалах.
Ага, ещё и 24-битный аргумент. Видать, ему надо было именно столько (например, сумма не слишком болшьшого количества квадратов 10-битных отсчётов АЦП - 16 дико мало, 32 дико много).

Код
;*******************************************************************************
*********************
;*
;*           Подпрограмма вычисления квадратного корня для 24-ти битного аргумента                  *
;*          (c) 1998 Alexander Trush   http://trush.da.ru   trush@ropnet.ru   2:5020/392.40
;*
;    Вы можете свободно использовать, распространять, модифицировать этот
;    код до тех пор, пока вы указываете моё авторство и распространяете
;    это требование. Кроме того, я хотел бы получать уведомление о
;    применении этого кода по e-mail (trush@kbotd.ru).

sqrt24:         ldi     mask,1; Используем маску в регистре, т.к. команды EORI нет...
        ldi     count,12; Последний бит значения корня не требует специального
            ; подхода - есть запас от потери битов аж 4 бита
        clr16   work_h, work_l
        clr16   dist_h, dist_l; Очистка накопителя значения корня


sqrt24_1:       cpi     src_h, 64
        cpc     work_l, dist_l
        cpc     work_h, dist_h
        brcs    sqrt24_2
          subi  src_h, 64
          sbc   work_l, dist_l
          sbc   work_h, dist_h
sqrt24_2:       rol     dist_l      
        rol     dist_h      
        eor     dist_l, mask; Инверсия младшего бита значания корня,
            ; т.к. при заёме должны писать 0, и 1 при отсутствии
        lsl     src_l; Сдвиг аргумента на 2 бита
        rol     src_m; work_h:work_l:src_h:src_m:src_l <<= 2
        rol     src_h
        rol     work_l
        rol     work_h

        lsl     src_l
        rol     src_m
        rol     src_h
        rol     work_l
        rol     work_h

        dec     count; Получили ли все биты значения корня кроме последнего?..
        brne    sqrt24_1

        cp      dist_l, work_l
        cpc     dist_h, work_h
        adc     dist_l, src_m; Команды ADCI нет, а src_m точно здесь равен 0
        adc     dist_h, src_m
        ret
;******************************************************************************


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
mse
сообщение Jul 15 2008, 07:28
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 709
Регистрация: 3-05-05
Пользователь №: 4 693



Цитата(ReAl @ Jul 14 2008, 15:59) *
... Видать, ему надо было именно столько (например, сумма не слишком болшьшого количества квадратов 10-битных отсчётов АЦП - 16 дико мало, 32 дико много).
...

24р это стандартная длина мантиссы. ;О). Видно, поэтому.
Go to the top of the page
 
+Quote Post
777777
сообщение Jul 15 2008, 10:22
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(ReAl @ Jul 14 2008, 15:59) *
Код
        clr16   work_h, work_l
        clr16   dist_h, dist_l; Очистка накопителя значения корня


Еще бы выяснить, что такое clr16...
Go to the top of the page
 
+Quote Post
Kovrov
сообщение Jul 15 2008, 11:37
Сообщение #8


Мастер-фломастер
****

Группа: Свой
Сообщений: 611
Регистрация: 29-12-05
Пользователь №: 12 700



ну наверное это
clr work_h
clr work_l


--------------------
Вон ПОПОВ, клоун клоуном, а радио изобрел!!
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 15 2008, 13:30
Сообщение #9


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(mse @ Jul 15 2008, 10:28) *
24р это стандартная длина мантиссы. ;О). Видно, поэтому.
В этом случае, не сомневаюсь, он бы выложил и нормализацию, и работу с порядком.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
jasper
сообщение Jul 16 2008, 06:38
Сообщение #10


Народный чинитель
***

Группа: Участник
Сообщений: 415
Регистрация: 15-07-05
Пользователь №: 6 811



Быстрый, но не очень точный способ извлечения корня:
Fast square root in C

Можно обойтись и без делений, если использовать аппроксимацию.
Для 0.5 <= x <= 1
sqrt(x) = 1.454895*x – 1.34491*x^2 + 1.106812*x^3 – 0.536499*x^4 + 0.1121216*x^5 + 0.2075806
Для значений x вне этого интервала, осуществляется масштабирование.
Go to the top of the page
 
+Quote Post
alexander55
сообщение Jul 16 2008, 09:42
Сообщение #11


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(yanita @ Jul 14 2008, 15:06) *
В цепи обратной связи мне надо произвести ряд арифметических преобразований, в том числе излечение корня и возведение в квадрат. Как это можно сделать максимально быстро на одном из микроконтроллеров AVR (извлечь корень и возвести в квадрат)?

Сделать быстро при таком варианте не получится. Мой опыт подсказывает, что надо поработать над алгоритмами регулирования.
Альтернативное предложение или идея.
Возможно системе регулирования для качественного регулирования можно сделать перерасчет входного сигнала под датчик, т.е. обратное преобразование. Тогда не требуется скоростная обработка в контуре регулирования.
Для индикации можно медленно пересчитать сигнал датчика по Вашим алгоритмам.
Go to the top of the page
 
+Quote Post
SpyBot
сообщение Jul 16 2008, 13:58
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 285
Регистрация: 5-11-05
Пользователь №: 10 491



Неплохо бы уточнить, чем измеряем. Возможно, можно будет обойтись табличкой.
Go to the top of the page
 
+Quote Post
alexander55
сообщение Jul 17 2008, 04:41
Сообщение #13


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(SpyBot @ Jul 16 2008, 17:58) *
Неплохо бы уточнить, чем измеряем. Возможно, можно будет обойтись табличкой.

Если озназначная функция и только одного параметра (датчика), то это хороший вариант.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jul 17 2008, 08:46
Сообщение #14


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(alexander55 @ Jul 16 2008, 12:42) *
Сделать быстро при таком варианте не получится. Мой опыт подсказывает, что надо поработать над алгоритмами регулирования.


Началось за здравие, кончилось за упокой.
1. Алгоритмы регулирования - может быть FUZZY logic будет проще.
2. Не верю в то, что автору надо больше разрядов, чем в uint16_t. В таком случае посчитаем: умножение 16*16 =18 тактов. При поразрядном уравновешивании имеем 16*18 =288 тактов+пересылка и сравнение. Скажем, выйдет чуть более 300 тактов. Это почти 20 мкс на 16МГц. Это долго?!
Go to the top of the page
 
+Quote Post
yanita
сообщение Jul 17 2008, 14:48
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 9-02-08
Из: Украина
Пользователь №: 34 891



Спасибо всем за помощь. Дело в том, что я не особо в микроконтроллерах разбираюсь. Структура измерительная, поэтому пожертвовать точностью никак не могу. Алгоритм измерения состоит из нескольких тактов и математической обработки, где и нужен корень. Математическая обработка не последующая, а в режиме измерения, поэтому обратная цепь становится инерцинной. Вот и хотелось бы добиться максимального быстродействия. Особенно интересует, насколько зависит быстродействие от алгоритмов того же деления и излечения корня. И еще какая разница, программировать контроллер на С или на асемблере, влияет ли на быстродействие?
Go to the top of the page
 
+Quote Post

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

 


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


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