Arduinio:简易GPS [转]

liyuan66 2013-04-25
很久以前就对Arduino产生兴趣,在论坛潜水很久了,新近入手一块Arduino UNO R3,一块LCD1602 Keypad Shield和一个GPS Shield,上Google搜索了一下,找到一个葡萄牙人编写的GPS解码程序,稍微修改了一下,增加了串口输出数据功能。
   然后,一个简易GPS诞生了,目前只有日期,时间和地点,速度显示功能而已。本人第一个作品。Arduino IDE 1.01编译通过



代码如下:
    #include <LiquidCrystal.h>  
    #include <SoftwareSerial.h>
    #define DADOS_LEN 100
    #define IDLEN 6
    #define TEMPLEN 11
    #define GPRMC 0
    #define GPGGA 1
    char data[DADOS_LEN]; //buffer for GPS data
    byte conta=0; //variavel auxiliar para contar
    char* idnmea[] = {"$GPRMC","$GPGGA"}; //IDs dos NMEA que vou utilizar
    byte verificador[]= {0,0}; //variavel auxiliar para verificar ID NMEA
    byte indice[12]; //Em uma linha $GPRMC contem 12 valores separados por virgulas. Esta variavel guarda a posi&#231;&#227;o do caracter de inicio de cada valor.
    byte contindice=0; //variavel auxiliar de controle usada na variavel indice[];
    byte menu=0; // Menu do LCD: 0-key RIGHT, 1-key UP, 2-key DOWN, 3-key LEFT, 4-key SELECT
    char tempmsg[TEMPLEN]; //variavel temporaria auxiliar para guarda o valor de um dado extraido do GPS.
    SoftwareSerial nss(3, 2);
    LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);
    int  adc_key_val[5] ={30, 150, 360, 535, 760 }; //valores do divisor de tens&#227;o do teclado do LCD Shield
    #define NUM_KEYS 5 //numero de teclas do teclado
    int adc_key_in; //valor da entrada analogica do teclado
    byte key=-1; //tecla pressionada
    byte oldkey=-1; //tecla pressionada anteriormente
     
    void setup()
       {
      Serial.begin(9600);
      nss.begin(9600);
      lcd.clear(); //Clear LCD
      lcd.begin(16,2);
      lcd.print("Arduino.cc");
      lcd.setCursor(0, 2); //set cursor on LCD at col 0 and row 2
      lcd.print("Arduino GPS");
      clearBuffer(); //clear buffer for GPS (databuffer)
      clearTemp(); //clear data for GPS (tempmsg)
      //Serial.begin(9600); //Inicia UART para comunicar com módulo GPS
       delay(3000);
    }
     
    void loop(){   
        while(nss.available()){//if serial port available
          data[conta] = nss.read(); //Read a byte of the serial port
          if(data[conta]==13){  //If the received byte is = to 13, end of transmission
            verificador[GPRMC]=0; //verifies idnmea[0] ($GPRMC)
            //verificador[GPGGA]=0;//verifies idnmea[1] ($GPGGA)
            for(byte i=1;i<=IDLEN;i++){ //checking the ID NMEA of string received
              if(data[i]==idnmea[GPRMC][i-1]){ //Verifies that is $GPRMC
                verificador[GPRMC]++; //increases 1
              }
     
              //I will not implement $GPGGA do not get too confused
              /*if(data[i]==idnmea[GPGGA][i-1]){ //Verifies that is $GPGGA
                verificador[GPGGA]++; //increases 1
              }*/
            }
            if(verificador[GPRMC]==IDLEN){ // if the line received is $GPRMC
              //A line string of GPRMC has 11 "," Divided into 12 data
              //exemplo: $GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70
              //            0      1   2    3    4     5    6    7    8     9     10    11
              // we interesting: 2-timestamp (UTC), 3-latitude, 4-North/South, 5-Longitude, 6-East/West,7-Speed in knots,9-date stamp
              contindice = 0;
              indice[contindice] = 1; //data[] inicia no caracter 1
              contindice++;
              for(byte i=1; i<DADOS_LEN;i++){ //crosses every line data[] identifying where each value of GPS
                if(data[i]==','){ //found the final of a data
                  indice[contindice] = i+1;
                  contindice++;
                }
              }
              adc_key_in = analogRead(0); //verifica entrada analogica do teclado
              key = get_key(adc_key_in); //interpreta valor da entrada analogica
              if (key != oldkey){ //verifica se o valor encontrado é diferente do valor anterior
                delay(50);                // faz um delay para o debounce
                adc_key_in = analogRead(0);   
                key = get_key(adc_key_in);                        // interpreta
                if (key != oldkey){                        //verifica se é diferente
                  oldkey = key; //atualiza oldkey
                  lcd.clear(); //clear LCD
                  if (key >=0){ //se alguma tecla foi pressionada
                    menu = key; //atualiza o menu
                  }
                }
              }
     
              switch(menu){
                 //show on  LCD the key pressed
                case 4: //SELECT 4-key
                    lcd.setCursor(1,0); //move cursor to LCD  column 1 row 0
                    lcd.print("True course"); //print text to LCD
                    lcd.setCursor(1,1); //move cursor to LCD  column 1 row 1
                    lcd.print(datastream(7)); //print text to LCD
                  break;            
                case 3: //LEFT 3-key
                    lcd.clear();
                    lcd.setCursor(0,0);
                    lcd.print("Lat:");
                    lcd.print(datastream(4));
                    lcd.print(" ");
                    lcd.print(datastream(3)); // datastream(byte)
                    lcd.setCursor(0, 1);
                    lcd.print("Lon:");
                    lcd.print(datastream(6));
                    lcd.print(" ");
                    lcd.print(datastream(5));
                    break;
                case 1: //UP   1-key
                  lcd.setCursor(1,0);
                  lcd.print("Date:");
                  lcd.print(datastream(9));
                  lcd.setCursor(1,1);
                  lcd.print("Time:");
                  lcd.print(datastream(1));
                  break;
                case 2: //DOWN  2-key
                  lcd.setCursor(1,0);
                  lcd.print("Speed:");
                  lcd.print(datastream(7));
                  lcd.setCursor(1,1);
                  lcd.print("knots");
                  break;
               }
                Serial.println("---------------");
             for (int i=0;i<=12;i++){
               switch(i){
                 case 0 :Serial.print("Time in UTC (HhMmSs): ");Serial.print(datastream(1));break;
                 case 1 :Serial.print("Status (A=OK,V=KO): ");Serial.print(datastream(2));break;
                 case 2 :Serial.print("Latitude: ");Serial.print(datastream(3));break;
                 case 3 :Serial.print("Direction (N/S): ");Serial.print(datastream(4));break;
                 case 4 :Serial.print("Longitude: ");Serial.print(datastream(5));break;
                 case 5 :Serial.print("Direction (E/W): ");Serial.print(datastream(6));break;
                 case 6 :Serial.print("Velocity in knots: ");Serial.print(datastream(7));break;
                 case 7 :Serial.print("Heading in degrees: ");Serial.print(datastream(8));break;
                 case 8 :Serial.print("Date UTC (DdMmAa): ");Serial.print(datastream(9));break;
                 case 9 :Serial.print("Magnetic degrees: ");break;
                 case 10 :Serial.print("(E/W): ");break;
                 case 11 :Serial.print("Mode: ");break;
                 case 12 :Serial.print("Checksum: ");Serial.print(datastream(11));break;
               }
     
               Serial.println("");
             }
             Serial.println("---------------");
            }
     
            conta = 0; //zero conta, or is, will start next line of GPS and data[conta] this at position 0
            clearBuffer(); //clear data[]
          }else{
            conta++; //increases conta, in other words, data[conta] skips to the next position
          }
     
        }
    }
    void clearBuffer(){
      for (byte i=0;i<DADOS_LEN;i++){       // clear variavel (buffer) received GPS data
        data[i]=' ';
      }  
    }
    void clearTemp(){
      for(byte i=0;i<TEMPLEN;i++)
        tempmsg[i]=' ';
    }
     
    char* datastream(byte inicio){
      /*
      Receive Datastream from GPS devices,then convert to Data We can read directly
      remenber that: 2-timestamp (UTC), 3-latitude, 4-North/South, 5-Longitude, 6-East/West,7-Speed in knots,9-date stamp
      */
      clearTemp();
      byte i;
      byte fim = indice[inicio+1]-2;
      inicio = indice[inicio];
      for(i=0;i<=(fim-inicio);i++){
        tempmsg[i] = data[inicio+i];
      }
      tempmsg[i] = '\0';
      return tempmsg;
    }
     
    // Convert ADC value to key number
    byte get_key(unsigned int input)
    {
      int k=menu;
      for (byte i = 0; i < NUM_KEYS; i++){
        if (input < adc_key_val[i]){
          k=i;
          return k;
        }
      }
      return k;
     
    }




对于以上基本功能,也试过直接调用TinyGPS库,代码更简单,但是光是没有按键选择功能的代码就有将近8KB,而本程序加入按键功能也才8KB大小。对于只需要基本定位信息而言,TinyGPS库可以不用。
GPS板淘宝上找的,如图,最便宜的一个就是了。



原文链接:http://www.geek-workshop.com/thread-3778-1-1.html
开坦克玩漂移 2013-04-25
楼主 ,不知这个板能否做人脸识别?
liyuan66 2013-04-27
开坦克玩漂移 写道
楼主 ,不知这个板能否做人脸识别?


朋友  请参考 http://openhardware.group.iteye.com/group/topic/37656
开坦克玩漂移 2013-04-27
liyuan66 写道
开坦克玩漂移 写道
楼主 ,不知这个板能否做人脸识别?


朋友  请参考 http://openhardware.group.iteye.com/group/topic/37656

谢谢。
Global site tag (gtag.js) - Google Analytics