Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Продвинутый GPS-логгер данных: отслеживание полёта в реальном времени, пиковая высота и скорость

Компоненты и материалы

КомпонентКоличество
Arduino UNO1
Набор перемычек (Busbar), комплект соединительных проводов1
Arduino Proto Shield1
TFT SPI LCD-экран 1.8" с разъёмом для MicroSD (или другой экран со слотом для SD-карты)1
GPS-модуль u-blox NEO-6M1

Необходимые инструменты

О проекте

Введение

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

Поэтому я решил собрать свой GPS-логгер на базе Arduino за менее чем 50 €.

Первый прототип основан на Arduino Uno R3, экране Sainsmart ST7735 со встроенным слотом для SD-карты и GPS-модуле NEO-6M V2.

Во второй версии планируется использовать Arduino Nano, OLED-экран SSD1306, тот же GPS-модуль и microSD-карту. Вес в корпусе составит около 40 г, размеры — 50×30×22 мм, что позволит легко разместить устройство в модели среднего размера. Этот проект в разработке (жду комплектующие).

Тестирование

Снять работу экрана Arduino в движущейся машине непросто, но мне это удалось — результат на видео.

Следующее тестирование пройдёт с новым компактным прототипом на радиоуправляемой модели. Продолжение следует!

Программный код

Основной скетч GPS-логгера

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#define cs 10
#define dc 9
#define rst 8
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
#define OLED_RESET 5

TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);

int x = 80, xh = 80;
int maxhigh = 0;
int maxspeed = 0, speed1 = 0;
int high1 = 0;

void setup() {
  Serial.begin(9600);
  ss.begin(GPSBaud);
  tft.initR(INITR_GREENTAB);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(5, 58);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
  tft.print("Initialization");
}

void loop() {
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN, ST7735_BLACK);

  while (ss.available() > 0) {
    gps.encode(ss.read());
    if (gps.location.isUpdated()) {
      drawFrame();
      // Координаты
      tft.setCursor(5, 44);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print("Latitude: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(gps.location.lat(), 6);

      tft.setCursor(5, 58);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print("Longitude: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(gps.location.lng(), 6);

      // Дата
      tft.setCursor(5, 7);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print("Date: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(gps.date.day()); tft.print(" ");
      tft.print(gps.date.month()); tft.print(" ");
      tft.print(gps.date.year());

      // Время
      tft.setCursor(5, 20);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print("Time: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(gps.time.hour() + 1); tft.print(" ");
      tft.print(gps.time.minute()); tft.print(" ");
      tft.print(gps.time.second()); tft.print(" ");

      // Высота
      tft.setCursor(5, 80);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print("H m: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(gps.altitude.meters(), 0); tft.print(" ");

      tft.setCursor(5, 95);
      updateMaxAltitude();
      tft.print("Hmax: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(maxhigh); tft.print(" ");
      drawAltitudeGraph();

      // Скорость
      tft.setCursor(5, 115);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print("V act: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(gps.speed.kmph(), 0); tft.print(" ");

      tft.setCursor(5, 130);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      updateMaxSpeed();
      tft.print("Vmax: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(maxspeed); tft.print(" ");
      drawSpeedGraph();

      // Спутники
      tft.setCursor(5, 147);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.print("Satellites: ");
      tft.setTextColor(ST7735_CYAN, ST7735_BLACK);
      tft.print(gps.satellites.value()); tft.print(" ");

      Serial.print("HDOP = ");
      Serial.println(gps.hdop.value());
      smartDelay(400);
    }
  }
}

static void smartDelay(unsigned long ms) {
  unsigned long start = millis();
  do {
    while (ss.available()) gps.encode(ss.read());
  } while (millis() - start < ms);
}

void drawFrame() {
  // Рисуем рамки и разделители на экране
  tft.drawLine(0, 0, 130, 0, ST7735_RED);
  tft.drawLine(0, 1, 130, 1, ST7735_RED);
  tft.drawLine(0, 158, 130, 158, ST7735_RED);
  tft.drawLine(0, 142, 130, 142, ST7735_RED);
  tft.drawLine(0, 141, 130, 141, ST7735_RED);
  tft.drawLine(0, 107, 130, 107, ST7735_RED);
  tft.drawLine(0, 108, 130, 108, ST7735_RED);
  tft.drawLine(80, 108, 80, 140, ST7735_RED);
  tft.drawLine(81, 109, 81, 140, ST7735_RED);
  tft.drawLine(80, 70, 80, 108, ST7735_RED);
  tft.drawLine(81, 70, 81, 108, ST7735_RED);
  tft.drawLine(0, 159, 130, 159, ST7735_RED);
  tft.drawLine(0, 0, 0, 156, ST7735_RED);
  tft.drawLine(1, 1, 1, 157, ST7735_RED);
  tft.drawLine(127, 0, 127, 156, ST7735_RED);
  tft.drawLine(126, 0, 126, 156, ST7735_RED);
  tft.drawLine(0, 35, 130, 35, ST7735_RED);
  tft.drawLine(0, 36, 130, 36, ST7735_RED);
  tft.drawLine(0, 70, 130, 70, ST7735_RED);
  tft.drawLine(0, 71, 130, 71, ST7735_RED);
}

void drawSpeedGraph() {
  int newValue = map(gps.speed.kmph(), 0, 150, 137, 110);
  x++;
  tft.drawPixel(x, newValue, ST7735_CYAN);
  if (x > 123) {
    x = 80;
    tft.fillRect(82, 110, 43, 30, ST7735_BLACK);
  }
}

void drawAltitudeGraph() {
  int newValue = map(gps.altitude.meters(), 0, 1000, 104, 72);
  xh++;
  tft.drawPixel(xh, newValue, ST7735_CYAN);
  if (xh > 123) {
    xh = 80;
    tft.fillRect(82, 72, 43, 35, ST7735_BLACK);
  }
}

void updateMaxSpeed() {
  speed1 = gps.speed.kmph();
  if (speed1 > maxspeed) maxspeed = speed1;
}

void updateMaxAltitude() {
  high1 = gps.altitude.meters();
  if (high1 > maxhigh) maxhigh = high1;
}

Версия с записью на SD-карту

#include <SPI.h>
#include <SD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#define cs 10
#define dc 9
#define rst 8
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
const int cs_sd = 4;
#define OLED_RESET 5

TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);

int x = 80, xh = 80;
int maxhigh = 0, maxspeed = 0, speed1 = 0, high1 = 0;

void setup() {
  Serial.begin(9600);
  ss.begin(GPSBaud);
  tft.initR(INITR_GREENTAB);
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(5, 58);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
  tft.print("Initialization");
  tft.setCursor(5, 70);
  tft.print("SD init");
  delay(1000);

  if (!SD.begin(cs_sd)) {
    tft.setCursor(5, 82);
    tft.print("SD Error");
    return;
  }
  tft.setCursor(5, 82);
  tft.print("SD OK");
  delay(1000);
  tft.fillScreen(ST7735_BLACK);

  File data = SD.open("donnees.txt", FILE_WRITE);
  data.println("");
  data.println("Start logging");
  data.close();
}

void loop() {
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN, ST7735_BLACK);

  while (ss.available() > 0) {
    gps.encode(ss.read());
    if (gps.location.isUpdated()) {
      drawFrame();
      // ... (отображение данных аналогично первому скетчу) ...

      // Запись на SD
      String Date = String(gps.date.day()) + " " + gps.date.month() + " " + gps.date.year();
      String Time = String(gps.time.hour() + 1) + " " + gps.time.minute() + " " + gps.time.second();

      File data = SD.open("donnees.txt", FILE_WRITE);
      data.println(Date + " " + Time + " " +
        String(gps.location.lat(), 6) + " " +
        String(gps.location.lng(), 6) + " " +
        String(gps.altitude.meters(), 0) + " " +
        String(maxhigh) + " " +
        String(gps.speed.kmph(), 0) + " " +
        String(maxspeed));
      data.close();

      smartDelay(400);
    }
  }
}

// Функции drawFrame, drawSpeedGraph, drawAltitudeGraph, updateMaxSpeed, updateMaxAltitude, smartDelay
// идентичны первому варианту.

Схема подключения

Схема подключения компонентов показана на изображении ниже.

Продвинутый GPS-логгер данных: отслеживание полёта в реальном времени, пиковая высота и скорость

Производственный процесс

  1. Создание быстрой надежной системы обнаружения пожара с Samsung SAMI, Arduino UNO и Raspberry Pi
  2. Мониторинг солнечной панели в реальном времени: дешёвая система сбора данных на Arduino и Excel
  3. Создание надежного монитора энергии и логгера данных на Arduino — пошаговое руководство
  4. Создание анимации и игр на LCD 16×2 с Arduino UNO
  5. Логгер температуры и влажности на Arduino с DHT11 и Ethernet Shield
  6. Простой калькулятор на Arduino UNO — базовый проект для начинающих
  7. Сборка портативного дисплея на основе эффекта сохранения изображения с Arduino UNO и ATtiny85
  8. Модуль GPS u-blox LEA-6H 02: Интеграция с Arduino и Python
  9. Создание интерактивного 4x4x4 светодиодного куба на Arduino Uno и 1Sheeld
  10. Управление Arduino Uno из Python 3: команды через последовательный порт и демонстрация с LED