|
Извлечение корня и возведение в квадрат в AVR, как быстрее |
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Jul 14 2008, 11:30
|

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

|
Цитата(yanita @ Jul 14 2008, 14:06)  Здравствуйте всем. У меня возникла следующая задача. В цепи обратной связи мне надо произвести ряд арифметических преобразований, в том числе излечение корня и возведение в квадрат. Как это можно сделать максимально быстро на одном из микроконтроллеров AVR (извлечь корень и возвести в квадрат)? Ну квадрат - это просто умножить число на себя, не вижу проблем. Если у выбранного AVR нет аппаратного умножения - то традиционно, сложениями и сдвигами. Корень - целочисленный - вычисляется вычитаниями и сдвигами, обсуждался много раз, искать надо. Например, тут или тут
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 14 2008, 11:59
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 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 ;******************************************************************************
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 16 2008, 06:38
|

Народный чинитель
  
Группа: Участник
Сообщений: 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 вне этого интервала, осуществляется масштабирование.
|
|
|
|
|
Jul 16 2008, 09:42
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(yanita @ Jul 14 2008, 15:06)  В цепи обратной связи мне надо произвести ряд арифметических преобразований, в том числе излечение корня и возведение в квадрат. Как это можно сделать максимально быстро на одном из микроконтроллеров AVR (извлечь корень и возвести в квадрат)? Сделать быстро при таком варианте не получится. Мой опыт подсказывает, что надо поработать над алгоритмами регулирования. Альтернативное предложение или идея. Возможно системе регулирования для качественного регулирования можно сделать перерасчет входного сигнала под датчик, т.е. обратное преобразование. Тогда не требуется скоростная обработка в контуре регулирования. Для индикации можно медленно пересчитать сигнал датчика по Вашим алгоритмам.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|