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

 
 
 
Reply to this topicStart new topic
> Управление цифровым резистором по синусоидальному закону, Вопрос по программе на языке Си
asc2000
сообщение Dec 7 2015, 12:00
Сообщение #1


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

Группа: Участник
Сообщений: 95
Регистрация: 5-08-10
Пользователь №: 58 763



Добрый день! Пытаюсь с помощью м-к ATtiny261 управлять цифровым потенциометром AD8400 по синусоидальному закону. Из осциллограммы видно, что потенциометр изменяет сопротивление в своем полном диапазоне, но всего лишь за несколько шагов, а не за 256, как должно быть. В чем может быть причина?

Фрагмент кода для CodeVisionAVR:

unsigned int q;
unsigned char s;


while (1)
{
for(q=0;q < 628; q++) //для всех 256 значений сопротивления
{
s=125*(sin(q/100)+1);
set_resistance(0x00, s);
}

};


Прикрепленное изображение
Go to the top of the page
 
+Quote Post
gerber
сообщение Dec 7 2015, 12:06
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088



Ошибка округления. У вас q целое число, соответственно, в интервале q от 0 до 99 синус равен нулю и т. д.


--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
Go to the top of the page
 
+Quote Post
blackfin
сообщение Dec 7 2015, 12:09
Сообщение #3


Гуру
******

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



А если так: s=125*(sin(q/100.0)+1); ..?
Go to the top of the page
 
+Quote Post
gerber
сообщение Dec 7 2015, 12:12
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 750
Регистрация: 1-11-11
Пользователь №: 68 088



Цитата(blackfin @ Dec 7 2015, 15:09) *
А если так: s=125*(sin(q/100.0)+1); ..?

Вероятно, не поможет, 100.0 будет приведено к целому по первому операнду выражения q/100.0
Нужно s = (unsigned char) (125.0*(sin((float)q/100.0) + 1.0));


--------------------
"... часами я мог наблюдать, как люди работают." (М. Горький)
Go to the top of the page
 
+Quote Post
XVR
сообщение Dec 7 2015, 12:49
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(gerber @ Dec 7 2015, 15:12) *
Вероятно, не поможет, 100.0 будет приведено к целому по первому операнду выражения q/100.0
Не будет. По правилам С если в арифметическом выражении участвует любое плавающее значение (не важно каким операндом), то все операнды будут приведены в плавающую форму и вычисляться соответственно.

Go to the top of the page
 
+Quote Post
asc2000
сообщение Dec 7 2015, 12:50
Сообщение #6


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

Группа: Участник
Сообщений: 95
Регистрация: 5-08-10
Пользователь №: 58 763



Цитата(gerber @ Dec 7 2015, 15:12) *
Нужно s = (unsigned char) (125.0*(sin((float)q/100.0) + 1.0));



Спасибо, получилось! Почти чистая синусоида:

Прикрепленное изображение
Go to the top of the page
 
+Quote Post
Mahagam
сообщение Dec 7 2015, 12:54
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 322
Регистрация: 2-07-04
Из: Minsk
Пользователь №: 240



QUOTE (gerber @ Dec 7 2015, 15:12) *
Вероятно, не поможет, 100.0 будет приведено к целому по первому операнду выражения q/100.0
Нужно s = (unsigned char) (125.0*(sin((float)q/100.0) + 1.0));

поможет. при операциях между int и float по стандарту всё переводится во float. однако 100.0 - это double. и как результат, q сначала будет переведено в double. хотя тут так или иначе будет конверсия в дабл, так как синус требует его на входе.

кроме того, так как результат синуса - дабл, то и добавляемая единичка, и 125 тоже будут переконверчены в double. и только в самом конце пребразованы в char.
для ATtiny261 работа с double - это аДъ. хотя возможно что родная математическая библиотека может иметь синус одинарной точности.
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 7 2015, 14:09
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Mahagam @ Dec 7 2015, 19:54) *
для ATtiny261 работа с double - это аДъ. хотя возможно что родная математическая библиотека может иметь синус одинарной точности.

Не знаю как codevision, iar вроде бы по умолчанию считает что doublы равны floatу, то есть оба 32х разрядные - с одинарной точностью.
codevision скорее всего тоже, иначе при 128 байтах памяти в тини261 это дейстительно аДъ

ну а для 8ми битного синуса и полинома третьей степени достаточно будет
Код
unsigned char sinus(unsigned char x){
  unsigned long a = 118;
  a *= x;
  a += 9039;
  a *= x;
  a = 26782194 - a;
  a *= x;
  return (a >> 24);  
}

это если 256 байт под таблицу жалко
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 22:38
Рейтинг@Mail.ru


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