Как заставить FLOAT выводить все знаки после запятой - обрезает координаты GPS

android.mk
Offline
Зарегистрирован: 16.01.2017

Добрый день всем! Использую NEO-6M в измерялке расстония между двумя координатами. Если я объявляю переменные котрые хранят широту и долготу как float - получаю 44.56 вместо 44.561236.

Если использую long - то показывает координату без точки: 44561236 (в таком виде расстояние не считает)

Если как-то так:

float  flat_oled = lat;
char flat_float[15];
dtostrf(flat_oled, 9, 6, flat_float);

//myOLED.print(  flat_float); 

то не хочет использовать это значение в расчетах - ругается на проблемы с преобразованием char во float

Вопрос - для float как-то задается количество знаков после точки, или может проблема в gps.f_get_position(&lat, &lon, &alt); которая дает только 2 знака? Float вообще может что-то сам обрезать?

#include <SoftwareSerial.h>
#include <TinyGPS.h>

#include <iarduino_OLED_txt.h> 
iarduino_OLED_txt myOLED(0x78);  
extern uint8_t SmallFontRus[]; 

TinyGPS gps;
SoftwareSerial gpsSerial(4, 3);

bool newdata = false;
unsigned long start;
float  lat, lon;
long alt;
float distance = 0;

void setup()
{
gpsSerial.begin(9600); 
Serial.begin(9600);


//дисплей
    myOLED.begin();                    
    myOLED.setFont(SmallFontRus);               
    myOLED.setCoding(TXT_UTF8); 

 myOLED.clrScr();    // Чистим экран.
 myOLED.print(  "ЖДЁМ GPS " ,      0, 4);
 delay(500);
}

void loop()
{
 float flat, flon;
static const float START_LAT = 44.561236, START_LON = 38.214238;


if (millis() - start > 1000) 
{
newdata = readgps();
if (newdata)
{
start = millis();
 
gps.f_get_position(&lat, &lon, &alt);

 myOLED.clrScr();   // Чистим экран.
 myOLED.print(  "Ш " ,      0, 0); // Выводим текст начиная с 0 столбца 0 строки. 

myOLED.print(  lat );    

myOLED.print(  "Д " ,      0, 1);
myOLED.print(  lon );


distance = latlng2distance(lat, lon, START_LAT, START_LON);
myOLED.print(  "Расстояние " ,      0, 4);
myOLED.print(  distance );    // Выводим текст начиная с 0 столбца 0 строки.


/*
//вараинт расстояния

unsigned long distance_bet =  TinyGPS::distance_between(lat, lon, START_LAT, START_LON) ;

myOLED.print(  distance_bet ,      0, 7);
*/

}}
}


// проверка наличия данных
bool readgps()
{
while (gpsSerial.available())
{
int b = gpsSerial.read();
//в библиотеке TinyGPS имеется ошибка: не обрабатываются данные с \r и \n
if('\r' != b)
{
if (gps.encode(b))
 return true;
}
}
return false;
}



float latlng2distance(float lat1, float long1, float lat2, float long2) {
    //радиус Земли
    unsigned long R = 6372795;
    //перевод коордитат в радианы
    lat1 *= 3.14 / 180;
    lat2 *= 3.14 / 180;
    long1 *= 3.14 / 180;
    long2 *= 3.14 / 180;
    //вычисление косинусов и синусов широт и разницы долгот
    float cl1 = cos(lat1);
    float cl2 = cos(lat2);
    float sl1 = sin(lat1);
    float sl2 = sin(lat2);
    float delta = long2 - long1;
    float cdelta = cos(delta);
    float sdelta = sin(delta);
    //вычисления длины большого круга
    float y = sqrt(pow(cl2 * sdelta, 2) + pow(cl1 * sl2 - sl1 * cl2 * cdelta, 2));
    float x = sl1 * sl2 + cl1 * cl2 * cdelta;
    float ad = atan2(y, x);
    float dist = ad * R; //расстояние между двумя координатами в метрах
    return dist;
}

А вариант:

float  lat, lon;

.......

gps.get_position(&lat, &lon, &alt);

выводит их целиком но без точки - 44561236

Может кто подскажет, как целиком вывести координату?

vvadim
Offline
Зарегистрирован: 23.05.2012
myOLED.print( distance , 5); 

 

android.mk
Offline
Зарегистрирован: 16.01.2017

не работает, не для distance нитак

myOLED.print(  lat ,5 );

- так же выводит 2 знака после точки

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

android.mk пишет:

Если как-то так:

float  flat_oled = lat;
char flat_float[15];
dtostrf(flat_oled, 9, 6, flat_float);

//myOLED.print(  flat_float); 

то не хочет использовать это значение в расчетах - ругается на проблемы с преобразованием char во float

Какое "это"? flat_oled? А нахрена его в расчётах использовать? Используйте flat_float.

Вы путаете мягкое с тёплым.

Запомните, переменная типа float (у Вас это flat_float) всегда содержит все какие умеет по своей точности знаки (примерно 6-7). Всегда! И у Вас нет никакого способа заставить её содержать меньше.

То, что при печати Вы видите два знака - это вопрос к печати, а вовсе не к самой переменной. В переменной всё есть. А печать печатает сколько ей нужно.

Поэтому возвращайтесь к тому коду и спокойно используйте flat_float в расчётах, а flat_oled для печати и не пудрите самому себе мозги.

android.mk
Offline
Зарегистрирован: 16.01.2017

flat_oled - всего лишь название переменной, что с ней не так? Думал как вывести все знаки после запятой.

Этот кусок кода можно смело выбросить, мне нужно использовать в расчетах lat и lon - как раз они показывают 2 символа после запятой.

>А печать печатает сколько ей нужно

в каком смысле "сколько ей нужно"?? и в порт и на дисплей выводится значение переменной lat, если я руками назначу ей значение 44.561236 и будет выведено 44.561236

b707
Offline
Зарегистрирован: 26.05.2017

android.mk пишет:

 

если я руками назначу ей значение 44.561236 и будет выведено 44.561236

в чем тогда проблема?

android.mk
Offline
Зарегистрирован: 16.01.2017

ЕвгенийП пишет:

Запомните, переменная типа float (у Вас это flat_float) всегда содержит все какие умеет по своей точности знаки (примерно 6-7). Всегда! И у Вас нет никакого способа заставить её содержать меньше.

Переменная float у меня lat изначально.

Это означает что недостающие разряды будут заполнены нулями? Иначе в противном случае ничего кроме 44.56 она не содержит?

android.mk
Offline
Зарегистрирован: 16.01.2017

b707 пишет:

android.mk пишет:

 

если я руками назначу ей значение 44.561236 и будет выведено 44.561236

в чем тогда проблема?

в том что мне координаты нужно назначать не руками, а получать от GPSки, а от неё коррдинаты тот код что я привел получает вида 44.56 а не 44.561236

Я думаю что проблема не с выводом на экран

b707
Offline
Зарегистрирован: 26.05.2017

то, как вы пробовали с dtostrf - это верное направление. Вам надо только с типами параметров разобраться, и все заработает.

Линукса нет? - если есть, напишите в нем простеньй код на Си и отладьте работу с dtostrf, а потом перенесите в ардуино

android.mk пишет:

Если как-то так:

float  flat_oled = lat;
char flat_float[15];
dtostrf(flat_oled, 9, 6, flat_float);

/

b707
Offline
Зарегистрирован: 26.05.2017

android.mk пишет:

Я думаю что проблема не с выводом на экран

ошибаетесь, проблема именно с выводом. "Внутри себя" ваши переменные содержат кучу знаков после запятой, но по умолчанию все операторы print в ардуино выводят только 2 знака.

android.mk
Offline
Зарегистрирован: 16.01.2017

b707 пишет:

ошибаетесь, проблема именно с выводом. "Внутри себя" ваши переменные содержат кучу знаков после запятой, но по умолчанию все операторы print в ардуино выводят только 2 знака.

хм.. а как-то так

myOLED.print( lat, 5);

или аналогично это лечится? (этот вариант не подошел)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я там ошибся, давайте перепишу

android.mk пишет:

Если как-то так:

float  flat_oled = lat;
char flat_float[15];
dtostrf(flat_oled, 9, 6, flat_float);

//myOLED.print(  flat_float); 

то не хочет использовать это значение в расчетах - ругается на проблемы с преобразованием char во float

Какое "это"? flat_float? А нахрена его в расчётах использовать? Используйте flat_oled

Вы путаете мягкое с тёплым.

Запомните, переменная типа float (у Вас это flat_oled) всегда содержит все какие умеет по своей точности знаки (примерно 6-7). Всегда! И у Вас нет никакого способа заставить её содержать меньше.

То, что при печати Вы видите два знака - это вопрос к печати, а вовсе не к самой переменной. В переменной всё есть. А печать печатает сколько ей нужно.

Поэтому возвращайтесь к тому коду и спокойно используйте flat_oledв расчётах, а flat_float для печати и не пудрите самому себе мозги.

Вот как-то так.

То что Вы вводите и выводие и там всё также, так это Вы строки вводите и выводите. 

Вы вообще понимаете, что означают там словечки float, char и т.п.?

b707
Offline
Зарегистрирован: 26.05.2017

android.mk пишет:

хм.. а как-то так

myOLED.print( lat, 5);

или аналогично это лечится? (этот вариант не подошел)

в той библиотеке, что вы используете - судя по всему нет. В этой библиотеке функция print не имеет параметров, управляющих числом знаков после запятой.

 


android.mk
Offline
Зарегистрирован: 16.01.2017

ЕвгенийП пишет:

так это Вы строки вводите и выводите

Да, ступил, каюсь, благодарю за помощь. Я выводил действительно строку. Если так

float www = 45.269576;
myOLED.print(  www ,      0, 7);

то дисплей выводит те же 2 знака после запятой. Неожиданная засада.

android.mk
Offline
Зарегистрирован: 16.01.2017

Тогда вопрос снят, print уже мелочи, выведу как-нибудь, главное что правильно считает.

Еще раз спасибо за помощь)

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Для вывода переводите в int/long умножением на 100000.
А потом выводить по частям, первые два знака, запятая, остальные знаки

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

dtostrf() поможет

android.mk
Offline
Зарегистрирован: 16.01.2017

DetSimen пишет:

dtostrf() поможет

да, так и сделал, работает:

char  lon[15];
dtostrf(lon, 9, 6, flon_float);
myOLED.print(  flon_float );

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

нудакёптать. мощная функция. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Тока нафига преобразовывать в lon, а печатать flon_float?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

это он по недомыслию. 

ТС, печатать надо результирующий буфер lon.

android.mk
Offline
Зарегистрирован: 16.01.2017

DetSimen пишет:

ТС, печатать надо результирующий буфер lon.

да, здесь в сообщении промахнулся, в скетче так написал:

char  flon_float[15];
dtostrf(lon, 9, 6, flon_float);
myOLED.print(  flon_float );

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Размер массива 

1

char  flon_float[15+1];

должен быть на 1 больше, чем максимальный размер получаемой строки 

2 dtostrf(lon, 9 + 6 = 15, flon_float);

чтоб еще терминальный \0 влез. 

android.mk
Offline
Зарегистрирован: 16.01.2017

Изменил, хотя вроде визуально всё выводилось при 15

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

а, да, 9 это и есть максимальная ширина строки.  тогда буфер до 10 уменьшить можно.