За (НЧ и ВЧ) генератор със синтезатор на честота си писах програмка, в която в EEPROM запомням параметри като последно използвана честота и последно използвана стъпка.
Прикачени файлове:
wsg_gen.jpg [ 255.7 KiB | Прегледано 8194 пъти ]
За честотата записът беше отработен преди и беше лесно. Но със стъпката не беше чак толкова ...
При варианти на стъпка от 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 [ 71.55 KiB | Прегледано 8195 пъти ]
----------------------------------------------
Вариант 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 [ 59.78 KiB | Прегледано 8194 пъти ]
----------------------------------------------
Вариант 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 [ 59.93 KiB | Прегледано 8194 пъти ]
----------------------------------------------
Вариант 4:
Код за потвърждение:
long z = 1;
for (byte j = 0; j < i; j++)
z *= 10;
Serial.println(z);
Прикачени файлове:
pow_04_serial.jpg [ 60.78 KiB | Прегледано 8194 пъти ]
----------------------------------------------
Накрая оставих в програмката вариант 4.
Ясно е, че в AVR няма математически копроцесор и посочените действия са емулирани и резултатите са със закръгления, но с посочения казус си загубих около 2 дни по 2 часа за проверки, писане с молив, печат на състояния на временни променливи, сравняване, чесане по главата ... Затова реших да го споделя за избягване на бъдещи "главоболия"

Вариантите по-горе за тестове са в архива:
Прикачени файлове:
arduino_pow.zip [189.02 KiB]
647 пъти
Ако има други по-лесни начини за избягване на
pow(base, exponent), моля, споделете
