====== GPS-спидометр и одометр ====== ** [[slot-box:start#хочу_собрать|Проекты на Arduino и Slot Shield]] ** В простых велокомпьютерах обычно считаются обороты колеса — зная количество оборотов в минуту не сложно подсчитать скорость и пройденное расстояние. Вот только датчики Холла на вилку ставить морока, они быстро покрываются грязью и начинают сбоить. Лишние провода отнюдь не украшают байк, а только привлекают внимание воришек. Да и что делать, если в хозяйстве не только велосипед, но ещё и самокат, ролики или сноуборд? {{ :slot-box:gps-speedometr:gps-velo.jpg |}} Мы пошли другим путём. Данные о скорости мы получаем от приёмника сигналов спутниковой навигации GLONASS/GPS. А дальше — дело техники. Милые сердцу моряков и авиаторов узлы мы переводим в привычные «км/ч», а информацию об изменении координат используем для определения пройденного расстояния. Полученные значения в реальном времени выводим на [[amp>product/troyka-quad-display?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|четырёхразрядный индикатор]], переключаясь между выводом скорости и дистанции обычной тактовой кнопкой. Получилось компактное устройство, которое быстро крепится на руль, раму или просто на руку. Без лишних проводов и проблем с калибровкой. * Платформы: [[amp>product/arduino-uno?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|Arduino Uno]], [[amp>product/arduino-leonardo?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|Arduino Leonardo]], [[amp>product/iskra-neo?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|Iskra Neo]] * Язык программирования: Arduino (C++) ===== Что потребуется ===== [[amp>collection/gps-speedometr?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki | Полный сет]] компонентов проекта. В сет входят: * [[amp>product/iskra-neo?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|Iskra Neo]] * [[amp>product/arduino-troyka-slot-shield?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|Troyka Slot Shield]] * [[amp>product/troyka-gps-glonass?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|GPS/GLONASS приёмник]] * четырёхразрядный индикатор [[amp>product/troyka-quad-display?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|Quad Display]] * [[amp>product/troyka-button?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|тактовая кнопка]] ===== Видеоинструкция ===== {{youtube>Z0q05XwDDh0?large}} ===== Как собрать ===== Установите [[amp>product/arduino-troyka-slot-shield?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|Troyka Slot Shield]] на [[amp>product/iskra-neo?utm_source=proj&utm_campaign=slot-proj-14&utm_medium=wiki|Iskra Neo]] {{ :slot-box:gps-speedometr:step1.png |}} Поверните GLONASS/GPS на 90 градусов против часовой стрелки и вставьте в правый верхний слот. {{ :slot-box:gps-speedometr:step2.png |}} Переверните Quad Dispaly вверх ногами и вставьте в центральный и правый слоты нижнего ряда. {{ :slot-box:gps-speedometr:step3.png |}} Переверните тактовую кнопку на 90 градусов против часовой стрелки и вставьте в центральный верхний слот. {{ :slot-box:gps-speedometr:step4.png |}} ===== Скетч ===== Прошейте контроллер скетчем через [[articles:arduino-ide-install|Arduino IDE]]. #include "TroykaButton.h" // создаём объект для работы с кнопкой TroykaButton button(A2); // библиотека для работы с дисплеем #include // создаём объект класса QuadDisplay и передаём номер пина CS QuadDisplay qd(10); // библиотека для работы с GPS устройством #include // создаём объект класса GPS и передаём в него объект Serial1 GPS gps(Serial1); // задаём размер массива для времени, даты, широты и долготы #define MAX_SIZE_MASS 16 // макросы #define SPEED 0 #define DISTANCE 1 // переменые для хранения текущей скорости и пройденного расстояния float speed; float distance = 0; // переменные для хранения координат float latitudeLast; float longitudeLast; // режим отображение: текущей скорости / пройденного расстояния bool state = SPEED; // флаг первого считывания данных с GPS-модуля bool firstStart = true; void setup() { // открываем последовательный порт для мониторинга действий в программе // для ревизии v1 модуля GPS: // Serial.begin(115200); // для ревизии v2 модуля GPS: Serial.begin(9600); // Serial.print("Serial init OK\r\n"); // открываем Serial-соединение с GPS-модулем // для ревизии v1 модуля GPS: // Serial1.begin(115200); // для ревизии v2 модуля GPS: Serial1.begin(9600); // инициализация дисплея qd.begin(); // инициализация кнопки button.begin(); } void loop() { // переменные для хранения текущих координат float latitude; float longitude; // считывание данных с кнопки button.read(); // если был клик if (button.justPressed()) { // меняем отображение скорости на расстояния или наоборот state = !state; // в зависимости от текущего состояния спидометра if (!state) { qd.displayDigits(QD_S, QD_P, QD_E, QD_d); } else { qd.displayDigits(QD_d, QD_I, QD_S, QD_t); } delay(1000); } // если пришли данные с GPS-модуля if (gps.available()) { // считываем данные и парсим gps.readParsing(); // считываем состояние GPS-модуля switch(gps.getState()) { // всё OK case GPS_OK: // считываем с GPS-модуля текушие координаты и скорость speed = gps.getSpeedKm(); latitude = gps.getLatitudeBase10(); longitude = gps.getLongitudeBase10(); // если данные с GPS-модуля пришли впервые if (firstStart) { // сохраняем текущие значения координат latitudeLast = latitude; longitudeLast = longitude; // первый запуск был совершен firstStart = false; } distance = distance + latlng2distance(latitudeLast, longitudeLast, latitude, longitude); // сохраняем текущие значения координат latitudeLast = latitude; longitudeLast = longitude; /* Serial.print(speed); Serial.print("\t"); Serial.print(latitude, 6); Serial.print("\t"); Serial.print(longitude, 6); Serial.print("\t"); Serial.println(distance);*/ // в зависимости от режима работы спидометра if(!state) { // выводим текущую скорость qd.displayFloat(speed, 1); } else { // выводим текущее расстояние qd.displayFloat(distance, 1); } break; // ошибка данных case GPS_ERROR_DATA: Serial.println("GPS error data"); break; // нет соединение со спутниками case GPS_ERROR_SAT: Serial.println("GPS no connect to satellites"); qd.displayDigits(QD_E, QD_r, QD_r, QD_NONE); break; } } } float latlng2distance(float lat1, float long1, float lat2, float long2) { //радиус Земли unsigned long R = 6372795; //перевод коордитат в радианы lat1 *= 3.14 / 180; lat2 *= 3.14 / 180; long1 *= 3.14 / 180; long2 *= 3.14 / 180; //вычисление косинусов и синусов широт и разницы долгот float cl1 = cos(lat1); float cl2 = cos(lat2); float sl1 = sin(lat1); float sl2 = sin(lat2); float delta = long2 - long1; float cdelta = cos(delta); float sdelta = sin(delta); //вычисления длины большого круга float y = sqrt(pow(cl2 * sdelta, 2) + pow(cl1 * sl2 - sl1 * cl2 * cdelta, 2)); float x = sl1 * sl2 + cl1 * cl2 * cdelta; float ad = atan2(y, x); float dist = ad * R; //расстояние между двумя координатами в метрах return dist; } ====== Что дальше? ====== Хотите собрать другой девайс? Выберите своё будущее устройство из [[slot-box:start#хочу_собрать|списка проектов на Slot Shield]]. ====== Часто задаваемые вопросы ====== > Где скачать необходимые библиотеки и как их установить? * [[https://github.com/amperka/QuadDisplay2|Библиотека для работы с дисплеем]] * [[https://github.com/amperka/TroykaGPS|библиотека для GLONASS/GPS модуля]] * [[https://github.com/amperka/TroykaButton|библиотека для тактовой кнопки]] * [[программирование:библиотеки|Как установить библиотеку]] > У моего модуля QuadDisplay всего три ноги и расположены они слева. Можно ли использовать его в этом проекте? Да, модуль можно использовать, но скетч, библиотеки и схема сборки отличаются. Мы уже тестируем версию скетча для старого дисплея и разместим её на этой странице в ближайшие дни.