Вывод данных из Seril порта на sd карту

Sasha_594
Offline
Зарегистрирован: 24.02.2019

Всем привет! Интересует вопрос: как вывести данные из serial порта в формате NMEA на SD карту.

Код отвечающий за вывод NMEA в serial порт:

// serial-порт к которому подключён GPS-модуль
#define GPS_SERIAL    Serial1
 
void setup()
{
  // открываем последовательный порт для мониторинга действий в программе
  // и передаём скорость 115200 бод
  Serial.begin(115200);
  while (!Serial) {
  }
  Serial.print("\r\nSerial init OK\r\n");
  // открываем Serial-соединение с GPS-модулем
  // и передаём скорсть 115200 бод
  GPS_SERIAL.begin(115200);
}
 
void loop()
{
  // если приходят данные из GPS-модуля - отправим их в порт компьютера
  if (GPS_SERIAL.available()) {
    Serial.write(GPS_SERIAL.read());
  }
  // если приходят данные из компьютера - отправим их в GPS-модуль
  if (Serial.available()) {
    GPS_SERIAL.write(Serial.read());
  }
}

Код полностью работает, взял с сайта Амперки. Как сделать, чтоб данные выводились в файл на SD карту?

Arduino leonardo, GPS приемник от амперки.

Обьясняйте, пожалуйста, подробно):)

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Уважаемый, а Вы не хотите внятно объяснить Ваши пожелания? Из какого порта (у Вас их 2) куда (в какой файл) писать? Как часто?

negavoid
Offline
Зарегистрирован: 09.07.2016

Ну тут-то вроде как ясно, мой кристал шар говорит, что ТС вряд ли будет слать NMEA в приёмник, стало быть, хочет логировать строчки от приёмника. Очень хочется, но программировать пока не умеет. Начать можно, например, так:

// serial-порт к которому подключён GPS-модуль
#define GPS_SERIAL    Serial1

#include <SPI.h>
#include <SD.h>
const int chipSelect = 4;  // задаём pin кардридера

void setup()
{
  // открываем последовательный порт для мониторинга действий в программе
  // и передаём скорость 115200 бод
  Serial.begin(115200);
  while (!Serial) {
  }
  Serial.print("\r\nSerial init OK\r\n");

  // инициализируем sd-карту
  SD.begin(chipSelect);

  // открываем Serial-соединение с GPS-модулем
  // и передаём скорсть 115200 бод
  GPS_SERIAL.begin(115200);
}

void loop()
{
  // если приходят данные из GPS-модуля
  if (GPS_SERIAL.available()) {
    byte data = GPS_SERIAL.read() ;   // считаем данные (по 1 байту - медленно!)
    Serial.write(data);               // отправим их в порт компьютера

    // и запишем данные на карту
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    if (dataFile) {
      dataFile.print(data);
      dataFile.close();
    }
  }

  // если приходят данные из компьютера - отправим их в GPS-модуль
  if (Serial.available()) {
    GPS_SERIAL.write(Serial.read());
  }
}

 

Sasha_594
Offline
Зарегистрирован: 24.02.2019

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

В Serial порт же пишется вот такое:

14:09:13.617 -> $GNGGA,110921.000,5541.0818,N,03741.5709,E,1,8,1.99,102.2,M,14.443

в файл TXT:

3671787171654449494851485646495752444444444448444

Нужен файл в формате NMEA, но простая замена расширения файла не помогла, он просто не создается 

negavoid
Offline
Зарегистрирован: 09.07.2016

В файл пишутся не цифры, а байты. Попробуйте вместо datafile.print(data); использовать datafile.write(data);

Sasha_594
Offline
Зарегистрирован: 24.02.2019

Стало еще хуже((

Порт:

14:54:43.573 -> ⸮B⸮ȯ⸮⸮ 5⸮,⸮l⸮⸮⸮⸮⸮⸮ʝ⸮⸮⸮3⸮6⸮⸮⸮⸮⸮⸮d.d⸮V⸮⸮⸮"⸮⸮⸮B)Æ$R

Флешка:

섆ㄖ⋁닌䊀‸섺ァꆉ鈡р상襩䍲⠌䈺じ鈲鈇璋↦섋ሌ⠐䀆䉂ȼ模㦩쑄蒱ᄱⱋ‭騳恀戳⦌⪩ㄆ舂阰닌䊀怸섪

negavoid
Offline
Зарегистрирован: 09.07.2016

<del> - это иногда на форуме создаётся два сообщения вместо одного.

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

// serial-порт к которому подключён GPS-модуль
#define GPS_SERIAL    Serial1

#include <SPI.h>
#include <SD.h>
const int chipSelect = 4;  // задаём pin кардридера

void setup()
{
  // открываем последовательный порт для мониторинга действий в программе
  // и передаём скорость 115200 бод
  Serial.begin(115200);
  while (!Serial) {
  }
  Serial.print("\r\nSerial init OK\r\n");

  // инициализируем sd-карту
  SD.begin(chipSelect);

  // открываем Serial-соединение с GPS-модулем
  // и передаём скорсть 115200 бод
  GPS_SERIAL.begin(115200);
}

void loop()
{
  String str = "";
  while (GPS_SERIAL.available())
  {
    char c = GPS_SERIAL.read();
    str += c;
  }

  if ( str != "" )
  {
    Serial.print(str);  // отправим их в порт компьютера

    // и запишем данные на карту
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    if (dataFile) {
      dataFile.print(str);
      dataFile.close();
    }
  }

  // если приходят данные из компьютера - отправим их в GPS-модуль
  if (Serial.available()) {
    GPS_SERIAL.write(Serial.read());
  }
}

 

Sasha_594
Offline
Зарегистрирован: 24.02.2019

Какая-то Ж настала:

Порт:

15:20:42.448 -> b$B0⸮⸮⸮,K⸮!ːCxP⸮⸮8! ⸮N⸮F`bƔpP⸮;y)⸮#t⸮43⸮⸮(@⸮8⸮(K⸮!ˀ!⸮

Флешка:

…№К)‚ўR¤6‚И.„°И¬ТFў@
ЪЇ6#Ё0Ж
negavoid
Offline
Зарегистрирован: 09.07.2016

Блин, ну нет у меня gps приёмника, чтобы посмотреть, что там посылается и проставить правильно типы :) Раз уж это обычный сериал и NMEA, предполагаю, что там должна быть обычная латиница с кодами от 0 до 127, стало быть и с byte, и с char, поидее, должно бы работать.

Попробуйте в 30 строке не char, а unsigned char c = GPS_SERIAL.read(); . Я вообще, даже не уверен, что то, что я вам пишу в качестве примеров, компилируется ))

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

Sasha_594 пишет:

Какая-то Ж настала:

потому что не надо быть таким жадным. :) Сначала заказали работу платно - но 1000р, видимо, стало жалко - вот теперь трахайтесь сами :) На сколько, интересно, вы рассчитывали - на 200? :)

Вот еще что нужно отметить - ваш код с амперки, якобы выводящий NMEA в Сериал - для Вашей задачи не подходит. Если я правильно помню ТЗ - вы хотели писать на СД только строчки $GPRMC, причем делать это раз в 5 секунд. Ваш же код сливает в Сериал все подряд, причем спамит по 5-10 раз в секунду. Вы этим кодом очень быстро забьете карточку всяким мусором.

Sasha_594
Offline
Зарегистрирован: 24.02.2019

Сейчас попробую. То что вы пишете компилируется, я проверяю, только я исправил пин кардридера, и уменьшил скорость на всякий до 9600.

negavoid
Offline
Зарегистрирован: 09.07.2016

Скорость изменили везде? И у сериала гпс приёмника, и у компьютерного? И в мониторе ком-порта иде выставили такую же? И приёмник точно отсылает данные на скорости 9600?

negavoid
Offline
Зарегистрирован: 09.07.2016

А, це экономист, а не ребёнок :) Ну, экономным вопросам - экономные ответы :)

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

negavoid - писать на карту надо не каждый символ, как у вас - а только когда появился конец строки.  И писать надо не символы и не байты, а строки. Тогда буквы будут буквами, а цифры - цифрами.

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

negavoid пишет:

А, це экономист, а не ребёнок :) Ну, экономным вопросам - экономные ответы :)

в профиле возраст 28 лет. Так что не ребенок - а вполне себе взрослый жмот.

negavoid
Offline
Зарегистрирован: 09.07.2016

Ну я маленько в курсе (#6) :)

Но если считать байт текстового протокола NMEA и записать его в файл (что тоже делать плохо, ибо пишется карта секторами), то в файле в итоге будут совершенно правильные строки, и даже с переносом, вроде бы нмеа присылает \n-ы.

Sasha_594
Offline
Зарегистрирован: 24.02.2019

negavoid пишет:

Попробуйте в 30 строке не char, а unsigned char c = GPS_SERIAL.read();

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

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

negavoid пишет:

Но если считать байт текстового протокола NMEA и записать его в файл), то в файле в итоге будут совершенно правильные строки, и даже с переносом, вроде бы нмеа присылает \n-ы.

если писать байты командой принт - не будут

Sasha_594
Offline
Зарегистрирован: 24.02.2019

negavoid пишет:

И приёмник точно отсылает данные на скорости 9600?

Видел где-то, что ограничивали скорость приемника до 9600, на всякий случай, тоже решил сделать так же

negavoid
Offline
Зарегистрирован: 09.07.2016

b707 пишет:
если писать байты командой принт - не будут

Он и write попробовал, не вышел каменный цветочек.

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

Sasha_594 пишет:

Видел где-то, что ограничивали скорость приемника до 9600, на всякий случай, тоже решил сделать так же

В этом случае НАДО СНАЧАЛА дать команду приемнику переключится на 9600.

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

negavoid пишет:

b707 пишет:
если писать байты командой принт - не будут

Он и write попробовал, не вышел каменный цветочек.

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

Sasha_594
Offline
Зарегистрирован: 24.02.2019

b707 пишет:

Sasha_594 пишет:

Какая-то Ж настала:

Сначала заказали работу платно - но 1000р стало жалко

Не в жадности дело, хочу разобраться реально в этом, что да куда

Sasha_594
Offline
Зарегистрирован: 24.02.2019

negavoid пишет:

Он и write попробовал...

Ваш последний пример рабоатет только в таком виде, write сюда не подставить((  dataFile.print(str)

negavoid
Offline
Зарегистрирован: 09.07.2016

b707 пишет:
Он сам себе злобный буратино. В библиотеке TroykaGPS, которую он до того пробовал - уже есть все для приема строк с GPS. Надо только добавить пару переменных и написать метод выдачи строки в сериал Но товарищ решил пойти путем копипаста обрывков кодов в инете. Флаг в руки.

Страсти-то какие творятся :)

Sasha_594 пишет:
Не в жадности дело, хочу разобраться реально в этом, что да куда
Это выйдет гораздо больше 1000р, если пересчитать на время, затраченное на обучение, а его потребуется немало.
negavoid
Offline
Зарегистрирован: 09.07.2016

Sasha_594 пишет:
Ваш последний пример рабоатет только в таком виде, write сюда не подставить((  dataFile.print(str)

Значит, в SD.h нет override функции write(String).

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

Sasha_594 - вот вам алгоритм, как нужно решать эту задачу.

1. читаете байт с GPS - но ничего с ним не делаете, а только складываете в строку
2. проверяете, нет ли в строке последовательности "$GPRMC". Если нашли - идем на п.3, если нет - на п.1
3. Очишаем строку до $GPRMC, сдвигаем остальное в начало строки
4. продолжаем принимать символы из сериала и проверяем, не является ли символ переводом строки "\n" Если да - идем на п.5
5. Записываем всю строку , начиная с $GPRMC до "\n" - на СД карту. Переходим снова к п. 1

Sasha_594
Offline
Зарегистрирован: 24.02.2019

Спасибо

Timurka
Offline
Зарегистрирован: 26.02.2019

Так же заинтересовался идей gps-логгера. Собрал и прошил по рекомендациям от амперки с доработками из этой ветки. 

Имею разные глюки: 1) Если СД читалка отцеплена или СД карта изьята, NMEA идет верный. Красиво пишется в окошке COM порта или крутит стрелку-показывает спутники в OziExplorer. Но при подсоединении СД NMEA на COM порт идет с пропусками и ошибками, а OziExplorer просто не видит спутников. На CД карту пишется файл из непонятного набора цифр. 2) Один из предложенных выше скетчей в итоге начал писать NMEA c приемника в СД, но с множеством ошибок и пропусков.

Куда капать, чего читать?

 

 

PRC
Offline
Зарегистрирован: 03.02.2019

Запись на карту не самый быстрый процесс, а если писать еще и побайтно, то накладных расходов становится ну очень много. Направление поиска откуда идут пропуски ясно?))

negavoid
Offline
Зарегистрирован: 09.07.2016

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