Перейти к содержанию
    

Управление цифровым резистором по синусоидальному закону

Добрый день! Пытаюсь с помощью м-к 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);

}

 

};

 

post-58763-1449488801_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если так: s=125*(sin(q/100.0)+1); ..?

Вероятно, не поможет, 100.0 будет приведено к целому по первому операнду выражения q/100.0

Нужно s = (unsigned char) (125.0*(sin((float)q/100.0) + 1.0));

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вероятно, не поможет, 100.0 будет приведено к целому по первому операнду выражения q/100.0
Не будет. По правилам С если в арифметическом выражении участвует любое плавающее значение (не важно каким операндом), то все операнды будут приведены в плавающую форму и вычисляться соответственно.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно s = (unsigned char) (125.0*(sin((float)q/100.0) + 1.0));

 

 

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

 

post-58763-1449492596_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вероятно, не поможет, 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 - это аДъ. хотя возможно что родная математическая библиотека может иметь синус одинарной точности.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

для 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 байт под таблицу жалко

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...