Traceur GPS voiture fiable avec carte temps réel Thinger.io
Composants et fournitures
| Composant | Quantité | Notes |
|---|---|---|
| Arduino Leonardo | 1 | Pour port série hardware dédié |
| Carte de développement SIM900 (GSM/GPRS) | 1 | Compatible SIM800 aussi |
| Module GPS u-blox NEO‑6M | 1 | |
| Antenne GPS | 1 | Les moins chères (eBay) peuvent mal capter ; privilégiez qualité |
| Résistance 220 Ω | 2 | Pour LED d'état |
| LED générique | 2 | Alimentation + verrou GPS |
| Plaque à souder 7×5 cm | 1 | Pour circuit LED ; breadboard possible si pas de boîtier |
| Module step-down 12 V → 5 V | 1 | Alimentation depuis batterie voiture / allume-cigare |
| Lecteur carte microSD (Adafruit, 5 V compatible) | 1 | Attention : beaucoup ne supportent que 3,3 V |
| Carte microSD | 1 |
Outils nécessaires
- Fer à souder
Applications et services en ligne
- Plateforme Thinger.io (IoT gratuit avec tableaux de bord cartographiques)
À propos de ce projet
Ce projet a débuté comme un simple « traceur GPS » et est devenu un « traceur GPS multipurpose ». C'est mon premier projet, la courbe d'apprentissage a été raide ; je suis ouvert à tout retour ou amélioration !
Le traceur est destiné à être placé dans une voiture et offre :
- Envoi des coordonnées GPS au cloud Thinger.io toutes les 2 minutes (affichage sur carte via dashboard). Communication par requêtes HTTP POST.
- Réponse aux commandes SMS : renvoi d'un lien Google Maps vers la position actuelle (ou dernière connue si pas de fix).
- Notification SMS tous les XX km (ex: rappel vidange bac à huile tous les 4000 km). Fonctionne comme un « odomètre » logiciel personnalisable.
J'ai vite été confronté aux limites mémoire de l'Arduino (RAM et flash) et ai dû optimiser le code et utiliser des bibliothèques légères.
Choix des composants
- NEO‑6M GPS : populaire, peu cher. Communication : port série hardware (Serial1 sur Leonardo).
- Antenne GPS : indispensable pour réception stable.
- SIM900 : GSM/GPRS. Communication : SoftwareSerial (broches 8/9). Fonctionne aussi avec SIM800.
- Arduino Leonardo : choisi pour son port série hardware natif (Serial1) en plus de l'USB (Serial). Sur Uno, il faut déconnecter le GPS pour flasher et pas de debug série.
- Lecteur microSD Adafruit : compatible 5 V (SPI). Stocke la distance parcourue. Vérifiez la tension supportée avant achat.
- LED d'état (alimentation, fix GPS) + résistances.
- Carte SIM avec data, PIN désactivé.
- Boîtier imprimable 3D (fichiers STL fournis).
Bibliothèques utilisées
- NeoGPS (par SlashDevin) : parsing GPS ultra‑léger, peu de RAM. Installable via le gestionnaire de bibliothèques. GitHub
- Time (Paul Stoffregen) : conversion fuseau horaire UTC. GitHub
- PetitFS (ChaN / greiman) : système de fichiers FAT ultra‑léger pour carte SD. GitHub
Pourquoi pas la bibliothèque officielle Thinger.io ? Elle occupe ~80 % de la flash sur Leonardo, ne laissant plus de place pour le reste. Nous utilisons donc des requêtes HTTP POST brutes vers l'API Thinger.io.
Commandes SMS supportées
- POS : renvoie coordonnées + lien Google Maps (ou dernière position connue).
- GETKM : renvoie distance cumulée depuis dernier reset.
- RESETKM : remet l'odomètre à zéro.
Configuration de NeoGPS
Après installation, modifiez GPSport.h dans le dossier de la bibliothèque (chemin selon OS) :
#ifndef GPSport_h
#define GPSport_h
#define gpsPort Serial1
#define GPS_PORT_NAME "Serial1"
#define DEBUG_PORT Serial
#endif
Ce fichier définit le port série vers le GPS. Adaptez selon votre carte (Serial2, Serial3 sur Mega).
Précision GPS : Le GPS n'est pas la méthode la plus précise pour cumuler des distances (dérive de position même à l'arrêt). Pour cette application, la précision relative suffit. Le logiciel ignore les déplacements < 10 m sur 15 s (considérés bruit). Échantillonnage 15 s (réductible pour plus de précision). Distance calculée en ligne droite (pas le chemin routier réel).
Configuration de PetitFS
Bibliothèque FAT ultra‑légère mais avec restrictions :
- Ne peut pas créer de fichier (fichier doit exister)
- Ne peut pas agrandir un fichier
- Ne peut pas mettre à jour le timestamp
- Ne peut pas ajouter des données (réécrit tout le fichier)
- Un seul fichier ouvert à la fois
Pourquoi l'utiliser ? Taille. La bibliothèque SD standard prend ~12 % de flash en plus. Avec PetitFS, le sketch final occupe ~96 % de la flash.
Modifications requises dans la bibliothèque :
pffArduino.h: définirSD_CS_PINà 10 (broche SS SPI).pffconf.h: désactiver (0)_USE_DIR,_USE_LSEEK,_FS_FAT12,_FS_FAT16pour gagner de la place.pff.cpp: ajouter le type de retourFRESULTà la fonctionpf_open(erreur de compilation sinon).
Préparation de la carte SD :
- Formatez en FAT32 (outil officiel SD Card Formatter).
- Créez deux fichiers à la racine :
dist.txtetsettings.txt(fournis dans le projet, format exact requis). dist.txt: distance initiale (ex: « 0 » pour partir de zéro).settings.txt: distance de déclenchement notification SMS (en mètres, ex: 4000000 pour 4000 km).
PetitFS écrit la longueur complète du tableau de caractères ; conservez les espaces de padding. Si le dispositif ne démarre pas (serial monitor vide), c'est souvent un problème de lecture fichier SD – utilisez les fichiers fournis.
Préparation de la carte SIM900
- Alimentation : L'Arduino ne fournit pas assez de courant (pics à 2 A). Utilisez une alim externe 5–9 V DC, ≥ 2 A, jack 5,5 mm. Sélecteur d'alimentation sur « externe ».
- Série : Configurez les jumpers sur « Software Serial ».
- Allumage logiciel : Soudez le jumper R13 pour commander l'allumage via Arduino (broche 7 → pin #9 du SIM900). Sinon, appuyez manuellement sur le bouton d'allumage.
- PIN SIM : Désactivez le code PIN de la carte SIM (via un téléphone).
- Firmware SIM900 (CRITIQUE) : La commande HTTP pour définir le header « Content-Type: application/json » n'est supportée qu'à partir du firmware **B10**. Vérifiez avec
AT+CGMR. Exemple ancienne version :Revision:1137B01SIM900M64_ST_AM(B01). Mettez à jour vers B10 ou supérieur (guide : ACOPTEX). Sans cela, les requêtes POST seront rejetées (400 Bad Request).
Ajustements du code pour votre projet
- APN : Dans
connectGPRS(), remplacez\"TeleXXX\"par l'APN de votre opérateur. - URL Thinger.io : Dans
postDataThinger(), remplacez l'URL et la clé d'autorisation par les vôtres (voir section intégration). - Fuseau horaire :
#define UTC_OFFSET 1(UTC+1). Adaptez. - Notification SMS : Modifiez le texte, la distance de déclenchement (dans
settings.txt), le numéro par défaut (DEFAULT_NUMBER), ou désactivez la section dansloop().
Intégration Thinger.io
- Créez un compte, puis un Bucket (base de données).
- Créez un Device HTTP (doc : docs.thinger.io). Nom de device **court** (clé d'auth plus courte = tient dans le buffer 256 octets).
- Dans le device > Callback > Settings : liez le Bucket créé.
- Dans Callback > Overview : notez l'URL de la méthode et l'en-tête Authorization (sans « Bearer »).
- Dans le code, remplacez l'URL et la clé dans
postDataThinger(). Important : passez dehttps://àhttps://(SIM900 ne supporte pas SSL). - Testez : le moniteur série doit afficher
+HTTPACTION: 1,200,0(succès).400= erreur URL/auth/SSL/firmware. - Créez un Dashboard Thinger.io avec widget « Map » sourcé sur le Bucket.
Pour ajouter plus de champs : modifiez le sprintf dans postDataThinger() : { \"longitude\": %s, \"latitude\": %s, \"date\": \"%s %s\" } – syntaxe stricte.
Boîtier imprimé 3D
Fichiers STL fournis :
- Partie haute (version haute ou compacte) – trous de fixation à percer (3 mm) après impression pour impression sans supports.
- Partie basse – logement SIM900 et Arduino avec découpes connecteurs.
- Clips de verrouillage SIM900 (pas de trous de fixation sur la carte).
Impression 0,2 mm, sans supports. Carte LED (7×5 cm) et GPS dans la partie haute ; Arduino + SIM900 dans la partie basse. Petits entretoises recommandées pour les PCB.
Alimentation depuis la voiture
Branché sur le circuit « allume-cigare » (coupé contact) pour démarrer/arrêter avec la voiture. Si vous voulez une alimentation permanente, branchez sur la batterie (avec pack batterie tampon optionnel). J'utilise un module step-down 12 V → 5 V bon marché (entrée 9–20 V) avec deux sorties USB pour alimenter Arduino et SIM900. Consommation ~110 mA en activité GSM (plus en mauvaise couverture).
Problèmes connus
- Si un SMS arrive pendant l'envoi HTTP POST vers Thinger.io, la commande SMS n'est pas traitée (pas de réponse). Renvoyez quelques secondes plus tard.
- Si l'Arduino démarre sans couverture réseau, il ne se reconnectera pas automatiquement quand le réseau revient (connexion seulement au démarrage).
Code principal (GPS_tracker_Leonardo_v2.ino – extraits clés)
#include <SoftwareSerial.h>
#include <NMEAGPS.h>
#include <GPSport.h>
#include <TimeLib.h>
#include "PF.h"
#include "PetitSerial.h"
#define UTC_OFFSET 1
#define TXPin 8
#define RXPin 9
#define PWRPin 7
#define DEFAULT_NUMBER "+4712345678"
FATFS fs;
String textMessage, number = DEFAULT_NUMBER;
char sms_msg[160];
float Lat = 0, Long = 0;
boolean valid_location = false;
uint8_t num_sat;
NeoGPS::Location_t prevFix;
NMEAGPS gps;
gps_fix fix;
const char *googlePrefix = "https://maps.google.com/maps?q=";
const char *filename = "DIST.TXT";
const char *settings = "SETTINGS.TXT";
// ... variables temps, distance, triggerDistance ...
SoftwareSerial SIM900(TXPin, RXPin);
void setup() {
pinMode(3, OUTPUT); pinMode(4, OUTPUT);
digitalWrite(3, HIGH); // LED power
Serial.begin(9600);
// while (!Serial); // décommenter seulement pour debug USB
SIM900.begin(9600);
gpsPort.begin(9600);
initializeSD();
SIM900power();
SIM900.println(F("AT"));
SIM900.println(F("AT+CMGF=1"));
SIM900.println(F("AT+CNMI=1,2,0,0,0"));
connectGPRS();
}
void loop() {
while (gps.available(gpsPort)) {
fix = gps.read();
num_sat = fix.satellites;
if (fix.valid.location) {
digitalWrite(4, HIGH); // LED GPS fix
Lat = fix.latitude(); Long = fix.longitude();
if (Lat != 0 && Long != 0 && !valid_location) {
valid_location = true; prevFix = fix.location;
}
}
if (fix.valid.date && fix.valid.time) {
timeFix = fix.dateTime; updateTime();
}
if (valid_location) {
// Mise à jour distance toutes les 15 s
static const unsigned long REFRESH_INTERVAL_UPD = 15000;
static unsigned long lastRefreshTime = millis();
if (millis() - lastRefreshTime >= REFRESH_INTERVAL_UPD) {
lastRefreshTime += REFRESH_INTERVAL_UPD;
float distanceDelta = prevFix.DistanceKm(fix.location) * 1000;
if (distanceDelta > 10 && distanceDelta < 10000) totalDistance += distanceDelta;
prevFix = fix.location;
}
// Écriture SD + envoi Thinger.io toutes les 2 min
static const unsigned long REFRESH_INTERVAL_WRITE_SD = 120000UL;
static unsigned long lastRefreshTimeWriteSD = millis();
if (millis() - lastRefreshTimeWriteSD >= REFRESH_INTERVAL_WRITE_SD) {
lastRefreshTimeWriteSD += REFRESH_INTERVAL_WRITE_SD;
// Écriture SD (PetitFS)
char buf[9]; dtostrf(totalDistance, 8, 0, buf);
if (PF.open(filename)) Serial.println(F("error open file"));
while (1) {
UINT nr;
if (PF.writeFile(buf, sizeof(buf), &nr)) Serial.println(F("error write file"));
if (nr == sizeof(buf)) { PF.writeFile(0, 0, &nr); break; }
}
// HTTP POST Thinger.io
char httpContent[60], tempstrLong[10], tempstrLat[10];
dtostrf(Lat, 2, 6, tempstrLat);
dtostrf(Long, 2, 6, tempstrLong);
sprintf(httpContent, "{\\\"longitude\\\": %s , \\\"latitude\\\": %s , \\\"date\\\": \\\"%s %s\\\" }", tempstrLong, tempstrLat, datePrint, timePrint);
char httpdataLen[20];
sprintf(httpdataLen, "AT+HTTPDATA=%i,10000", strlen(httpContent));
postDataThinger(httpdataLen, httpContent);
}
}
}
// Notification SMS si distance > seuil
if (totalDistance > triggerDistance) {
char distanceTotalMsg[10];
itoa(totalDistance / 1000, distanceTotalMsg, 10);
sprintf(sms_msg, "Empty catchtank! Current distance: %skm", distanceTotalMsg);
textMessage = ""; number = DEFAULT_NUMBER; totalDistance = 0;
sendSMS(sms_msg);
}
updateSerial(); // traitement SMS entrants
}
// Fonctions : updateSerial(), SIM900power(), updateSIM900(), extractSenderNumber(),
// sendSMS(), connectGPRS(), postDataThinger(), initializeSD(), updateTime()
// ... (code complet dans le fichier .ino)
Pièces imprimées 3D et fichiers
- Partie haute (plus haute / compacte) – trous de fixation à percer
- Partie basse – découpes connecteurs
- Clips verrouillage SIM900
- Fichiers
dist.txtetsettings.txtà placer sur la carte SD
Schéma de câblage
Schéma complet de connexion (image fournie).
Processus de fabrication
- Fabrication des planches à repasser : conception, matériaux et processus de production
- Construction et design des planches de surf : des racines polynésiennes à l'innovation moderne
- Suivi d'actifs GPS extérieur : tendances, défis et technologies émergentes
- Raspberry Pi dévoile le MCU RP2040 et la carte Pico à 4 $
- Intégration de données de capteurs sur Raspberry Pi : Guide pratique complet
- Maîtriser la Carte PSoC 6 Pioneer avec le Shield IoT Add-On : Guide du Développeur
- Maîtriser la fonction Python map() : syntaxe, exemples et bonnes pratiques
- Exploiter les systèmes d'intégration internes pour la fabrication de précision
- Les dangers de rouler avec un niveau de liquide de refroidissement bas