Справочници, схемотехника, теория > Програмиране на микроконтролери, програматори, цифрови проекти
GPS-автопилот - алгоритъм
VITAN:
Браво, браво 8)
Е, с 2 ардуино-та ще стане :)
EDM electronics:
Сблъсках се със следния проблем:
Счетох, че вътрешната памет на Ардуино НАНО е твърде малка за запис на маршрути и поставих външна 24CL128. Това е огромна памет за целта.
Проблема обаче се състои в това, че езикът IDE /компилатора най-вече/ възприема най-голямо число с променлива запетая тип float. То е с големина 4 байта. Има и double, но то е същото float.
При смятане с такива числа или запис в паметта точността се ограничава до 7 разряда, независимо от запетаята. Т.е. точността на 4235672.3 е същата като 42.356723. Последната цифра /осмия разряд/ варира с 2-3 стойности.
Някой от програмистите, имате ли идея как да го направя с абсолютна точност до 8 разряд?
Пробвах при запис с умножение по сто, а при четене с деление на 100, но не става, запазва се точността до 7 разряд, осмия вече варира.
Записа правя, като записвам 4 отделни байта с разбиване на числото float на 4, а при четене се четат отделните байтове и се сумира в тип float . Ползвам две отделни функции за запис и четене.
#include <Eeprom24C128_256.h>
#define EEPROM_ADDRESS 0x50
static Eeprom24C128_256 eeprom(EEPROM_ADDRESS);
void setup()
{
float val_1 = 42.899751;
float val_2 = 0;
Serial.begin(9600);
eeprom.initialize();
EEPROM_float_write(0, val_1);
for (int ii = 0; ii<4; ii=ii+4)
{
val_2 = EEPROM_float_read(ii);
// запис в серниния порт
Serial.println(val_2,6);
}
}
void loop(){}
void EEPROM_float_write (int addr, float val) // запис в ЕЕПРОМ
{
byte *x = (byte *)&val;
for(byte i = 0; i < 4; i++)
{
eeprom.writeByte(i+addr, x);
delay(10);
}
}
float EEPROM_float_read (int addr) // четене от ЕЕПРОМ
{
byte x[4];
for(byte i = 0; i < 4; i++) x = eeprom.readByte(i+addr);
float *y = (float *)&x;
delay(10);
return y[0];
}
juliang:
--- Цитат на: juliang в Февруари 17, 2020, 09:28:03 pm ---Ако работиш с числа с плаваща запетая нещата вероятно ще са малко по-добри, но трябва да внимаваш изключително много при преминаването от абсолютни географски координати към разстояния. Не е изключено катастрофално да загубваш точност, защото ардуиното си работи с числа със 7-8 значещи цифри.
--- Край на цитат ---
Аз като говоря не приказвам...
Решението е да вземеш една сравнително близка точка за "нула" и да работиш с цели числа спрямо нея. 4 байта са +/- 2 милиарда, което ако работиш в сантиметри са +/- 20 000 километра. Така че ако смяташ в цели числа дори и ако приемеш нулата за нула градуса северна и нула градуса източна... пак България ще влезе в обхвата. А ако хванеш една точка в България, или примерно 45 градуса северна и 45 градуса източна, то ще можеш да обхванеш цяла България дори и в милиметри (което е абсолютно безмислено).
Обаче ти искаш да ползваш синуси, тангенси, квадратни корени ... дето връщат нецели числа... Не че не става, но пак ще трябва да мислиш какво се случва и кога е възможно рязко да загубиш точност.
НЕ МОЖЕШ да работиш с 8-я разряд, защото сметките ти ще са грешни. Дробните числа се представят като а*1/2 + b*1/4 + c*1/8 + d*1/16 + .... (а, b, c, d.... са битове и са 0 или 1) и просто няма как да запишеш точно 1/3 или 1/7. Затова вътрешно се смята с 8 знака точност, но ти се дава само до 7-я, който със сигурност е точен, а 8-я се спестява защото не винаги отговаря на истината.
EDM electronics:
Ползвам формулата с тангенси, котангенси и т.н. предимно защото само с нея мога да реализирам котвата. Не че твоята идея не е добра, напротив. Дори съм решил, скоро като завърша проекта, да направя и твоя алгоритъм, винаги мога да направя отделен скеч, като сменя само алгоритъма на навигацията, друго се запазва.
Седем разряда са напълно достатъчни за точността, но аз малко прекалявам и се престаравам. Осмия разряд от координатите от 0-9 дава толеранс 1 м. Точността ми в този разряд бяга с до 3 единици или 30 см. Това говоря при запис на координатите в паметта. Такава точност при следване на маршрут не ми е нужна и бих казал практически невъзможна, защото има много други фактори, които ще пречат на такава точност, главния от които е GPS-приемника.
При него 8-ми разряд варира с до 10-15 единици и ако няма хубав сигнал дори повече - играе си там постоянно се мени. Мислих да му слагам медиантен филтър и може би ще му сложа, защото този филтър елиминира отскоците и не дава средна средна аритметична стойност, като сбор от някщолко, а отделя средното показание от няколкото, колкото задам - примерно 5-6, ако настроя GPS-a на 5-6 Hz опресняване.
Та с тая любителска техника не мога да постигна кой знае какво. Има много добри приемници, но са скъпи и у нас трудно се намират, а и не виждам чак такъв смисъл, да гоня сантиметри точност. Дори в тази връзка съм предвидил умишлено намаляване на точността с около 2 м. Т.е. при наближаване на отправната точка, ако разчитам на навигатора да мина през нея, елеминирайки вълни, вятър и т.н., няма да се случи често и ще подмина точката, тогава навигатора ще дава команда назад, кръгове и т.н., което е недопустимо. Зетова в скеча съм задал условие, ако текущото разстояние е по-малко или равно на 2 метра, се зарежда следващата запеметена точка от маршрута за следване. Два метра това е радиус, т.е. трябва да улуча кръг с размер 4 м, изпусна ли го почва кръжене. ;)
Иначе има софтуерно решение на проблема с точността на 8-мия разряд, но все още не съм го осмислил. Функция, която свежда грешката на 8-мия разряд до 9.5, т.е. остава погрешност само 0,5 или това е да го наречем 5 см. Ако имаш интерес погледни и коментирай:
http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-tip-float-kak-ne-utonut#comment-341969
// Возведение числа f в целую, неотрицательную степень n
//
float iPow(const float f, const int n) {
if (n <= 0) return 1;
if (n == 1) return f;
float f2 = iPow(f, n / 2);
f2 *= f2;
return (n & 1) ? f2 * f : f2; // если n - нечётно, надо ещё раз домножить на f
}
nizo:
EDM, ако отвориш документацията:
https://www.arduino.cc/reference/en/language/variables/data-types/double/
пише, че double е обикновенно 4 байта, но Arduino Due има 8 байтов double с такава конструкция.
Навигация
[0] Списък на темите
Премини на пълна версия