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çã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ã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
|
|
开坦克玩漂移
2013-04-27
liyuan66 写道
谢谢。 |
相关讨论
相关资源推荐
- Labview 控制arduinio实现8*8点阵转圈圈
- arduinio笔记23:使用I2C接口配合LCD显示
- ARDUINIO开发板与ANDROID手机蓝牙通信的设计与实现
- ARDUINIO开发板与ANDROID手机蓝牙通信的设计与实现.pdf
- 基于ARDUINIO的5路红外循迹小车
- Ardunio建立电机类控制步进电机转角与转向、转速
- Arduino的控制(三):arduino发命令控制步进电机(前后转动度数)
- Arduino超声波智能循迹避障小车简易教程
- WeCare:通知系统,将通知您亲人的下落
- Arduino-MidiWah:基于 Arduino 的哇音和带 MIDI 控制的电位器之间的桥接