PIC 32 + GPS

Stampa
( 4 Votes ) 
Valutazione attuale:  / 4
ScarsoOttimo 
Categoria principale: Elettronica Categoria: Microcontrollori
Data pubblicazione
Scritto da teppei68 Visite: 689

PIC 32 + GPS

INTRODUZIONE:

Prima di passare ai display grafici ci soffermeremo in questo articolo ancora con LCD16x2 il PIC32 e un modulo GPS, quindi sarà implementata, oltre a quello che abbiamo già visto negli articoli precedenti, la porta seriale, l'interrupt sulla porta seriale, e la codifica del protocollo NMEA183 ecco una foto del prototipo montato sempre sulla millefori (a volte costose schede di sviluppo non sono necessarie!eek):

Si può notare nella parte superiore del millefori il modulo GPS tale modulo all'inizio era un'antenna GPS bluetooth per cellulare, la parte bluetooth era guasta quindi è stata by passata mentre la linea tx rx (TTL) è stata direttamente prelevata  dal processore GPS e  connesso ad una delle due porte seriali del PIC32.

Una breve occhiata alle caratteristiche del processore SIRF per rendersi conto delle potenzialità del ricevitore GPS(la CPU è adirittura un ARM7), è curioso come ormai i componenti esterni siano ridotti all'osso!

PROTOCOLLO NMEA183.

Il processore SIRF fornisce in uscita alla seriale dei dati con uno standard predefinito dal PROTOCOLLO NMEA183 , vi inserisco il link per capire cos'è

files/teppei68/NMEA0183.pdf

Sostanzialmente riporto due cose fondamentali del protocollo:

1)Caratteristica TX e RX dati:

                                                                   - Baud rate: 4800 (*)

                                                                  - Number of data bits: 8 (bit 7 is 0)

                                                                  - Stop bits: 1 (or more)

                                                                  - Parity: none

                                                                  - Handshake: none

  (*) Nota che la velocità di trasmissione nel caso del SIRF è di Baud rate 57k6

 

2)Il protocollo dati NMEA183 (il quale comprende la comunicazione dati GPS, Autopiloti, Radar,RadioTelefoni etc.) quindi in uscita della seriale avremmo

     una serie di stringhe a pacchetto dati come segue:

 

$GPZDA,144630.000,10,07,2012,,*55

$GPGGA,144630.000,4500.0000,N,01100.0000,E,1,07,1.3,25.2,M,47.2,M,,0000*6A

$GPGLL,4500.0000,N,01100.0000,E,144630.000,A,A*5E

$GPGSA,A,3,31,30,25,02,12,29,14,,,,,,1.9,1.3,1.4*34

$GPGSV,3,1,10,29,79,243,33,25,76,053,36,31,45,303,46,12,37,095,28*7F

$GPGSV,3,2,10,02,29,053,34,14,15,236,22,21,12,184,24,30,05,293,35*74

$GPGSV,3,3,10,10,02,047,23,05,01,095,22*71

$GPRMC,144630.000,A,4500.0000,N,01100.0000,E,0.26,24.98,100712,,,A*5F

 

questo pacchetto dati viene fornito dal GSC3 via seriale (TTL) ogni secondo, il PIC32 resta in ascolto sulla sua porta seriale, abilitando l’interrupt preposto, e quindi ad ogni stimolo si attiverà per ricevere il pacchetto dati in questione, la stringa presa in considerazione nel progetto è l’ultima:

 

$GPRMC,144630.000,A,4500.0000,N,01100.0000,E,0.26,24.98,100712,,,A*5F

 

il significato di tale stringa è qui esposto:

 

RMC Recommended Minimum Navigation Information

12

1 2 3 4 5 6 7 8 9 10 11|

| | | | | | | | | | | |

$--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a*hh

1) Time (UTC)

2) Status, V = Navigation receiver warning

3) Latitude

4) N or S

5) Longitude

6) E or W

7) Speed over ground, knots

8) Track made good, degrees true

9) Date, ddmmyy

10) Magnetic Variation, degrees

11) E or W

12) Checksum

 

Per conoscere il significato delle altre stringhe basta sfogliare il datasheet, è stata presa in considerazione questa stringa per i suoi requisiti (informazioni base per la navigazione) a livello software si tratterà di isolare la stringa scelta ed estrapolare i dati che a noi interessano vediamo in linea di principio  come viene effettuato:

 

- Il pacchetto con tutte le stringhe viene caricato tutto (questo per sfruttare tutte le informazioni ricevute) in un ARRAY sfruttando ancora una volta le librerie

    microchip.

- Si legge l'intero ARRAY ponendo come filtro, in questo caso  $GPRMC.

- Individuata la stringa voluta si estrapolano i dati che vogliamo questa volta il filtro lo fanno le virgole le quali identificano un campo all'interno della stringa.

- Alla fine l'ARRAY viene cancellato

 

Ed il gioco è fatto, premendo il pulsante si può visualizzare alternativamente la Velocità oppure LAT/LONG qui sotto c'è il listato completo mancante delle solite

librerie LCD e Delay , i LED giallo lampeggia ad ogni pacchetto dati ricevuto il verde avvisa se c'è stato un errore nella comunicazione UART tra PIC e SIRF

il rosso lampeggia con il TMR1. (dovrebbe lampeggiare ma non l'ho ancora inserito nel circuito!).

 
/* ********************************************************************
 * Program: GPS receiver by UART, NMEA183 protocol, internal clock    *
 * and minimal configuration pin (see datasheet).                         *
 * MCU: PIC32MX440F128H    64 Pin QFN                                      *
 * Compiler: C32 V2.02                                                  *
 * Development software: MPLAB IDE 8.83 + PICKIT2                      *
 * Author : Mirko Musto 20/09/2012                                      *
 * ********************************************************************/  
 
#include <p32xxxx.h>
#include <plib.h>                                     // Adds support for PIC32 Peripheral Library functions and macros
#include <16x2.h>                                    // full support 16x2
#include <delayLCD.h>                                // delay support only ms
 
#pragma config FNOSC    = FRCPLL                    // Oscillator Selection internal clock 8mhz
#pragma config FPLLIDIV = DIV_2                     // PLL Input Divider  
#pragma config FPLLMUL  = MUL_24                    // PLL Multiplier
#pragma config FPLLODIV = DIV_8                     // PLL Output Divider
#pragma config FPBDIV   = DIV_1                     // Peripheral Clock divisor  
#pragma config FWDTEN   = OFF                       // Watchdog Timer
#pragma config WDTPS    = PS1                       // Watchdog Timer Postscale
#pragma config FCKSM    = CSDCMD                    // Clock Switching & Fail Safe Clock Monitor
#pragma config OSCIOFNC = OFF                       // CLKO Enable
#pragma config POSCMOD  = OFF                        // Primary Oscillator   
#pragma config IESO     = OFF                       // Internal/External Switch-over
#pragma config FSOSCEN  = OFF                       // Secondary Oscillator  
#pragma config CP       = OFF                       // Code Protect
#pragma config BWP      = OFF                       // Boot Flash Write Protect
#pragma config PWP      = OFF                       // Program Flash Write Protect
//#pragma config ICESEL   = ICS_PGx2                  // ICE/ICD Comm Channel Select
#pragma config DEBUG    = OFF                       // Debugger  
 
#define puls     PORTDbits.RD1
#define giallo     PORTCbits.RC14
#define verde     PORTCbits.RC13  
#define rosso   PORTDbits.RD0
 
// global var
unsigned int  errorValue = 0x00, j = 0, jj = 0, n = 0x00;
unsigned char     i = 196,  m = 0;
char data[1024];
char *buffer=data;
 
// Function
void clean(char *var);
 
int main(void){
    // local var
    char  a=0x00, b=0x00, c=0x00, cerca=0;    
    
    mPORTCClearBits                (BIT_13 | BIT_14 );     
    mPORTDClearBits            (BIT_0 | BIT_3 | BIT_7);         
    mPORTEClearBits                (BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 );  
    mPORTFClearBits                (BIT_0 | BIT_1 );     
    
    mPORTCSetPinsDigitalOut        (BIT_13 | BIT_14 );     
    mPORTDSetPinsDigitalIn        (BIT_1 | BIT_2 );                  
    mPORTDSetPinsDigitalOut     (BIT_0 | BIT_3 | BIT_7);             
    mPORTESetPinsDigitalOut        (BIT_0 | BIT_1 | BIT_2 | BIT_3);  
    mPORTFSetPinsDigitalOut        (BIT_0 | BIT_1 );             
    
    ConfigIntUART1(UART_ERR_INT_EN|UART_RX_INT_EN|UART_INT_PR2|UART_INT_SUB_PR2|UART_TX_INT_DIS);
    OpenUART1(UART_EN|UART_NO_PAR_8BIT|UART_1STOPBIT|
              UART_IRDA_DIS|UART_DIS_BCLK_CTS_RTS|UART_NORMAL_RX|UART_BRGH_SIXTEEN,    //UART_ENABLE_PINS_TX_RX_ONLY
              UART_TX_ENABLE|UART_RX_ENABLE|UART_INT_RX_CHAR|UART_ADR_DETECT_DIS,        
              12);    // 57600 bps, 8-N-1
 
    OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_256, 0x1FE);    // configure the core timer roll-over rate (100msec)
    ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_2);
             
    INTEnableSystemMultiVectoredInt();
 
    initLCD();    
    DelayMs(1000);    
    stringLCD(0x80,"******GPS*******");
    stringLCD(0xC0,"wait 2 min......");
    DelayMs(15000);
    cleanLCD();
    //putsUART1("*** UART Interrupt-driven Application Example ***\r\n");  // Solo in debug
       stringLCD(0x80,"Lat:            ");
    stringLCD(0xC0,"Lon:            ");
 
                         
while(1){                                            // endless loop
            if(puls==0)
            {    m++;
                if(m>=2)m=0;
                verde=!verde;
                cleanLCD();
                DelayMs(500);
                if(m==0)
                {
                    stringLCD(0x80,"Lat:            ");
                    stringLCD(0xC0,"Lon:            ");
                }
                if(m==1)
                {
                    stringLCD(0x80,"Speed over gnd: ");
                    stringLCD(0xC0,"         Knots/h");
                }
            }
 
            if((m==0)||(m==1)||(m==2))
            {
                if(buffer[n] == 'R')
                {
                    n++;
                    if(buffer[n] == 'M')
                    {
                        n++;
                        if(buffer[n] == 'C')
                         
                        {
                             
                            if(m==0){
                             
                            while(cerca<=2)
                                {                                    // Search data  
                                      if(buffer[n]==',')cerca++;
                                    n++;
                                }
                            i=133;
                            while(cerca<=4)
                                {                                    // Lat. N/S
                                      if(buffer[n]==',')cerca++;
                                    visualizza(i,buffer[n]); 
                                    i++;
                                    n++;
                                }
                            i=196;
                            while(cerca<=6)
                                {                                    // Long. E/O
                                      if(buffer[n]==',')cerca++;
                                    visualizza(i,buffer[n]); 
                                    i++;
                                    n++;
                                }
                                    }
                            if(m==1){ 
                         
                            while(cerca<=6)
                                {                                    // Search data  
                                      if(buffer[n]==',')cerca++;
                                    n++;
                                }
                            i=192;
                            while(cerca<=7)
                                {                                    // Speed over ground
                                      if(buffer[n]==',')cerca++;
                                    visualizza(i,buffer[n]); 
                                    i++;
                                    n++;
                                }
                         
                                    }
                            DelayMs(100);
                            n=0;
                            cerca=0;
                            giallo=!giallo;
                            clean(buffer);
                        }
                        else
                        {
                            n++;
                            if(n>=640)n=0;
                        }
                    }
                    else
                    {
                        n++;
                        if(n>=640)n=0;
                    }
                }
                else
                {
                    n++;
                    if(n>=640)n=0;
                }
            }
 
                               
        }            // END endless loop
return 0;
                }    // END main
 
 
void clean(char *var)
{     
    int z = 0;
    while(var[z] != '\0')
    {    
        var[z] = '\0';
        z++; 
    }
}
 
void __ISR(_UART1_VECTOR, ipl2) IntUart1Handler(void)
{    
    if(INTGetFlag(INT_SOURCE_UART_RX(UART1)))
    {
        INTClearFlag(INT_SOURCE_UART_RX(UART1));                                            // Clear the RX interrupt Flag
        getsUART1(1024,buffer,50);                                                            // feed buffer
        if(UART1GetErrors() & (_U1STA_OERR_MASK | _U1STA_FERR_MASK | _U1STA_PERR_MASK))        // handle an error on UART 1
        {
             UART1ClearAllErrors();                                                            // handle error...
            verde=1;                                                                        // Say me if an error occur
        }
 
    }
} // End interrupt
 
 
void __ISR(_TIMER_1_VECTOR, ipl2) _Timer1Handler(void)
{
    rosso=!rosso;                    // flicker Led rosso  
    mT1ClearIntFlag();                // clear the interrupt flag
}
 

SCHEMA ELETTRICO.

Per lo  schema elettrico vi rimando alla pubblicazione precedente PIC32+LCD l'aggiunta del modulo infatti comporta solo la connessione dei pin U1TX e U1RX che sono corrispondenti ai pin 51 e 50 e l'alimentazione per il modulo GPS stesso vi aggiungo il link della guida alle periferiche del 32: files/teppei68/32-bit-Peripheral-Library-Guide.pdf   in quanto è sempre bene averla a portata di mano! Il sorgente è sufficientemente commentato per quanto riguarda le impostazioni della UART1 (interrupt,RX/TX a char/string,error ect) vi rimando alla guida linkata che è esaustiva. Il trasporto, del sorgente, su un qualsiasi altro PIC o microcontrollore non dovrebbe essere troppo complesso.

Alcune foto:

 

Eccomi munito di bicicletta con il GPS (non proprio portatile...) le coordinate se inserite in google map vi diranno in che luogo misterioso mi trovo!

 

 

Qui posizionato nel cestino visualizza la velocità! ed in fine un breve anzi brevissimo filmato:

 

Si parte, premo il pulsante per vedere la velocità, (non sono riuscito aimè ad impostare la durata del video) E con questo concludiamo alla prossima.

Please register or login to add your comments to this article.
Joomla 1.7 Templates designed by College Jacke