Домашно GPS тракер на Arduino. Най-добрите GPS тракери за автомобили (маяци)

Домашно GPS тракер на Arduino.  Най-добрите GPS тракери за автомобили (маяци)
Домашно GPS тракер на Arduino. Най-добрите GPS тракери за автомобили (маяци)

Персонални GPS предаватели

Днес напредъкът върви с такова темпо, че устройствата, които преди бяха обемисти, скъпи и високоспециализирани, бързо губят размер, тегло и цена, но придобиват много нови функции.

Ето как устройствата, базирани на GPS технология, достигнаха до джобните джаджи и се настаниха здраво там, давайки на хората нови възможности. Особено си струва да се подчертаят отделните GPS предаватели.

По същество това са същите GPS тракери, предназначени само за използване не в превозно средство, а от човек в ежедневието.

В зависимост от модела, няколко различни устройства. В най-простата си форма това е просто малка кутия без дисплей, която ви позволява да контролирате движенията на деца, животни или други предмети, на който е фиксиран.

Вътре в него има GPS модул, който определя координатите на земята, GSM/GPRS модул, който предава информация и получава команди за управление, както и източник на захранване, който осигурява автономна работаВ продължение на дълго време.

Функционалност на GPS предавателите

С увеличаването на функционалността се появяват следните възможности на устройството:


Опции за GPS предаватели

В зависимост от конфигурацията корпусите на трансмитера може да се различават значително. Предлагат се различни модели под формата на мобилни телефони, класически навигатори или дори ръчни часовници.

Цветният дизайн на специалните версии и полезните допълнения позволяват на децата да се отнасят към тези устройства не като към „родителски шпиони“, а като към модерни и практични джаджи.

Като предимство си струва да се посочи фактът, че много версии на устройството работят добре без абонаментни такси за услугите на специализирани оператори, а цялата необходима информация се изпраща на клиента директно чрез интернет или SMS съобщения, което позволява значителни спестявания относно поддръжката на такова оборудване.

Статии за GPS тракери

В тази статия ще покажа как да използвате gsm модул с arduino, като използвам sim800L като пример. Същите инструкции са напълно подходящи за използване на всякакви други gsm модули, например sim900 и т.н., тъй като всички модули работят приблизително по същия начин - това е обменът на AT команди през порта.

Ще покажа използването на модула с arduino на примера на SMS реле, което може да се използва за дистанционно управление на устройството чрез SMS команди. Това може да се използва заедно с автомобилни аларми и др.

Модулът е свързан към Arduino чрез UART интерфейс на софтуерен сериен порт, работещ на 2 и 3 цифрови пина на Arduino nano.

Работа с Arduino с GSM модули

За захранване на модула е необходимо напрежение в диапазона от 3.6V до 4.2V, което означава, че ще трябва да използвате допълнителен стабилизатор на напрежението, тъй като Arduino има инсталиран стабилизатор 3.3 V, който не е подходящ за захранване на модула , втората причина за инсталиране на допълнителен стабилизатор е, че GSM модулът е сериозно натоварване, тъй като има слаб предавател, който осигурява стабилна комуникация с клетъчната станция. Захранването за Arduino nano се подава към VIN щифта - това е стабилизатор, вграден в Arduino, който гарантира, че модулът работи в широк диапазон на напрежение (6-10V). Релейният модул се свързва според зададения програмен текст към пин 10 на Arduino nano и може лесно да се смени с всеки друг, който работи като цифров изход.

Работи по следния начин: инсталирайте SIM карта в GSM модула, включете захранването и изпратете SMS с текст „1“ на номера SIM картиза да включим нашето реле, за да го изключим изпращаме SMS с текст „0“.

#включи
SoftwareSerial gprsSerial(2, 3); // задайте щифтове 2 и 3 за софтуерен порт
int LedPin = 10; // за реле

void setup()
{
gprsSerial.begin(4800);
pinMode(LedPin, ИЗХОД);

// настройка на получаване на съобщение

gprsSerial.print("AT+CMGF=1\r");
gprsSerial.print("AT+IFC=1, 1\r");
забавяне (500);
gprsSerial.print("AT+CPBS=\"SM\"\r");
забавяне (500); // забавяне за обработка на команда
gprsSerial.print("AT+CNMI=1,2,2,1,0\r");
забавяне (700);
}

Низ currStr = "";
// ако този ред е съобщение, тогава променливата ще приеме стойността True
boolean isStringMessage = false;

void loop()
{
ако (!gprsSerial.available())
връщане;

char currSymb = gprsSerial.read();
if ('\r' == currSymb) (
if (isStringMessage) (
// ако текущият ред е съобщение, тогава...
ако (!currStr.compareTo("1")) (
digitalWrite(LedPin, HIGH);
) иначе ако (!currStr.compareTo("0")) (
digitalWrite(LedPin, LOW);
}
isStringMessage = невярно;
) иначе (
if (currStr.startsWith("+CMT")) (
// ако текущият ред започва с “+CMT”, следващото съобщение
isStringMessage = вярно;
}
}
currStr = "";
) иначе ако ('\n' != currSymb) (
currStr += String(currSymb);
}
}

Видео версия на статията:

Етикети: #Arduino, #SIM800L

Вашият знак:

Продукти, използвани в тази статия:

← GPS регистратор на arduino | Управление на реле през COM порт →

GSM скенер на RTL-SDR

| У дома| английски | Развитие | ЧЗВ |

Основни характеристики на скенера

GSM скенерът сканира GSM каналите надолу по веригата и показва информация за нивото на сигнала и дали каналът принадлежи на един от трите основни клетъчни оператора MTS, Beeline и Megafon. Въз основа на резултатите от работата си скенерът ви позволява да запазите списък с идентификатори базови станции MCC, MNC, LAC и CI за всички сканирани канали.
GSM скенер може да се използва за оценка на нивото на GSM сигнала и сравняване на качеството на сигнала различни оператори, оценки на радиопокритие, при вземане на решение за инсталиране на усилватели на клетъчен сигнал и настройка на техните параметри, за образователни цели и др.
Скенерът работи под Windows и използва прост и евтин приемник - RTL-SDR. Можете да прочетете за RTL-SDR на:
RTL-SDR (RTL2832U) и софтуерно дефинирани радио новини и проекти,
RTL-SDR – OsmoSDR,
RTL-SDR на руски.
Параметрите RTL-SDR определят основните характеристики на скенера. Разбира се, GSM скенерът не е заместител на нормалното измервателно оборудване.
Скенерът се разпространява безплатно, без никакви ограничения за използване.
Сегашна версияподдържа обхвата GSM 900 и не поддържа GSM 1800. Това се определя от факта, че работната честота на RTL-SDR с тунер R820T е ограничена до 1760 MHz. Има надежда, че използването на експерименталния драйвер RTL-SDR ще позволи работа в поне част от диапазона 1800 MHz.

Стартиране на скенера

Последната версия на скенера може да бъде изтеглена от тази връзка. Просто разархивирайте файла на удобно място и стартирайте gsmscan.exe.
Предишни версии на скенера, връзка към хранилището с източници и друга информация, свързана с разработката, се намират на страницата за разработка.
За да работи скенера, е необходимо инсталирането на RTL-SDR драйвери; ако те все още не са инсталирани, това може да се направи удобно с помощта на програмата Zadig, за да се опише процедурата за инсталиране.

Използване на скенера

По-долу е изглед на прозореца на програмата на скенера:

Хоризонталната ос показва номера на GSM канала под формата на ARFCN или в MHz, а вертикалната ос показва нивото на сигнала в dBm. Височината на линията показва силата на сигнала.

GSM модул NEOWAY M590 комуникация с Arduino

Ако BS идентификаторите са декодирани успешно и отговарят на идентификаторите на трите основни телекомуникационни оператора, линиите се оцветяват в съответните цветове.
Падащите списъци в горната част на екрана ви позволяват да изберете SDR приемника, ако са свързани няколко, работния обхват GSM 900 или GSM 1800 и мерните единици по хоризонталната ос ARFCN или MHz.
Бутоните ви позволяват да запазите отчет за работата на скенера под формата на списък с декодирани базови станции, да изчистите резултатите от декодирането на BS и да получите информация за програмата.

Принципи и особености на работа.

По време на работа програмата сканира работния честотен диапазон със стъпка 2,0 MHz (10 GSM канала) и дигитализира сигнала с честота на дискретизация 2,4 MHz. Процесът на сканиране се състои от бързо преминаване през целия диапазон за измерване на силата на сигнала и бавно преминаване за декодиране на BS идентификаторите.

Една стъпка на декодиране се извършва след преминаване на целия диапазон за измерване на мощността. По този начин в диапазона GSM 900 нивото на сигнала се актуализира приблизително веднъж на всеки 2 s, а пълното декодиране отнема около 1 минута.
Поради лошото качество на сигнала, получен от RTL-SDR, вероятността за правилно декодиране на системната информация (SI) на BS канала за управление на излъчване (BCCH) не е висока. Флуктуациите в нивото на сигнала в резултат на многопътно разпространение също намаляват вероятността от декодиране на системна информация. Поради тези причини, за да се получат BS идентификатори, е необходимо скенерът да натрупа информация за период от около 10 минути. Но дори и в този случай не всички канали осигуряват достатъчно ниво и качество на сигнала на дадено място за декодиране дори от най-идеалния приемник. Освен това не всички GSM канали се използват за работа по стандарта GSM, както се вижда на фигурата по-горе, канали 975 - 1000 са заети от Megafon за работа по стандарта UMTS.
По време на работа скенерът добавя системна информация за нови декодирани канали към общия масив от информация за каналите. Но информацията за предварително декодирани канали не се изтрива, когато системната информация не е декодирана на тази стъпка, и остава в масива. За да изчистите тази информация, използвайте бутона за изчистване на резултатите от BS декодирането.
Когато щракнете върху бутона за запазване на отчета, натрупаните резултати се записват в текстов файлс име, съставено от името на програмата, датата и часа на записване на данните. По-долу е даден пример за част от отчетния файл:
Скенерът е проектиран да работи под Windows 7, 8.1 и 10. Работата е тествана с три копия на RTL-SDR с тунер R820T, други видове тунери не са тествани.
Специална версия на програмата е компилирана за работа под Windows XP, тя работи няколко пъти по-бавно от стандартната версия.

развитие.

Програмата за скенер се доставя такава, каквато е, без никакви гаранции или отговорност. Ако имате разумни идеи как да разширите функционалността или да подобрите работата на скенера, ние сме готови да обсъдим възможността за тяхното внедряване.
Можете да участвате в разработката на скенера; за да направите това, посетете страницата за разработка.
Предвижда се по-нататъшно развитие на GSM скенера, евентуално с Ваше участие.

Имате ли нужда от точен източник на време от GPS? Тази статия ще ви покаже как да използвате GPS модул, за да получите час, дата и координати и как да ги покажете на LCD с помощта на Arduino.

Какво е необходимо?

  • компютър с инсталиран Arduino IDE;
  • Arduino (ние използваме Arduino Mega);
  • GPS модул (ние използваме EM-411, възможни са и други, които поддържат NMEA протокол, например VK2828U7G5LF или GY-NEO6MV2);
  • макет, джъмпери и потенциометър 5 kOhm;
  • TinyGPS библиотека (връзка по-долу).

Въведение

Развитието на глобалната система за позициониране или GPS започва в началото на 70-те години. Всяка държава (Русия, САЩ, Китай и др.) има своя собствена система, но повечето сателитни навигационни съоръжения в света използват системата на САЩ.

Всеки сателит в системата има атомен часовник, който непрекъснато се наблюдава и настройва от NORAD (Северноамериканското командване на аерокосмическата отбрана) всеки ден.

По същество приемникът използва своя часовник, за да измери TOA (време на пристигане) на четири сателитни сигнали. Въз основа на TOA и TOT (време на предаване), приемникът изчислява четири стойности на времето на полет (TOF), които се различават една от друга в зависимост от разстоянието от сателита до приемника. След това, от четирите стойности на TOF, приемникът изчислява своята позиция в 3D пространството и отклонението на своя часовник.

Най-евтините GPS приемници имат точност от около 20 метра за повечето места на Земята. Сега нека видим как да направите свой собствен GPS часовник с помощта на Arduino.

Хардуер

Моят GPS модул има 6 пина: GND, Vin, Tx, Rx и отново GND. Шестият щифт не е свързан никъде. Щифтът GND е свързан към корпуса на Arduino, Vin е свързан към шината +5V на Arduino, Tx е свързан към щифт 10 на Arduino, а щифтът Rx не е свързан никъде, тъй като няма да изпращаме никакви съобщения към GPS модула. Моят модул предава сателитни данни, използвайки интерфейса RS-232 при 4800 bps, които се получават от Arduino на пин 10.

По-долу има снимка на GPS модула:

GPS модул EM-411

Модулът изпраща това, което е известно като NMEA съобщения. Тук можете да видите пример за едно NMEA съобщение и неговото обяснение (откъс от техническо описание):

$GPGGA,161229.487,3723.2475,N,12158.3416,W,1.07,1.0,9.0,M,0000*18

GGA формат на данните
ИмеПримерЕдинициОписание
ID на съобщението$GPGGA Заглавка на GGA протокол
UTC време161229.487 hhmmss.sss (двуцифрени часове, две цифрени минути, след това секунди до хилядни)
Географска ширина3723.2475
N/S флагн N - север, S - юг
Географска дължина12158.3416 ддмм.мммм (първите две цифри са градуси, след това минути до най-близките десет хилядни)
E/W флагУ E - изток, W - запад
Индикатор за местоположение1
  • 0 - местоположението е недостъпно или неправилно;
  • 1 - GPS SPS режим, местоположението е правилно;
  • 2 - диференциален GPS, режим SPS, правилно местоположение;
  • 3 - GPS PPS режим, местоположението е правилно.
Брой използвани сателити07 Варира от 0 до 12
HDOP1.0 Влошаване на хоризонталната точност
Височина спрямо морското равнище9.0 метра
ЕдинициМметра
Геоидална разлика Разлика между земен елипсоид WGS-84 и морско ниво (геноид)
ЕдинициМметра
Възраст на диференциалните GPS данни секундиНулеви полета, когато не се използва DGPS
ID на станцията, предаваща диференциални корекции0000
Чекова сума*18
Край на съобщението

Всички тези данни се получават от Arduino чрез пин 10. Библиотеката TinyGPS чете GPGGA и GPRMC съобщения (вижте листа с данни за подробности относно GPRMC).

Arduino не е показан на диаграмата. Свържете се периферни устройстваспоред подписани връзки.


Схема на GPS часовник на arduino

Софтуер

Когато се подаде захранване, GPS модулът отнема известно време, за да получи правилното местоположение от сателитите. Когато се получи местоположение, модулът изпраща NMEA съобщения до Arduino. Библиотеката TinyGPS съдържа функция за получаване на часа и датата от GPRMC съобщение. Нарича се crack_datetime() и приема седем указателя към променливи като параметри: година година, месец месец, ден от месец ден, час час, минути минути, секунди секунди и стотни от секундата стотни. Извикването на функцията изглежда така:

GPS.crack_datetime(&година, &месец, &ден, &час, &минута, &секунда, &стотни);

Извикването на тази функция ви връща правилните стойности в променливите, стига всичко да е наред с хардуера.

За да получите вашето местоположение, можете да извикате функцията f_get_position(). Тази функция приема два указателя към променливи като параметри: ширина, ширина и дължина, дължина. Извикването на тази функция изглежда така:

Gps.f_get_position(&широчина, &дължина);

Изходен текст на програмата:

#включи #включи #включи #define RXPIN 10 #define TXPIN 9 #define GPSBAUD 4800 #define RS 2 #define EN 3 #define D4 4 #define D5 5 #define D6 6 #define D7 7 TinyGPS gps; SoftwareSerial uart_gps(RXPIN, TXPIN); Течнокристален LCD (RS, EN, D4, D5, D6, D7); // Променливи int seconds; int timeoffset = 1; // Потребителят трябва да промени единицата на подходящата часова зона. В примера използваме смяна от +1 час. // Декларация на функции. void getgps(TinyGPS &gps); // Функция за настройка - работи само когато е включен void setup() ( Serial.begin(115200); // Стартиране на серийния интерфейс за отстраняване на грешки uart_gps.begin(GPSBAUD); // Стартиране на UART приемника за GPS lcd.begin(16 ,2) ; // LCD съобщение lcd.print("GPS часовник"); // Забавяне на приветстващото съобщение (1000); // Изчакайте една секунда lcd.clear(); // Изчистване на LCD ) // Основен програмен цикъл - винаги изпълнява се void loop () ( while(uart_gps.available()) ( int c = uart_gps.read(); if(gps.encode(c)) ( getgps(gps); ) ) ) /* * Тази функция получава данни от GPS модула * и ги показва на LCD дисплея */ void getgps(TinyGPS &gps) ( int year; float latitude, longitude; byte месец, ден, час, минута, секунда, стотни; gps.f_get_position(&latitude, &longitude); gps .crack_datetime(&година, &месец, &ден, &час, &минута, &секунда, &стотни); час = час + timeoffset; lcd.clear();//lcd.setCursor(0, 0); lcd.print("Време: ") ; ако (час<= 9) { lcd.print("0"); lcd.print(hour, DEC); } else { lcd.print(hour, DEC); } lcd.print(":"); if (minute <=9) { lcd.print("0"); lcd.print(minute, DEC); } else { lcd.print(minute, DEC); } lcd.print(":"); if (second <= 9) { lcd.print("0"); lcd.print(second, DEC); } else { lcd.print(second, DEC); } lcd.setCursor(0,1); lcd.print("Date: "); if (day <= 9) { lcd.print("0"); lcd.print(day, DEC); } else { lcd.print(day, DEC); } lcd.print("-"); if (month <= 9) { lcd.print(month, DEC); } else { lcd.print(month, DEC); } lcd.print("-"); lcd.print(year, DEC); delay(2000); lcd.clear(); lcd.print("Lat: "); lcd.print(latitude, DEC); lcd.setCursor(0,1); lcd.print("Lon: "); lcd.print(longitude, DEC); delay(2000); // Debugging purpose only. Serial.print(latitude, DEC); Serial.print(" - "); Serial.println(longitude, DEC); }

Днес ще направим GPS тракер, базиран на Arduino MKR FOX 1200, който изпраща точни GPS данни през мрежата на Sigfox.

Това става още по-актуално за много страни поради засиления контрол върху всякакви вносни технически устройства, особено тези, свързани с GPS.

Стъпка 1. Какво ще ни трябва

Наборът от части за този урок не е голям:

  • Arduino MKR Fox 1200 × 1
  • GPS модул (по избор, но използвахме реплика на ublox NEO6m (ATGM332D) × 1
  • NPN транзистор с общо предназначение (ние използвахме BC548) × 1
  • Резистор 1 kOhm × 1

Стъпка 2. Информация за проекта

Тракерът използва GPS модул ATGM332, за да получи GPS позиция с по-голяма точност от услугите за местоположение, предоставени от Sigfox. След това данните за артикула се изпращат като "низ" през мрежата на Sigfox и накрая се доставят по имейл.

Arduino MKR FOX 1200

Платката е подобна на Arduino Zero, която е базирана на SAM D21 и включва ATA8520 Sigfox модул. Това е платка с ниска мощност, която се доставя с платката с безплатен едногодишен абонамент за мрежата Sigfox (до 140 съобщения на ден), както и безплатен достъп до услугата за местоположение Намерете го.

GPS модул ATGM332

Този евтин GPS модул с ниска мощност пасва много добре на Arduino MKR FOX 1200, тъй като работи само с 2,7 V (номинално 3,3 V).

Първоначално трябваше да купя модул NEO6m2, който има режим на готовност, но се наложи да използвам NEO6. Всъщност това беше модул ATGM332. В резултат на това той нямаше режим на готовност, така че беше необходимо да се използва транзистор, за да се включи GPS модулът, когато е необходимо, и да се изключи, за да се пести батерията. Нашата цел е да имаме информация за местоположението доста рядко, т.е. 4 съобщения на час, тъй като Sigfox позволява само 140 съобщения на ден.

Използваме библиотеката TinyGPS (https://github.com/mikalhart/TinyGPS) за декодиране на GPS рамки.

Транзисторен ключ

Беше необходимо да се включва и изключва GPS, когато е необходимо. Релейните модули са твърде обемисти и мощни, ако трябва да превключите само 3V товар и няколко милиампера. Освен това повечето релейни модули изискват 5 V. Така че транзисторът би бил по-добро решение. Освен това, MKR FOX 1200 осигурява само 7 mA на I/O щифта.

BC548 NPN транзистор ще свърши работа. Когато нулевият сигнал се приложи към основата на транзистора, той се изключва, действайки като отворен ключ и не протича колекторен ток. Когато се приложи положителен сигнал към основата на транзистора, той става "включен", действайки като затворен превключвател и през устройството протича максимален ток на веригата.

Стъпка 3. Схема на свързване

Единственият източник на захранване са две батерии 1,5 V AA, които захранват Arduino MKR FOX 1200. GPS модулът получава захранване от платката Arduino.

Arduino MKR FOX 1200 комуникира с GPS модула, използвайки втория сериен порт чрез пинове 13 и 14, наречени Serial1 в кода. Изходът за данни TX на GPS модула е свързан към входа за серийни данни (щифт 13) на платката Arduino.

Освен това платката Arduino използва PIN2 за включване и изключване на GPS модула, както е обяснено по-горе.

Стъпка 4. Код на проекта

Можете да изтеглите или копирате кода на нашия проект по-долу:

#включи #включи #включи //incluimos TinyGPS #define WAITING_TIME 15 #define GPS_PIN 2 #define GPS_INFO_BUFFER_SIZE 128 bool debug = false; TinyGPS gps;//GPS обект //GPS данни променливи int година; байт месец, ден, час, минута, секунда, стотни; неподписани дълги знаци; неподписани кратки изречения, неуспешна_контролна сума; char GPS_info_char; char GPS_info_buffer; неподписан int получен_сигнал; bool message_started = невярно; int i = 0; // GPS координатна структура, 12 байта размер на 32-битови платформи struct gpscoord ( float a_latitude; // 4 байта float a_longitude; // 4 байта float a_altitude; // 4 байта); плаваща ширина = 0.0f; плаваща дължина = 0.0f; надморска височина на плаване = 0; //////////////// Функция за изчакване ////////////////// void Wait(int m, bool s) ( //m минути да изчака //s бавни светодиодни импулси if (debug) ( Serial.print("Изчакване: "); Serial.print(m); Serial.println(" min."); ) digitalWrite(LED_BUILTIN, LOW); if ( s) ( int seg = m * 30; for (int i = 0; i< seg; i++) { digitalWrite(LED_BUILTIN, HIGH); //LED on delay(1000); digitalWrite(LED_BUILTIN, LOW); //LED off delay(1000); } } else { int seg = m * 15; for (int i = 0; i < seg; i++) { digitalWrite(LED_BUILTIN, HIGH); //LED on delay(1000); digitalWrite(LED_BUILTIN, LOW); //LED off delay(3000); } } } /////////////////// Sigfox Send Data function //////////////// void SendSigfox(String data) { if (debug) { Serial.print("Sending: "); Serial.println(data); if (data.length() >12) ( Serial.println("Съобщението е твърде дълго, само първите 12 байта ще бъдат изпратени"); ) ) // Премахване на EOL //data.trim(); // Стартиране на модула SigFox.begin(); // Изчакайте поне 30 mS след първата конфигурация (100 mS преди) delay(100); // Изчиства всички чакащи прекъсвания SigFox.status(); забавяне (1); if (debug) SigFox.debug(); забавяне (100); SigFox.beginPacket(); SigFox.print(данни); if (debug) ( int ret = SigFox.endPacket(true); // изпращане на буфер към мрежата на SIGFOX и изчакване на отговор if (ret > 0) ( Serial.println("Няма предаване"); ) else ( Serial.println ("Предаване е наред"); ) Serial.println(SigFox.status(SIGFOX)); Serial.println(SigFox.status(ATMEL)); if (SigFox.parsePacket()) ( Serial.println("Отговор от сървъра: "); while (SigFox.available()) ( Serial.print("0x"); Serial.println(SigFox.read(), HEX); ) ) else ( Serial.println("Не може да се получи отговор от сървър"); Serial.println("Проверете покритието на SigFox във вашия район"); Serial.println("Ако сте на закрито, проверете покритието от 20dB или се приближете до прозорец"); ) Serial.println(); ) else ( SigFox.endPacket(); ) SigFox.end(); ) ////////////////// Преобразуване на GPS функция ////////////////// /* Преобразуване на GPS данни за плаване в Char данни * / String ConvertGPSdata(const void* data, uint8_t len) ( uint8_t* bytes = (uint8_t*)data; String cadena; if (debug) ( Serial.print("Length: "); Serial.println(len); ) за (uint8_t i = len - 1; i< len; --i) { if (bytes[i] < 12) { cadena.concat(byte(0)); // Not tested } cadena.concat(char(bytes[i])); if (debug) Serial.print(bytes[i], HEX); } if (debug) { Serial.println(""); Serial.print("String to send: "); Serial.println(cadena); } return cadena; } ////////////////////////// Get GPS position function///////////////////// String GetGPSpositon() { int messages_count = 0; String pos; if (debug) Serial.println("GPS ON"); digitalWrite(GPS_PIN, HIGH); //Turn GPS on Wait(1, false); while (messages_count < 5000) { while (Serial1.available()) { int GPS_info_char = Serial1.read(); if (GPS_info_char == "$") messages_count ++; // start of message. Counting messages. if (debug) { if (GPS_info_char == "$") { // start of message message_started = true; received_char = 0; } else if (GPS_info_char == "*") { // end of message for (i = 0; i < received_char; i++) { Serial.write(GPS_info_buffer[i]); // writes the message to the PC once it has been completely received } Serial.println(); message_started = false; // ready for the new message } else if (message_started == true) { // the message is already started and I got a new character if (received_char <= GPS_INFO_BUFFER_SIZE) { // to avoid buffer overflow GPS_info_buffer = GPS_info_char; received_char++; } else { // resets everything (overflow happened) message_started = false; received_char = 0; } } } if (gps.encode(GPS_info_char)) { gps.f_get_position(&latitude, &longitude); altitud = gps.altitude() / 100; // Store coordinates into dedicated structure gpscoord coords = {altitud, longitude, latitude}; gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths); if (debug) { Serial.println(); Serial.println(); Serial.print("Latitud/Longitud: "); Serial.print(latitude, 5); Serial.print(", "); Serial.println(longitude, 5); Serial.println(); Serial.print("Fecha: "); Serial.print(day, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/"); Serial.print(year); Serial.print(" Hora: "); Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC); Serial.print("."); Serial.println(hundredths, DEC); Serial.print("Altitud (metros): "); Serial.println(gps.f_altitude()); Serial.print("Rumbo (grados): "); Serial.println(gps.f_course()); Serial.print("Velocidad(kmph): "); Serial.println(gps.f_speed_kmph()); Serial.print("Satelites: "); Serial.println(gps.satellites()); Serial.println(); } gps.stats(&chars, &sentences, &failed_checksum); if (debug) Serial.println("GPS turned off"); digitalWrite(GPS_PIN, LOW); //GPS turned off pos = ConvertGPSdata(&coords, sizeof(gpscoord)); //Send data return pos; } } } pos = "No Signal"; } //////////////////SETUP/////////////////// void setup() { if (debug) { Serial.begin(9600); while (!Serial) {}// wait for serial port to connect. Needed for native USB port only Serial.println("Serial Connected"); } //Serial1 pins 13-14 for 3.3V connection to GPS. Serial1.begin(9600); while (!Serial1) {} if (debug) { Serial.println("GPS Connected"); } pinMode(GPS_PIN, OUTPUT); //pin de interruptor del GPS if (!SigFox.begin()) { Serial.println("Shield error or not present!"); return; } // Enable debug led and disable automatic deep sleep if (debug) { SigFox.debug(); } else { SigFox.end(); // Send the module to the deepest sleep } } //////////////////////LOOP//////////////////////// void loop() { String position_data; position_data = GetGPSpositon(); SendSigfox(position_data); Wait(WAITING_TIME, false); }

Стъпка 5: Изпращане на GPS информация чрез Sigfox

Искахме да изпратим GPS информация, използвайки плаващи данни, но когато опитахме, винаги получавахме нулеви стойности.

Търсене в интернет доведе до този проект в GitHub - https://github.com/nicolsc/SmartEverything_SigFox_GPS от Николас Лискони. Той използва AT команди за изпращане на всякакъв тип данни и преобразува "float" в "hex". Arduino MKR FOX 1200 обаче няма AT режим и не успяхме да го накараме да работи.

Бяха направени няколко десетки теста и чрез модифициране на кода на Nichol беше намерен начин да се изпрати "низ", който беше анализиран от платформата "float: 32" на Sigfox и можеше да се използва директно без никакво преобразуване.

Данните на Sigfox са ограничени до 12 байта. Данни, които се изпращат към мрежата на SigFox:

  • Latitude, float: тип 32 (float:32type), 4 байта.
  • Дължина, float: тип 32 (float:32type), 4 байта.
  • Височина, float: 32 типа (float:32type), 4 байта.

Стъпка 6: Конфигуриране на обратно извикване на Sigfox

Персонализирана конфигурация за обратно извикване на Sigfox:

Lat::float:32lng::float:32 alt::float:32

Ще получите имейл:

За да видите лесно позицията, ние включихме URL адреса в Google Карти, използвайки информацията, която извлечехме:

И накрая, резултатът от нашия Arduino GPS тракер:

Това е всичко, желая ви страхотни проекти!

Данните се записват в електронна таблица dataGPS.csv, чийто формат отговаря на изискванията на услугата Google My Maps.

    Език за програмиране: Arduino (C++)

Видео инструкция

От какво имаш нужда

Как се сглобява

gps-tracker.ino // библиотека за работа с устройства през SPI#включи // библиотека за работа с SD карта#включи // библиотека за работа с GPS устройство#включи // създайте обект от класа GPS и му предайте обекта Serial1 GPS gps (сериен1); // LED щифт#define LED_PIN A0 // бутон щифт #define BUTTON_PIN 13 // закачете CS micro-sd карта#define CHIP_SELECT_PIN 9 // интервал от време за запис на данни на картата#define ИНТЕРВАЛ 5000 // задаваме размера на масива за час, дата, географска ширина и дължина#define MAX_SIZE_MASS 16 // масив за съхраняване на текущия час char време [MAX_SIZE_MASS]; // състояние на запис bool stateRec = невярно; // запомня текущото времедълго началоMillis = millis() ; void setup() ( // отваряне на серийния порт за наблюдение на действията в програмата Serial.begin(115200); // изчакайте, докато мониторът на серийния порт се отвори // за да проследим всички събития в програмата// while (!Serial) ( // ) Serial.print ("Serial init OK \r\n") ; // отворете серийна връзка с GPS модула Serial1.begin(115200); // задайте светодиода в изходен режим pinMode(LED_PIN, OUTPUT) ; // задайте бутона в режим на влизане pinMode(BUTTON_PIN, INPUT_PULLUP) ; // извежда информация за инициализация към серийния порт Serial.println("Инициализиране на SD карта...") ; // инициализиране на SD картата while (! SD.begin (CHIP_SELECT_PIN) ) ( Serial.println ("Картата е неуспешна или не присъства") ; delay(1000) ; ) // извежда информация към серийния порт Serial.println("Инициализирана карта"); // създаване на обект dataFile от класа File за работа с файловеФайл dataFile = SD.open("dataGPS.csv" , FILE_WRITE) ; // ако файлът съществуваако (файл с данни) ( // запишете името на бъдещите данни на картата с памет dataFile.println("Време, координати, скорост" ); // затворете файла dataFile.close(); Serial.println("Запазване OK"); ) else ( Serial.println ("Грешка при отваряне на test.csv" ) ; ) ) void loop() ( // Запишете натискането на бутона if (! digitalRead(BUTTON_PIN) ) ( // промяна на състоянието „запис“ / „не запис“ на картата с памет stateRec = ! stateRec; // промяна на състоянието на светодиода за индикация digitalWrite(LED_PIN, stateRec) ; ) // ако данните идват от GPS модулаако (gps.available()) ( // четене на данни и анализиране gps.readParsing(); // проверка на състоянието на GPS модула switch (gps.getState () ) ( // всичко е наред case GPS_OK: Serial.println ("GPS е наред" ) ); // ако зададеният интервал от време е изтекъл if (millis() - startMillis > INTERVAL && stateRec) ( // запазване на данни в карта с памет saveSD() ; // запомня текущото време startMillis = millis() ; ) прекъсване ; // случай на грешка в данните GPS_ERROR_DATA: Serial.println ("GPS данни за грешка" ) ; прекъсване ; // няма връзка със сателити case GPS_ERROR_SAT: Serial.println ( „GPS няма връзка със сателити“) ; прекъсване ; ) ) ) // функция за запис на данни в карта с памет void saveSD() ( File dataFile = SD.open("dataGPS.csv" , FILE_WRITE) ; // ако файлът съществува и е бил отворенако (файл с данни) ( // чете текущото време gps.getTime(време, MAX_SIZE_MASS); // запишете часа на картата с памет dataFile.print(" \" " ) ; dataFile.print(време); dataFile.print(" \" " ) ; dataFile.print ("," ); dataFile.print(" \" " ) ; // чете и записва координатите на географската ширина и дължина в картата с памет dataFile.print(gps.getLatitudeBase10(), 6); dataFile.print ("," ); dataFile.print(gps.getLongitudeBase10(), 6); dataFile.print(" \" " ) ; dataFile.print ("," ); dataFile.print(gps.getSpeedKm()); dataFile.println("км/ч"); dataFile.close(); Serial.println("Запазване OK"); ) else ( Serial.println ("Грешка при отваряне на test.csv" ) ; ) )

Добър ден (вечер/нощ по избор).

Днес ще има преглед на GPS приемника и приложението му в практиката.


ПРЕДГОВОР

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

Имаше само няколко от най-обширните ревюта за този GPS приемник - около 4, един от тях беше наистина добър, останалите бяха описани общо. Няма да се повтарям много.

Както обикновено предупреждение:

Цялата отговорност, а именно независимото проникване в тялото на готовия продукт с последващо нарушаване на неговата цялост и ефективност, се носи от лицето, което е извършило това действие.

Външен вид

Размерите на този модул не са по-големи от 35 x 24 мм и той може да намери своето място не само в носима електроника, но и в RC устройства.

Комплектът включва пасивна антена:

Ако желаете, винаги можете да замените активния или да го направите сами, като използвате този метод:

Днес модулът не е остарял модел и се използва активно, + има поддръжка на производителя.

На фигурата по-долу показах кои линии къде трябва да бъдат свързани, за да може GPS да бъде открит в компютъра:

Изглежда нещо подобно:

След това инсталирайте приложението U-center, връзката е дадена по-горе, и изберете порта:

По подразбиране комуникираме на 9600 бода.

Ето как обикновено работи всичко, което хванах на закрито:

Свързване на модула към Arduino

Нека подготвим програмиста за фърмуер:

След това зашиваме тази скица в Nano:

Допълнителна информация

// ArduinoISP // Copyright © 2008-2011 Randall Bohn // Ако имате нужда от лиценз, вижте // http://www.opensource.org/licenses/bsd-license.php // // Тази скица превръща Arduino в AVRISP, използващ следните изводи на Arduino: // // Пин 10 се използва за нулиране на целевия микроконтролер. // // По подразбиране хардуерните SPI пинове MISO, MOSI и SCK се използват за комуникация // с целта. На всички Arduinos тези щифтове могат да бъдат намерени // на ICSP/SPI хедъра: // // MISO °. . 5V (!) Избягвайте този щифт на Due, Zero... // SCK. . MOSI // . . GND // // На някои Arduinos (Uno,...), щифтовете MOSI, MISO и SCK са същите щифтове като // цифровите щифтове 11, 12 и 13, съответно. Ето защо много уроци ви инструктират // да свържете целта към тези щифтове. Ако намирате това окабеляване за по // практично, дефинирайте USE_OLD_STYLE_WIRING. Това ще работи дори когато // не използвате Uno. (На Uno това не е необходимо). // // Като алтернатива можете да използвате всеки друг цифров щифт, като конфигурирате // софтуерен ("BitBanged") SPI и имате подходящи дефиниции за PIN_MOSI, // PIN_MISO и PIN_SCK. // // ВАЖНО: Когато използвате Arduino, който не е толерантен към 5V (Due, Zero, ...) като // програмист, уверете се, че не излагате нито един от щифтовете на програмиста на 5V. // Лесен начин за постигане това е за захранване на цялата система (програматор // и цел) при 3V3. // // Поставете светодиод (с резистор) на следните щифтове: // 9: Сърдечен ритъм - показва, че програмистът работи // 8: Грешка - Светва, ако нещо се обърка (използвайте червено, ако това има смисъл) // 7: Програмиране - В комуникация с подчинения // #include "Arduino.h" #undef SERIAL #define PROG_FLICKER true // Конфигуриране на SPI часовник (в Hz).// Например за ATtiny @ 128 kHz: листът с данни гласи, че и високият, и ниският // SPI тактов импулс трябва да бъдат > 2 цикъла на процесора, така че вземете 3 цикъла, т.е. разделете целта // f_cpu на 6: // # define SPI_CLOCK (128000/6) // // Достатъчно бавен часовник за ATtiny85 @ 1 MHz е разумна настройка по подразбиране: #define SPI_CLOCK (1000000/6) // Изберете хардуерен или софтуерен SPI, в зависимост от SPI тактовата честота. // В момента само за AVR, за други архитектури (Due, Zero,...), хардуерният SPI // вероятно е твърде бърз. #if defined(ARDUINO_ARCH_AVR) #if SPI_CLOCK > (F_CPU / 128) #define USE_HARDWARE_SPI #endif #endif // Конфигуриране кои пинове да се използват: // Стандартната конфигурация на щифтове. #ifndef ARDUINO_HOODLOADER2 #define RESET 10 // Използвайте щифт 10, за да нулирате целта, а не SS #define LED_HB 9 #define LED_ERR 8 #define LED_PMODE 7 // Разкоментирайте следния ред, за да използвате старото окабеляване в стил Uno // (използвайки щифт 11, 12 и 13 вместо заглавката SPI) на Leonardo, Due. .. // #define USE_OLD_STYLE_WIRING #ifdef USE_OLD_STYLE_WIRING #define PIN_MOSI 11 #define PIN_MISO 12 #define PIN_SCK 13 #endif // HOODLOADER2 означава стартиране на скици върху чиповете за сериен преобразувател ATmega16U2 // на Uno или Mega платки. Трябва да използваме изведени щифтове: #else #define RESET 4 #define LED_HB 7 #define LED_ERR 6 #define LED_PMODE 5 #endif // По подразбиране използвайте хардуерни SPI щифтове: #ifndef PIN_MOSI #define PIN_MOSI MOSI #endif #ifndef PIN_MISO #define PIN_MISO MISO #endif #ifndef PIN_SCK #define PIN_SCK SCK #endif // Принудително налагане на bitbanged SPI, ако не се използват хардуерните SPI пинове: #if (PIN_MISO != MISO) || (PIN_MOSI != MOSI) || (PIN_SCK != SCK) #undef USE_HARDWARE_SPI #endif // Конфигуриране на серийния порт за използване. // // Предпочитайте USB виртуалния сериен порт (известен още като собствен USB порт), ако Arduino има такъв: // - той не се нулира автоматично (с изключение на магическата скорост на предаване от 1200). // - по-надежден е поради USB ръкостискане. // // Leonardo и подобни имат USB виртуален сериен порт: "Serial". // Due и Zero имат USB виртуален сериен порт: "SerialUSB". // // На Due и Zero може да се използва и "Serial", при условие че деактивирате автоматичното нулиране. // За да използвате "Serial": #define SERIAL Serial #ifdef SERIAL_PORT_USBVIRTUAL #define SERIAL SERIAL_PORT_USBVIRTUAL #else #define SERIAL Serial #endif // Конфигуриране на скоростта на предаване: #define BAUDRATE 19200 // #define BAUDRATE 115200 // #define BAUDRATE 100000 0 #define HWVER 2 #define SWMAJ 1 #define SWMIN 18 // STK дефиниции #define STK_OK 0x10 #define STK_FAILED 0x11 #define STK_UNKNOWN 0x12 #define STK_INSYNC 0x14 #define STK_NOSYNC 0x15 #define CRC_EOP 0x 20 //добре, това е пространство... void impulse(int pin, int times); #ifdef USE_HARDWARE_SPI #include "SPI.h" #else #define SPI_MODE0 0x00 клас SPISettings ( public: // часовникът е в Hz SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) : clock(clock) ( (void) bitOrder; ( void) dataMode; ); private: uint32_t часовник; приятелски клас BitBangedSPI; ); клас BitBangedSPI (публичен: void begin() ( digitalWrite(PIN_SCK, LOW); digitalWrite(PIN_MOSI, LOW); pinMode(PIN_SCK, OUTPUT); pinMode(PIN_MOSI, OUTPUT); pinMode(PIN_MISO, INPUT); ) void beginTransaction(SPISettings настройки) ( pulseWidth = (500000 + settings.clock - 1) / settings.clock; if (pulseWidth == 0) pulseWidth = 1; ) void end() () uint8_t transfer (uint8_t b) ( for (unsigned int i = 0;i< 8; ++i) { digitalWrite(PIN_MOSI, (b & 0x80) ? HIGH: LOW); digitalWrite(PIN_SCK, HIGH); delayMicroseconds(pulseWidth); b = (b << 1) | digitalRead(PIN_MISO); digitalWrite(PIN_SCK, LOW); // slow pulse delayMicroseconds(pulseWidth); } return b; } private: unsigned long pulseWidth; // in microseconds }; static BitBangedSPI SPI; #endif void setup() { SERIAL.begin(BAUDRATE); pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); pinMode(LED_ERR, OUTPUT); pulse(LED_ERR, 2); pinMode(LED_HB, OUTPUT); pulse(LED_HB, 2); } int error = 0; int pmode = 0; // address for reading and writing, set by "U" command unsigned int here; uint8_t buff; // global block storage #define beget16(addr) (*addr * 256 + *(addr+1)) typedef struct param { uint8_t devicecode; uint8_t revision; uint8_t progtype; uint8_t parmode; uint8_t polling; uint8_t selftimed; uint8_t lockbytes; uint8_t fusebytes; uint8_t flashpoll; uint16_t eeprompoll; uint16_t pagesize; uint16_t eepromsize; uint32_t flashsize; } parameter; parameter param; // this provides a heartbeat on pin 9, so you can tell the software is running. uint8_t hbval = 128; int8_t hbdelta = 8; void heartbeat() { static unsigned long last_time = 0; unsigned long now = millis(); if ((now - last_time) < 40) return; last_time = now; if (hbval >192) hbdelta = -hbdelta; ако (hbval< 32) hbdelta = -hbdelta; hbval += hbdelta; analogWrite(LED_HB, hbval); } static bool rst_active_high; void reset_target(bool reset) { digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? HIGH: LOW); } void loop(void) { // is pmode active? if (pmode) { digitalWrite(LED_PMODE, HIGH); } else { digitalWrite(LED_PMODE, LOW); } // is there an error? if (error) { digitalWrite(LED_ERR, HIGH); } else { digitalWrite(LED_ERR, LOW); } // light the heartbeat LED heartbeat(); if (SERIAL.available()) { avrisp(); } } uint8_t getch() { while (!SERIAL.available()); return SERIAL.read(); } void fill(int n) { for (int x = 0; x < n; x++) { buff[x] = getch(); } } #define PTIME 30 void pulse(int pin, int times) { do { digitalWrite(pin, HIGH); delay(PTIME); digitalWrite(pin, LOW); delay(PTIME); } while (times--); } void prog_lamp(int state) { if (PROG_FLICKER) { digitalWrite(LED_PMODE, state); } } uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { SPI.transfer(a); SPI.transfer(b); SPI.transfer©; return SPI.transfer(d); } void empty_reply() { if (CRC_EOP == getch()) { SERIAL.print((char)STK_INSYNC); SERIAL.print((char)STK_OK); } else { error++; SERIAL.print((char)STK_NOSYNC); } } void breply(uint8_t b) { if (CRC_EOP == getch()) { SERIAL.print((char)STK_INSYNC); SERIAL.print((char)b); SERIAL.print((char)STK_OK); } else { error++; SERIAL.print((char)STK_NOSYNC); } } void get_version(uint8_t c) { switch © { case 0x80: breply(HWVER); break; case 0x81: breply(SWMAJ); break; case 0x82: breply(SWMIN); break; case 0x93: breply("S"); // serial programmer break; default: breply(0); } } void set_parameters() { // call this after reading parameter packet into buff param.devicecode = buff; param.revision = buff; param.progtype = buff; param.parmode = buff; param.polling = buff; param.selftimed = buff; param.lockbytes = buff; param.fusebytes = buff; param.flashpoll = buff; // ignore buff (= buff) // following are 16 bits (big endian) param.eeprompoll = beget16(&buff); param.pagesize = beget16(&buff); param.eepromsize = beget16(&buff); // 32 bits flashsize (big endian) param.flashsize = buff * 0x01000000 + buff * 0x00010000 + buff * 0x00000100 + buff; // AVR devices have active low reset, AT89Sx are active high rst_active_high = (param.devicecode >= 0xe0); ) void start_pmode() ( // Нулиране на целта преди задвижване на PIN_SCK или PIN_MOSI // SPI.begin() ще конфигурира SS като изход, така че е избран главният режим на SPI. // Дефинирахме RESET като пин 10, което за много Arduinos е не SS пин. // Така че трябва да конфигурираме RESET като изход тук, // (reset_target() първо задава правилното ниво) reset_target(true); pinMode(RESET, OUTPUT); SPI.begin(); SPI.beginTransaction (SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0)); // Вижте таблици с данни на AVR, глава „Алгоритъм за програмиране на SERIAL_PRG“: // Импулсът RESET след PIN_SCK е нисък: digitalWrite(PIN_SCK, LOW); delay(20); // разреждане на PIN_SCK, произволно избрана стойност reset_target(false); // Импулсът трябва да бъде минимум 2 целеви тактови цикъла на CPU, така че 100 usec е добре за CPU // скорости над 20 KHz delayMicroseconds(100); reset_target(true); // Изпратете командата за активиране на програмиране: delay(50); // лист с данни: трябва да е > 20 msec spi_transaction(0xAC, 0x53, 0x00, 0x00); pmode = 1; ) void end_pmode() ( SPI.end(); // Ние сме на път да вземем целта е извън нулиране, така че конфигурирайте SPI щифтовете като вход pinMode(PIN_MOSI, INPUT); pinMode(PIN_SCK, INPUT); reset_target(false); pinMode(НУЛИРАНЕ, ВХОД); pmode = 0; ) void universal() ( uint8_t ch; fill(4); ch = spi_transaction(buff, buff, buff, buff); breply(ch); ) void flash(uint8_t hilo, unsigned int addr, uint8_t data) ( spi_transaction(0x40) + 8 * hilo, addr >> 8 & 0xFF, addr & 0xFF, data); ) void commit(unsigned int addr) ( if (PROG_FLICKER) ( prog_lamp(LOW); ) spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); if (PROG_FLICKER) ( delay(PTIME); prog_lamp(HIGH); ) ) unsigned int current_page() ( if (param.pagesize == 32) ( return here & 0xFFFFFF0; ) if ( param.pagesize == 64) ( връщане тук & 0xFFFFFFFE0; ) if (param.pagesize == 128) ( връщане тук & 0xFFFFFFC0; ) if (param.pagesize == 256) ( връщане тук & 0xFFFFFF80; ) връщане тук; ) void write_flash(int length) ( fill(length); if (CRC_EOP == getch()) ( SERIAL.print((char) STK_INSYNC); SERIAL.print((char) write_flash_pages(length)); ) else ( error++; SERIAL.print((char) STK_NOSYNC); ) ) uint8_t write_flash_pages(int length) ( int x = 0; unsigned int page = current_page(); докато (x< length) { if (page != current_page()) { commit(page); page = current_page(); } flash(LOW, here, buff); flash(HIGH, here, buff); here++; } commit(page); return STK_OK; } #define EECHUNK (32) uint8_t write_eeprom(unsigned int length) { // here is a word address, get the byte address unsigned int start = here * 2; unsigned int remaining = length; if (length >param.eepromsize) ( error++; return STK_FAILED; ) while (remaining > EECHUNK) ( write_eeprom_chunk(start, EECHUNK); start += EECHUNK; resting -= EECHUNK; ) write_eeprom_chunk(start, remaining); връщане STK_OK; ) // запис (дължина) байтове, (начало) е байт адрес uint8_t write_eeprom_chunk(unsigned int start, unsigned int length) ( // това записва байт по байт, писането на страница може да е по-бързо (4 байта наведнъж) fill(length); prog_lamp(LOW); for (unsigned int x = 0; x< length; x++) { unsigned int addr = start + x; spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]); забавяне (45); ) prog_lamp(HIGH); връщане STK_OK; ) void program_page() ( char result = (char) STK_FAILED; unsigned int length = 256 * getch(); length += getch(); char memtype = getch(); // флаш памет @тук, (дължина) байтове ако (memtype == "F") ( write_flash(length); return; ) if (memtype == "E") ( result = (char)write_eeprom(length); if (CRC_EOP == getch()) ( SERIAL.print ((char) STK_INSYNC); SERIAL.print(result); ) else ( error++; SERIAL.print((char) STK_NOSYNC); ) return; ) SERIAL.print((char)STK_FAILED); return; ) uint8_t flash_read(uint8_t hilo, unsigned int addr) ( return spi_transaction(0x20 + hilo * 8, (addr >> 8) & 0xFF, addr & 0xFF, 0); ) char flash_read_page(int length) ( for (int x = 0; x< length; x += 2) { uint8_t low = flash_read(LOW, here); SERIAL.print((char) low); uint8_t high = flash_read(HIGH, here); SERIAL.print((char) high); here++; } return STK_OK; } char eeprom_read_page(int length) { // here again we have a word address int start = here * 2; for (int x = 0; x < length; x++) { int addr = start + x; uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, адрес & 0xFF, 0xFF); SERIAL.print((char)ee); ) върне STK_OK; ) void read_page() ( char result = (char)STK_FAILED; int length = 256 * getch(); length += getch(); char memtype = getch(); if (CRC_EOP != getch()) ( error++; SERIAL .print((char) STK_NOSYNC); return; ) SERIAL.print((char) STK_INSYNC); if (memtype == "F") result = flash_read_page(length); if (memtype == "E") result = eeprom_read_page (дължина); SERIAL.print(резултат); ) void read_signature() ( if (CRC_EOP != getch()) ( error++; SERIAL.print((char) STK_NOSYNC); return; ) SERIAL.print((char) STK_INSYNC ); uint8_t високо = spi_transaction(0x30, 0x00, 0x00, 0x00); SERIAL.print((char) високо); uint8_t средно = spi_transaction(0x30, 0x00, 0x01, 0x00); SERIAL.print((char) средно); uint8_t ниско = spi_transaction(0x30, 0x00, 0x02, 0x00); SERIAL.print((char) ниско); SERIAL.print((char) STK_OK); ) //////////////// ///////////////////////// /////////////////////// / ///////////////// ////////////////////////////// // /// ///////////////////////////////// void avrisp() ( uint8_t ch = getch (); switch (ch) ( case "0": // грешка при влизане = 0; empty_reply(); break; case "1": if (getch() == CRC_EOP) ( SERIAL.print((char) STK_INSYNC); SERIAL. print("AVR ISP"); SERIAL.print((char) STK_OK); ) else (грешка++; SERIAL.print((char) STK_NOSYNC); ) break; case "A": get_version(getch()); break; case "B": fill(20); set_parameters(); empty_reply(); break; case "E": // разширени параметри - игнорирайте за сега fill(5); empty_reply(); break; case "P": if (!pmode) start_pmode(); empty_reply(); break; case "U": // задайте адрес (дума) тук = getch(); тук += 256 * getch(); empty_reply(); break; case 0x60: //STK_PROG_FLASH getch(); // low addr getch(); // high addr empty_reply(); break; case 0x61: //STK_PROG_DATA getch(); // data empty_reply(); break; case 0x64: //STK_PROG_PAGE program_page(); break; case 0x74: //STK_READ_PAGE "t" read_page(); break; case "V": //0x56 universal(); break; case "Q": //0x51 error = 0; end_pmode() празен_отговор(); прекъсване; case 0x75: //STK_READ_SIGN "u" read_signature(); прекъсване; // очакваме команда, а не CRC_EOP // така можем да се върнем в случай на синхронизация CRC_EOP: error++; SERIAL.print((char) STK_NOSYNC); прекъсване; // всичко друго, което ще върнем STK_UNKNOWN default: error++; if (CRC_EOP == getch()) SERIAL.print((char)STK_UNKNOWN); иначе SERIAL.print((char)STK_NOSYNC); ) )

След това изберете вашия Pro Mini контролер, посочете ArduinoISP програмиста и шийте контролера с помощта на командата Скица -> Качване чрез програмисти натиснете бутона Reset на Pro mini, фърмуерът на контролера ще започне да мига (при мен работи само при втория опит, трябва да имам търпение):

Както казах по-горе, наистина обичам да прикрепям дисплеи към всякакви джаджи, е, просто е страховито, така че това "проект"желанието ми не остана незабелязано.

Какво ни трябва за всичко това:

Като цяло събрах всички боклуци, които лежаха наоколо:

1. SD карта модул, много огромен, така че се опитах да се отърва от него възможно най-скоро.

2. Дисплей, базиран на контролера PCD8544, добре познатият дисплей на Nokia.

3. Карта с памет 1GB, с непопулярния стандарт MiniSD, нямах идея къде да я сложа, но исках да пусна всичко да работи, така че да работи за ползата от навигацията.

4. Ще ви трябва мозък, голям Pro Mini мозък на 328P чип.

Както писах по-горе, ще шием Arduino Nano със зашит в него буутлоудър.

Като цяло се опитах много да вместя целия проект в нано, добре, просто наистина. Не става, отказваме се или от картата памет, или от дисплея.

5. Разбира се, самият модул + антена, както писах по-горе, можете да направите сами.

6. А да, за малко да забравя, ще ти трябва още един калъф, иначе какво устройство е без калъф.

Като калъф пак са закупени, но в сребърна форма, за проба. Ще кажа това, абсолютно не ми хареса сребристия цвят, черното изглежда по-добре.

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

Свързваме се с Pro Mini по следната схема:

Дисплей:

RST-D6
CE - D7
DC-D5
DIN - D4
CLK-D3
VCC - 5V (по избор в моя случай, в други 3.3V)
Светлина - GND
GND - GND

Подсветката не ми трябваше и затова не я свързах.

CS-D10
MOSI-D11
MISO-D12
SCK-D13
GND - GND
5V - VCC (по избор в моя случай, в някои с преобразувател се свързваме към 3.3V)

GPS модул:

RX-D8
TX-D2
GND - GND
VCC-3.3 (3.3 е границата!)

Не забравяйте да свържете антената към модула, взех захранването от Nano Tk. беше свързан за отстраняване на грешки, тогава всичко ще бъде преобразувано в батерията.

Приблизителен изглед:

Кодът е прост и ясен; за да го използвате вероятно ще ви трябва . По-нататък. Останалите са вградени. Според кода редът е time*0.000001+5, по същество пренесох времето в смилаема форма и добавих часова зона. Можете да пропуснете това и пак да получите чисти резултати.

Друг нюанс по отношение на библиотеката на дисплея е следният: дисплеят, включително този с нулевата линия, има общо 6 реда. Което е доста малко, така че трябва незабавно да решите каква информация да се показва; някои ще трябва да се показват в символи, спестявайки място. Дисплеят се преначертава всяка секунда, докато се актуализира и записва информация, идваща от сателити.

Ако има грешка при четене на файл или няма достъп до SD картата, ще се покаже съобщение SD-, в други случаи SD+.

#включи #включи #включи #включи //CS-D10, MOSI-D11, MISO-D12, SCK-D13, GND - GND, 5V - VCC (по избор в моя случай, в някои случаи се свързваме към 3.3V, ако няма конвертор) Файл GPS_file; TinyGPS gps; SoftwareSerial gpsSerial(2, 8);//RX - 8 пинов, TX - 2 пинов статичен PCD8544 lcd; //RST - D6, CE - D7, DC - D5, DIN - D4, CLK - D3, VCC - 5V (по избор, ако има преобразувател на 3.3V линия), светлина - GND, GND - GND bool newdata = невярно; неподписано дълго начало; дълга ширина, дължина; без подпис дълго време, дата; void setup() (lcd.begin(84, 48); gpsSerial.begin(9600); Serial.begin(9600); pinMode(10, OUTPUT); if (!SD.begin(10))( lcd.setCursor( 0, 0); lcd.println("SD-"); return;) lcd.setCursor(0, 0); lcd.println("SD+"); GPS_file = SD.open("GPSLOG.txt", FILE_WRITE) ; if (GPS_file)( Serial.print("Пише се в test.txt..."); GPS_file.print("LATITUDE"); GPS_file.print(","); GPS_file.print("LONGITUDE"); GPS_file .print(","); GPS_file.print("ДАТА"); GPS_file.print(","); GPS_file.print("ВРЕМЕ"); GPS_file.print(","); GPS_file.print("ВИСОЧИНА" "); GPS_file.println(); GPS_file.close(); Serial.println("готово."); )else( Serial.println("грешка при отваряне на test.txt"); ) lcd.setCursor(0,3) ; lcd.print("ALT: "); lcd.setCursor(0,2); lcd.print("SPD: "); lcd.setCursor(0,4); lcd.print("LAT: "); lcd .setCursor(0,5); lcd.print("LON: "); ) void loop() ( if (millis() - start > 1000)( newdata = readgps(); if (newdata)( start = millis( ); gps.get_position(&lat, &lon); gps.get_datetime(&дата, &час); lcd.setCursor(50,1); lcd.print(дата); lcd.setCursor(55,0); lcd.print(време*0,000001+5); lcd.setCursor(22, 4); lcd.print(lat); lcd.setCursor(22, 5); lcd.print(long); lcd.setCursor(22, 2); lcd.print(gps.f_speed_kmph()); lcd.setCursor(22, 3); lcd.print(gps.f_altitude()); ) ) GPS_file = SD.open("GPSLOG.txt", FILE_WRITE); if(GPS_file)( GPS_file.print(lat); GPS_file.print(","); GPS_file.print(lon); GPS_file.print(","); GPS_file.print(дата); GPS_file.print(", "); GPS_file.print(time*0.000001+5); GPS_file.print(","); GPS_file.print(gps.f_altitude()); GPS_file.println(); GPS_file.close(); )else( lcd .setCursor(0, 0); lcd.println("SD-"); ) ) bool readgps())( while (gpsSerial.available())( int b = gpsSerial.read(); if("\r" ! = b)( if (gps.encode(b)) return true;)) return false;)

След като мигате фърмуера, ще видите нещо подобно (в скицата изходната дата е редактирана до десния край под часа):

Можете да си поиграете с подреждането на елементите, имаше и такава опция, но разбрах, че осредняването на координатите дава огромна грешка и отказах.

За батериите, които ползвам LI-ion батерия. Купувам на едро батерии за екшън камери и ги използвам в занаятите си, освен това винаги могат да ми бъдат полезни за екшън камера, която използвам на походи. .

Използвайки макет, събирайки всичко заедно:

Залепих парче електрическа лента върху кутията за картата с памет, тъй като тя е в контакт с контактите на зарядното устройство. Мигаме картата с памет във FAT16.

След това стартираме и проверяваме, като не забравяме да включим превключвателя:

Обработка на резултатите

Резултатите са представени като текстов файл:

Задайте разделителя на колони на запетая:

След това можете да заредите всичко в софтуера Google Earth Pro, като използвате раздела Файл -> Отвори, отворете нашия файл и изберете колоните, отговарящи за географската ширина и дължина, и вземете подобна следа (тъй като бях на едно място, получих разпръснати точки):

Можете да изберете точка и да покажете целия брой точки, които съответстват на нея:

Долен ред

Като цяло логърът работи, можете да напишете песен, последвано от редактиране на картата. Също така в софтуерот Google, следата може да бъде запазена в по-популярен формат, който другите карти поддържат.

Повече от задоволих любопитството си.

Недостатъкът е, че е малка антена; понякога студеното стартиране може да отнеме до 10 минути (в зависимост от облачността и времето от деня). Антената, разбира се, може да бъде заменена с домашна или закупена допълнително; на пазара има доста активни антени.

Благодаря за отделеното време.

Актуализация от 22.05.18г

1. Смених корпуса и направих антена от връзката, която предоставих. (Намалено време за студен старт, намира сателити по-бързо, много по-бързо.)

2. Преместих конектора за отстраняване на грешки навън (след като си поиграя, ще напиша по-интересен фърмуер, ще го публикувам тук)

3. За да намаля заеманото място, разглобих дисплея и го запоих към него.

Засега това е гледката.

Планирате да купите +129 Добави към любими Ревюто ми хареса +170 +299