asc2000 0 7 декабря, 2015 Опубликовано 7 декабря, 2015 · Жалоба Добрый день! Пытаюсь с помощью м-к 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); } }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 7 7 декабря, 2015 Опубликовано 7 декабря, 2015 · Жалоба Ошибка округления. У вас q целое число, соответственно, в интервале q от 0 до 99 синус равен нулю и т. д. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 14 7 декабря, 2015 Опубликовано 7 декабря, 2015 · Жалоба А если так: s=125*(sin(q/100.0)+1); ..? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
gerber 7 7 декабря, 2015 Опубликовано 7 декабря, 2015 · Жалоба А если так: s=125*(sin(q/100.0)+1); ..? Вероятно, не поможет, 100.0 будет приведено к целому по первому операнду выражения q/100.0 Нужно s = (unsigned char) (125.0*(sin((float)q/100.0) + 1.0)); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 7 декабря, 2015 Опубликовано 7 декабря, 2015 · Жалоба Вероятно, не поможет, 100.0 будет приведено к целому по первому операнду выражения q/100.0Не будет. По правилам С если в арифметическом выражении участвует любое плавающее значение (не важно каким операндом), то все операнды будут приведены в плавающую форму и вычисляться соответственно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
asc2000 0 7 декабря, 2015 Опубликовано 7 декабря, 2015 · Жалоба Нужно s = (unsigned char) (125.0*(sin((float)q/100.0) + 1.0)); Спасибо, получилось! Почти чистая синусоида: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Mahagam 0 7 декабря, 2015 Опубликовано 7 декабря, 2015 · Жалоба Вероятно, не поможет, 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 - это аДъ. хотя возможно что родная математическая библиотека может иметь синус одинарной точности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 52 7 декабря, 2015 Опубликовано 7 декабря, 2015 · Жалоба для 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 байт под таблицу жалко Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться