goodking
|
|
« : 26-05-2011 14:50 » |
|
Привет, пишу прогу для МК. Цель-генерация ШИМ сигналов. Проблема следующая.
double high; unsigned int fin; int z; for (z=1;z<=10;z++) { high=sin((2*PI/10)*z); high=high*100; if (high>0) { fin=high; PCA0CPH0=128+fin; } else { fin=high; PCA0CPH0=128-fin; } } В даном случае функция sin выдает некорректные значения. В чем может быть проблема?
|
|
|
Записан
|
|
|
|
Sla
|
|
« Ответ #1 : 26-05-2011 15:02 » |
|
хех
а не проще ли рассчитать синусоиду заранее, сохранить в таблице, а затем по индексу вытягивать?
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
baldr
|
|
« Ответ #2 : 26-05-2011 15:07 » |
|
goodking, а что значит "неправильные"? И именно ли функция sin(), а не твой код? В каком месте ты снимаешь показания?
|
|
|
Записан
|
Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
|
|
|
Ochkarik
|
|
« Ответ #3 : 26-05-2011 17:39 » |
|
goodking, просто интересно... а зачем вам такая дикая связь между синусоидой и широтно-импульсной модуляцией?))))
PS кстати, классный микроконтроллер с поддержкой float point... дайте два!)
PPS прикольно с преобразованиями должно выглядеть. из double в unsigned int....
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
goodking
|
|
« Ответ #4 : 27-05-2011 06:39 » |
|
Прошу прощения за несвоевременный ответ =)). По порядку а не проще ли рассчитать синусоиду заранее, сохранить в таблице, а затем по индексу вытягивать? дело в том, что я никогда раньше не работал с ШИМ, пока просто прикидываю, как оно будет. просто интересно... а зачем вам такая дикая связь между синусоидой и широтно-импульсной модуляцией?)))) связь такая, что скважность ШИМ сигнала должна изменяться по синусоидальному закону, задается количество периодов в секунду, ну и количество ШИМ импульсов... PS кстати, классный микроконтроллер с поддержкой float point... дайте два!) silabs, а что, еще есть такие, что не поддерживают PPS прикольно с преобразованиями должно выглядеть. из double в unsigned int.... согласен, но это так прикидка, если посоветуете, как значение в 8-битном регистре изменять пропорционально полученному значению double буду благодарен а что значит "неправильные"? И именно ли функция sin(), а не твой код? В каком месте ты снимаешь показания? то-есть сначала я посчитал вручную. в отладочном окне смотрю значение переменной в этом месте. С тем, что должно быть не совпадает. =)
|
|
|
Записан
|
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #5 : 27-05-2011 06:52 » |
|
Попробуй явно указывать double для операций. Также вынеси PI на первое место, что бы выражение интерпретировалось как float: high=sin((PI*2/10)*double(z) ); high=high*100.0;
Какой прототип для sin()? Может, double не поддерживается, а только float? Может, h-файл с прототипом sin() не подключен, и компилятор не понимает, с чем работает sin(), и предполагает int sin(int) ?
|
|
« Последнее редактирование: 27-05-2011 06:55 от PredatorAlpha »
|
Записан
|
|
|
|
goodking
|
|
« Ответ #6 : 27-05-2011 07:21 » |
|
спасибо, с синусом вроде разобрался.
теперь вопрос, как это значение занести в регистр PCA0CPH0 ?
|
|
|
Записан
|
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #7 : 27-05-2011 12:17 » |
|
спасибо, с синусом вроде разобрался. теперь вопрос, как это значение занести в регистр PCA0CPH0 ?
Ну, неплохо было бы уточнить, что это за регистр и как он расположен - в памяти, на портах или как...... Наверняка в h-файлах он как-то описан, например #define PCA0CPH0 (*(volatile Uint16*)0x1234) Что означает 16-битный регистр расположенный по адресу 0х1234 (Естественно, вместо Uint16 может стоять что-то типа unsigned short) Тогда доступ к нему получается так: #include "mcregisters.h" ..... { PCA0CPH0 = 0x6655; // Записываем 0x6655 в регистр PCA0CPH0 } Если нет h-файлов, что описывают регистры, то можно описать самому. Если он в памяти - то так как выше, если на портах - смотри руководство по компилятору как организован доступ к портам. Если это не memory-mapped регистр и не портовый регистр, а регистр процессора, то разработчик компилятора должен описать способ доступа к такому, нередко это делается напрямую, хотя может быть и через inline-функции на ассемблере.
|
|
« Последнее редактирование: 27-05-2011 12:34 от PredatorAlpha »
|
Записан
|
|
|
|
Sla
|
|
« Ответ #8 : 27-05-2011 12:32 » |
|
в любом случае все должно быть сведено к целочисленному значению
синусоида сначала рассчитывается с определенным шагом (шаг определяется возможностью адресации) Причем ее не нужно рассчитывать от 0 до пи достаточно рассчитать от 0 до пи/2 Значения вычислять от квадранта x<=PI/2 - берем напрямую из таблицы PI/2<x<=PI инвертируем индекс и берем из таблицы PI<x<=PI*3/2 инвертируем индекс и берем из таблицы и инвертируем данные PI*3/2<x<=2PI инвертируем данные
ps если не ошибся...
|
|
« Последнее редактирование: 27-05-2011 12:37 от Sla »
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #9 : 27-05-2011 12:39 » |
|
Sla, не забывай что на МК памяти (оперативной) часто и килобайта нет... Для десятка пойдёт, но ведь это только предварительный пример.... Это надо специально рассчитанные таблицы к коду прилинковывать, записывать во flash вместе с программой, потом их отдельной подпрограммой, собственно для этого написанной, читать. Для новичка это может оказать непосильной задачей, что намертво прибъёт всё начинание программиста. Хотя так и стоит сделать. Хотя если подумать, то возиться с float на МК это очень большое извращение.
|
|
« Последнее редактирование: 27-05-2011 13:07 от PredatorAlpha »
|
Записан
|
|
|
|
goodking
|
|
« Ответ #10 : 27-05-2011 13:08 » |
|
Ну, неплохо было бы уточнить, что это за регистр и как он расположен - в памяти, на портах или как. это регистр- старший байт 16ти разрядного модуля захвата. ШИМ сигнал генерится следующим образом: В регистр PCA0CPH0 заносится величина захвата. Запускается таймер/счетчик. Если код таймера совпадает с кодом в регистре PCA0CPH0-ножка микроконтроллера устанавливается в высокий уровень. Когда величина счетчика достигает значения 0xff-на ножке устанавливается лог.0. То есть меняя значение в PCA0CPH0 меняем скважность выходного сигнала. Вообще-то можно использовать 16-ти разрядный ШИМ, но там частота сигнала получается 49MGz/65535=747Hz, а это мало, поэтому использую 8 битный. Вопрос как лучше значение регистра сравнения изменять пропорционально получаемой переменной double??
|
|
|
Записан
|
|
|
|
Sla
|
|
« Ответ #11 : 27-05-2011 13:20 » |
|
синусоида рассчитывается предварительно и хранится в коде... Так что ОЗУ здесь не очень-то и нужно.
Может я уже отстал, но что-то мне не встречались МК с плавающей запятой. Но даже если и есть, то все равно нужно переводить в целочисленное, для того чтоб, хотя бы записать или в порт, или в тот же регистр таймера
Судя по названию регистра PCA0CPH0 это что-то из 51-ой серии а там пока о флоат рано думать
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
goodking
|
|
« Ответ #12 : 27-05-2011 13:42 » |
|
PCA0CPH0 это что-то из 51-ой серии а там пока о флоат рано думать
ну почему, silabs 8051f120, все поддерживается. Память 2к функций, 64к прогр.
|
|
|
Записан
|
|
|
|
Sla
|
|
« Ответ #13 : 27-05-2011 13:59 » |
|
goodking, что поддерживается? float? а ну-ка командочку в студию...
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #15 : 27-05-2011 14:43 » |
|
Ну, если тебя не смущает, что вычисление синуса идёт от 823 до 5558 тактов, то вперёд!
Добавь ещё пару сотен тактов на умножение, и сотню на несколько преобразований int=>float и float=>int. И зацени время одного прохода по циклу. Кстати, команд я там не заметил... Только описание некоторых функций (программных!!) библиотеки.
|
|
« Последнее редактирование: 27-05-2011 14:52 от PredatorAlpha »
|
Записан
|
|
|
|
goodking
|
|
« Ответ #16 : 27-05-2011 14:52 » |
|
Ну, если тебя не смущает, что вычисление синуса идёт от 823 до 5558 тактов, то вперёд!
Добавь ещё пару сотен тактов на умножение, и сотню на несколько преобразований int=>float и float=>int. И зацени время одного прохода по циклу.
То-есть лучше вычислять синусоиду заранее?
|
|
|
Записан
|
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #17 : 27-05-2011 14:54 » |
|
То-есть лучше вычислять синусоиду заранее? Если есть время попить кофе, то можно и так....
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Online
Пол:
Пролетал мимо
|
|
« Ответ #18 : 27-05-2011 16:29 » |
|
Если нужно вычислить функцию синуса с постоянным приростом угла, То сушествует замечательная фунция в тригонометрии. sin(A+B) = sin(A) * cos(B) + cos(A) * sin(B) cos(A+B) = cos(A) * cos(B) - sin(A) * sin(B)
Т.е. действие вычисления следуюшего синуса сведется к 4 умножениям, 1 прибавлению и 1 отниманию.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 27-05-2011 16:43 » |
|
А ещё существуют таблицы Брадиса Уже давно посчитаны, осталось только найти электронный вариант (а у нас были такие жёлтые брошурки - всеобщая ненависть школьников )
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Online
Пол:
Пролетал мимо
|
|
« Ответ #20 : 27-05-2011 16:44 » |
|
Алексей1153++, Ну это то, что предлагал уже Слава
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 27-05-2011 16:53 » |
|
ну да )
кстати, в экселе за 5 минут вся эта таблица делается, а при желании - сразу в нужном для вставки в код форматированном виде.
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #22 : 27-05-2011 18:41 » |
|
в целочисленных процах синус(и вытекающие) считают четырмя методами. 1. по таблице, на четверть периода по фазе, с требуемым шагом - жрет много памяти, если нужна хоть какая то точность. 2. при помощи какой нибудь апроксимирующей функции. порядка 5-7го. довольно кривенько, но иногда прокатывает. иногда такие либы и идут комплекте (обнаружил в TMS) 3. по кордику - это классика жанра, описаний в нете полно должно быть. считается итеративно, но очень простой цикл. у меня точность 14бит получалось за 160тактов помоему, на TMS с двумя АЛУ. хотя на C51 не факт что это будет очень быстро. 4. сочетание таблицы с последующим уточнением по кордику - самый смак) любой компромисс между памятью, скоростью и точностью.
ЗЫ тема по-моему в раздел мк) PPS по кордику, это почти как Finch изложил)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Вад
|
|
« Ответ #23 : 27-05-2011 20:24 » |
|
Ochkarik, согласен, переношу тему в "Микроконтроллеры"
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #24 : 28-05-2011 09:01 » |
|
Silabs делает хорошие чипы, но система команд там по прежнему MCS-51. По этому будет много быстрее работать с фиксированной точкой, а не с плавающей. Я не про синусы, а про умножения (синусы надо через таблицы делать - 128..512 байт программной памяти на всю таблицу). Встроенный умножитель всего на 8 бит - потребуются функции работы с большей разрядностью.
Возвращаясь к базовой задаче. Очень хотелось бы увидеть словесное описание алгоритма, применительно к данному железу. Повторение синуса - не такая простая задача, как может показаться. Также хотелось бы услышать физические параметры: тактовая частота чипа, частота ШИМ, диапазон частот воспроизводимого через ШИМ сигнала.
|
|
« Последнее редактирование: 28-05-2011 09:06 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #25 : 28-05-2011 12:01 » |
|
Т.е. действие вычисления следуюшего синуса сведется к 4 умножениям, 1 прибавлению и 1 отниманию. Если итеративно считать A+dA, будет накапливаться погрешность. Если по условию значение хранится в 8-битном регистре, погрешность будет накапливаться очень быстро. При желании можно даже составить функцию, которая по заданному dA и заданным точностям исходных данных и результата определить предельное количество итераций. Для 8-бит аргумента оптимально будет вбить статическую хэш-таблицу значений. Её размер 256 значений (если значение тоже 8 бит - 256 байтов) - думаю, без проблем влезет даже в самый скромный контроллер. Производительность - как у выборки значения из массива по индексу.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
goodking
|
|
« Ответ #26 : 30-05-2011 11:28 » |
|
описание алгоритма, применительно к данному железу. Думаю так- рассчитываю значения синусов для определенного количества точек=>заношу все значения в массив=> в непрерывном цикле поочередно заношу эти значения в регистр сравнения. физические параметры: тактовая частота чипа, частота ШИМ, диапазон частот воспроизводимого через ШИМ сигнала. тактовая-макс.4.9 MGz ШИМ-меняется (макс.30000 Gz)
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #27 : 30-05-2011 13:38 » |
|
30кГц, это частота основной гармоники ШИМ или частота дискретизации выходных отсчетов? в последнем случае вы должны уложится в 160тактов/отсчет. про первый вариант я пока молчу)
PS в непрерывном можно, но вам тогда придется отключить все прерывания, и выравнивать все условные переходы по числу тактов. иначе фаза гулять будет. обычно это делают через программирование таймера и прерывание.
|
|
« Последнее редактирование: 30-05-2011 13:39 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Sla
|
|
« Ответ #28 : 30-05-2011 14:01 » |
|
Не путай систему команд и библиотеку... Думаю так- рассчитываю значения синусов для определенного количества точек=>заношу все значения в массив=> в непрерывном цикле поочередно заношу эти значения в регистр сравнения.
У тебя синусоида рассчитывается каждый раз по разному?
|
|
|
Записан
|
Мы все учились понемногу... Чему-нибудь и как-нибудь.
|
|
|
goodking
|
|
« Ответ #29 : 30-05-2011 14:45 » |
|
У тебя синусоида рассчитывается каждый раз по разному? характеристики (обводящая частота, частоат заполнения) будут меняться
|
|
|
Записан
|
|
|
|
|