Как постичь непостижимое

Chichay
Offline
Зарегистрирован: 12.03.2018

Здравствуйте уважаемые гуру ардуин!

Увлекла меня тема Ардуино)))  И решил я примкнуть к вашей банде.

Поморгал светодиодом, сделал радиоуправление для лодки.

Теперь хочу сделать автопилот для лодки.

Для начала решил вытащить GPS координаты в сериалпорт , взял Arduino Nano и GPS модуль NEO-M8N и пока у меня ничего не выходит.

Помогите разобраться пожалуйста как вывести в сериал монитор GPS координаты.

Сейчас пишет только вот это:

$PSV32,01,5,10121,1,911,2,Simple TinyGPS library v. 13

by Mikal Hart

 

 

 

соединил:

GND → GND
TX → Цифровой вывод (D10)
RX → цифровой вывод (D9)
Vcc → 5Vdc

 

Взял пример скетча из библиотеки TinyGPS

 

#include <SoftwareSerial.h>

 

#include <TinyGPS.h>

 

/* This sample code demonstrates the normal use of a TinyGPS object.

   It requires the use of SoftwareSerial, and assumes that you have a

   9600-baud serial GPS device hooked up on pins 9(rx) and 10(tx).

*/

 

TinyGPS gps;

SoftwareSerial ss(9, 10);

 

void setup()

{

  Serial.begin(9600);

  ss.begin(9600);

 

  Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version());

  Serial.println("by Mikal Hart");

  Serial.println();

}

 

void loop()

{

  bool newData = false;

  unsigned long chars;

  unsigned short sentences, failed;

 

  // For one second we parse GPS data and report some key values

  for (unsigned long start = millis(); millis() - start < 1000;)

  {

    while (ss.available())

    {

      char c = ss.read();

      //Serial.write(c); // uncomment this line if you want to see the GPS data flowing

      if (gps.encode(c)) // Did a new valid sentence come in?

        newData = true;

    }

  }

 

  if (newData)

  {

    float flat, flon;

    unsigned long age;

    gps.f_get_position(&flat, &flon, &age);

    Serial.print("LAT=");

    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);

    Serial.print(" LON=");

    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);

    Serial.print(" SAT=");

    Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());

    Serial.print(" PREC=");

    Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());

  }

 

  gps.stats(&chars, &sentences, &failed);

  //Serial.print(" CHARS=");

  //Serial.print(chars);

  //Serial.print(" SENTENCES=");

  //Serial.print(sentences);

  //Serial.print(" CSUM ERR=");

  //Serial.println(failed);

  if (chars == 0)

    Serial.println("** No characters received from GPS: check wiring **");

}

 

 

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

Chichay пишет:
И решил я примкнуть к вашей банде.
Тогда, прежде, чем писать на форум, почитайте его, и вставляйте код по правилам. В таком виде здесь код мало кто согласится читать.

Chichay
Offline
Зарегистрирован: 12.03.2018

[quote=ЕвгенийП]

почитайте его, и вставляйте код по правилам. 

[code]

#include <SoftwareSerial.h>

#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   9600-baud serial GPS device hooked up on pins 9(rx) and 10(tx).
*/

TinyGPS gps;
SoftwareSerial ss(9, 10);

void setup()
{
  Serial.begin(9600);
  ss.begin(9600);
  
  Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
}

void loop()
{
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

  // For one second we parse GPS data and report some key values
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      //Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

  if (newData)
  {
    float flat, flon;
    unsigned long age;
    gps.f_get_position(&flat, &flon, &age);
    Serial.print("LAT=");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    Serial.print(" LON=");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    Serial.print(" SAT=");
    Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
    Serial.print(" PREC=");
    Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
  }
  
  gps.stats(&chars, &sentences, &failed);
  //Serial.print(" CHARS=");
  //Serial.print(chars);
  //Serial.print(" SENTENCES=");
  //Serial.print(sentences);
  //Serial.print(" CSUM ERR=");
  //Serial.println(failed);
  if (chars == 0)
    Serial.println("** No characters received from GPS: check wiring **");
}


[/code]

Спасибо Евгений за совет. Я новичек в этом деле, как Вы уже поняли. В таком виде будет правильно?

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

Этот модуль сам по себе гонит IMEA, потому, для начала, сделайте безо всякой библиотеки - тупое копирование ss в Serial.  Совсем тупое, типа такого

#include <SoftwareSerial.h>

SoftwareSerial ss(4,5);

void setup(void) {
	Serial.begin(115200);
	ss.begin(9600);
	Serial.println("Fun begins:");
}

void loop(void) {
	if (Serial.available()) ss.write(Serial.read());
	if (ss.available()) Serial.write(ss.read());
}

Когда и если Вы увидите нормальный IMEA код в мониторе, Вы будете уверены, что у Вас живой модуль, что он правильно подключён и т.п.

Только тогда переходите к библиотеке.

Chichay
Offline
Зарегистрирован: 12.03.2018

Попробывал Ваш код. Скорости поставил обе по 9600. все работает. Данные идут вот так:

Fun begins:
⸮b⸮⸮⸮⸮r⸮⸮⸮⸮⸮brb⸮⸮⸮⸮⸮r⸮ʚ⸮⸮b*b⸮b⸮⸮b⸮r⸮⸮b⸮⸮⸮r⸮bjbj⸮⸮r⸮bjbbR⸮⸮jR :r95⸮⸮i⸮)ɋ I⸮Iɋ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮I⸮⸮IɉI⸮⸮⸮⸮⸮K)ɨH⸮⸮⸮⸮j))⸮i⸮鉋⸮ɋ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮I⸮⸮IɉI⸮⸮⸮⸮⸮K)⸮⸮H⸮⸮⸮ԕi⸮)⸮))⸮ I⸮II⸮ ⸮b⸮⸮b⸮⸮bbb⸮⸮b⸮⸮b⸮b⸮⸮⸮⸮⸮⸮⸮b⸮⸮b⸮⸮:⸮9⸮b⸮b⸮⸮b⸮⸮b⸮b⸮⸮b⸮b⸮b⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮b⸮b⸮b⸮b⸮⸮R⸮j:⸮9b⸮b⸮⸮b⸮⸮b⸮⸮⸮⸮b⸮b⸮b⸮b⸮ʢ⸮⸮b⸮b⸮⸮b⸮⸮:b9⸮b⸮b⸮⸮b⸮⸮b⸮b⸮⸮⸮⸮⸮⸮⸮b⸮⸮b⸮⸮b⸮⸮⸮⸮⸮⸮b⸮⸮:b95b⸮b⸮⸮b⸮⸮b⸮b⸮⸮b⸮⸮⸮⸮⸮⸮⸮bb⸮⸮ʊ⸮bb⸮b⸮⸮⸮bR*i⸮i⸮) ⸮b⸮⸮b⸮⸮⸮b⸮⸮b¢b⸮b⸮⸮b⸮*⸮⸮⸮I⸮ӓɊ ⸮+⸮)⸮⸮⸮b*b⸮⸮⸮⸮r⸮⸮b
b
R⸮j$GNRMC,080329.00,A,5511.42667,N,06119.49344,E,0.029,,260818,,,A*60
$GNVTG,,T,,M,0.029,N,0.054,K,A*37
$GNGGA,080329.00,5511.42667,N,06119.49344,E,1,05,2.42,272.6,M,-133,,*6
$GGS,A3,60226,,,,,,5252.2,.6*F
$GGS,,37,6,,,,,,,,.5,.4,4661
GPSV3,,1,2,2,8,3,0,,2,0,5,0534130911,40
$PGV,,21,1,0,51,1,8,2432200022,9,1,7,5,*E
$GGS,,31,2,2,15,4263529,4,9,0,63*4
GGS,31,0663307,2,7,2,1,,8,8,66,3,7,68*6
и т.д.
ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Ну, я не знаю что там за кракозябы в начале, у меня вроде сразу нормально идёт (если склероз не изменяет, могу попробовать сейчас, если хотите). Но, если это нормально, то разбирайтесь, что у Вас с бибилотекой.

a5021
Offline
Зарегистрирован: 07.07.2013

С кракозябрами все нормально. NEO8M, во всяком случае тот, с которым я имел  дело, вел себя точно так же. Строковые данные вперемешку с двоичными. Периодами. Но координат в потоке нет. Видимо он в помещении его запускает.

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

Не знаю, восьмой у меня в доме (посерёдке причём, а не у окна) аж 12 штук наловил.

Chichay
Offline
Зарегистрирован: 12.03.2018

Попробовал еще раз. Теперь нормально, без кракозяблов.

Fun begins:
31,118,,73,49,051,39,81,21,336,44,,,,37*52
$GNGLL,5511.32245,N,06119.48690,E,171507.00,A,A*7C
$GNRMC,171508.00,A,5511.32216,N,06119.48663,E,0.096,,260818,,,A*6A
$GNVTG,,T,,M,0.096,N,0.177,K,A*33
$GNGGA,171508.00,5511.32216,N,06119.48663,E,1,03,3.88,114.7,M,-133,,,63
$NSAA,,5,,,,,,,,.0,3881.01D
$NGA,,28,7,,,,,,,4.13.8,.0*1
GGS,21,5,6,,9,6,2,471,2,3,283926,,671
$PGV,,,0,3,,3974
 
Координаты присутствуют:
5511.32245,N
06119.48690,E
 
Но не могу вытащить отдельно координаты с помощью TinyGPS.
Попробывал еще такой код, уже с дисплеем, но на дисплей выводит значения 55,00 и 61,00 (те,что я ввел в float lat = 61,lon = 55; // создать переменную для объекта широты и долготы ):
[code]
#include <LiquidCrystal.h> 
#include <SoftwareSerial.h> 
#include <TinyGPS.h> 
float lat = 61,lon = 55; // создать переменную для объекта широты и долготы  
SoftwareSerial gpsSerial(9,10);//rx,tx 
LiquidCrystal lcd(12,11,5,4,3,2); 
TinyGPS gps; // создать gps объект


void setup(){ 
Serial.begin(9600); // соединяем serial 
Serial.println("Полученный сигнал GPS:"); 
gpsSerial.begin(9600); // подключаем gps датчик
lcd.begin(16,2); 
} 

void loop(){  
  while(gpsSerial.available()){ // проверка gps данных
  if(gps.encode(gpsSerial.read()))// шифровать gps данные 
  {  
  gps.f_get_position(&lat,&lon); // получить широту и долготу
  // отобразить позицию 
  } 
} 
String latitude = String(lat,6); 
  String longitude = String(lon,6); 
//Serial.println(latitude+";"+longitude); 
delay(1000); 

//Serial.print("Position: "); 
  //Serial.print( "E: "); 
  //Serial.print(lat,20); 
  //Serial.print(";"); 
  //Serial.print("N: "); 
  //Serial.println(lon,20);  
  lcd.clear(); 
  lcd.setCursor(1,0);
  //lcd.print("E: "); 
  lcd.print(lat,13);
  lcd.setCursor(1,1);
  //lcd.print("N: "); 
  lcd.print(lon,13);  
  {
  if (Serial.available()) gpsSerial.write(Serial.read());
  if (gpsSerial.available()) Serial.write(gpsSerial.read());
}
}
[/code]

 
 

 

Chichay
Offline
Зарегистрирован: 12.03.2018

Да,и еще, прочитал винете сегодня, что под эту библиотэку нужно neo-m8n как-то настраивать, что-бы в правильном формате данные отдавал. Но я не знаю как и в каком формате нужно передавать этой библиотеке данные.

Еще вычитал, что есть какая-то специальная библиотека NeoGPS-master. Но как с ней работать я опять же не знаю.

Посоветуйте что-нибудь......

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Chichay пишет:

Посоветуйте что-нибудь......

Совет "читать документацию к библиотекам", или "смотреть код библиотек, если там ни документации, ни примеров нет" - не катит, да?

Chichay
Offline
Зарегистрирован: 12.03.2018

 

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

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

Chichay пишет:

 уже с дисплеем

Вы специально себе приключений ищете? Я же Вам говорил, шаг за шагом, не лепите одну сложность на другую.

Удаляйте нахрен всё с 26 по 47 строку, а после 22-ой поставьте вывод в сериал значений lat и lon. И пока не увидиет их нормальными, забудьте про дисплеи и прочую лабуду.

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

Chichay пишет:

Посоветуйте что-нибудь......

Советую. Вы строки на экране видите? Они же нормальные? Ну, и разбирайте их сами - назрнае Вам вообще библиотека? Я вот именно так и делаю.

Chichay
Offline
Зарегистрирован: 12.03.2018

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

Chichay пишет:

Посоветуйте что-нибудь......

Советую. Вы строки на экране видите? Они же нормальные? Ну, и разбирайте их сами - назрнае Вам вообще библиотека? Я вот именно так и делаю.

Ну Евгенй, мне до восьмидесятого уровня еще далеко))))

Но проблему свою я решил))

Короче, с моей Наночкой сработала только TinyGPS++

взял скетч из примера. Работает только шуба заворачивается.))) Ну и конечно дислей прикрутил. На дисплее координаты показывает.

Евгений, а можешь объяснить мне нормально, как стоматолог гинекологу как без библиотеки координаты вытащить?

sadman41
Offline
Зарегистрирован: 19.10.2016

Chichay пишет:

Евгений, а можешь объяснить мне нормально, как стоматолог гинекологу как без библиотеки координаты вытащить?

Помните такой аттракцион под названием "разбор предложения на члены"? Существительное там, глагол, подлежащее и т.п. Ну вот и тут так же - по сепаратору разбираете, потом делаете вывод - в текущем фрагменте текса координата или нет.

Chichay
Offline
Зарегистрирован: 12.03.2018

Принципиально я понимаю)) Но в  програмировании не силен. Можете на примере показать?

sadman41
Offline
Зарегистрирован: 19.10.2016

Что вам даст пример программного кода, если вы принципиально его не понимаете?

Chichay
Offline
Зарегистрирован: 12.03.2018

У меня книжка есть. Я читать умею. А на конкретном примере я лучше понимаю.

sadman41
Offline
Зарегистрирован: 19.10.2016

Извольте пример: http://all-ht.ru/inf/prog/c/func/strtok.html

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

Chichay пишет:

У меня книжка есть. Я читать умею. А на конкретном примере я лучше понимаю.

Могу, но только вот в таком виде.

Задача: во входном потоке, читаемом из Serial найти стрoку вида

$GNGLL,5511.32245,N,06119.48690,E,171507.00,A,A*7C

И вытащить из неё красное число - широту и зелёное число - долготу.

Решение:

всегда, в любой задаче начинайте с полного высокоуровневого описания, вставляя низкоуровневые функции так, как если бы они у Вас уже были, не забывая чётко описывать что они должны делать. Когда верхний уровень написан, внимательно, всё проверьте и приступайте к написанию оставленных "на потом" функций. С ними поступайте также - расписывайте верхний уровень и спускайтесь ниже пока очередные функции не окажутся тривиальными.

Т.е. всегда двиайтесь по шагам. На место пока недостающих функций ставьте заглушки

Вот давайте: первый уровень

void setup(void) {
	Serial.begin(57600);
}

//
//	Читаeм долготу и широту, складывает в lon и lat
// Возвращает true, если прочитала и false если нет
//
bool readLatLon(double & lat, double & lon) {
        lat = 321.321;
        lon = 123.123;
	return true;
}

void loop(void) {
	//
	// Широта и долгота
	//
	double lat, lon;
	//
	// Читаем широту и долготу и если успешно прочитались, печатаем
	//
	if (readLatLon(lat, lon)) {
		Serial.print("Latitude: ");
		Serial.println(lat, 5);
		Serial.print("Llongtitude: ");
		Serial.println(lon, 5);
	}
}

Вместо функции readLatLon, здесь написана заглушка, которая вроде как делает то, чего ожидает функция loop. Заглушка нужна для проверки, всё ли в порядке в loop.

Это надо запустить и проверить. И только если всё в порядке, переходить к следующему шагу. Если что-то не так - дожимать, отлаживать, а о следующем шаге даже не думать.

После того, как мы убедимся, что всё корректно работает (только после этого!) мы делаем вывод, что у нас всё в порядке и если мы сумеем написать правильную функцию readLatLon, то у нас всё будет замечательно.

Пока всё было понятно?

Следующий шаг - пишем функцию readLatLon:

void setup(void) {
	Serial.begin(57600);
}

//
// (ЗАГЛУШКА)
// Эта функция принимает символ из Serial и возвращает
//	указатель на полученную строку или NULL, если строка
//	ещё не получена.
// Строка всегда начинается с $ и заканчивается \r или \n
//
char * getStrFromSerial(void) {
	return "$GNGLL,5511.32245,N,06119.48690,E,171507.00,A,A*7C";
}


//
//	Читаeм долготу и широту, складывает в lon и lat
// Возвращает true, если прочитала и false если нет
//
bool readLatLon(double & lat, double & lon) {
	// 
	//	getStrFromSerial() вернёт строку, полученную из Serial
	// или NULL, если строка ещё пока не получена
	//
	const char * str = getStrFromSerial();
	//
	//	Если строка ещё не получена, выходим
	//
	if (str == NULL) return false;
	//
	//	Если строка не начинается с "$GNGLL",
	// то она нам не нужна выходим
	//
	const char * prefix = "$GNGLL";
	if (strncmp(str, prefix, strlen(prefix))) return false;
	//
	//	Ищем первую запятую в строке str
	//
	 char * comma = strchr(str, ',');
	//
	//	Если не нашли (строка кривая пришла?) - выходим
	//
	if (!comma) return false;
	//
	//	со следующего символа просле запятой идёт числоа - широта
	//
	lat = atof(comma+1);
	//
	//	Ищем вторую запятую после начала числа-широты
	//
	comma = strchr(comma+1, ','); // сначала ищем первую запятую
	if (!comma) return false; // почему-то не нашли :((((
	comma = strchr(comma+1, ','); // теперь ищем вторую запятую
	if (!comma) return false; // почему-то не нашли :((((
	//
	//	со следующего символа просле запятой идёт числоа - долгота
	//
	lon = atof(comma+1);
	//
	//	Вроде всё
	//
	return true;
}

void loop(void) {
	//
	// Широта и долгота
	//
	double lat, lon;
	//
	// Читаем широту и долготу и если успешно прочитались, печатаем
	//
	if (readLatLon(lat, lon)) {
		Serial.print("Latitude: ");
		Serial.println(lat, 5);
		Serial.print("Llongtitude: ");
		Serial.println(lon, 5);
	}
}

Здесь мы написали всё, считая, что функция чтения строки из сериала (getStrFromSerial) у нас уже есть. Вместо неё пока поставили заглушку, которая всегда выдаёт правильную строку, которую "типа прочитала". опять же заглушка нужна для отладки функции readLatLon. Это надо запустить, проверить и т.п.

После того, как мы убедимся, что всё корректно работает (только после этого!) мы делаем вывод, что у нас всё в порядке и если мы сумеем написать правильную функцию getStrFromSerial, то у нас всё будет замечательно.

Следующий шаг - пишем функцию getStrFromSerial

void setup(void) {
	Serial.begin(57600);
}

//
// Эта функция принимает символ из Serial и возвращает
//	указатель на полученную строку или NULL, если строка
//	ещё не получена.
// Строка всегда начинается с $ и заканчивается \r или \n
//
static const int MAX_LEN = 120;	// 120 - максимальная длина строки - надо посмотреть правильное значение в описании протокола!

char * getStrFromSerial(void) {
	static bool waitingForStrBegin = true; // истина, если мы ждём начала строки ($)
	static char strBuf[MAX_LEN];	// буфер для строки
	static int ptr = 0;	// индекс свободного байта в буфере

	//
	//	Если буфер переполнился, печатаем сообщение и начинаем ждать новую строку
	//
	if (ptr >= MAX_LEN) {
		Serial.println("*** Error: Too long string!!!");
		ptr = 0;
		waitingForStrBegin = true;
		return NULL;
	}
	//
	//	Если в Serial ничего нет - выходим
	//	А если есть, то читаем 1 символ
	//
	if (!Serial.available()) return NULL;
	const char c = Serial.read();
	//
	//	Если мы ждём начала строки, то сравинваем 
	//	прочитанный символ с '$', если равен - начало найдено
	//
	if (waitingForStrBegin) {
		if (c == '$') {
			ptr = 0;
			strBuf[ptr++] = c;
			waitingForStrBegin = false;
		} 
		return NULL;
	}
	//
	//	Если прочитанный символ - перевод строки или возврат каретки
	//	то считаем, что строка закончилась. Возвращаем её,
	// а сами готовимся ждать новую.
	//
	if (c == '\r' || c == '\n') {
		strBuf[ptr] = '\0';
		waitingForStrBegin = true;
		return strBuf;
	}
	//
	//	Просто записываем символ в строку
	//
	strBuf[ptr++] = c;
	return NULL;
}

//
//	Читаeм долготу и широту, складывает в lon и lat
// Возвращает true, если прочитала и false если нет
//
bool readLatLon(double & lat, double & lon) {
	// 
	//	getStrFromSerial() вернёт строку, полученную из Serial
	// или NULL, если строка ещё пока не получена
	//
	const char * str = getStrFromSerial();
	//
	//	Если строка ещё не получена, выходим
	//
	if (str == NULL) return false;
	//
	//	Если строка не начинается с "$GNGLL",
	// то она нам не нужна выходим
	//
	const char * prefix = "$GNGLL";
	if (strncmp(str, prefix, strlen(prefix))) return false;
	//
	//	Ищем первую запятую в строке str
	//
	 char * comma = strchr(str, ',');
	//
	//	Если не нашли (строка кривая пришла?) - выходим
	//
	if (!comma) return false;
	//
	//	со следующего символа просле запятой идёт числоа - широта
	//
	lat = atof(comma+1);
	//
	//	Ищем вторую запятую после начала числа-широты
	//
	comma = strchr(comma+1, ','); // сначала ищем первую запятую
	if (!comma) return false; // почему-то не нашли :((((
	comma = strchr(comma+1, ','); // теперь ищем вторую запятую
	if (!comma) return false; // почему-то не нашли :((((
	//
	//	со следующего символа просле запятой идёт числоа - долгота
	//
	lon = atof(comma+1);
	//
	//	Вроде всё
	//
	return true;
}

void loop(void) {
	//
	// Широта и долгота
	//
	double lat, lon;
	//
	// Читаем широту и долготу и если успешно прочитались, печатаем
	//
	if (readLatLon(lat, lon)) {
		Serial.print("Latitude: ");
		Serial.println(lat, 5);
		Serial.print("Llongtitude: ");
		Serial.println(lon, 5);
	}
}

Ну, вот теперь можете вводить ту Вашу строку в Serial и смотреть как она вполне корректно извлекает то, что нужно.

Главное, что я хотел показать. Не кидайтесь делать всё сразу - делайте по частям. Части бейте так, чтобы каждая была Вам понятна и обозрима. Вместо неготовых вещей используйте заглушки. котрые ведут себя "как настоящие". Переходите к написанию заглушек только когда всё их окружение точно работает как надо.

Тогда Вы будете всегда биться с маленьким, обозримым куском. Не пытайтесь написать всё сразу - и экран, и ввод, и вывод и ещё хрен знает что - только по кусочкам, шаг за шагом. Всё сразу Вы не отладите потому что "много всего" и что глючит - непонятно (а скорее всего ещё и "не одно что-то").

Вы уловили главную мысль?

Могу свой опыт привести. Я программирую больше лет, чем многие форумчане живут. Многие вещи. которые Вам кажутся проблемами. я делаю не думая, на автопилоте, НО я никогда не пишу функций (и стало быть не отлаживаю за раз) больших чем те. которые я могу увидеть на экране без листания. Я всегда вижу отлаживаемый кусок целиком. Вы же (я всех здешних новичков имею в виду) навалите строк триста и плачете "почему не работает". Я же столько даже не пытаюсь "навалить" - так же как и у Вас не заработает. Я делаю кусочками, которые я могу охватить взглядом и отлаживаю эти кусочки. Понимаете подход? Не валите всё в кучу. Вы в этой теме постоянно это делаете. У Вас ещё NMEA ни хрена не разбирается, а Вы уже туда на кой-то хрен экран пристроили. зачем? Чтобы одни ошибки на другие наложить?

sadman41
Offline
Зарегистрирован: 19.10.2016

Только, наверное, NMEA.

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

Наверное

Chichay
Offline
Зарегистрирован: 12.03.2018

ЕвгенийП, вот большое тебе, человеческое спасибо!

С мая месяца читаю разные форумы по ардуино, и почти всегда собеседниками являются мнящие себя профессионалами лузеры, которые восновном флудят и издеваются над теми, кто чуть меньше них знает. Но при этом пользы от них 0+ (в пределах случайной погрешности).

Огромный тебе респект за то, что потратил на меня свое время и интелект! Благодаря тебе, я перешел на новый уровень!))))

 

Со своей стороны обязуюсь усвоить, (хотя в приципе и так все предельно понятно) только запомнить нужно. Ну это практикой закрепится, я думаю.

TD27T
Offline
Зарегистрирован: 08.04.2016

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

всегда, в любой задаче начинайте с полного высокоуровневого описания, вставляя низкоуровневые функции так, как если бы они у Вас уже были, не забывая чётко описывать что они должны делать. Когда верхний уровень написан, внимательно, всё проверьте и приступайте к написанию оставленных "на потом" функций. С ними поступайте также - расписывайте верхний уровень и спускайтесь ниже пока очередные функции не окажутся тривиальными.

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

я никогда не пишу функций (и стало быть не отлаживаю за раз) больших чем те. которые я могу увидеть на экране без листания. Я всегда вижу отлаживаемый кусок целиком.

Рубрика "Вредные советы для новичков"?

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

TD27T пишет:

 Рубрика "Вредные советы для новичков"?

А что не так? - вполне разумная рекомендация - оформлять код в виде коротких самодостаточных процедур и функций - в противоположность типичному коду начинающих, стремящихся всю программу запихнуть внутрь loop()

SLKH
Offline
Зарегистрирован: 17.08.2015

b707 пишет:

TD27T пишет:

 Рубрика "Вредные советы для новичков"?

А что не так? - вполне разумная рекомендация - оформлять код в виде коротких самодостаточных процедур и функций - в противоположность типичному коду начинающих, стремящихся всю программу запихнуть внутрь loop()

с обязательным выводом всего сразу на жк-дисплей!

TD27T
Offline
Зарегистрирован: 08.04.2016

b707 пишет:

TD27T пишет:

 Рубрика "Вредные советы для новичков"?

А что не так? - вполне разумная рекомендация - оформлять код в виде коротких самодостаточных процедур и функций - в противоположность типичному коду начинающих, стремящихся всю программу запихнуть внутрь loop()

Хм... Ну там ворох проблем, на самом деле:

1. Начать с того, что если человек понимает, что такое функция и как оно работает, то он как бы и сам догадается. Если не понимает - то вопросы типа "а почему я не могу вот тут переменную созданную вон там" ему радости не добавят.

2. Проектирование приложения "сверху вниз" по уровням абстракции возможно только при довольно хорошем знании возможностей и ограничений инфраструктуры (языка, среды, платформы и т.п.). Иначе можно неприятно ткнуться носом в эти самые ограничения и недостаток возможностей. Сам с год назад наступил на эти грабли - архитектура, которую я придумал в ардуину не вписалась и немало уже написанного кода кода улетело тогда в корзину. Т.е. методика хорошая, но не для новичков.

3. Это вкусовщина, конечно, но формировать функции по критерию "чтобы помещалось в экран" - зло.

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

TD27T пишет:

3. Это вкусовщина, конечно, но формировать функции по критерию "чтобы помещалось в экран" - зло.

Это классика времен Дейкстры. 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Chichay пишет:

Как постичь непостижимое

У Козьмы Петровича Пруткова этому посвящено целых пять пунктов списка афоризмов. Сколько тебе ещё нужно, чтобы понять?

№3.  Никто не обнимет необъятного. 
№44.  Никто не обнимет необъятного. 
№67.  Никто не обнимет необъятного! 
№104.  Плюнь тому в глаза, кто скажет, что можно обнять необъятное! 
№160.  Опять скажу: никто не обнимет необъятного! 
Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

TD27T пишет:
формировать функции по критерию "чтобы помещалось в экран" - зло.
Может и зло, но чертовски удобное зло. Особенно, когда это днлается с умом, а так, что это единственный критерий.

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

TD27T пишет:

2. Проектирование приложения "сверху вниз" по уровням абстракции возможно только при довольно хорошем знании возможностей и ограничений инфраструктуры (языка, среды, платформы и т.п.).

ИМХО, проектирование приложения всегда требует "знаний возможностей и ограничений инфраструктуры" - независмо от метода - "сверху вниз", справа-налево или еще как

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

b707 пишет:
проектирование приложения всегда требует "знаний возможностей и ограничений инфраструктуры"

Не, ну это 

TD27T пишет:
не для новичков.

От новичков требуется тока уметь скачать из сети похожий скетч и запостить на форум вопль "памагити!". А знания, проектирование, это всё от лукавого. 

TD27T, я прав?

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

для новичков loop() длиной в 4 файла - это намайна. так и надо. 

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

DetSimen пишет:

для новичков loop() длиной в 4 файла - это намайна. так и надо. 

ага. И еще нормально - всем, с кем не согласен - поставить в форуме -1

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

b707 пишет:

ага. И еще нормально - всем, с кем не согласен - поставить в форуме -1

Та тут это нинашто не влияет

TD27T
Offline
Зарегистрирован: 08.04.2016

b707 пишет:

TD27T пишет:

2. Проектирование приложения "сверху вниз" по уровням абстракции возможно только при довольно хорошем знании возможностей и ограничений инфраструктуры (языка, среды, платформы и т.п.).

ИМХО, проектирование приложения всегда требует "знаний возможностей и ограничений инфраструктуры" - независмо от метода - "сверху вниз", справа-налево или еще как

Хм... Ну, так-то, я против этого и не возражал, собственно. Прочитайте внимательнее, что я там пишу. Знания требуются в любом случае, но, вот, при озвученном подходе, уровень этих знаний должен быть весьма высоким.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

TD27T пишет:

3. Это вкусовщина, конечно, но формировать функции по критерию "чтобы помещалось в экран" - зло.

Нет, это добро.

А если возникают сомнения, берите 5К и ставьте его на попа.

https://www.nix.ru/autocatalog/lcd_iiyama/27-ZHK-monitor-IIYAMA-ProLite-XB2779QQS-S1-Silver-s-povorotom-ekrana-LCD-Wide-5120x2880-DVI-HDMI-DP_345195.html

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

TD27T пишет:

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

ну если понятие "область видимости переменных" (это то самое, что вы описали как "почему я не могу переменную здесь описанную там") - это высокий уровень знаний, то таки да, требуется высокий уровень :) И так требуется. что я бы даже есказал. что с более низким уровнем в программирование и соваться незачем.

И еще - если человек без знания инфрастуктуры написал кучу кода, которая не вписалась в ардуину и в итоге пропала даром - то это вовсе не из-за подхода "сверху вниз". Думаю, что без знаний этот человек ровно так же нагородил бы бесполезной ахинеи и при любом другом подходе.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

TD27T пишет:
3. Это вкусовщина, конечно, но формировать функции по критерию "чтобы помещалось в экран" - зло.
  Не верьте этому. Если вы пишите функцию и ее работа уже не помещается вам в голову, то разбейте ее на две.  Но если ее уже не возможно разбить для четкого вашего понимание, то бросте программировать. это не ваше.  А так можно смотреть на экран видеть на весь экран фигу.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

TD27T пишет:
3. Это вкусовщина, конечно, но формировать функции по критерию "чтобы помещалось в экран" - зло.
  Не верьте этому. Если вы пишите функцию и ее работа уже не помещается вам в голову, то разбейте ее на две.  Но если ее уже не возможно разбить для четкого вашего понимание, то бросте программировать. это не ваше.  А так можно смотреть на экран видеть на весь экран фигу.

void setup() {
    LCD.Init_0(); // первые 10 команд инициализации дисплея
    LCD.Init_1(); // вторый 10 команд инициализации дисплея
    LCD.Init_2(); // третьи 10 команд инициализации дисплея
    LCD.Init_3(); // оставшиеся 7 команд инициализации дисплея
}

 

TD27T
Offline
Зарегистрирован: 08.04.2016

andriano пишет:

TD27T пишет:

3. Это вкусовщина, конечно, но формировать функции по критерию "чтобы помещалось в экран" - зло.

Нет, это добро.

А если возникают сомнения, берите 5К и ставьте его на попа.

Вы даже не представляете насколько в точку попали.

Не стану разводить полемику по п.3, т.к., как я уже сказал - это вкусовщина и для программирования МК, когда текст всей программы со всеми библиотеками редко превышает пару тысяч строк проблема не так актуальна. Просто поясню моё негативное отношение к данной парадигме (к сожалению, не знаю как загнать текст под спойлер, ибо не всем он будет интересен и к ардуино отношения не имеет, но имеет к бездумному использованию и навязыванию спорных принципов построения кода).

Итак, в своём посте форумчанин сказал, что он никогда не пишет функций, текст которых не помещается в экран. Т.е. размер кода рассматривается как определяющий фактор. Нет, я понимаю, подразумевается, что вкупе с логической завершенностью, возможностью повторного использования и всё вот это вот. Но тем не менее. Одна контора, с которой мы сотрудничаем, некоторое время назад, похоже, приняла подобный подход в качестве корпоративного стандарта, ибо в их текстах начали появляться цепочки вызовов неприличной глубины и конструкции вида "делаемЧтоТо(), делаемЧтоТо_продолжаем(), делаемЧтоТо_продолжаемДалее()...". Бред, тупость, пофигизм? Ну так-то да, но мне вот с этим приходится жить. Почти привык уже, но бесит всё равно.

Лично я из ситуаций "10 функций по 1000 строк" и "160 функций по 60 строк" предпочту первую. Не стану дробить логически атомарный код в угоду размеру. Не буду выделять в функцию логику, которая не предполагает повторного использования (кроме случаев, когда того требует архитектура). Такой, вот, мой подход. На единственноправильность не претендую. Никому не навязываю.

TD27T
Offline
Зарегистрирован: 08.04.2016

b707 пишет:

TD27T пишет:

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

ну если понятие "область видимости переменных" (это то самое, что вы описали как "почему я не могу переменную здесь описанную там") - это высокий уровень знаний, то таки да, требуется высокий уровень :) И так требуется. что я бы даже есказал. что с более низким уровнем в программирование и соваться незачем.

Ну передёргиваете же... Зачем? "Уровень знаний" и "видимость переменных" относятся к разным граням вопроса, я даже их в разные пункты определил для наглядности. Кстати, область видимости - просто наиболее очевидный пример, можно и другие привести: ссылки на сдохшие переменные стека, например. Не в частностях суть.

TD27T
Offline
Зарегистрирован: 08.04.2016

b707 пишет:

И еще - если человек без знания инфрастуктуры написал кучу кода, которая не вписалась в ардуину и в итоге пропала даром - то это вовсе не из-за подхода "сверху вниз". Думаю, что без знаний этот человек ровно так же нагородил бы бесполезной ахинеи и при любом другом подходе.

Признаться, думал, что знаю. Оплошал.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

TD27T пишет:
Итак, в своём посте форумчанин сказал, что он никогда не пишет функций

Ну, это просто придирание к словам. Понятное дело, что всё нужно делать с умом. Ежели без ума, так ... пошли дурака Богу молиться.

И кстати, как раз категорическое "никогда" очень полезно именно для новичков, ты, просто, похоже, никогда не имел с ними дела так чтобы плотно (типа не преподавал, например). Тебя когда машину водить учили, не говорили что-нибудь типа "со временем начнёшь чувствовать когда нужно переключать передачи, а пока не чувствуешь - переключай 20-40-60". Также и здесь. Специалист понимает с чем он имеет дело и количество строк его не очень заботит, а вот как объяснить новичку. чтобы не писал длинных простыней? 10 - строк - это длинная? А 50? А 51? Где критерий "длинности"? Ему нужно дать понятный критерий, которым бы он мог пользоваться, пока не научится "чувствовать".

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

TD27T пишет:

Лично я из ситуаций "10 функций по 1000 строк" и "160 функций по 60 строк" предпочту первую. Не стану дробить логически атомарный код в угоду размеру. Не буду выделять в функцию логику, которая не предполагает повторного использования (кроме случаев, когда того требует архитектура).

"Логически атомарный код" длиной 1000 строк? :) На языке высокого уровня, а не на асме?

Что-то ржу :)

ИМХО, вы просто не умеете выделять в коде логические блоки.

Когда пишу программу, я не забочусь специально о длине функций. Но как-то само получается, что большинство моих процедур содержат 10-20 строк. Даже не 60, как вы пишете.

Кстати то, что большинство ваших процедур не предполагают повторного использования - тоже признак того, что вы не видите в них логических частей и пишете как единое целое.

простой пример. Если вы опишете заварку чая и приготовление кофе как две огромное функции "готовим чай" и "готовим кофе" - у вас получится два куска по 1000 строк. А если расписать каждую как последовательность операций

"заливаем воду в емкость"

"зажигаем плиту"

"нагреваем воду"

"доводим до кипения"

"засыпаем кофе" или "добавляем заварку"

- то выяснится. что две трети процедур в обоих задачай - одинаковые, и итоговый код можно уместить в 1500 строк вместо 2000. А поскольку такие упрощения можно сделать на нескольких уровнях - то реально программа из процедур длиной в 50 строк будет раза в три-пять короче, чем аналогичная по функциям простыня из двух адовых кусков по 1000 строк.

Как вывод из вышеизложенного - никакой вкусовщиной тут и не пахнет. Выбора  "10 функций по 1000 строк" или "160 функций по 60 строк" на самом деле нет. Написание длинных процедур (длиннее 30-50 строк примерно) - это просто низкий уровень проектирования программы.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Дорогой TD27T!

Ты ведь начинающий программист (и электронщик), о чем говорит простой поиск по твоему НИКу на форуме:

==============================================================

Найдено результатов: примерно 29 (за 0,11 сек.)
   
arduino.ru/forum/.../polimorfizm-v-arduino
TD27T. Offline. Зарегистрирован: 08.04.2016. Полиморфизма в ардуино, как я понимаю, в общем случае нет: нет STL, нет RTTI.
arduino.ru/.../predelnyi-vykhodnoi-tok-sdvigovogo-registra
images?q=tbn:ANd9GcQRRR1pAnq5IvZRUxoTAi1
TD27T. Offline. Зарегистрирован: 08.04.2016. Подскажите, умные люди, какую нагрузку можно вешать на лапы 74HC595N, чтоб ему при ...
arduino.ru/.../kak-ukazat-konkretnuyu-biblioteku-v-arduino-ide
TD27T. Offline. Зарегистрирован: 08.04.2016. Ткните, пожалуйста нуба носом в правильный ответ, а то весь мозг сломал уже.
arduino.ru/forum/apparatnye-voprosy/nano-i-wdt
images?q=tbn:ANd9GcQZq5c1V12rExMhvN-YOnG
TD27T. Offline. Зарегистрирован: 08.04.2016. Собственно, задача: погружать контроллер в продолжительный здоровый сон экономии ...
arduino.ru/.../kak-poluchit-vysokoimpedansnoe-sostoyanie-linii
images?q=tbn:ANd9GcRumbB6qokTu_jb_8ufBTe
TD27T, удобнее всего на реле. Мелкие твердотельные типа кр293кп1б , мелкие герконовые -, тоже лучше советские, типа рэс85, ...
arduino.ru/.../problema-s-platoi-zaryadki-litievykh-akkumulyatorov
TD27T. Offline. Зарегистрирован: 08.04.2016. Купил у китайцев платку заряда литиевых аккумуляторов, такую вот. И столкнулся с такой ...
arduino.ru/.../initsializatsiya-zakrytogo-staticheskogo-polya-klassa
Offline. Зарегистрирован: 19.02.2016. TD27T пишет: ... TD27T. Offline. Зарегистрирован: 08.04.2016. Спасибо, друзья. Разобрался. Верх.
arduino.ru/forum/.../problema-s-bibliotekoi-linkedlisth
TD27T. Offline. Зарегистрирован: 08.04.2016. Понадобились мне связанные списки. Гугл сходу предложил библиотеку LinkedList.h.
===============================================================
 
 
 
Так какого же хера ты влез со своим мнением? Оспорить профессионала? То, что тебе не стыдно, это ясно, это возрастное, ...но хоть смешно?
Грамотно писать читаемый и сопровождаемый код можно только медодом ДЕКОМПОЗИЦИИ, основы которого любезно изложил Евгений.
В функции выделяют не только повторяющиеся части кода, но даже однократно используемые, ради логики и простоты чтения блока кода верхнего уровня. 
Доступный твоему мозгу пример из практики Ардуино - это вызов (наприммер) lcd.init(). Он производится ровно ОДИН раз в коде. По твоей логике его нужно заменить на содержимое, так ;) ;) ;), заодно и Serial.begin() и т.д. и т.п. Надеюсь дошло?
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Слава Богу, сподобился таки я на старости лет узнать, что такое декомпозиция. Теперь понял хоть. :-)

TD27T
Offline
Зарегистрирован: 08.04.2016

b707 пишет:

Когда пишу программу, я не забочусь специально о длине функций. Но как-то само получается, что большинство моих процедур содержат 10-20 строк.

Если вы чего-то не видели, то это не значит, что этого не существует. У вас 10-20 строк средняя длина процедуры. У меня 200-300. Тысяча - действительно редкость, но не то, чтобы прям вот из ряда вон. А самый большой SQL-запрос, в котором доводилось ковыряться, был порядка 5000 строк. Вот это ад был, да.

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

Та авнакодеров то везде хватает. Особенно в SQL

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

Дед, та ладно Вам! Ещё одно слово узнали? Помаленьку становитесь "культурной девушкой"? :))))

«Мадмуазель Собак слыла культурной девушкой — в ее словаре было около ста восьмидесяти слов. При этом ей было известно одно такое слово, которое Эллочке даже не могло присниться. Это было богатое слово — гомосексуализм. Фима Собак, несомненно, была культурной девушкой» (И. Ильф и Е. Петров)