парсинг NMEA

gzp13
Offline
Зарегистрирован: 06.04.2015
$GPVTG, x.x, T x.x, M x.x, N x.x, K *hh <CR><LF> 

1. Направление курса в градусах, T 

2. Магнитное склонение в градусах, М 

3. Скорость над поверхностью (SOG) в узлах, N = узлы 

4. Скорость над поверхностью (SOG) в км/ч, К = км/ч 

5. hh Контрольная сумма строки (обязательно) 

Пример сообщения: 

$GPVTG,217.5,T,208.8,M,000.00,N,000.01,K*4C

Ну допустим я достану отсюда скорость в км/час, но я хочу ввести еще поправку +3км/час

 

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

gzp13 пишет:

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

 

Спидометры всех гражданских авто ВСЕГДА завышают. И это не случайность - это в законе прописано.

Кроме того, чаще всего они завышают неравномерно, чем выше скорость - тем больше прибавка. выше 100 кмч редко у какой легковушки спидометр не врет +10-15 кмч. Так что идея прибавлять именно 4 кмч - довольно сомнительна.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

gzp13 пишет:

не спидометром автомобиля часом ?

Именно им) Даже если и спидометр автомобиля завышает...

они все априори завышают на 3-7 км/ч.

у вас есть точный инструмент замера скорости, а вы хотите его уровнять не понятно с чем.

закономерный вопрос - зачем ?

и почему не наоборот ?

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

gzp13 пишет:
Ну допустим я достану отсюда скорость в км/час, но я хочу ввести еще поправку +3км/час

вы все время какие-то странные проблемы ставите. Прибавить к скорости +3 кмч - это проблема?

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

b707 пишет:

Кроме того, чаще всего они завышают неравномерно, чем выше скорость - тем больше прибавка. выше 100 кмч редко у какой легковушки спидометр не врет +10-15 кмч.

мой гад почти линейный :)

5-7 км/ч в диапазоне 30-120.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

b707 пишет:

gzp13 пишет:
Ну допустим я достану отсюда скорость в км/час, но я хочу ввести еще поправку +3км/час

вы все время какие-то странные проблемы ставите. Прибавить к скорости +3 кмч - это проблема?

его не устраимает скорость 3 км/ч на неподвижной машине.

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

xDriver пишет:

его не устраимает скорость 3 км/ч на неподвижной машине.

а он рассчитывает с неподвижного GPS получать строго 0 кмч? - наивно

gzp13
Offline
Зарегистрирован: 06.04.2015

Хорошо, убедили. Буду считать что скорость GPS точна.

Вот отладил код, все хорошо когда вывожу данные в com порт через Serial.print. Но при попытке вывести скорость и кол-во спутников на дисплей данные не выводятся. Предполагаю что дело в переменных.Вывод на дисплей организован в строках 219-222. И при таком коде почему то не выводятся данные в COM порт через Serial.print

#include <SoftwareSerial.h>
#include <iarduino_OLED.h>
#include <MsTimer2.h> 
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 57600;
SoftwareSerial ss(RXPin, TXPin);
iarduino_OLED  myOLED(0x3C);                               // Объявляем объект myOLED, указывая адрес дисплея на шине I2C: 0x3C или 0x3D.
extern uint8_t MediumFontRus[]; // Подключаем шрифт MediumFontRus.
extern uint8_t SmallFontRus[]; 
extern uint8_t BigNumbers[]; 
int flag=0;
int flag1=0;
int flag2=0;
byte n;
byte regim=1;
byte speed;


void setup(void) {
Serial.begin(9600);
  ss.begin(GPSBaud);
  pinMode(7, OUTPUT);    
//MsTimer2::set(90, flash); // 500ms period
  pinMode(9,OUTPUT);
  digitalWrite(9,HIGH);
  delay(200);
  myOLED.begin();
 
myOLED.setFont(MediumFontRus);                           // Указываем шрифт который требуется использовать для вывода цифр и текста.
myOLED.print(F("УРАГАН-13"), 8,24);
myOLED.print(F("Клеменчев"), 11,60);
  delay(2000);
  ss.begin(GPSBaud);
//Serial.begin(9600);
myOLED.setFont(MediumFontRus);
myOLED.clrScr();
myOLED.print(("ГОРОД"), 5,14);

n=1;
}


//
// Эта функция принимает символ из Serial и возвращает
//  указатель на полученную строку или NULL, если строка
//  ещё не получена.
// Строка всегда начинается с $ и заканчивается \r или \n
//
static const int MAX_LEN = 160; // 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 (!ss.available()) return NULL;
  const char c = ss.read();
  //Serial.print(c);
  //
  //  Если мы ждём начала строки, то сравинваем 
  //  прочитанный символ с '$', если равен - начало найдено
  //
  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 & time,double & num_sat, double & date , double & gps_speed  ) 
{
// 

  //  getStrFromSerial() вернёт строку, полученную из Serial
  // или NULL, если строка ещё пока не получена
  //
  const char * str = getStrFromSerial();
  //
  //  Если строка ещё не получена, выходим
  //
  if (str == NULL) return false;
  //
  //  Если строка не начинается с "$GPGGA или GPRMC",
  // то она нам не нужна выходим
  //
  const char * prefix = "$GPGGA";
  const char * prefix2 = "$GPRMC";
 if (  ! strncmp(str, prefix, strlen(prefix))) 
  {
  //  Ищем первую запятую в строке str
  //
   char * comma = strchr(str, ',');
  //
  //  Если не нашли (строка кривая пришла?) - выходим
  //
  if (!comma) return false;
  //
  //  со следующего символа просле запятой идёт числоа - широта
  //
  time = atof(comma+1);
  //
  //  Ищем вторую запятую после начала числа-широты
  //
 comma = strchr(comma+1, ','); // сначала ищем первую запятую 2
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 4
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 6
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7
  if (!comma) return false; // почему-то не нашли :((((
  //
  //  со следующего символа просле запятой идёт числоа - долгота
  //
  num_sat = atof(comma+1);
 return true;
  }
  
  //  Вроде всё
  //
  
 else if  ( ! strncmp(str, prefix2, strlen(prefix2)))
 {
 char * comma = strchr(str, ',');
  //
  //  Если не нашли (строка кривая пришла?) - выходим
  //
  if (!comma) return false;
  //
  //  со следующего символа просле запятой идёт числоа - широта
  //
  //time = atof(comma+1);
  //
  //  Ищем вторую запятую после начала числа-широты
  //
 comma = strchr(comma+1, ','); // сначала ищем первую запятую 2
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 4
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 6
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7
    if (!comma) return false; // почему-то не нашли :((((
    
    gps_speed=atof(comma+1)*1.852;   // переводим скорость в км/час
    
    comma = strchr(comma+1, ','); // сначала ищем первую запятую 8
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 9
  if (!comma) return false; // почему-то не нашли :((((
  date=atof(comma+1);
  //return true;
}
else return false;

}
void loop(void) {
   double time,num_sat, gps_speed,date;  
myOLED.setCursor(80,55);
myOLED.setFont(MediumFontRus);
myOLED.print("КМ/Ч");   
   
   //Читаем время,кол-во спутников,дату,скорость если успешно прочитались, печатаем
  
 if (readLatLon(time,num_sat, date,gps_speed)) {
  
   
    Serial.print("time: ");
    Serial.println(time, 2);
    Serial.print("num_sat: ");
    Serial.println(num_sat, 0);
    Serial.print("date: ");
    Serial.println(date, 0);
    Serial.print("speed: ");
    Serial.println(gps_speed, 0);
    myOLED.setFont(MediumFontRus);
   myOLED.print(num_sat,103,14,0);
  myOLED.setFont(BigNumbers);
  myOLED.print(gps_speed,30,55,0);
  }
 }
 

 

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

gzp13 пишет:
Скорость с GPS поступает в узлах в час

Скорость на может быть в узлах в час - это единица ускорения.

А с GPS скорость приходит и в узлах, и в км/ч берите ту, какая Вам нужна.

gzp13
Offline
Зарегистрирован: 06.04.2015
А с GPS скорость приходит и в узлах, и в км/ч берите ту, какая Вам нужна.

С этим я разобрался вроде, спасибо, теперь вот не могу все это вывести на дисплей OLED 128x64. Прблемку описал чуть выше, в посте №58

Выяснил, что при добавлении строк вывода данных на экран, в Serial порту появляется сообщение "ERROR : too long string!!!"

Что бы это значило... и как с этим бороться?

 

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

Ну, описал, и молодец. Может кто и отзовётся.

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

gzp13
Offline
Зарегистрирован: 06.04.2015

Согласен с Вами, мне тоже интересно, просто я завис уже пять дней, чувствую что сам не разберусь. На библиотеке TinyGPS сделал все как хотел, но там слишком медленная скорость,9600, не подходит для машины слишком медленно. Вот по Вашим примерам кое чего добился. Осталось все вывести на дисплей, не думал что возникнет проблема, а она блин возникла.

renoshnik
Offline
Зарегистрирован: 11.04.2013

gzp13 пишет:

А с GPS скорость приходит и в узлах, и в км/ч берите ту, какая Вам нужна.

С этим я разобрался вроде, спасибо, теперь вот не могу все это вывести на дисплей OLED 128x64. Прблемку описал чуть выше, в посте №58

Выяснил, что при добавлении строк вывода данных на экран, в Serial порту появляется сообщение "ERROR : too long string!!!"

Что бы это значило... и как с этим бороться?

 

строки от №59 до №64

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

gzp13 пишет:

 уже пять дней

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

gzp13
Offline
Зарегистрирован: 06.04.2015
строки от №59 до №64

Выяснил, что как только добавляю строку с библиотеки IArduino_OLED , то сразу ошибки.

 

renoshnik
Offline
Зарегистрирован: 11.04.2013

gzp13 пишет:

строки от №59 до №64

Выяснил, что как только добавляю строку с библиотеки IArduino_OLED , то сразу ошибки.

 

правильно...  SoftwareSerial.h  не вывозит ...

подключи дефолтный сериал ( 0, 1 ).

gzp13
Offline
Зарегистрирован: 06.04.2015
подключи дефолтный сериал ( 0, 1 ).

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

APJ
Offline
Зарегистрирован: 25.03.2015

Подскажите как изменить частоту на приёмнике Unlox neo-M8N. Как поменять скорость порта я нашёл, а частоту передачи что-то не найти. Через U-centre меняет, но после выключения питания всё слетает, так как на плате не припаяна память.

 

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

этот модуль работает на частоте обновлений данных либо 5 либо 10 Герц, надо посмотреть что шлет U-centre в порт при смене частоты.

APJ
Offline
Зарегистрирован: 25.03.2015

По дефолту 1 Гц. Уже думал над перехватом сообщения с U-centre.

gzp13
Offline
Зарегистрирован: 06.04.2015
Подскажите как изменить частоту на приёмнике 

Я вот так сделал и все работает, правда у меня стоит батарейка.

Перейти в общем меню Receiver=> Action=> Save Config. Если этого не сделать приемник после следующего включения перейдет к первоначальным настройкам. 

 

APJ
Offline
Зарегистрирован: 25.03.2015

gzp13 пишет:

Подскажите как изменить частоту на приёмнике 

Я вот так сделал и все работает, правда у меня стоит батарейка.

Перейти в общем меню Receiver=> Action=> Save Config. Если этого не сделать приемник после следующего включения перейдет к первоначальным настройкам. 

 

Там не батарейка, а ионистор. Как я понял он только для сохранения альманаха спутников, для более быстрого старта.

Сейчас меняю скорость порта этим сообщением-   ss.print("$PUBX,41,1,3,3,38400,0*24\r\n");

Хватает до первого выключения питания.

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

APJ пишет:

Сейчас меняю скорость порта этим сообщением-   ss.print("$PUBX,41,1,3,3,38400,0*24\r\n");

Хватает до первого выключения питания.

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

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

gzp13 пишет:

Скорость с GPS поступает в узлах в час

Узлы в час - это не скорость, а ускорение.

Цитата:

Но мой GPS занижает скорость на 4км/час, т.е мне надо прибавить еще 4км/час.Но тогда при нулевой скорости у меня на дисплее будет индицироваться 4км/час.

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

 

Если же Вы хотите, чтобы Ваш прибор показывал не истинную скорость, а ту, что показывает автомобильный спидометр, почитайте ГОСТ на спидометры, чтобы выяснить, по какому алгоритму тот завышает показания и, соответственно, примените этот алгоритм к показаниям своего датчика.

gzp13
Offline
Зарегистрирован: 06.04.2015

Коллеги, добился я вывода необходимых мне данных с частотой 5Гц, т. е каждые 200мс,но после добавления в код других условий( стоит две кнопки, светодиод, OLED дисплей), частота получения данных от GPS разу снижается, вывод сообщений происходит то через 400мс, то через 800мс.Ясно, что код жрёт, это можно победить или нет? И параллельно вопрос, не могу через аппаратный serial вывести информацию о данных с GPS на дисплей. Подключаю правильно, RX-TX, TX-RX.

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

gzp13 пишет:
И параллельно вопрос, не могу через аппаратный serial вывести информацию о данных с GPS на дисплей. Подключаю правильно, RX-TX, TX-RX.

поясните, что имеется в виду, а то пока фраза звучит бредово, если учесть, что дисаплей у вас ОЛЕД и никакого сериала в нем нет

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

gzp13 пишет:
Ясно, что код жрёт, это можно победить или нет?

Можно. Как именно? ХЗ, т.к. ХЗ что там за код.

gzp13 пишет:
вопрос, не могу через аппаратный serial вывести информацию о данных с GPS на дисплей.

Это не вопрос - это утверждение. Принято к сведению, что Вы не можете.

renoshnik
Offline
Зарегистрирован: 11.04.2013

gzp13 пишет:
Коллеги, добился я вывода необходимых мне данных с частотой 5Гц, т. е каждые 200мс,но после добавления в код других условий( стоит две кнопки, светодиод, OLED дисплей), частота получения данных от GPS разу снижается, вывод сообщений происходит то через 400мс, то через 800мс.Ясно, что код жрёт, это можно победить или нет? И параллельно вопрос, не могу через аппаратный serial вывести информацию о данных с GPS на дисплей. Подключаю правильно, RX-TX, TX-RX.

Конечно можно, если код правильно написать .

gzp13
Offline
Зарегистрирован: 06.04.2015
Можно. Как именно? ХЗ, т.к. ХЗ что там за код.

Вот привожу кусочек из LOOP,который существенно подтормаживает вывод данных gps.Приемник gps подключен к ардуино через SoftSerial( D4,D3), через аппаратный Serial(D1,D0) подкдючал, данные gps вообще не выводятся на дисплей. А код с парсингом NMEA сообщения Вы видели, тем более я его копировал из Вашего урока) Сегодня кстати испытывал в машине при езде, так вот почему то кол-во спутником не верное, скачет беспрерывно, и скорость при движении то 0 то правильная, думаю это зависит не от качества приема сигнала gps, аваидимо не много не правильно у меня выводятся данные о скорости и спутниках.

void loop(void) {
  double time, speed,num_sat, date;
   //Читаем время,кол-во спутников,дату,скорость если успешно прочитались, печатаем
   if (readLatLon(time,num_sat, date,speed)) 
{
if (digitalRead(5)==HIGH&&flag==0)  //по нажатию кнопки включается либо режим
 {                                   // ГОРОД либо ТРАССА
  regim++;
    flag=1;
   n=1;
  if (regim>2) regim=1;
 }
  if (digitalRead(6)==LOW&&flag==1)
  {
   flag=0;
   }
if (regim==1) 
{  
   myOLED.setFont(MediumFontRus); 
    myOLED.print("ГОРОД ", 2,14);
    myOLED.print("КМ/Ч",80,55);
  speed1=1;
}
if (regim==2) 
{
   myOLED.setFont(MediumFontRus); 
   myOLED.print("ТРАССА ", 2,14);
   myOLED.print("КМ/Ч",80,55);
  speed1=2;
}
if (digitalRead(6)==HIGH&&flag2==0 )  // по нажатию кнопки выключается либо включается OLED дисплей
 {                                     // через полевой транзистор
  flag2=1;
  digitalWrite(9,!digitalRead(9));
    if (n==1) 
{
  myOLED.setFont(MediumFontRus); 
    myOLED.print("ГОРОД ", 2,14);
    myOLED.print("КМ/Ч",80,55);
}
    if (n==2) 
{
  myOLED.setFont(MediumFontRus); 
   myOLED.print("ТРАССА ", 2,14);
   myOLED.print("КМ/Ч",80,55);
}
    myOLED.begin();
   }
   
 if (digitalRead(6)==LOW &&flag2==1 )
  {
    flag2=0;
   }

  if (speed1==1)                          //если скорость более 78км/ч моргает светодиод
  {                                       //если менее-гаснет
    if (speed>=78 )
    {
      digitalWrite(7, !digitalRead(7));
    }
  else 
  {
       digitalWrite(7,LOW);
  }
    }
if (speed1==2)
{
  if (speed>=108)                            //если скорость более 108км/ч моргает светодиод
  {                                       //если менее-гаснет          
     digitalWrite(7, !digitalRead(7));
    }
  else 
  {
    digitalWrite(7,LOW);
  }
 }
   myOLED.setCursor(95,14); 
   myOLED.setFont(MediumFontRus);
   myOLED.print(0);
   myOLED.print(num_sat,110,14,0);                 //выводим кол-во спутников
    if (speed<100)                                 // тут при выводе скорости, если число двухзначное
{                                                // закрашиваем младший разряд
   myOLED.drawRect   (59, 28,  78, 57, true , 0);
  } 
  if (speed<10)
  {
    myOLED.drawRect   (44, 28,  78, 57, true , 0); 
   }
  myOLED.setFont(BigNumbers);
  myOLED.print(speed,30,55,0);                         //выводим скорость
    //Serial.print("time: ");
    //Serial.println(time, 2);
    //Serial.print("num_sat: ");
    //Serial.println(num_sat,0);
    //Serial.print("date: ");
    //Serial.println(date, 0);
    //Serial.print("speed: ");
    //Serial.println(speed, 0);
  }
 }

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

Предложения оптимизации  выложенного кода

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

За этот небольшой кусочек кода 5 раз выбирается один и тот же экранный фонт. Зачем? - выбирайте фонт только тогда, когда он реально меняется

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

Ну и вообще, написано как курица лапой накарябала. сорри :)

Кстати. судя по коду. вы делайте предупреждайку о превышении скорости против гаишных камер. А оно надо? В большинстве регистраторов с GPS и почти во всех навигаторах эта функция уже встроена.  Более того, щас почти каждый смартфон имеет ЖПС. скачайте программку с маркета и пользуйтесь ...

gzp13
Offline
Зарегистрирован: 06.04.2015

Да, это просто сигнализатор превышения скорости в городе и на трассе, первысил заданный порог-загорелся светодиод, ну можно еще птщплку поставить, например с писком на 1сек.Штрафы замучали, смотреть постоянно на спидометр не удобно, антирадар имеется, но хочется просто-загорелась лампочка-сбавь скорость, и не надо снимать с торпеды.А эти антирадары, регистраторы с GPS у меня в районе надо снимать-дураков хватает.Телефон-не интересно).

Выводить в эту позицию пробел - в несколько раз (или даже в десятки раз) быстрее.

А как записать эту строку.


myOLED.print("  ",25,55,0);
myOLED.print(speed,30,55,0);

Или это не правильно?

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

gzp13 пишет:

А как записать эту строку.


myOLED.print("  ",25,55,0);
myOLED.print(speed,30,55,0);

Или это не правильно?

ну если вы точно вычислили позицию пробеоа (а вы должны были ее вычислить, когда drawrect делали - то такая строчка должна работать

gzp13
Offline
Зарегистрирован: 06.04.2015

Спасибо, буду пробовать.

А как Вы думаете, если в этом коде ошибка при парсинге сообщений? Просто сегодня проверял в действии конкретно это код, как писал выше спутники не правильно выводятся, и скорость то 0 то реальная.

//#include "timer-api.h"
//#include <MsTimer2.h>
#include <iarduino_OLED.h>
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 57600;
SoftwareSerial ss(RXPin, TXPin);
iarduino_OLED  myOLED(0x3C);                               // Объявляем объект myOLED, указывая адрес дисплея на шине I2C: 0x3C или 0x3D.
extern uint8_t MediumFontRus[]; // Подключаем шрифт MediumFontRus.
extern uint8_t SmallFontRus[]; 
extern uint8_t BigNumbers[]; 
int flag=0;
int flag1=0;
int flag2=0;
byte n;
byte regim=1;
byte speed1;
 //int _timer = TIMER_DEFAULT;
 
void setup(void) {
  //timer_init_ISR_1Hz(TIMER_DEFAULT);
//Serial.begin(115200);
  ss.begin(GPSBaud);
  myOLED.begin();
  delay(200);
  pinMode(7, OUTPUT);
   pinMode(9,OUTPUT);
  digitalWrite(9,HIGH);
  delay(200);
  myOLED.begin(); 
myOLED.setFont(MediumFontRus);                           // Указываем шрифт который требуется использовать для вывода цифр и текста.
myOLED.print(F("УРАГАН-13"), 8,24);
myOLED.print(F("Клеменчев"), 11,60);
  delay(2000);
  myOLED.clrScr();
myOLED.print(("ГОРОД"), 5,14);
//myOLED.print("КМ/Ч",80,55);
//MsTimer2::set(90, flash); // 500ms period   
}


//
// Эта функция принимает символ из Serial и возвращает
//  указатель на полученную строку или NULL, если строка
//  ещё не получена.
// Строка всегда начинается с $ и заканчивается \r или \n
//
static const int MAX_LEN = 140; // 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 (!ss.available()) return NULL;
  const char c = ss.read();
  //Serial.print(c);
  //
  //  Если мы ждём начала строки, то сравинваем 
  //  прочитанный символ с '$', если равен - начало найдено
  //
  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 & time,double & num_sat, double & date , double & speed  ) 
{
  

  //  getStrFromSerial() вернёт строку, полученную из Serial
  // или NULL, если строка ещё пока не получена
  //
  const char * str = getStrFromSerial();
  //
  //  Если строка ещё не получена, выходим
  //
  if (str == NULL) return false;
  //
  //  Если строка не начинается с "$GPGGA или GPRMC",
  // то она нам не нужна выходим
  //
  const char * prefix = "$GPGGA";
  const char * prefix2 = "$GPRMC";
 if (  ! strncmp(str, prefix, strlen(prefix))) 
  {
  //  Ищем первую запятую в строке str
  //
   char * comma = strchr(str, ',');
  //
  //  Если не нашли (строка кривая пришла?) - выходим
  //
  if (!comma) return false;
  //
  //  со следующего символа просле запятой идёт числоа - широта
  //
  time = atof(comma+1);
  //
  //  Ищем вторую запятую после начала числа-широты
  //
 comma = strchr(comma+1, ','); // сначала ищем первую запятую 2
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 4
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 6
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7
  if (!comma) return false; // почему-то не нашли :((((
  //
  //  со следующего символа просле запятой идёт числоа - долгота
  //
  num_sat = atoi(comma+1);
 return true;
  }
  
  //  Вроде всё
  //
  
 else if  ( ! strncmp(str, prefix2, strlen(prefix2)))
 {
 char * comma = strchr(str, ',');
  //
  //  Если не нашли (строка кривая пришла?) - выходим
  //
  if (!comma) return false;
  //
  //  со следующего символа просле запятой идёт числоа - широта
  //
  //time = atof(comma+1);
  //
  //  Ищем вторую запятую после начала числа-широты
  //
 comma = strchr(comma+1, ','); // сначала ищем первую запятую 2
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 4
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 6
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7
    if (!comma) return false; // почему-то не нашли :((((
    
    speed=atof(comma+1)*1.852;   // переводим скорость в км/час
    //speed=85;
   // comma = strchr(comma+1, ','); // сначала ищем первую запятую 8
  //if (!comma) return false; // почему-то не нашли :((((
  //comma = strchr(comma+1, ','); // теперь ищем вторую запятую 9
  //if (!comma) return false; // почему-то не нашли :((((
  date=atof(comma+1);
  //return true;
}
else return false;

}
void loop(void) {
  double time, speed,num_sat, date;
//myOLED.setCursor(80,55);
//myOLED.setFont(MediumFontRus);
//myOLED.print("КМ/Ч"); 

 
//if (num_sat<4) speed=0;
  
 //myOLED.setCursor(80,55);
//myOLED.setFont(MediumFontRus);
//myOLED.print("КМ/Ч");
 //myOLED.print(("ГОРОД"), 5,14); 
   //Читаем время,кол-во спутников,дату,скорость если успешно прочитались, печатаем
  
 if (readLatLon(time,num_sat, date,speed)) {
 

if (digitalRead(5)==HIGH&&flag==0)  //по нажатию кнопки включается либо режим
 {                                   // ГОРОД либо ТРАССА
  regim++;
    flag=1;
   n=1;
  if (regim>2) regim=1;
 }
  if (digitalRead(6)==LOW&&flag==1)
  {
   flag=0;
   }
if (regim==1) 
{  
   myOLED.setFont(MediumFontRus); 
    myOLED.print("ГОРОД ", 2,14);
    myOLED.print("КМ/Ч",80,55);
  speed1=1;
}
if (regim==2) 
{
   myOLED.setFont(MediumFontRus); 
   myOLED.print("ТРАССА ", 2,14);
   myOLED.print("КМ/Ч",80,55);
  speed1=2;
}

if (digitalRead(6)==HIGH&&flag2==0 )  // по нажатию кнопки выключается либо включается OLED дисплей
 {                                     // через полевой транзистор
  flag2=1;
  digitalWrite(9,!digitalRead(9));
    if (n==1) 
{
  myOLED.setFont(MediumFontRus); 
    myOLED.print("ГОРОД ", 2,14);
    myOLED.print("КМ/Ч",80,55);
}
    if (n==2) 
{
  myOLED.setFont(MediumFontRus); 
   myOLED.print("ТРАССА ", 2,14);
   myOLED.print("КМ/Ч",80,55);
}
    myOLED.begin();
   }
   
 if (digitalRead(6)==LOW &&flag2==1 )
  {
    flag2=0;
   }

  if (speed1==1)                          //если скорость более 78км/ч моргает светодиод
  {                                       //если менее-гаснет
    if (speed>=78 )
    {
      digitalWrite(7, !digitalRead(7));
    }
  else 
  {
       digitalWrite(7,LOW);
  }
    }
if (speed1==2)
{
  if (speed>=108)                            //если скорость более 108км/ч моргает светодиод
  {                                       //если менее-гаснет          
     digitalWrite(7, !digitalRead(7));
    }
  else 
  {
    digitalWrite(7,LOW);
  }
 }
   myOLED.setCursor(95,14); 
   myOLED.setFont(MediumFontRus);
   myOLED.print(0);
   myOLED.print(num_sat,110,14,0);
   // myOLED.print(num_sat,103,14,0);

 if (speed<100)                                 // тут при выводе скорости, если число двухзначное
{                                                // закрашиваем младший разряд
   myOLED.drawRect   (59, 28,  78, 57, true , 0);
  } 
  if (speed<10)
  {
    myOLED.drawRect   (44, 28,  78, 57, true , 0); 
   }
  myOLED.setFont(BigNumbers);
  myOLED.print(speed,30,55,0);
  

   
    //Serial.print("time: ");
    //Serial.println(time, 2);
    //Serial.print("num_sat: ");
    //Serial.println(num_sat,0);
    //Serial.print("date: ");
    //Serial.println(date, 0);
    //Serial.print("speed: ");
    //Serial.println(speed, 0);
  }
 }

Вот еще возник вопрос, можно объявить переменные speed,num_sat,time  не локальными а глобальными? Тогда можно вывести все проверки из цикла loop в void skorst() например, или в этом нет особого смысла?

renoshnik
Offline
Зарегистрирован: 11.04.2013

gzp13 пишет:

Можно. Как именно? ХЗ, т.к. ХЗ что там за код.

Вот привожу кусочек из LOOP,который существенно подтормаживает вывод данных gps.Приемник gps подключен к ардуино через SoftSerial( D4,D3), через аппаратный Serial(D1,D0) подкдючал, данные gps вообще не выводятся на дисплей. А код с парсингом NMEA сообщения Вы видели, тем более я его копировал из Вашего урока) Сегодня кстати испытывал в машине при езде, так вот почему то кол-во спутником не верное, скачет беспрерывно, и скорость при движении то 0 то правильная, думаю это зависит не от качества приема сигнала gps, аваидимо не много не правильно у меня выводятся данные о скорости и спутниках.

void loop(void) {
  double time, speed,num_sat, date;
   //Читаем время,кол-во спутников,дату,скорость если успешно прочитались, печатаем
   if (readLatLon(time,num_sat, date,speed)) 
{
if (digitalRead(5)==HIGH&&flag==0)  //по нажатию кнопки включается либо режим
 {                                   // ГОРОД либо ТРАССА
  regim++;
    flag=1;
   n=1;
  if (regim>2) regim=1;
 }
  if (digitalRead(6)==LOW&&flag==1)
  {
   flag=0;
   }
if (regim==1) 
{  
   myOLED.setFont(MediumFontRus); 
    myOLED.print("ГОРОД ", 2,14);
    myOLED.print("КМ/Ч",80,55);
  speed1=1;
}
if (regim==2) 
{
   myOLED.setFont(MediumFontRus); 
   myOLED.print("ТРАССА ", 2,14);
   myOLED.print("КМ/Ч",80,55);
  speed1=2;
}
if (digitalRead(6)==HIGH&&flag2==0 )  // по нажатию кнопки выключается либо включается OLED дисплей
 {                                     // через полевой транзистор
  flag2=1;
  digitalWrite(9,!digitalRead(9));
    if (n==1) 
{
  myOLED.setFont(MediumFontRus); 
    myOLED.print("ГОРОД ", 2,14);
    myOLED.print("КМ/Ч",80,55);
}
    if (n==2) 
{
  myOLED.setFont(MediumFontRus); 
   myOLED.print("ТРАССА ", 2,14);
   myOLED.print("КМ/Ч",80,55);
}
    myOLED.begin();
   }
   
 if (digitalRead(6)==LOW &&flag2==1 )
  {
    flag2=0;
   }

  if (speed1==1)                          //если скорость более 78км/ч моргает светодиод
  {                                       //если менее-гаснет
    if (speed>=78 )
    {
      digitalWrite(7, !digitalRead(7));
    }
  else 
  {
       digitalWrite(7,LOW);
  }
    }
if (speed1==2)
{
  if (speed>=108)                            //если скорость более 108км/ч моргает светодиод
  {                                       //если менее-гаснет          
     digitalWrite(7, !digitalRead(7));
    }
  else 
  {
    digitalWrite(7,LOW);
  }
 }
   myOLED.setCursor(95,14); 
   myOLED.setFont(MediumFontRus);
   myOLED.print(0);
   myOLED.print(num_sat,110,14,0);                 //выводим кол-во спутников
    if (speed<100)                                 // тут при выводе скорости, если число двухзначное
{                                                // закрашиваем младший разряд
   myOLED.drawRect   (59, 28,  78, 57, true , 0);
  } 
  if (speed<10)
  {
    myOLED.drawRect   (44, 28,  78, 57, true , 0); 
   }
  myOLED.setFont(BigNumbers);
  myOLED.print(speed,30,55,0);                         //выводим скорость
    //Serial.print("time: ");
    //Serial.println(time, 2);
    //Serial.print("num_sat: ");
    //Serial.println(num_sat,0);
    //Serial.print("date: ");
    //Serial.println(date, 0);
    //Serial.print("speed: ");
    //Serial.println(speed, 0);
  }
 }

Как это ты так умудрился подключиться ???

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015
static const uint32_t GPSBaud = 57600;

не думаю что это хорошая идея. ходят разные мнения, мое личное - SoftwareSerial на скоростях выше 38400 работает не стабильно.

renoshnik
Offline
Зарегистрирован: 11.04.2013

gzp13 пишет:

Спасибо, буду пробовать.

А как Вы думаете, если в этом коде ошибка при парсинге сообщений? Просто сегодня проверял в действии конкретно это код, как писал выше спутники не правильно выводятся, и скорость то 0 то реальная.

применяй аппаратный сериал !!! больше повторять не буду...

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Готовый код аналогичного устройства есть у Алекса Гайвера на Ютубе

gzp13
Offline
Зарегистрирован: 06.04.2015
применяй аппаратный сериал !!!

Да я вчера припаял провода, но вот на дисплей данные с GPS не получилолсь вывести.

void setup() {
    Serial.begin(57600); // устанавливаем последовательное соединение
}
void loop() {
    if (Serial.available() > 0) {  // тут далее идет код
      ......
........
}
Как это ты так умудрился подключиться ???

А что не правлиьного в моем подключении?

 

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

ua6em пишет:

Готовый код аналогичного устройства есть у Алекса Гайвера на Ютубе

Ой, не надо. Выкладывл он тут свои коды - ни одного без грубейших ошибок ... нафиг-нафиг, чем такое брать за основу, лучше с нуля писать.

renoshnik
Offline
Зарегистрирован: 11.04.2013

gzp13 пишет:

применяй аппаратный сериал !!!

Да я вчера припаял провода, но вот на дисплей данные с GPS не получилолсь вывести.

void setup() {
    Serial.begin(57600); // устанавливаем последовательное соединение
}
void loop() {
    if (Serial.available() > 0) {  // тут далее идет код
      ......
........
}
Как это ты так умудрился подключиться ???

А что не правлиьного в моем подключении?

 

 

Игде в вашем (приведенном выше) коде, в "лупе" идет обращение к сериалу ?

То, что запостили пример из учебника, молодец, хоть знаешь, что есть такой учебник ...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

ua6em пишет:

Готовый код аналогичного устройства есть у Алекса Гайвера на Ютубе

Ой, не надо. Выкладывл он тут свои коды - ни одного без грубейших ошибок ... нафиг-нафиг, чем такое брать за основу, лучше с нуля писать.


 так он же студент, его учит кто-то )))

gzp13
Offline
Зарегистрирован: 06.04.2015
Игде в вашем (приведенном выше) коде, в "лупе" идет обращение к сериалу ?

Чот Вы меня совсем запутали. Строка 48.


void setup(void) {
  //timer_init_ISR_1Hz(TIMER_DEFAULT);
Serial.begin(57600);
   myOLED.begin();
  delay(200);
  pinMode(7, OUTPUT);
   pinMode(9,OUTPUT);
  digitalWrite(9,HIGH);
  delay(200);
  myOLED.begin(); 
myOLED.setFont(MediumFontRus);                           // Указываем шрифт который требуется использовать для вывода цифр и текста.
myOLED.print(F("УРАГАН-13"), 8,24);
myOLED.print(F("Клеменчев"), 11,60);
  delay(2000);
  myOLED.clrScr();
myOLED.print(("ГОРОД"), 5,14);
//myOLED.print("КМ/Ч",80,55);
//MsTimer2::set(90, flash); // 500ms period   
}


//
// Эта функция принимает символ из Serial и возвращает
//  указатель на полученную строку или NULL, если строка
//  ещё не получена.
// Строка всегда начинается с $ и заканчивается \r или \n
//
static const int MAX_LEN = 140; // 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();
  //Serial.print(c);
  //
  //  Если мы ждём начала строки, то сравинваем 
  //  прочитанный символ с '$', если равен - начало найдено
  //
  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 & time,double & num_sat, double & date , double & speed  ) 
{
  

  //  getStrFromSerial() вернёт строку, полученную из Serial
  // или NULL, если строка ещё пока не получена
  //
  const char * str = getStrFromSerial();
  //
  //  Если строка ещё не получена, выходим
  //
  if (str == NULL) return false;
  //
  //  Если строка не начинается с "$GPGGA или GPRMC",
  // то она нам не нужна выходим
  //
  const char * prefix = "$GPGGA";
  const char * prefix2 = "$GPRMC";
 if (  ! strncmp(str, prefix, strlen(prefix))) 
  {
  //  Ищем первую запятую в строке str
  //
   char * comma = strchr(str, ',');
  //
  //  Если не нашли (строка кривая пришла?) - выходим
  //
  if (!comma) return false;
  //
  //  со следующего символа просле запятой идёт числоа - широта
  //
  time = atof(comma+1);
  //
  //  Ищем вторую запятую после начала числа-широты
  //
 comma = strchr(comma+1, ','); // сначала ищем первую запятую 2
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 4
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 6
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7
  if (!comma) return false; // почему-то не нашли :((((
  //
  //  со следующего символа просле запятой идёт числоа - долгота
  //
  num_sat = atoi(comma+1);
 return true;
  }
  
  //  Вроде всё
  //
  
 else if  ( ! strncmp(str, prefix2, strlen(prefix2)))
 {
 char * comma = strchr(str, ',');
  //
  //  Если не нашли (строка кривая пришла?) - выходим
  //
  if (!comma) return false;
  //
  //  со следующего символа просле запятой идёт числоа - широта
  //
  //time = atof(comma+1);
  //
  //  Ищем вторую запятую после начала числа-широты
  //
 comma = strchr(comma+1, ','); // сначала ищем первую запятую 2
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 4
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 6
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7
    if (!comma) return false; // почему-то не нашли :((((
    
    speed=atof(comma+1)*1.852;   // переводим скорость в км/час
    //speed=85;
   // comma = strchr(comma+1, ','); // сначала ищем первую запятую 8
  //if (!comma) return false; // почему-то не нашли :((((
  //comma = strchr(comma+1, ','); // теперь ищем вторую запятую 9
  //if (!comma) return false; // почему-то не нашли :((((
  date=atof(comma+1);
  //return true;
}
else return false;

}
void loop(void) {
  double time, speed,num_sat, date;
//myOLED.setCursor(80,55);
//myOLED.setFont(MediumFontRus);
//myOLED.print("КМ/Ч"); 

 
//if (num_sat<4) speed=0;
  
 //myOLED.setCursor(80,55);
//myOLED.setFont(MediumFontRus);
//myOLED.print("КМ/Ч");
 //myOLED.print(("ГОРОД"), 5,14); 
   //Читаем время,кол-во спутников,дату,скорость если успешно прочитались, печатаем
  
 if (readLatLon(time,num_sat, date,speed)) {
 

if (digitalRead(5)==HIGH&&flag==0)  //по нажатию кнопки включается либо режим
 {                                   // ГОРОД либо ТРАССА
  regim++;
    flag=1;
   n=1;
  if (regim>2) regim=1;
 }
  if (digitalRead(6)==LOW&&flag==1)
  {
   flag=0;
   }
if (regim==1) 
{  
   myOLED.setFont(MediumFontRus); 
    myOLED.print("ГОРОД ", 2,14);
    myOLED.print("КМ/Ч",80,55);
  speed1=1;
}
if (regim==2) 
{
   myOLED.setFont(MediumFontRus); 
   myOLED.print("ТРАССА ", 2,14);
   myOLED.print("КМ/Ч",80,55);
  speed1=2;
}

if (digitalRead(6)==HIGH&&flag2==0 )  // по нажатию кнопки выключается либо включается OLED дисплей
 {                                     // через полевой транзистор
  flag2=1;
  digitalWrite(9,!digitalRead(9));
    if (n==1) 
{
  myOLED.setFont(MediumFontRus); 
    myOLED.print("ГОРОД ", 2,14);
    myOLED.print("КМ/Ч",80,55);
}
    if (n==2) 
{
  myOLED.setFont(MediumFontRus); 
   myOLED.print("ТРАССА ", 2,14);
   myOLED.print("КМ/Ч",80,55);
}
    myOLED.begin();
   }
   
 if (digitalRead(6)==LOW &&flag2==1 )
  {
    flag2=0;
   }

  if (speed1==1)                          //если скорость более 78км/ч моргает светодиод
  {                                       //если менее-гаснет
    if (speed>=78 )
    {
      digitalWrite(7, !digitalRead(7));
    }
  else 
  {
       digitalWrite(7,LOW);
  }
    }
if (speed1==2)
{
  if (speed>=108)                            //если скорость более 108км/ч моргает светодиод
  {                                       //если менее-гаснет          
     digitalWrite(7, !digitalRead(7));
    }
  else 
  {
    digitalWrite(7,LOW);
  }
 }
   myOLED.setCursor(95,14); 
   myOLED.setFont(MediumFontRus);
   myOLED.print(0);
   myOLED.print(num_sat,110,14,0);
   // myOLED.print(num_sat,103,14,0);

 if (speed<100)                                 // тут при выводе скорости, если число двухзначное
{                                                // закрашиваем младший разряд
   myOLED.drawRect   (59, 28,  78, 57, true , 0);
  } 
  if (speed<10)
  {
    myOLED.drawRect   (44, 28,  78, 57, true , 0); 
   }
  myOLED.setFont(BigNumbers);
  myOLED.print(speed,30,55,0);
  

   
    //Serial.print("time: ");
    //Serial.println(time, 2);
    //Serial.print("num_sat: ");
    //Serial.println(num_sat,0);
    //Serial.print("date: ");
    //Serial.println(date, 0);
    //Serial.print("speed: ");
    //Serial.println(speed, 0);
  }
 }
xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015
  //
  //  Если в Serial ничего нет - выходим
  //  А если есть, то читаем 1 символ
  //
  if (Serial.available()) return NULL;

все с точностью до наоборот!

gzp13
Offline
Зарегистрирован: 06.04.2015

Удалено

gzp13
Offline
Зарегистрирован: 06.04.2015

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




#include <iarduino_OLED.h>
#include <SoftwareSerial.h>
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 57600;
//
SoftwareSerial ss(RXPin, TXPin);
iarduino_OLED  myOLED(0x3C);                               // Объявляем объект myOLED, указывая адрес дисплея на шине I2C: 0x3C или 0x3D.
extern uint8_t MediumFontRus[]; // Подключаем шрифт MediumFontRus.
extern uint8_t SmallFontRus[]; 
extern uint8_t BigNumbers[]; 
int flag=0;
int flag1=0;
int flag2=0;
byte n;
byte regim=1;
byte speed1;
 //int _timer = TIMER_DEFAULT;
 
void setup(void) {
  //timer_init_ISR_1Hz(TIMER_DEFAULT);
Serial.begin(57600);
  ss.begin(GPSBaud);
  myOLED.begin();
  delay(200);
  pinMode(7, OUTPUT);
   pinMode(9,OUTPUT);
  digitalWrite(9,HIGH);
  delay(200);
  myOLED.begin(); 
myOLED.setFont(MediumFontRus);                           // Указываем шрифт который требуется использовать для вывода цифр и текста.
myOLED.print(F("УРАГАН-13"), 8,24);
myOLED.print(F("Клеменчев"), 11,60);
  delay(2000);
  myOLED.clrScr();
myOLED.print(("ГОРОД"), 5,14);
myOLED.setCursor(80,55);
myOLED.setFont(MediumFontRus);
//myOLED.print("КМ/Ч"); 
}
//
// Эта функция принимает символ из Serial и возвращает
//  указатель на полученную строку или NULL, если строка
//  ещё не получена.
// Строка всегда начинается с $ и заканчивается \r или \n
//
static const int MAX_LEN = 170; // 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 (!ss.available()) return NULL;
  const char c = ss.read();
  //Serial.print(c);
  //
  //  Если мы ждём начала строки, то сравинваем 
  //  прочитанный символ с '$', если равен - начало найдено
  //
  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 & time,double & num_sat,  double & speed  ) 
{
  

  //  getStrFromSerial() вернёт строку, полученную из Serial
  // или NULL, если строка ещё пока не получена
  //
  const char * str = getStrFromSerial();
  //
  //  Если строка ещё не получена, выходим
  //
  if (str == NULL) return false;
  //
  //  Если строка не начинается с "$GPGGA или GPRMC",
  // то она нам не нужна выходим
  //
  const char * prefix = "$GPGGA";
  const char * prefix2 = "$GPRMC";
 if (  ! strncmp(str, prefix, strlen(prefix))) 
  {
  //  Ищем первую запятую в строке str
  //
   char * comma = strchr(str, ',');
  //
  //  Если не нашли (строка кривая пришла?) - выходим
  //
  if (!comma) return false;
  //
  //  со следующего символа просле запятой идёт числоа - широта
  //
  time = atof(comma+1);
  //
  //  Ищем вторую запятую после начала числа-широты
  //
 comma = strchr(comma+1, ','); // сначала ищем первую запятую 2
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 4
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 6
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7
  if (!comma) return false; // почему-то не нашли :((((
   num_sat = atof(comma+1);
 return true;
  } 
  //  
  //  
  else if  ( ! strncmp(str, prefix2, strlen(prefix2)))
 {
 char * comma = strchr(str, ',');
  //
  //  Если не нашли (строка кривая пришла?) - выходим
  //
  if (!comma) return false;
  //
  //  со следующего символа просле запятой идёт числоа - широта
  //
  //time = atof(comma+1);
  //
  //  Ищем вторую запятую после начала числа-широты
  //
 comma = strchr(comma+1, ','); // сначала ищем первую запятую 2
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 3
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 4
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 5
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // сначала ищем первую запятую 6
  if (!comma) return false; // почему-то не нашли :((((
  comma = strchr(comma+1, ','); // теперь ищем вторую запятую 7
    if (!comma) return false; // почему-то не нашли :((((
     speed=atof(comma+1)*1.852;   // переводим скорость в км/час

  //return true;
}
else return false;

}

void loop() {
  double speed,num_sat, time;


   //Читаем время,кол-во спутников,,скорость если успешно прочитались, печатаем
  
 if (readLatLon(time, num_sat,speed)) {
    Serial.print("time: ");
    Serial.print(time, 2);
    Serial.print("          num_sat: ");
    Serial.print(num_sat,0);
    //Serial.print("                      date: ");
    //Serial.println(date, 0);
    Serial.print("                     speed: ");
    Serial.println(speed, 4);
    
 } 
  }
 
 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кто или что мешает напечатать введённую строку целиком и посмотреть что в ней?

gzp13
Offline
Зарегистрирован: 06.04.2015

Кто или что мешает напечатать введённую строку целиком и посмотреть что в ней?

хм.....извинясь конечно, но как это сделать?

и еще меня смущают строки 149 и 181

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

надо вывести всю строку и посмотреть, это ошибка при разборе строки или так отдает GPS

gzp13
Offline
Зарегистрирован: 06.04.2015

Вот благодаря Вашему совету выяснил, что эту туфту выдает gps.

$GPRMC,124720.00,A,5540.33651,N,03727.56573,E,0.109,,171018,,,A*71
$GPGGA,124720.00,5540.33651,N,03727.56573,E,172,28,.,,5

time: 124720.00          num_sat: 28                     speed: 0.109

Кол-во спутников в сообщении GPGGA после седьмой запятой. Вопрос, если выход? 

Может это из-за того, что надо использовать не SoftSerial а аппаратный?

 

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

попробуйте, опустите скорость до 19200