Hướng dẫn lập trình Quectel L70R với Arduino

Test với Arduino + LCD Keypad Shield

Chuẩn bị về phân cứng

Code tham khảo trên mạch Arduino - Uno VN01:

Code này sẽ hiển thị các thông tin về thời gian, tọa độ, tốc độ nhận được từ module GPS lên màn hình LCD, các bạn dùng phím bấm "RIGHT" trên shield LCD để chuyển trang màn hình.

(Lưu ý: Anten GPS phải để ngoài trời hoặc gần cửa sổ thì mới có thể bắt được tín hiệu từ vệ tinh GPS )

// code tham khảo do MLAB xây dựng dành cho Arduino, LCD Keypad Shield, Module GPS L70R
// website: http://smart-techvn.com/
// Nội dung: Hiển thị các thông tin về thời gian, tốc độ, tọa độ nhận được từ GPS L70R lên LCD. Sử dụng nút bấm Right để chuyển trang.
// include the library code:
#include <LiquidCrystal.h>
#include "string.h"
#include "stdlib.h"



// Buttons
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5


// GPRMC
#define GPRMC_MID          0
#define GPRMC_UTC         1
#define GPRMC_STS         2
#define GPRMC_LAT         3
#define GPRMC_LAT_NS      4
#define GPRMC_LON         5
#define GPRMC_LON_EW      6
#define GPRMC_SOG         7
#define GPRMC_COG         8
#define GPRMC_DAT         9 
#define GPRMC_MAV         10
#define GPRMC_MAV_EW      11
#define GPRMC_MOD         12

typedef union
{
  unsigned char array_time[7];
  struct
  {
    unsigned char year;
    unsigned char month;
    unsigned char date;
    unsigned char hour;
    unsigned char minute;
    unsigned char sec;
  }time;
}SysTime;

typedef enum
{
  DISPLAY_GPS = 0,
  DISPLAY_RTC,
  DISPLAY_SPEED_ORG,
  DISPLAY_MAX
}DISPLAY_E;

typedef struct{       
  bool State_gps;     /*!< trang thai gps 1 = co tin hieu, 0 = mat tin hieu */
  SysTime time_gps;   /*!< time gps  */
  float Lat;     /*!< vi do */
  float Lng;     /*!< kinh do */
  float SpeedGPS;     /*!< Toc do GPS */
  float OrGPS;      /*!< Huong GPS 360 do */
}GPS_T;     /*!< cau truc du lieu hanh trinh */

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);



static float gps_convert_lon_to_float(unsigned char *lon_str, unsigned char *WE);
static float gps_convert_lat_to_float(unsigned char *lon_str, unsigned char *NS);
static void  NMEA_GPRMC_Decoder(GPS_T *gps_data, String data);
static int   GetMessageFeilds(unsigned char **message_feildls, unsigned char *msg, unsigned char separate_char, int max_feild_get);

GPS_T g_gps_data = {false, {0,0,0,0,0,0,0}, 0, 0, 0, 0};

int read_LCD_buttons(){               // read the buttons
    int adc_key_in = analogRead(0);       // read the value from the sensor 

    // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
    // we add approx 50 to those values and check to see if we are close
    // We make this the 1st option for speed reasons since it will be the most likely result

    if (adc_key_in > 1000) return btnNONE; 

    // For V1.1 us this threshold
    if (adc_key_in < 50)   return btnRIGHT;  
    if (adc_key_in < 250)  return btnUP; 
    if (adc_key_in < 450)  return btnDOWN; 
    if (adc_key_in < 650)  return btnLEFT; 
    if (adc_key_in < 850)  return btnSELECT;  
    return btnNONE;                // when all others fail, return this.
}



void setup() {

  
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  Serial.setTimeout(5);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // prints title with ending line break
  Serial.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n");

  
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("MLAB:Hello World!");
  lcd.setCursor(0, 1);
  lcd.print("smart-techvn.com");
  

}
int button_pressed, tmp_button, table_display = 0;
void loop() {
  char print_lcd[16];
  char float_str[10];
  int index_gprmc = 0;
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):

  tmp_button = read_LCD_buttons();
  if(button_pressed != tmp_button)
  {
    Serial.println("Key pressed");
    button_pressed = tmp_button;
    if(button_pressed == btnRIGHT)
    {
      table_display++;
      if(table_display >= DISPLAY_MAX)
      {
        table_display = 0;
      }
    }
    if(button_pressed == btnLEFT)
    {
      if(table_display == 0)
      {
        table_display = DISPLAY_MAX - 1;
      }
      else
      {
        table_display--;  
      }
    }
  }
  while (Serial.available() > 0) 
  {
    String str = Serial.readStringUntil(0x0D);
    index_gprmc = str.indexOf("GPRMC");
    if(index_gprmc != -1)  // Just run gprmc
    {
      str = str.substring(index_gprmc);
      NMEA_GPRMC_Decoder(&g_gps_data, str);
      switch(table_display)
      {
        case DISPLAY_GPS:
        {
          if(g_gps_data.State_gps == true)
          {
            lcd.clear();
            lcd.setCursor(0, 0);
            dtostrf(g_gps_data.Lat, 10, 6, float_str);
            sprintf(print_lcd, "lat: %s", float_str);
            lcd.print(print_lcd);
            lcd.setCursor(0, 1);
            dtostrf(g_gps_data.Lng, 10, 6, float_str);
            sprintf(print_lcd, "lng: %s", float_str);
            lcd.print(print_lcd);
            
          }
          else
          {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("GPS not fix");
          }
          break;
        }
        case DISPLAY_RTC:
        {
          lcd.clear();
          lcd.setCursor(0, 0);
          sprintf(print_lcd, "%04d/%02d/%02d"  , 2000 + g_gps_data.time_gps.time.year  \
                                              , g_gps_data.time_gps.time.month  \
                                              , g_gps_data.time_gps.time.date);
          lcd.print(print_lcd);
          lcd.setCursor(0, 1);
          sprintf(print_lcd, "%02d:%02d:%02d", g_gps_data.time_gps.time.hour   \
                                              , g_gps_data.time_gps.time.minute   \
                                              , g_gps_data.time_gps.time.sec);
          lcd.print(print_lcd);
          break;
        }
        case DISPLAY_SPEED_ORG:
        {
          lcd.clear();
          lcd.setCursor(0, 0);
          dtostrf(g_gps_data.SpeedGPS, 5, 2, float_str);
          sprintf(print_lcd, "SPEED : %s", float_str);
          lcd.print(print_lcd);
          lcd.setCursor(0, 1);
          dtostrf(g_gps_data.OrGPS, 5, 2, float_str);
          sprintf(print_lcd, "ORG : %s", float_str);
          lcd.print(print_lcd);
          break;
        }
        default:
        break;
      }
    }
  }
}

static int GetMessageFeilds(unsigned char **message_feildls, unsigned char *msg, unsigned char separate_char, int max_feild_get)
{
  int count_feild = 0;
  *message_feildls = msg;
  message_feildls++;
  count_feild++;
  while(*msg !='\0')
  {
    if(*msg == separate_char)
    {
      *msg = '\0';
      *message_feildls = msg + 1;
      message_feildls++;
      count_feild++;
      if(count_feild >= max_feild_get)
        return count_feild;
    }
    msg++;
  }
  return count_feild;
}


static float gps_convert_lon_to_float(unsigned char *lon_str, unsigned char *WE)
{
  unsigned char hours[3+1]; 
  unsigned char minutes[8+1];
  float ret;

  memset(hours,0,sizeof(hours));
  memset(minutes,0,sizeof(minutes));

  strncpy( hours, lon_str, 3 );
  strncpy( minutes, lon_str + 3 , strlen(lon_str) - 3 );

  ret = atof(hours);
  ret += atof(minutes)/60;
  if(strcmp(WE, "W") == 0)
  {
    return -ret;
  }
    return ret;
}

static float gps_convert_lat_to_float(unsigned char *lat_str, unsigned char *NS)
{
  unsigned char hours[2+1]; 
  unsigned char minutes[8+1];
  float ret;

  memset(hours,0,sizeof(hours));
  memset(minutes,0,sizeof(minutes));

  strncpy( hours, lat_str, 2 );
  strncpy( minutes, lat_str + 2 , strlen(lat_str) - 2 );

  ret = atof(hours);
  ret += atof(minutes)/60;
  if(strcmp(NS, "S") == 0)
  {
    return -ret;
  }
    return ret;
}

static void NMEA_GPRMC_Decoder(GPS_T *gps_data, String data)
{
  //Get data
  unsigned char data_bytes[128];
  unsigned long time;
  unsigned char hour, minute, second, date, month, year;
  char *message_field[13];
  data.getBytes(data_bytes, 128);
  if(GetMessageFeilds(message_field, data_bytes, ',', 13) == 13)
  {
      if(strcmp(message_field[GPRMC_MID], "GPRMC") != 0)
      {
        return;
      }
      if( strcmp(message_field[GPRMC_STS],"A") == 0)
      {
        gps_data->State_gps = true;
        
        gps_data->SpeedGPS = atof(message_field[GPRMC_SOG]) * 1.852;
        gps_data->OrGPS = atof(message_field[GPRMC_COG]);
        gps_data->Lat = gps_convert_lat_to_float(message_field[GPRMC_LAT], message_field[GPRMC_LAT_NS]);
        gps_data->Lng = gps_convert_lon_to_float(message_field[GPRMC_LON], message_field[GPRMC_LON_EW]);  
      }
      else if( strcmp(message_field[GPRMC_STS],"V") == 0)
      {
        gps_data->State_gps = false;
        gps_data->Lat = 0;
        gps_data->Lng = 0;
        gps_data->SpeedGPS = 0;
        
      }
      *(message_field[GPRMC_UTC] + 6) = '\0';
      
      time = atof(message_field[GPRMC_UTC]);
    
      hour = (unsigned char)(time / 10000);
      minute = (unsigned char)((time % 10000) / 100);
      second = (unsigned char)(((time % 10000) % 100));
    
      time = atof(message_field[GPRMC_DAT]);
      date = (unsigned char)(time / 10000);
      month = (unsigned char)((time % 10000) / 100);
      year = (unsigned char)(((time % 10000) % 100));
    
    
      gps_data->time_gps.time.year = year;
      gps_data->time_gps.time.month = month;
      gps_data->time_gps.time.date = date;
      gps_data->time_gps.time.hour = hour;
      gps_data->time_gps.time.minute = minute;
      gps_data->time_gps.time.sec = second;
  }
}

 

Viết đánh giá

Họ và tên:


Đánh giá của bạn: Lưu ý: Không hỗ trợ HTML!

Bình chọn: Dở            Hay

Nhập mã bảo vệ: