Accéder au GPS via I2C sur un BerryGPS-IMU

Accéder au GPS via I2C sur un BerryGPS-IMU

Le BerryGPS-IMU utilise un module GPS CAM-M8C U-Blox, ce module GPS comprend une interface DDC entièrement compatible I2C.

Ce guide montrera comment lire des phrases NMEA à partir du module GPS via I2C, à l’aide d’un Raspberry Pi. Cela laisse l’interface série du Raspberry Pi libre pour d’autres utilisations. Vous pouvez également utiliser un connecteur QWIIC pour connecter le BerryGPS-IMU au Raspberry Pi

Nous allons créer un nœud virtuel où nous enverrons les phrases NMEA, nous allons ensuite configurer GPSD pour lire ce nœud virtuel.

Caveat: Il existe un bug d’étirement de l’horloge I2C bien connu sur le Raspberry Pi qui sera rencontré lors de la tentative de communication avec le module uBlox via I2C natif. Cela se traduit par des caractères aléatoires apparaissant dans les données récupérées.
Nous allons couvrir deux méthodes pour contourner ce problème;

Méthode 1 – Incluez de nombreuses vérifications pour ignorer les phrases NMEA contenant des données corrompues.
Le nombre total de phrases NMEA qui seront corrompues est très faible (20 sur 1 000), ce qui rend cette méthode très utilisable.

Méthode 2 – Utilisant peu cogner pour surmonter le bug d’étirement de l’horloge. Cela n’entraînera aucune erreur, mais nécessite la désactivation d’I2C sur le Raspberry Pi.

Par défaut, le module GPS du BerryGPS-IMU n’est pas connecté au bus I2C. Cela peut être corrigé en plaçant une goutte de soudure sur les cavaliers JP11 et JP10 au dos du PCB.

BerryGPS-IMU I2C GPS

Activez I2C sur votre Raspberry Pi et réglez la vitesse sur 400Khz.

pi@raspberrypi ~ $ sudo nano /boot/config.txt

Vers le bas, ajoutez la ligne suivante

dtparam=i2c_arm=on,i2c_arm_baudrate=400000

Maintenant, redémarrez.

Vous pouvez confirmer si vous voyez le module GPS en utilisant la commande ci-dessous.

pi@raspberrypi ~ $ sudo i2cdetect -y 1

Voici la sortie lorsqu’un BerryGPS-IMU est connecté. 42 est le module GPS

pi@raspberrypi ~ $ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 abcdef
00 : — — — — — — — — — — — — —
10: — — — — — — — — — — — — 1c — — —
20: — — — — — — — — — — — — — — — —
30 : — — — — — — — — — — — — — — — —
40 : — — 42 — — — — — — — — — — — — —
50 : — — — — — — — — — — — — — — — —
60 : — — — — — — — — — — 6a — — — — —
70 : — — — — — — — 77

Créez le script python qui lira les données via I2C depuis le module GPS

pi@raspberrypi ~ $ nano i2c-gps.py

Copiez dans le code ci-dessous;


#! /usr/bin/python
import time
import smbus
import signal
import sys

BUS = None
address = 0x42
gpsReadInterval = 0.03

def connectBus():
    global BUS
    BUS = smbus.SMBus(1)

def parseResponse(gpsLine):

  if(gpsLine.count(36) == 1):                           # Check #1, make sure '$' doesnt appear twice
    if len(gpsLine) < 84:                               # Check #2, 83 is maximun NMEA sentenace length.
        CharError = 0;
        for c in gpsLine:                               # Check #3, Make sure that only readiable ASCII charaters and Carriage Return are seen.
            if (c < 32 or c > 122) and  c != 13:
                CharError+=1
        if (CharError == 0):#    Only proceed if there are no errors.
            gpsChars="".join(chr(c) for c in gpsLine)
            if (gpsChars.find('txbuf') == -1):          # Check #4, skip txbuff allocation error

                gpsStr, chkSum = gpsChars.split('*',2)  # Check #5 only split twice to avoid unpack error
                gpsComponents = gpsStr.split(',')

                chkVal = 0

                for ch in gpsStr[1:]: # Remove the $ and do a manual checksum on the rest of the NMEA sentence
                     chkVal ^= ord(ch)
                if (chkVal == int(chkSum, 16)): # Compare the calculated checksum with the one in the NMEA sentence
                     print gpsChars

def handle_ctrl_c(signal, frame):
        sys.exit(130)

#This will capture exit when using Ctrl-C
signal.signal(signal.SIGINT, handle_ctrl_c)

def readGPS():
    c = None
    response = []
    try:
        while True: # Newline, or bad char.
            c = BUS.read_byte(address)

            if c == 255:
                return False
            elif c == 10:
                break
            else:
                response.append(c)

        parseResponse(response)

    except IOError:
        connectBus()
    except Exception,e:
        print e

connectBus()

while True:
    readGPS()
    time.sleep(gpsReadInterval)

Vous pouvez tester le script avec python i2c-gps.py. Si vous avez une position GPS, vous obtiendrez une sortie similaire à celle ci-dessous.

pi@raspberrypi ~ $ python i2c-gps.py
$GNRMC,071423.00,A,3254.18201,S,15243.27916,E,0.252,,110721,,,A*72
$GNVTG,,T,,M,0.252,N,0.466,K,A*3C
$GNGGA,071423.00,3254.18201,S,15243.27916,E,1,10,1.01,29.0,M,22.6,M,,*63
$ GNGSA,A,3,30,14,07,17,13,19,15,,,,,,1,66,1.01,1.31*17
$GNGSA,A,3,73,74,72,,,,,,,,,,1,66,1,011,1,31*1C
$GPGSV,3,1,12,01,21,124,,06,13,009,20,07,11,048,21,13,47,286,34*70
$GPGSV,3,2,12,14,54,143,27,15,25,253,31,17,84,132,28,19,70,328,31*7D
$GPGSV,3,3,12,21,09,139,,24,08,225,18,28,,,29,30,49,052,26*45
$GLGSV,3,1,10,65,14,243,16,71,00,330,,72,15,287,21,73,39,099,22*65
$GLGSV,3,2,10,74,53,176,19,75,16,227,,80,000,070,,83,24,149,*64

Créez un nœud virtuel, c’est là que nous enverrons les phrases NMEA du module GPS.

pi@raspberrypi ~ $ mknod /tmp/gps p

Exécutez maintenant le script python et redirigez la sortie vers le nœud virtuel que nous venons de créer.
Nous utiliserons également stdbuf ainsi la sortie du script est envoyée au nœud virtuel une ligne à la fois. Sans cela, la sortie est mise en mémoire tampon et n’est envoyée au nœud virtuel que lorsque la mémoire tampon est pleine.

pi@raspberrypi ~ $ stdbuf -oL python i2c-gps.py > /tmp/gps

Configurer GPSD pour utiliser le tampon virtuel

Non, vous pouvez configurer GPSD pour qu’il pointe vers le tampon virtuel.

pi@raspberrypi ~ $ sudo nano /etc/default/gpsd

Chercher
APPAREILS= » »
et le changer en
APPAREILS= »/tmp/gps »

Redémarrez GPSD pour que les nouveaux paramètres prennent effet.

pi@raspberrypi ~ $ sudo systemctl redémarrer gpsd.socket

Vous pouvez maintenant commencer à utiliser votre module GPS avec votre Raspberry Pi

Confirmez que vous faites ne pas avoir I2C activé. Il ne devrait y avoir aucun périphérique i2c sous /dev/

pi@raspberrypi ~ $ ls /dev/i2c*
ls : impossible d’accéder à ‘/dev/i2c*’ : aucun fichier ou répertoire de ce type

Si I2C est activé, la commande ci-dessus renverra un fichier dans le répertoire /dev/.
Vous pouvez désactiver I2C dans /boot/config.txt

pi@raspberrypi ~ $ sudo nano /boot/config.txt

Recherchez la ligne ci-dessous et commentez-la en ajoutant un « https://www.raspberryme.com/accessing-gps-via-i2c-on-a-berrygps-imu/# » devant.

dtparam=i2c_arm=on

Maintenant, redémarrez.

Créez le script python qui lira les données par bit banging I2C à partir du module GPS

pi@raspberrypi ~ $ nano i2c-gps.py

Copiez dans le code ci-dessous;

import time
import signal
import sys
import pigpio

address = 0x42
gpsReadInterval = 0.03

SDA=2
SCL=3
pi = pigpio.pi()
pi.set_pull_up_down(SDA, pigpio.PUD_UP)
pi.set_pull_up_down(SCL, pigpio.PUD_UP)
pi.bb_i2c_open(SDA,SCL,100000)

def handle_ctrl_c(signal, frame):
        pi.bb_i2c_close(SDA)
        pi.stop()
        sys.exit(130)

#This will capture exit when using Ctrl-C
signal.signal(signal.SIGINT, handle_ctrl_c)

def readGPS():
    c = None
    response = []

    while True: # Newline, or bad char.
        a=pi.bb_i2c_zip(SDA, [4, address, 2, 6, 1])  # Bit bang I2C read. 2 = Start, 6 = read, 1= How many bytes to read
        c = ord(a[1])
        if c == 255:
            return False
        elif c == 10:
            break
        else:
            response.append(c)

    gpsChars="".join(chr(c) for c in response)  #Convert list to string
    print gpsChars

while True:
    readGPS()
    time.sleep(gpsReadInterval)

Créez un nœud virtuel, c’est ici que nous enverrons les phrases NMEA du module GPS à

pi@raspberrypi ~ $ mknod /tmp/gps p

Exécutez maintenant le script python et redirigez la sortie vers le nœud virtuel que nous venons de créer.
Nous utiliserons également stdbuf ainsi la sortie du script est envoyée au nœud virtuel une ligne à la fois. Sans cela, la sortie est mise en mémoire tampon et n’est envoyée au nœud virtuel que lorsque la mémoire tampon est pleine.

pi@raspberrypi ~ $ stdbuf -oL python i2c-gps.py > /tmp/gps

Configurer GPSD pour utiliser le tampon virtuel

Non, vous pouvez configurer GPSD pour pointer vers le tampon virtuel

pi@raspberrypi ~ $ sudo nano /etc/default/gpsd

Chercher
APPAREILS= » »
et le changer en
APPAREILS= »/tmp/gps »

Redémarrez GPSD pour que les nouveaux paramètres prennent effet.

pi@raspberrypi ~ $ sudo systemctl redémarrer gpsd.socket

Vous pouvez maintenant commencer à utiliser votre module GPS avec votre Raspberry Pi