www.kn34pc.com

Форум на силистренските радиолюбители
Дата и час: 23 Сеп 2018, 02:21

Часовете са според зоната UTC + 2 часа [ DST ]




Напиши нова тема Отговори на тема  [ 2 мнения ] 
Автор Съобщение
 Заглавие: Arduino: pow(base, exponent)
МнениеПубликувано на: 20 Сеп 2017, 23:22 
Offline
Аватар

Регистриран на: 07 Дек 2006, 18:24
Мнения: 825
Местоположение: Силистра
За (НЧ и ВЧ) генератор със синтезатор на честота си писах програмка, в която в EEPROM запомням параметри като последно използвана честота и последно използвана стъпка.
Прикачени файлове:
wsg_gen.jpg
wsg_gen.jpg [ 255.7 KiB | Прегледано 431 пъти ]

За честотата записът беше отработен преди и беше лесно. Но със стъпката не беше чак толкова ...
При варианти на стъпка от 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 Hz (само по степените на 10) за да не запомням числото в long (4 клетки), реших да "мина" с една - помним "броя нули", а при четене възстановяваме стъпка = 10 на степен "брой нули".

Дсетично логаритмуване на "стъпката"
Код за потвърждение:
n = log10(step);

"дава" "броя нули" и така нормално се записваше в паметта параметър "стъпка".

Наобратно - при старт просто трябваше да възстановя:
Код за потвърждение:
step = pow(10, n);

където step е изчислената стъпка, а n е "броя нули", изчетени от EEPROM.

Но като резултат стъпката беше неточна и все с разлика с това, което трябваше ...

Докато накрая "хамалски" заместих pow(10, n) с избор:
Код за потвърждение:
ако n е 0, то step = 0;
ако n е 1, то step = 1;
ако n е 2, то step = 10;
ако n е 3, то step = 100;
...
ако n е 7, то step = 10000000;

----------------------------------------------
Задачата беше решена, но въпросът не ми дава покой. Днес вече се "съмнявах" в правилността на математичното изчисление някъде по веригата "компилатор-микроконтролер". Нахвърлях си тестови код.

Резултати:
----------------------------------------------
Вариант 1:
Код за потвърждение:
for (byte i = 0; i < 8; i++) {
  ...
  Serial.println(pow(10, i));
}

Прикачени файлове:
pow_01_serial.jpg
pow_01_serial.jpg [ 71.55 KiB | Прегледано 432 пъти ]

----------------------------------------------
Вариант 2:
Код за потвърждение:
for (byte i = 0; i < 8; i++) { 
  ...
  float z = pow(10, i);
  long j = (long)round(z);
  Serial.println(j);
}

Прикачени файлове:
pow_02_serial.jpg
pow_02_serial.jpg [ 59.78 KiB | Прегледано 431 пъти ]

----------------------------------------------
Вариант 3:
Код за потвърждение:
for (byte i = 0; i < 8; i++) {
  switch (i) {
    case 0: j = 1; break;
    case 1: j = 10; break;
    ...
    case 7: j = 10000000; break;
  }
  Serial.println(j);
}

Прикачени файлове:
pow_03_serial.jpg
pow_03_serial.jpg [ 59.93 KiB | Прегледано 431 пъти ]

----------------------------------------------
Вариант 4:
Код за потвърждение:
long z = 1;
for (byte j = 0; j < i; j++)
  z *= 10;
Serial.println(z);

Прикачени файлове:
pow_04_serial.jpg
pow_04_serial.jpg [ 60.78 KiB | Прегледано 431 пъти ]

----------------------------------------------
Накрая оставих в програмката вариант 4.

Ясно е, че в AVR няма математически копроцесор и посочените действия са емулирани и резултатите са със закръгления, но с посочения казус си загубих около 2 дни по 2 часа за проверки, писане с молив, печат на състояния на временни променливи, сравняване, чесане по главата ... Затова реших да го споделя за избягване на бъдещи "главоболия" :biggrin

Вариантите по-горе за тестове са в архива:
Прикачени файлове:
arduino_pow.zip [189.02 KiB]
39 пъти

Ако има други по-лесни начини за избягване на pow(base, exponent), моля, споделете :smile


Върнете се в началото
 Профил  
 
МнениеПубликувано на: 21 Сеп 2017, 00:34 
Offline
Аватар

Регистриран на: 07 Дек 2006, 18:24
Мнения: 825
Местоположение: Силистра
То още от 10^2 започва закръглението ...
Код за потвърждение:
for (double i = 0.0; i < 8.0; i = i + 1.0) {
  ...
  Serial.println(pow(10.0, i), 20);
}

Прикачени файлове:
pow_05_serial.jpg
pow_05_serial.jpg [ 115.96 KiB | Прегледано 428 пъти ]

Пфу, от прости мат. действия стават сложнотии. Няма използвам pow(base, exponent) занапред по възможност значи ... :mail


Върнете се в началото
 Профил  
 
Покажи мненията от миналия:  Сортирай по  
Напиши нова тема Отговори на тема  [ 2 мнения ] 

Часовете са според зоната UTC + 2 часа [ DST ]


Кой е на линия

Потребители, разглеждащи този форум: 0 регистрирани и 1 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
cron
Форумът се задвижва от phpBB® Forum Software © phpBB Group
Преведено от yarnaudov.com