Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Commentez, partagez et proposez des Tutos en langage BASIC et PASCAL !
Réception des trames GPS
pspic
Débutant
Débutant
Messages : 32
Âge : 71
Enregistré en : septembre 2017
Localisation : 68

#1 Message par pspic » ven. 20 oct. 2017 13:57

Réception GPS
Lcd1.JPG

Ce tutoriel permet de se familiariser avec :
La réception des trames GPS et leurs exploitations.
La conversion de l’heure UTC envoyée par le GPS en heure locale en tenant compte des décalages horaires été / hiver.
L’affichage des données sur un LCD 4x20 en liaison I2C avec un PIC et qui indique la date, l'heure locale, la longitude, la latitude, la vitesse et l'azimut).

Matériel :

Une carte Easy Pic 5 équipé d’un PIC 18F2520
Un récepteur GPS GP-735T (Ou un module NEO-6M-001 qui coûte que quelques Euros)
https://www.lextronic.fr/P27906-rcepteur-gps-oem-gp-735t.html
Un afficheur LCD 4x20. + module de conversion I2C – parallèle PCF8574A

1 / Partie GPS

Liaison PIC – GPS
CablGps.JPG

Transmission des données entre le module GPS et le PIC en TTL à 9600 bauds
Une LED sur RA0 indique la réception d'un nouveau paquet de trames.

Lecture des trames avec extraction de la trame GPRMC :

Paqu.JPG

Le GPS envoi un paquet de trames avec en début de chaque trame le caractère $ et en fin de trame les caractères CR LF.

Détail de la trame GPRMC.

DetailGPRMC.JPG

Nota : Le champ Déclinaison n’est pas transmis par le module GP-735T

Extraction de la trame GPRMC :

Code : Tout sélectionner

'Lecture des trames GPS avec filtre sur la trame GPRMC___________________________
      Deb: Rec = ""
      T1 = 0
      i = 0
  do                                 'Recherche début trame (caractère $)
  loop until ReadChr = 36
    i = -1
     do                              'Extraction Trames
      inc(i)
      Rec = Rec + char(ReadChr)      'Lecture trame caractère par caractère
        if i = 2 then
         if Rec[2]="R" then inc(T1) else dec(T1) end if  'Fltrer sur trame RMC
        end if
          if i = 3 then
           if Rec[3]="M" then inc(T1) else dec(T1) end if
          end if
            if i = 4 then
             if Rec[4]="C" then inc(T1) else dec(T1) end if
              if T1 <> 3 then goto Deb end if             'GPRMC non trouvé
            end if
     loop until Rec[i]=chr(10)                       'Fin trame


Extraction des champs de la trame GPRMC :

Comme la taille de certains champs est variable, il faut utiliser le séparateur virgule pour extraire les différents champs.

Code : Tout sélectionner

'Extraction des champs de la trame GPRMC________________________________________
         Scv = ""
         Indv = 0
         for Bc1 = 0 to strlen(Rec)
          if Rec[Bc1]="*" then Pchs = Bc1 end if     'Position caractère *
           if Bc1 > 5 then                           'Néglige GPRMC,
            if Rec[Bc1] <> "," then
              Scv = Scv + Rec[Bc1]
             else
              if Indv = 0 then Cp.Hr= Scv[0]+Scv[1]+Scv[2]+Scv[3]+Scv[4]+Scv[5] end if
               if Indv = 1 then Cp.Va = Scv end if
                if Indv = 2 then Cp.La = Scv end if
                 if Indv = 3 then Cp.Lad = Scv end if
                  if Indv = 4 then Cp.Lo = Scv end if
                   if Indv = 5 then Cp.Lod = Scv end if
                    if Indv = 6 then Cp.Vi = Scv end if
                     if Indv = 7 then Cp.Az = Scv  end if
                      if Indv = 8 then Cp.Dt = Scv end if
             Scv = ""
             inc(Indv)
            end if
           end if
         next Bc1


Lecture du checksum envoyé avec la trame :

Chs= "00" + Rec[Pchs+1] + Rec[Pchs+2] 'Checksum dans la trame, Pchs = position de *

Calcul du checksum de la trame reçue

Ce calcul est fait sur la portion de trame compris entre les caractères $ (36) et * (42)

Code : Tout sélectionner

'Fonction contrôle cheksum (entre "$" et "*" et renvoi 0 si ok)_________________
 sub function CtrlCs(dim byref Rec3 as string[80], dim byref ChS1 as string[4],dim Pt as word ) as integer
  dim ChSum as word
  dim Bc as integer
  dim ChSumTxt as string[4]

   ChSum = 0
   for bc = 0 to (Pt - 1)
    ChSum = ChSum xor ord(Rec3[Bc])  'Calcul checksum sur trame recue
   next bc
    ChSumTxt = ""
    wordtohex(ChSum,ChSumTxt)
   result = StrCmp(ChSumTxt,ChS1)     'Si Cs reçu = Cs calculé alors result = 0
 end sub


Calcul timestamp heure et date reçus du GPS :

Comme le GPS envoi l’heure UTC il faut la convertir en heure locale.
Pour convertir l’heure UTC en heure locale, nous devons comparer le timestamp de l’heure actuelle aux timestamps des changements d’horaires été et hiver
Pour cela nous utilisons Time_dateToEpoch de la librairie Time, qui transforme une date heure en en une valeur LongInt qui représente le nombre de secondes depuis le 1er janvier 1960 à 00:00:00.

Code : Tout sélectionner

'Calcul timestamp actuel________________________________________________________
 sub function CalcEpoch(dim byref GmtSat as string[12])as longint
  dim ts1 as TimeStruct
  J1Str, M1Str, H1Str, N1Str, S1Str, Yy as string[3]
  Jr, Mo,He, Mn, Se as word
  Y1Str as string[5]
  Yr as word
     
     H1Str = GmtSat[0]+ GmtSat[1]
       He = strtoword("0"+H1Str)
       N1Str = GmtSat[2]+ GmtSat[3]
       Mn = strtoword("0"+N1Str)
        S1Str = GmtSat[4]+ GmtSat[5]
        Se = strtoword("0"+S1Str)
         J1Str = GmtSat[6]+ GmtSat[7]
         Jr = strtoword("0"+J1Str)
          M1Str = GmtSat[8]+ GmtSat[9]
          Mo = strtoword("0"+M1Str)
           Y1Str = "20" + GmtSat[10]+ GmtSat[11]
           Yr = strtoword(Y1Str)     
    Ts1.ss = byte(Se)
    Ts1.mn = byte(Mn)
    Ts1.hh = byte(He)
    Ts1.wd = 0
    Ts1.md = byte(Jr)
    Ts1.mo = byte(Mo)
    Ts1.yy = word(Yr)
   result = Time_DateToEpoch(@Ts1) 'Timestamp actuel
 end sub


Calcul Timestamp du changement d’heure hiver été.

Code : Tout sélectionner

'Recherche jour du passage hiver --> éte________________________________________
 sub function TsEte(dim An1 as word) as longint
    Ts10.ss = 0
    Ts10.mn = 0
    Ts10.hh = 1                                                                  '1 heure UTC
    Ts10.wd = 0
    Ts10.md = 31 - (integer(((5*(2000+An1))/4)+4)) mod 7   'Jour
    Ts10.mo = 3                                                                 'Mois de mars
    Ts10.yy = An1+2000
   result = Time_DateToEpoch(@Ts10)                                 'Timestamp été
 end sub


Calcul Timestamp du changement d’heure été hiver.

Code : Tout sélectionner

'Recherche jour du passage été --> hiver________________________________________
 sub function TsHiv(dim An1 as word) as longint
    Ts10.ss = 0
    Ts10.mn = 0
    Ts10.hh = 1                                                                   '1 heure UTC
    Ts10.wd = 0
    Ts10.md = 31 - (integer(((5*(2000+An1))/4)+1)) mod 7    'Jour
    Ts10.mo = 10                                                                 'Mois d'octobre
    Ts10.yy = An1+2000
   result = Time_DateToEpoch(@Ts10) 'Timestamp été
 end sub


Conversion Heure UTC en heure locale :

Nous pouvons maintenant définir le décalage horaire à appliquer.
Par convention le passage :
Hiver --> été se fait le dernier dimanche de mars à 01:00:00 soit UTC + 7200 secondes.
Eté --> hiver se fait le dernier dimanche d’octobre à 01:00:00 soit UTC + 3600 secondes.

Code : Tout sélectionner

   EpAct =  CalcEpoch(UtcSat)                  'Calcul  timestamp actuel
   EpEte =  TsEte(AnAct)                          'Timestamp hiver --> éte
   EpHiv =  TsHiv(AnAct)                         'Timestamp été --> hiver

         if ((EpAct >= EpEte) and (EpAct < EpHiv)) then
          EpochCor = EpAct + 7200                                      'Si été Utc + 2
         else
          EpochCor = EpAct + 3600                                      'Si hiver Utc + 1
         end if
       Time_epochToDate(EpochCor,@ts2)                          'Decode le timestamp corrigé


Mise en forme heure et date :

Code : Tout sélectionner

'Mise en forme date time________________________________________________________
        'hh
        bytetostr(ts2.hh,hhStr)
        ltrim(hhStr)
        if ts2.hh < 10 then hhStr = "0" + hhStr end if
        'mn
        bytetostr(ts2.mn,mnStr)
        ltrim(mnStr)
        if ts2.mn < 10 then mnStr = "0" + mnStr end if
        'ss
        bytetostr(ts2.ss,ssStr)
        ltrim(ssStr)
        if ts2.ss < 10 then ssStr = "0" + ssStr end if
        ScTime = hhStr+":"+mnStr+":"+ssStr
        'md
        bytetostr(ts2.md,mdStr)
        ltrim(mdStr)
        if ts2.md < 10 then mdStr = "0" + mdStr end if
        'mo
        bytetostr(ts2.mo,moStr)
        ltrim(moStr)
        if ts2.mo < 10 then moStr = "0" + moStr end if
        'yy
        wordtostr(ts2.yy,yyStr)
        ltrim(yyStr)
        ScDate = mdStr+"/"+moStr+"/"+yyStr
       VitKmh = ConvVit(Cp.Vi)                              'Conversion noeuds – kmh


Formatage dd°mm' ss.ddd'' :

Code : Tout sélectionner

'Procedure affichage latitude au format dd°mm'ss.ddd_________________________________
Sub procedure AfLat(dim byref Lat1 as string[10])
 dim SecLat as string[6]
     SecLatFl as float
     SecLatStr as string[17]

   copy(SecLat,Lat1,4,6)               'copie partie secondes
   SecLatFl = str2float(SecLat) * 60
   Float2Str(SecLatFl,SecLatStr,3)
   Ltrim(SecLatStr)
   ScLat = "Lat = " +Cp.La[0]+ Cp.La[1]+chr($DF)+Cp.La[2]+Cp.La[3]+"'"+ SeclatStr +" "+ Cp.Lad
   I2c_lcd_out(3,1,Sclat)               'Affiche latitude sur Lcd
end sub


Affichage résultats :

Code : Tout sélectionner

'Affichage sur LCD______________________________________________________________
      I2c_lcd_out(1,1,ScDate+"  "+ScTime)
      AfLat(cp.La)
      AfLon(Cp.Lo)
      I2c_lcd_out(4,1,("V = "+VitKmh + " Az = " + Cp.Az))


Lecture des trames GPS avec un PC :
Gp_Pc.JPG

A la mise sous tension, il faut entre 30 et 240 secondes pour obtenir la liaison avec le GPS.

2 / Partie LCD

Liaison PIC – LCD :

Broche RC3 (SLC) du PIC vers broche SCL du module PCF 8574A
Broche RC4 (SDA) du PIC vers broche SDA du module PCF 8574A
Mettre des résistances pull up sur SCL et SDA sur PCF 8574T, mais inutile sur PCF 8574A.
VCC EasyPic vers VCC PCF 8574A
GND Easy Pic vers GND PCF 8574A

Détail du module PCF 8574A :
Im1.JPG

Ce module est à souder à l’arrière du LCD en respectant l’orientation.

Adressage du PCF 8574A :

Adresses.JPG


Le code complet en MikroBasic :

Les librairies utilisées dans ce projet :
Lib.JPG

Strng_P18 se trouve sous Libstock 1487242654_Utilities_MikroBasic_Pic.
Le fichier de configuration :
CfgGpsLcdTxt.txt
(Pour l'utiliser, il faut renommer l'extension en .CfgSch)
Ram utilisé = 555 octets (36.6%)
Rom utilisé = 17961 octets (54.8%) d'où l'utilisation d'un PIC 18F2520

Code : Tout sélectionner

program Gps_Lcd

'Projet GpsLcd 20/10/2017 en MikroBasic
'Ce programme reçoit les trames GPS une fois par seconde.
'La trame GPRMC est isolée et les différents champs qui la composent sont extraits.
'L'heure UTC reçue est convertie en heure locale été - hiver.
'Les champs sont affichés sur un LCD I2C 4x20.
'PIC 18F2520, Q = 8 Mhz (PLL 4 x Fosc1 32 Mhz).
'Librairie StrngUtils_p18 activée

'Module LCD I2C 4x20____________________________________________________________
 include Mod_Lcd_I2c      'Module avec les procédures de gestion I2C_LCD

'Déclaration structure GPS__________________________________________________________
structure GpsStruc
  dim Hr as string[6]     'Heure hhmmss
  dim Va as string[1]     'Validation
  dim La as string[10]    'Latitude
  dim Lad as string[1]    'Direction latitude
  dim Lo as string[11]    'Longitude.
  dim Lod as string[1]    'Direction longitude
  dim Vi as string[5]     'Vitesse
  dim Az as string[5]     'Azimut
  dim Dt as string[6]     'Date jjmmaa
end structure

'Déclaration des variables______________________________________________________
Dim Rec as string[80]                        'Trame reçue
ScTime as string[8]                          'hh:mm:ss
ScDate as string[10]                         'jj/mm/aaaa
ScLat,ScLon as string[20]                    'Lignes Lcd
UtcSat as string[12]                         'Heure date UTC
i, Bc1 as integer                            'Indices de boucles
Indv, T1, Pchs as byte                       'Cnt champs
Chs as string[4]                             'Cheksum lu en string
VitKmh as string[5]                          'Vitesse en kmh en string
ts2, ts10 as TimeStruct                      'Structures Time
EpochCor, EpAct, EpEte, EpHiv as longint     'Timestamps
hhStr,mnStr,ssStr,mdStr,moStr as string[3]   'Chaines date time
yyStr as string[5]                           'Chaine année
AnAct as word                                'Année courte actuelle
Scv as string[11]                            'Champs
Cp as GpsStruc                               'Structure champs

'Fonction lecture RX Uart_______________________________________________________
 sub function ReadChr as byte
  do
  loop until UART1_Data_Ready = 1
  result=UART1_Read
 end sub

'Fonction contrôle cheksum (entre "$" et "*" et renvoi 0 si ok)_________________
 sub function CtrlCs(dim byref Rec3 as string[80], dim byref ChS1 as string[4],dim Pt as word ) as integer
  dim ChSum as word
  dim Bc as integer
  dim ChSumTxt as string[4]

   ChSum = 0
   for bc = 0 to (Pt - 1)
    ChSum = ChSum xor ord(Rec3[Bc])  'Calcul checksum sur trame recue
   next bc
    ChSumTxt = ""
    wordtohex(ChSum,ChSumTxt)
   result = StrCmp(ChSumTxt,ChS1)     'Si Cs reçu = Cs calculé alors result = 0
 end sub

'Conversion vitesse en noeud en kmh_____________________________________________
 sub function ConvVit(dim byref ScVit as string[5]) as string[5]
  dim PosP as word                    'Position du point décimal
      Ve, Vd as string[5]             'Valeurs entiere et décimale en string
      VeW, VdW as word                'Valeurs entiere et décimale en word
      Vf as float                     'Vitesse en kmh en float
      Vfs as string[23]               'Vitesse en kmh en string
 
  PosP = StrStr(ScVit,".")            'Recherche position point décimal
   if PosP = 1 then                   'Si point en 1 (origine 0)
    Ve = ScVit[0]+""
    Vd = ScVit[2] + ScVit[3] + ScVit[4]
   end if
    if PosP = 2 then                  'Si point en 2
     Ve = ScVit[0] + ScVit[1]
     Vd = ScVit[3] + ScVit[4]
    end if
     if PosP = 3 then                 'Si point en 3
      Ve = ScVit[0] + ScVit[1] + ScVit[2]
      Vd = ScVit[4]+""
     end if
      VeW = strtoword(Ve)     'Conversion valeur entiere en word
      VdW = strtoword(Vd)     'Conversion valeur décimale en word
       if PosP = 1 then VF = (float(VeW) + (float(VdW) /1000))*1.852 end if
       if PosP = 2 then VF = (float(VeW) + (float(VdW) /100))*1.852 end if
       if PosP = 3 then VF = (float(VeW) + (float(VdW) /10))*1.852 end if
    floattostr(Vf,Vfs)
   result = Vfs[0]+Vfs[1]+Vfs[2]+Vfs[3]+Vfs[4]
 end sub

'Recherche jour du passage hiver --> éte (Dernier dimanche de mars à 1h UTC)____
 sub function TsEte(dim An1 as word) as longint
    Ts10.ss = 0
    Ts10.mn = 0
    Ts10.hh = 1                                            '1 heure
    Ts10.wd = 0
    Ts10.md = 31 - (integer(((5*(2000+An1))/4)+4)) mod 7   'Jour
    Ts10.mo = 3                                            'Mois de mars
    Ts10.yy = An1+2000                                     'An
   result = Time_DateToEpoch(@Ts10)                        'Timestamp été
 end sub

'Recherche jour du passage été --> hiver (Dernier dimanche d'octobre à 1h UTC)__
 sub function TsHiv(dim An1 as word) as longint
    Ts10.ss = 0
    Ts10.mn = 0
    Ts10.hh = 1                                             '1 heure
    Ts10.wd = 0
    Ts10.md = 31 - (integer(((5*(2000+An1))/4)+1)) mod 7    'Jour
    Ts10.mo = 10                                            'Octobre
    Ts10.yy = An1+2000                                      'An
   result = Time_DateToEpoch(@Ts10)                         'Timestamp été
 end sub

'Calcul timestamp actuel________________________________________________________
 sub function CalcEpoch(dim byref GmtSat as string[12])as longint
  dim ts1 as TimeStruct
      J1Str, M1Str, H1Str, N1Str, S1Str, Yy as string[2]
      Jr, Mo,He, Mn, Se as word
      Y1Str as string[5]
      Yr as word
 
      H1Str = GmtSat[0]+ GmtSat[1]
       He = strtoword("0"+H1Str)
       N1Str = GmtSat[2]+ GmtSat[3]
       Mn = strtoword("0"+N1Str)
        S1Str = GmtSat[4]+ GmtSat[5]
        Se = strtoword("0"+S1Str)
         J1Str = GmtSat[6]+ GmtSat[7]
         Jr = strtoword("0"+J1Str)
          M1Str = GmtSat[8]+ GmtSat[9]
          Mo = strtoword("0"+M1Str)
           Y1Str = "20" + GmtSat[10]+ GmtSat[11]
           Yr = strtoword(Y1Str)     
    Ts1.ss = byte(Se)
    Ts1.mn = byte(Mn)
    Ts1.hh = byte(He)
    Ts1.wd = 0
    Ts1.md = byte(Jr)
    Ts1.mo = byte(Mo)
    Ts1.yy = word(Yr)
   result = Time_DateToEpoch(@Ts1) 'Timestamp actuel
 end sub
 
'Procedure affichage latitude au format dd°mm'ss.ddd_________________________________
Sub procedure AfLat(dim byref Lat1 as string[10])
 dim SecLat as string[6]
     SecLatFl as float
     SecLatStr as string[17]

   copy(SecLat,Lat1,4,6)               'copie partie secondes
   SecLatFl = str2float(SecLat) * 60
   Float2Str(SecLatFl,SecLatStr,3)
   Ltrim(SecLatStr)
   ScLat = "Lat = " +Cp.La[0]+ Cp.La[1]+chr($DF)+Cp.La[2]+Cp.La[3]+"'"+ SeclatStr +" "+ Cp.Lad
   I2c_lcd_out(3,1,Sclat)               'Affiche latitude sur Lcd
end sub

'Procedure affichage longitude au format dd°mm'ss.ddd_________________________________
Sub procedure AfLon(dim byref Lon1 as string[11])
 dim SecLon as string[6]
     SecLonFl as float
     SecLonStr as string[17]

   copy(SecLon,Lon1,5,6)                    'Copie partie secondes
   SecLonFl = str2float(SecLon) * 60
   Float2Str(SecLonFl,SecLonStr,3)
   Ltrim(SecLonStr)
   ScLon = "Lon =" +Cp.Lo[0]+ Cp.Lo[1]+Cp.Lo[2]+chr($DF)+Cp.Lo[3]+Cp.Lo[4]+"'"+ SeclonStr +" "+ Cp.Lod
   I2c_lcd_out(2,1,Sclon)                   'Affiche longitude sur Lcd
end sub

main:'__________________________________________________________________________
UART1_INIT(9600)
delay_ms(250)
ADCON1 = $0F
CMCON = 7
PORTA = $0
PORTB = $0
PORTC = $0
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000
  I2C1_Init(100000)             'Init I2C à 100 kbit / s.
  delay_ms(500)
  I2C_LCD_Init()                'Init LCD
  I2C_LCD_Cmd(_LCD_CURSOR_OFF)  'Curseur non visible
  I2C_LCD_Cmd(_LCD_CLEAR)       'Effacement du LCD
  I2C_Lcd_Out(1,1,"      Demo GPS      ")
  Delay_ms(2000)
  I2c_Lcd_Out(3,1,"Recherche satellite ")

 While true
'Lecture des trames GPS avec filtre sur la trame GPRMC___________________________
      Deb: Rec = ""
      T1 = 0
      i = 0
  do                                 'Recherche début trame (caractère $)
  loop until ReadChr = 36
    i = -1
     do                              'Extraction Trames
      inc(i)
      Rec = Rec + char(ReadChr)      'Lecture trame caractère par caractère
        if i = 2 then
         if Rec[2]="R" then inc(T1) else dec(T1) end if  'Fltrer sur trame RMC
        end if
          if i = 3 then
           if Rec[3]="M" then inc(T1) else dec(T1) end if
          end if
            if i = 4 then
             if Rec[4]="C" then inc(T1) else dec(T1) end if
              if T1 <> 3 then goto Deb end if             'GPRMC non trouvé
            end if
     loop until Rec[i]=chr(10)                       'Fin trame

'Extraction des champs de la trame GPRMC________________________________________
         Scv = ""
         Indv = 0
         for Bc1 = 0 to strlen(Rec)
          if Rec[Bc1]="*" then Pchs = Bc1 end if     'Position caractère *
           if Bc1 > 5 then                           'Néglige GPRMC,
            if Rec[Bc1] <> "," then
              Scv = Scv + Rec[Bc1]
             else
              if Indv = 0 then Cp.Hr= Scv[0]+Scv[1]+Scv[2]+Scv[3]+Scv[4]+Scv[5] end if
               if Indv = 1 then Cp.Va = Scv end if
                if Indv = 2 then Cp.La = Scv end if
                 if Indv = 3 then Cp.Lad = Scv end if
                  if Indv = 4 then Cp.Lo = Scv end if
                   if Indv = 5 then Cp.Lod = Scv end if
                    if Indv = 6 then Cp.Vi = Scv end if
                     if Indv = 7 then Cp.Az = Scv  end if
                      if Indv = 8 then Cp.Dt = Scv end if
             Scv = ""
             inc(Indv)
            end if
           end if
         next Bc1

         Chs= "00" + Rec[Pchs+1] + Rec[Pchs+2]    'Checksum reçu
         UtcSat = Cp.Hr + Cp.Dt                   'hhmmss + jjmmaa
         AnAct = strtoword(Cp.Dt[4]+ Cp.Dt[5])    'An actuel

  if CtrlCs(Rec,ChS, Pchs) = 0 then              'Si checksum calculé = checksum reçu
   if Cp.Va[0] = "A" then                        'Si trame valide
      LatA.0 = 1                                  'Led RA0 = 1
       EpAct =  CalcEpoch(UtcSat)                 'Calcul  timestamp actuel
       EpEte =  TsEte(AnAct)                      'Calcul hiver --> éte
       EpHiv =  TsHiv(AnAct)                      'Calcul été --> hiver
         if ((EpAct >= EpEte) and (EpAct < EpHiv)) then
          EpochCor = EpAct + 7200                 'Si été Utc + 2
         else
          EpochCor = EpAct + 3600                 'Si hiver Utc + 1
         end if
       Time_epochToDate(EpochCor,@ts2)            'Decode le timestamp corrigé

'Mise en forme date time________________________________________________________
        'hh
        bytetostr(ts2.hh,hhStr)
        ltrim(hhStr)
        if ts2.hh < 10 then hhStr = "0" + hhStr end if
        'mn
        bytetostr(ts2.mn,mnStr)
        ltrim(mnStr)
        if ts2.mn < 10 then mnStr = "0" + mnStr end if
        'ss
        bytetostr(ts2.ss,ssStr)
        ltrim(ssStr)
        if ts2.ss < 10 then ssStr = "0" + ssStr end if
        ScTime = hhStr+":"+mnStr+":"+ssStr
        'md
        bytetostr(ts2.md,mdStr)
        ltrim(mdStr)
        if ts2.md < 10 then mdStr = "0" + mdStr end if
        'mo
        bytetostr(ts2.mo,moStr)
        ltrim(moStr)
        if ts2.mo < 10 then moStr = "0" + moStr end if
        'yy
        wordtostr(ts2.yy,yyStr)
        ltrim(yyStr)
        ScDate = mdStr+"/"+moStr+"/"+yyStr
         VitKmh = ConvVit(Cp.Vi)                'Conversion noeuds - kmh

'Affichage sur LCD______________________________________________________________
      I2c_lcd_out(1,1,ScDate+"  "+ScTime)
      AfLat(cp.La)
      AfLon(Cp.Lo)
      I2c_lcd_out(4,1,("V = "+VitKmh + " Az = " + Cp.Az))

   end if     'Validation A
  end if      'Checksum OK
  LatA.0 = 0  'Led RA0 = 0
 delay_ms(50)
 wend
end.


Le module de gestion du LCD I2C :

'Ce module utilise la librairie I²C full master MSSP

Code : Tout sélectionner

'Commandes du LCD
symbol _LCD_FIRST_ROW         = $80     'Déplace curseur en ligne 1
symbol _LCD_SECOND_ROW        = $C0     'Déplace curseur en ligne 2
symbol _LCD_THIRD_ROW        = $94     'Déplace curseur en ligne 3
symbol _LCD_FOURTH_ROW       = $D4     'Déplace curseur en ligne 4
symbol _LCD_CLEAR             = $01     'Efface LCD
symbol _LCD_RETURN_HOME       = $02     'Retour curseur en position initiale
symbol _LCD_CURSOR_OFF        = $0C     'Curseur invisible
symbol _LCD_UNDERLINE_ON      = $0E     'Curseur bas visible
symbol _LCD_BLINK_CURSOR_ON   = $0F     'Curseur clignotant
symbol _LCD_MOVE_CURSOR_LEFT  = $10     'Curseur à gauche sans changer les datas en RAM
symbol _LCD_MOVE_CURSOR_RIGHT = $14     'Curseur à droite sans changer les datas en RAM
symbol _LCD_TURN_ON           = $0C     'LCD marche
symbol _LCD_TURN_OFF          = $08     'LCD arrêté
symbol _LCD_SHIFT_LEFT        = $18     'Shift LCD à gauche sans changer les datas en RAM
symbol _LCD_SHIFT_RIGHT       = $1E     'Shift LCD à droite sans changer les datas en RAM
symbol LCD_ADDR = $7E                   'Adresse PCF 8574AT (3 straps ouverts soit 111)

dim txt1 as string[20]        'Texte ligne 1
       txt2 as string[20]        'Texte ligne 2
       txt3 as string[20]       'Texte ligne 3
       txt4 as string[20]       'Texte ligne 4

sub procedure I2C_LCD_Cmd (dim out_char as byte)
sub procedure I2C_LCD_Init()
sub procedure I2C_LCD_Chr(dim row as byte, dim column as byte, dim out_char as byte)
sub procedure I2C_LCD_Chr_Cp(dim out_char as byte)
sub procedure I2C_LCD_Out(dim row as byte, dim column as byte, dim byref text as string)
sub procedure I2C_LCD_Out_Cp(dim byref text as string)

implements

'_Envoi de commandes au LCD______________________________________________________
sub procedure I2C_LCD_Cmd (dim out_char as byte)
    dim hi_n, lo_n, rs as  byte
    rs = 0
    hi_n = out_char and $F0
    lo_n = (out_char << 4) and $F0
    I2C1_Start()
    I2C1_Is_Idle()
    I2C1_Wr(LCD_ADDR)
    I2C1_Is_Idle()
    I2C1_Wr(hi_n or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr(hi_n or rs or $00 or $08)
    I2C1_Is_Idle()
    Delay_us(100)
    I2C1_Wr(lo_n or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr(lo_n or rs or $00 or $08)
    I2C1_Is_Idle()
    I2C1_stop()
    if(out_char = $01) then
     Delay_ms(2)
    end if
end sub

'_Initialisation du LCD_________________________________________________________
sub procedure I2C_LCD_Init()
    dim rs as byte
    rs = 0
    I2C1_Start()
    I2C1_Is_Idle()
    I2C1_Wr(LCD_ADDR)  'Adresse du module I2C
    I2C1_Is_Idle()
    Delay_ms(30)
    I2C1_Wr($30 or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr($30 or rs or $00 or $08)
    I2C1_Is_Idle()
    Delay_ms(10)
    I2C1_Wr($30 or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr($30 or rs or $00 or $08)
    I2C1_Is_Idle()
    Delay_ms(10)
    I2C1_Wr($30 or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr($30 or rs or $00 or $08)
    I2C1_Is_Idle()
    Delay_ms(10)
    I2C1_Wr($20 or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr($20 or rs or $00 or $08)
    I2C1_Is_Idle()
    I2C1_Stop()
    Delay_ms(10)
    I2C_LCD_Cmd($28)
    I2C_LCD_Cmd($06)
end sub

'_Envoi un caractère à la position Ligne, Colonne________________________________
sub procedure I2C_LCD_Chr(dim row as byte, dim column as byte, dim out_char as byte)
    dim hi_n, lo_n,rs as byte
    rs = 1
    select case (row)
        case 1
        I2C_LCD_Cmd($80 + (column - 1))         'Ligne 1
        case 2
        I2C_LCD_Cmd($C0 + (column - 1))         'Ligne 2
        case 3
        I2C_LCD_Cmd($94 + (column - 1))        'Ligne 3
        case 4
        I2C_LCD_Cmd($D4 + (column - 1))        'Ligne 4
    end select
    hi_n = out_char and $F0
    lo_n = (out_char << 4) and $F0
    I2C1_Start()
    I2C1_Is_Idle()
    I2C1_Wr(LCD_ADDR)
    I2C1_Is_Idle()
    I2C1_Wr(hi_n or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr(hi_n or rs or $00 or $08)
    I2C1_Is_Idle()
    Delay_us(100)
    I2C1_Wr(lo_n or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr(lo_n or rs or $00 or $08)
    I2C1_Is_Idle()
    I2C1_stop()
end sub

'_Envoi un caractère à la position courante du curseur__________________________
sub procedure I2C_LCD_Chr_Cp(dim out_char as byte)
    dim hi_n, lo_n, rs as byte
    rs = $01
    hi_n = out_char and $F0
    lo_n = (out_char << 4) and $F0
    I2C1_Start()
    I2C1_Is_Idle()
    I2C1_Wr(LCD_ADDR)
    I2C1_Is_Idle()
    I2C1_Wr(hi_n or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr(hi_n or rs or $00 or $08)
    I2C1_Is_Idle()
    Delay_us(100)
    I2C1_Wr(lo_n or rs or $04 or $08)
    I2C1_Is_Idle()
    Delay_us(50)
    I2C1_Wr(lo_n or rs or $00 or $08)
    I2C1_Is_Idle()
    I2C1_stop()
end sub

'_Envoi un texte à la ligne, colonne____________________________________________
sub procedure I2C_LCD_Out(dim row as byte, dim column as byte, dim byref text as string)
    dim i as byte
    for i = 0 to Strlen(text) - 1
        I2C_LCD_Chr(row, column, text[i])
        column = column + 1
    next i
end sub

'_Envoi un texte à partir de la position du curseur__________________________________________
sub procedure I2C_LCD_Out_Cp(dim byref text as string)
    dim i as byte
    for i = 0 to Strlen(text) - 1
         I2C_LCD_Chr_Cp(text[i])
    next i
end sub

end.
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Modifié en dernier par pspic le ven. 9 févr. 2018 17:23, modifié 19 fois.

Réception des trames GPS
Temps-x
Avatar de l’utilisateur
Confirmé
Confirmé
Messages : 960
Enregistré en : juillet 2016
Localisation : Terre

#2 Message par Temps-x » lun. 23 oct. 2017 02:04

Bonjour pspic, et bonjour tous le monde,

:bravo: Pour le tutoriel,

:eek: Super bien expliqué, belle présentation, et en plus de cela bien détaillé, chapeau bas.

Merci !
Modifié en dernier par Temps-x le mar. 24 oct. 2017 01:51, modifié 1 fois.
Quand la souris nargue le chat, c'est que son trou n'est pas loin.

Réception des trames GPS
satinas
Passioné
Passioné
Messages : 314
Enregistré en : novembre 2015

#3 Message par satinas » lun. 23 oct. 2017 11:20

Bonjour,
Pas mal le calcul du jour du dernier dimanche du mois. J'avais jamais vu aussi simple, ma version beaucoup plus laborieuse va se raccourcir, merci.

Réception des trames GPS
venom
Avatar de l’utilisateur
Passioné
Passioné
Messages : 423
Âge : 33
Enregistré en : avril 2016
Localisation : . <------ ici
Contact :

#4 Message par venom » lun. 23 oct. 2017 22:31

Bonjour,

Bravo pour ce joli tutoriel pspic :shock: 8-)






@++
En fait tout est une question de BIT ? :-D

Réception des trames GPS
pspic
Débutant
Débutant
Messages : 32
Âge : 71
Enregistré en : septembre 2017
Localisation : 68

#5 Message par pspic » jeu. 26 oct. 2017 17:39

Bonjour,
Je viens de changer le format d'affichage latitude et longitude en dd°mm'ss.sss au lieu de xxxx.xxxxx (voir le tuto).

Réception des trames GPS
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 1088
Âge : 68
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#6 Message par paulfjujo » jeu. 26 oct. 2017 20:11

bonsoir pspic et à tous,


:bravo: Tres belle presentation !

remark : un test du nb de satellites visibles par le GPS, permettrait de valider ou pas les données ..
et d'avoir un element Qualité de reception.
Probleme vecu, surtout par temps tres nuageux.
A moins que la donnée "Etat A" englobe déja ce test ?

:+1: pour avoir mis la liste des lib utilisées !

:+1: à gagner encore en mettant
les statistiques RAM et ROM utilisés
et le fichier de config *.cfgsh

exit je sais, la critique est aisée ,mais l'art est difficile ! .. mais c'est une critique positive !

Réception des trames GPS
pspic
Débutant
Débutant
Messages : 32
Âge : 71
Enregistré en : septembre 2017
Localisation : 68

#7 Message par pspic » ven. 27 oct. 2017 11:20

Bonjour Paul,
Merci pour tes conseils pertinents.
Je viens d'ajouter l'occupation Ram - Rom, ainsi que le fichier de configuration.
Pour utiliser ce fichier il doit être renommé de Txt en Cfgsch, car ce forum n'accepte pas l'extension Cfgsch pour les pièces jointes.
Je ne suis pas certain que le nombre de satellites soit un critère de qualité ?
Dans l'exemple ci-après avec 4 satellites, je n'ai pas de status valide alors qu'au pas suivant j'ai toujours 4 satellites avec un status valide.
TramGp.JPG

Je n'ai pas trouvé les conditions qui font que le status passe de V en A, si quelqu'un a l'explication ?

Ce projet m'a fait découvrir la librairie Utilities/StrngUtils (Libstock), qui est très intérresante pour manipuler des chaines.
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.

Réception des trames GPS
Jérémy
Administrateur du site
Administrateur du site
Messages : 2161
Âge : 39
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#8 Message par Jérémy » ven. 17 nov. 2017 19:18

Vraiment un super boulot !
C'est en faisant des erreurs, que l'on apprend le mieux !!!


Retourner vers « Langage BASIC & PASCAL »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 0 invité