Domotique - Température: Thermostat on the www, Google Calendar est mon ami

Suite à la mise en oeuvre du DS18B20, je m'étais fait une petite page web (en complément de celle présentant les courbes) permettant de régler la température désirée, ainsi que le capteur sur lequel étaient réalisés les contrôles.
Le côté pratique de cette page est vite apparu: il était possible de modifier la température de n'importe où dans le monde, que ce soit à la maison ou ailleurs, du moment qu'un accès web était présent.

D'un autre côté, il n'était pas possible de programmer la température désirée sur le long terme, et transformer ladite page web pour en faire un point d'entrée de thermostat d'ambiance me freinait à plusieurs niveaux:

  • faire une IHM au format html (ou autre) permettant de facilement programmer plusieurs plages de températures sur plusieurs jours (et sans se limiter, comme sur certains thermostats, à 2 niveau de chauffe possibles et des plages découpées à la demi-heure) est mission impossible ou presque (et je n'ai pas que ça à faire)
  • il fallait ensuite envoyer l'info à mon serveur à la maison pour que ça finisse d'une manière ou d'une autre dans mon Arduino
  • il fallait enfin modifier le sketch de l'Arduino afin que lui aussi gère toutes ces données, et cette mission me paraissait aussi plaisante que celle du premier point
J'ai donc cherché sur le web des solutions clés en main, sachant que l'aspect graphique devait être pré-maché au maximum: j'ai réalisé cette installation pour l'aspect Arduino, pas pour passer des heures à faire des pages web.
Je suis donc rapidement tombé sur le seul candidat potentiel: le calendrier de Google, d'autant que j'ai vite vu que Python est l'ami de Google, et que des librairies de mise en oeuvre sont existantes.
Google Calendar permet de s'affranchir de tout l'aspect graphique, est utilisable partout car il n'y a pas de client à installer, et marche même dans l'univers Android. On peut donc même faire chauffer la maison quand on est dans le train, histoire qu'il fasse bon quand on arrive à la maison !

Pré-requis
Pour pouvoir mettre en oeuvre cette interface entre Google Calendar et Arduino, il faut:

  • Un accès Gmail
  • L'id du calendrier
  • un PC faisant l'interface entre Arduino et le www, hébergeant un script python qui va récupérer les données dans Google Calendat
Accéder à Google Calendar
Sous Google Calendar, afin de ne pas trop polluer mon planning utilisé pour la vie courante, j'ai créé un nouvel agenda en cliquant sur la liste déroulante située à coté de Mes agendas

Il faut ensuite récupérer l'ID de cet agenda, il nous sera utile pour y accéder depuis le code Python.
Cliquer sur la liste déroulante située à côté de l'agenda créé (Thermostat dans mon cas), puis sur Propriétés
L'ID de l'agenda est visible au niveau de l'URL.
Attention à ne pas récupérer l'adresse dispo au niveau de la zone d'insertion du planning: ça risque de ne pas fonctionner


Thermostat d'ambiance
L'avantage indéniable de l'utilisation d'un agenda est de pouvoir définir des plages de chauffe précises, répétables facilement, et dans lesquelles il est possible de définir une température précise.
Mon choix s'est porté sur la synthaxe suivante:
Th_nom-sonde:température-désirée

En complément, j'ai défini une synthaxe simplifiée:
Th_nom-sonde, ou même Th_
Dans ce cas, la température appliquée est une température définie en configuration (par l'intermédiaire d'une page web).

Afin de ne pas avoir à tapisser tout le planning de plaquettes, une absence de plaquette entraîne l'application  automatique d'une autre température de consigne, telle que la température hors gel qu'on trouve sur les thermostats habituels


Il est donc toujours possible d'utiliser le thermostat à minima:
  • pas de plaquette = température hors gel
  • plaquette sans consigne = température de consigne

Google Calendar est interrogé toutes les 5mn. Par l'intermédiaire d'une séquence spécifique, il est possible de forcer une interrogation immédiate de l'agenda


Paramètres par défaut
En complément des 2 températures une valeur de delta (écart de température à atteindre pendant le cycle de chauffe avant l'arrêt du chauffage) est définie, ainsi qu'un capteur de température.
Ces paramètres sont modifiables par l'intermédiaire d'une page web sécurisée, et récupérés toutes les 10mn par le script Python.
Par l'intermédiaire d'une séquence spécifique, il est possible de forcer une prise en compte immédiate de ces valeurs

Zoom sur les échanges de données
Ci-dessous, un résumé (un peu succinct) des échanges entre les modules principaux: web, PC, Arduino:

Récupérer les données de Google Calendar
Le code Python permettant de récupérer les données de Calendar est simple. Il récupère la liste des évènements de la journée, puis contrôle si des évènements sont actifs au temps courant.
Si un évènement est actif, le titre de la tâche est récupéré puis traitée pour être transmise à l'Arduino

Connexion à Google Calendar sur la plage désirée (la journée courante):

import gdata.calendar.service
import gdata.calendar
import datetime

cal_client = gdata.calendar.service.CalendarService()
cal_client.email = "VOTRE_LOGIN"
cal_client.password = "VOTRE_PASSWORD"
cal_client.source = 'Google-Calendar_Python_Sample-1.0'
cal_client.ProgrammaticLogin()

query = gdata.calendar.service.CalendarEventQuery('ID_CALENDAR@group.calendar.google.com', 'private', 'full')
auj=str(datetime.date.today())
query.start_min = auj
dem=str(datetime.date.today()+datetime.timedelta(1))
query.start_max = dem
feed = cal_client.CalendarQuery(query)

Contrôle des heures début/fin des consignes:

for event in feed.entry:
    for a_when in event.when:
        str_date_deb=a_when.start_time
        # Passage du format str au format datetime, pour pouvoir contrôler ensuite les heures de début/fin avec l'heure courante:
        date_deb = datetime.datetime(int(str_date_deb[0:4]) , int(str_date_deb[5:7]), int(str_date_deb[8:10]), int(str_date_deb[11:13]), int(str_date_deb[14:16]), int(str_date_deb[17:19]), int(str_date_deb[20:22]))
        str_date_deb=a_when.end_time
        date_fin = datetime.datetime(int(str_date_deb[0:4]) , int(str_date_deb[5:7]), int(str_date_deb[8:10]), int(str_date_deb[11:13]), int(str_date_deb[14:16]), int(str_date_deb[17:19]), int(str_date_deb[20:22]))
   
        if ((date_deb<=datetime.datetime.now()) and (date_fin>=datetime.datetime.now())):
              print "Cons.:",event.title.text  
              print "Debut:",date_deb
              print "Fin:",date_fin

Voilà !
Vous avez normalement tous les outils vous permettant de lire le contenu de Google Calendar. Google permet aussi bien d'autres actions, comme créer de nouvelles entrées par exemple.



PS: Merci à Code 18 pour cette modif permettant d'insérer du code proprement dans blogspot !

Domotique - Température: Le traitement des trames côté PC

Le traitement des trames côté PC est effectué à l'aide d'un script écrit en Python.
Le script lit les trames sur le port série et les enregistre toutes les 5mn dans un fichier (ce qui donne une précision correcte). Toutes les 10mn, le script envoie le contenu du fichier au serveur web.


Lors de la lecture d'une trame sur le port série, le script Python ajoute une info de datage car l'Arduino ne le permet pas (à moins de l'équiper d'un DTC1307).


Accessoirement, le script fait, toutes les 24 heures, le ménage dans le fichier émis pour ne pas que celui-ci grossisse de trop.
Les données supprimées du fichier sont sauvegardées dans un fichier d'historique, avec une précision de 2 heures.
Ce fichier est lui aussi envoyé vers le serveur pour un affichage ultérieur.

Explications du script, dans les grandes lignes:

Déclaration du port série et lecture du port:
Nota: La lecture du port série nécessite d'installer la librairie pyserial.
import serial
ser = serial.Serial('COM4',9600) # Le num de port est à récupérer sous Windows. La vitesse doit être cohérente de celle configurée sur l'Arduino
line = ser.readline() # Lecture d'une trame sur le port série

Connexion à un serveur ftp et envoi de fichier:
connect = ftp.FTP(host,user,password) # on se connecte au serveur ftp

                                                            # host: adresse du serveur FTP
                                                            # user: votre identifiant
                                                            # password: votre mot de passe

a = open('TempsData.txt', 'rb') # On ouvre le fichier à envoyer en binaire
connect.storbinary('STOR TempsData.txt',a) # On envoie le fichier de données
a.close()


Le script Python est téléchargeable ici.

A bientôt pour la partie PHP (mais ça ne va pas être pour tout de suite, il faut que je fasse un peu de ménage dans le script)

Domotique - Température: Le résultat en courbes

Avant de mettre le sketch et les scripts Python et PHP en ligne, je vous invite à visualiser les courbes de températures comme si vous y étiez !
Ce sont les vraies, issues des capteurs !

Pour info, j'habite Vauréal. Vous pourrez donc à partir d'aujourd'hui connaitre la température extérieure ;)

Le tout est visible ici

Il reste quelques affinages à faire sur le dessin des courbes, notamment l'historique complet, et l'échelle verticale lorsque la sonde extérieure n'est pas sélectionnée.

Domotique - Température: Trame Arduino et sketch

Désirant pouvoir mettre en oeuvre un système permettant de rajouter / d'enlever des capteurs de température en ayant un minimum de mises à jours à effectuer, il était nécessaire de définir une trame d'envoi de données permettant de contrôler certains paramètres, tels que la présence d'une sonde par exemple.

La trame émise par l'Arduino a donc la forme suivante:
nb_capteurs;ref_capt1;Temp_capt1;ref_capt2;Temp_capt2;ref_capt3;Temp_capt3.....
En cas de retrait du capteur 2 par exemple, on se retrouve avec une trame du genre:
nb_capteurs;ref_capt1;Temp_capt1;ref_capt3;Temp_capt3.....

Les modules placés en aval seront donc aptes à connaître le nombre de capteurs branchés, et surtout d'associer les données de température aux bons capteurs.

Il est donc nécessaire de connaître le nombre de capteurs branchés à l'Arduino avant même d'envoyer des données sur le port série. En One-wire il n'y a pas, à ma connaissance, de moyen d'interroger la ligne afin d'avoir un retour du nombre de modules qui y seraient branchés.
Dans la pratique, le sketch Arduino effectue un reset de la ligne One-wire, puis interroge séquentiellement tous les capteurs de la ligne.
Lorsqu'aucun capteur ne répond plus, toute la chaîne a été parcourue, il faut refaire un reset pour réinitialiser la séquence de récupération de données. C'est donc lorsque toute la chaîne est parcourue que l'on connait le nombre de capteurs.

Il faut donc, à l'issue de la récupération de toutes les valeurs, envoyer le tout sur le port série.
Pour faciliter le stockage, j'ai choisi de travailler avec des chaines au format String, largement plus pratique que les tableaux de chaînes. Les classes String, non documentées dans le référentiel Arduino français le sont par contre dans la version anglaise de l'aide officielle

Génération de la trame:
Séquentiellement, les données vont être récupérées comme suit:

La trame finale:

3;4e87;19.9;c172;20.0;4574;18.5;
3;4e87;19.9;c172;20.1;4574;18.3;
3;4e87;19.9;c172;20.0;4574;18.1;

Les valeurs des 3 capteurs, référencés 4e87, C172, 4574 sont récupérées et envoyées sur la trame.
Ces références sont directement issues des ref 64 bits des composants.


Le sketch
Comme je l'ai déjà indiqué, ce sketch est tiré directement de l'excellent exemple de mise en oeuvre du DS18B20 sur le site mon-club-elec.fr, ici-même.
Les principales modifications concernent:
- la possibilité de mettre en oeuvre plusieurs capteurs
- la génération de la trame à l'issue de la lecture de tous les capteurs

Le sketch est disponible ici

Domotique - Température: Les modules de traitement

N'ayant pas de shield éthernet sous la main, j'ai attaqué ce projet en traitant les données par l'intermédiaire d'un PC.

Dans la pratique, la platine Arduino récupère les infos des capteurs de température, génère une trame avec toutes les données, et diffuse cette trame sur la liaison série.
Le PC récupère cette trame, et l'enregistre périodiquement dans un fichier de log.
Cycliquement, le fichier de log est envoyé sur le serveur Web.

La page web est générée sur le serveur web, au moyen d'un script PHP.


Côté PC, le traitement est effectué en Python.

Alternatives possibles:
La première d'entre elle est bien sûr de mettre en place un shield éthernet pour pouvoir se passer d'un PC.

Une autre alternative possible (si on reste dans le cas de l'utilisation d'un PC) est de se passer d'un serveur web. Il suffit de sauvegarder les données sur un service éthernet permettant de partager des fichiers, tel que Dropbox.com. Le service Dropbox s'utilise comme un répertoire local. Il suffit d'y sauvegarder un fichier pour le retrouver quelques secondes plus tard (pour des tailles de fichier raisonnables) sur tous les autres PC connectés au même compte Dropbox.

Domotique - Température: cahier des charges

Voici, dans les grandes lignes, ce à quoi doit répondre mon installation ... A noter que cette liste peut évoluer à tout instant en fonction des mes envies !

- Contrôler la température dans plusieurs pièces de la maison et en extérieur.
- Etre en mesure de pouvoir rajouter/retirer des capteurs sans à avoir à tout reprendre au niveau de la programmation, ni sans avoir à tout redémarrer
- Pouvoir visualiser la température à l'instant courant, mais aussi les variations sur les x dernières heures, x pouvant être modifié
- Pouvoir effectuer cette visualisation depuis n'importe quel ordinateur connecté à internet


Je pense pouvoir dire que ces critères sont remplis, même s'il reste des choses à faire au niveau de la gestion de l'affichage.

Avant d'aborder les aspects logiciels et matériels, voici un petit aperçu de relevés sur 3 capteurs ...

Domotique - Température: le DS18B20

Dans le cadre d'un de mes projets, je recherchais un moyen de mesurer une température, sans avoir à me prendre la tête à faire des montages complexes pour étalonner le capteur, convertir les mesures en numérique et j'en passe.

Je suis rapidement tombé sur un capteur répondant à mes critères: le DS1820.
Ce capteur a même 2 autres atouts, qui m'ont amené à initier mon projet de domotique:
- sa techno one-wire, qui, comme son nom ne l'indique pas, permet de mettre en oeuvre ce composant avec 2 fils seulement, et surtout permet d'utiliser plusieurs capteurs sur ces 2 mêmes fils !
- sa résolution. J'ai jeté mon dévolu sur le DS18B20 qui a une résolution de 0.0625°. Je me dis qu'avec une telle précision, il doit être fiable ;) A noter qu'il existe le DS18S20, qui a une résolution plus faible

Autre atout, et de taille: le web regorge d'exemples de mise en oeuvre avec l'Arduino. Je n'ai donc pas réinventé la poudre et je me suis largement inspiré de ce qui est très bien présenté sur le site mon-club-elec

J'ai cependant retouché le sketch car il ne répondait pas vraiment à mon cahier des charges, à savoir:
- permettre de relier plusieurs capteurs de température: dans sa version d'origine, et malgré ce que j'ai cru comprendre dans les explications, le sketch ne permet d'interroger qu'un seul capteur
- ne pas limiter l'installation domotique à un nombre de capteurs fixe, ce qui nécessiterait des retouches trop complexes en cas de modifications (ajout/retrait) de capteurs. Le sketch modifié envoie, en plus des valeurs mesurées, les ref des capteurs ainsi que le nombre de capteurs détectés

/Flash: Après le proto ...

Après pas mal de km parcourus, et surtout avant les km à parcourir pour les vacances, il était temps de passer sur un avertisseur un peu plus facile à intégrer dans la voiture, en passant sur un modèle avec un ATMega 328 en stand alone.
Toutes les fonctions logicielles développées sur le proto sont présentes, par contre les sketchs en V0.x ne sont pas compatibles.

Le schéma

Le PCB est composé de 2 cartes: une partie dans le compartiment moteur, une seconde (encadrement orange) dans l'habitacle. La carte SD, le bouton poussoir permettant l'enregistrement de nouveaux radar, le buzzer (avec un inter permettant de le faire taire au cas où), restent à portée de main et d'oreille ...

Le sketch vient prochainement, le temps de faire un peu de ménage dedans ...

GrandRoue: Ca se termine !

Edit du 22/06: Ajout d'un mode d'emploi un peu plus graphique ...

Mon horloge a fonctionné pendant quelques jours, et quelques mises à jour se sont faites sentir pour diversifier les modes d'affichage possibles ...

Modes d'affichage:
Il y a désormais 4 modes d'affichages possibles, et chacun de ces mode peut être associé à un des 3 niveaux de luminosité pré-définis: en obscurité totale, en luminosité maximale, et en luminosité normale.

Les 4 modes d'affichage sont:

  • Minimal:
    • Heures sur 2 LED
    • Minutes sur 1 LED
    • Pas de secondes
  • sans trotteuse:
    • Heures sur 3 LED
    • Minutes sur 2 LED
    • Pas de secondes
  • Normal:
    • Heures sur 3 LED
    • Minutes sur 2 LED
    • Secondes sur 1 LED
  • Video inverse:
    • L'affichage des LED est inversé par rapport au mode normal: les aiguilles sont représentées par des LED éteintes, le reste de la roue étant allumé
Ces modes permettent d'adapter l'affichage à la luminosité ambiante: en complément de l'intensité d'éclairement des LED qui était déjà implémenté, la vidéo inverse permet par exemple d'avoir un max de luminosité tandis que l'affichage minimal permet d'alléger au max cet affichage tout en permettant de connaitre l'heure (idéal dans une chambre par exemple).

Des photos arriveront bientôt pour illustrer tout ça, mais prendre des LED en photo n'est pas facile, surtout quand il ne fait pas très jour ...

Sauvegarde des paramètres:
Les mode d'affichage sont configurables sans reprogrammation, avec les interrupteurs. Les valeurs sont sauvegardées automatiquement, ce qui permet de les conserver en cas de coupure (et de les réappliquer au démarrage suivant)

Réglages:
  1. Appui de 5 secondes sur le bouton Enter
    • les minutes et secondes s'effacent pour permettre le réglage des heures (par appui sur '+' & '-')
  2. Appui sur le bouton Enter
    • Les heures sont enregistrées
    • Les heures sont effacées, les minutes sont affichées pour permettre leur réglage
  3. Appui sur le bouton Enter
    • Les minutes sont enregistrées
    • Les secondes sont passées à 0
    • Les 3 LED du haut (59, 0, 1 minute) s'allume pendant 5 secondes:
      • Si pas de nouvelle action pendant ces 5 secondes: fin des réglages
      • Si appui: Les réglages continuent pour affecter les modes d'affichages:
  4. Appui sur le bouton Enter en moins de 5 secondes:
    • La LED 0 s'allume pendant quelques secondes: réglage du mode de luminosité normal
    • puis 4 groupes de 3 LED s'allument:
      • bas gauche=mode mini
      • haut gauche=mode sans trotteuse
      • haut droit=mode normal
      • bas droit=vidéo inverse
    • Le mode sélectionné est représenté par l'extinction de la LED du centre dans un des groupes. Le changement de mode se fait par les boutons '+' & '-'
  5. Appui sur le bouton Enter
    • La LED 15 s'allume pendant quelques secondes:réglage du mode de luminosité max
      • Même procédure que précédemment
  6. Appui sur le bouton Enter
    • La LED 15 s'allume pendant quelques secondes:réglage du mode de luminosité max
      1. Même procédure que précédemment
  7. Appui sur le bouton Enter: Fin des réglages

Comme un dessin vaut mieux qu'un long discours, voici un mode d'emploi un peu plus graphique, téléchargeable ici ...

GrandRoue: Le sketch

Dernière version disponible: Version 03, intégrant les dernières fonctionnalités en terme de gestion de l'affichage


Merci tout de même de citer vos sources en cas d'exploitation ...

MAX7219: Piloter des LED ...

Le MAX7219 permet de contrôler des matrices de LED, mais aussi des afficheurs 7 segments, bargraphs...

Je ne traiterai que le cas que j'ai moi-même mis en oeuvre dans mon horloge: le driver de LED.


Son utilisation est assez simple: une librairie MATRIX existe pour en faciliter l'usage.

Cette librairie se résume (vue de l'extérieur) à une ligne de déclaration et 3 commandes:

  • Déclaration:
    • Matrix led_clock = Matrix(DIN, CLK, LOAD, nb_MAX);
      Les variables DIN, CLK, LOAD correpondent aux  num de pins Arduino reliées à ces signaux
      La variable nb_MAX correspond au nombre de MAX7219 mis en cascade. Jusqu'à 8 chips peuvent être mis en cascade
  • Commandes:
    • led_clock.setBrightness(taux);Permet de régler la luminosité, de 0 à 15. Le réglage se fait malheureusement pour toutes les LED de façon globale
    • led_clock.clear();
      Eteint toutes les LED
    • led_clock.write(col,rang,valeur);
      Affecte la valeur LOW ou HIGH à la LED située aux coordonnées x,y

Matrice de LED:
Brochage MAX7219:
Din, Load, Clock sont à relier à l'Arduino
Dout n'est utilisé qu'en cas d'utilisation en cascade de plusieurs MAX7219
Iset doit être relié au +5v par l'intermédiaire d'une résistance.

La valeur de cette résistance est à choisir avec précaution car le driver peut surchauffer en cas de mauvais dimensionnement. Un tableau de dimensionnement est disponible dans la datasheet, page 11. Voici son extract:

La datasheet indique d'autre part le positionnement d'une capa de 0.1µF entre la pin 19 et la masse

Sketch:
La mise en oeuvre du MAX7219 est on ne peut plus simple avec ces 4 instructions.
Tout se jouera sur l'imagination du développeur pour faire des animations recherchées.

Il suffit d'allumer/éteindre la LED visée. L'adressage se fait LED à LED (pas de traitement de groupe avec cette librairie)

GrandRoue: Horloge murale

Je vous présente ma dernière "création": une horloge murale (qui essaie d'être) design: GrandRoue

Elle est basée sur:
  • un Arduino (bien-sûr !) , pour le moment c'est un Duemilanove mais ce sera une version Standalone dans la version finale de cette horloge
  • un DS1307 RTC, pour lequel j'avais déjà fait une première approche dans ce billet
  • un MAX7219, driver de LED, permettant de piloter jusqu'à 64 LED. Ca tombre bien: j'en ai 60 dans mon horloge ... sa mise en oeuvre est décrite ici
Les 60 LED sont dispatchées sur le pourtour de la "roue", et représentent chacune un 60ième d'heure.
Pour distinguer l'aiguille de l'heure des minutes et secondes, j'ai choisi le concept suivant:
  • l'aiguille des heures est représentée par 3 LED allumées
  • l'aiguille des minutes par 2 LED allumées
  • l'aiguille des secondes par 1 LED

Fonctionnalités offertes:
Et bien elle donne l'heure !
Ni plus (pour le moment) ni moins ...
Il est bien-sûr possible de régler cette heure, et l'heure courante est conservée en cas de coupure de courant par la pile du module DS1307

Ajout en Version 02: la luminosité des aiguilles est ajustée en fonction de la luminosité ambiante.
Je pensais aussi rajouter une fonction minuterie (pour cuire les oeufs ;) ), voire une fonction réveil, mais je ne sais pas si je vais m'y pencher ...
Je rajouterai aussi certainement des petits effets lumineux qui tourneront toutes les heures, histoire de rendre le tout vraiment original

La GrandRoue en photos, et vidéo:
Pas facile de prendre des photos quand il fait sombre ...



Cette version est juste un test pour voir ce que pouvait donner une horloge avec ce design: elle fait 50cm, les LED sont "plantées" par l'arrière, dans de l'Isorel. Elles sont soudées sur de petites platines d'essais.
Dans la version finale, les LED seront sur des PCB par groupe de 8, et une plaque de plexi opaque couvrira les LED pour mieux diffuser la lumière (les plaques de plexi sont vendues en 50cm de côté, d'où la taille retenue ...)

Explications techniques:
Le sketch peut être décomposé en 2 grandes fonctions:
  • La gestion du DS1307, comprenant la récupération de l'heure courante, le réglage, l'enregistrement d'une nouvelle heure. Le tout est déjà expliqué ici
  • L'affichage de l'heure sur le cercle de LED. Cette fonction est gérée par le MAX7219.
Le MAX7219 gérant les LED sous forme de matrice de 8x8 éléments, j'ai numéroté mes LED comme suit:


C 1  2  3  4  5  6  7  8
R -----------------------
1 0  1  2  3  4  5  6  7
2 8  9  10 11 12 13 14 15
3 16 17 18 19 20 21 22 23
4 24 25 26 27 28 29 30 31
5 32 33 34 35 36 37 38 39
6 40 41 42 43 44 45 46 47
7 48 49 50 51 52 53 54 55
8 56 57 58 59

Il y a donc dans le sketch une petite moulinette permettant de passer d'un adressage matriciel à un adressage linéraire ...

Lire / Ecrire sur une carte SD (et plus si affinité)

Soyons clair: je ne suis pas un pro de l'interfaçage Arduino - carte SD. Je l'ai mis en oeuvre dans le cadre de mon avertisseur radar /Flash pour y lire la liste des radar, et y stocker des données, par exemple des positions de nouveaux radar.
Ce qui suit est le résultat de mes recherches et mes essais.

Les librairies disponibles pour interfacer Arduino et les cartes SD

- La librairie SD, intégrée à l'IDE Arduino depuis la version 0.22.
- La librairie sdfat créée par William Greiman, d'où est tirée la librairie SD.

Principaux points communs entre ces 2 librairies
- Les 2 librairies gèrent les noms de fichier au format 8.3 (et seulement ceux-ci) et gèrent les FAT 16 et 32
- Les 2 librairies permettent (bien-sûr !) la création, lecture, écriture, suppression de fichiers

Principales différences entre ces 2 librairies
- La librairie SD est fournie dans le package de l'IDE (depuis la version 0.22). Il faut par contre installer la librairie sdfat (dispo sur ce site)
- La librairie SD ne lit que les fichiers situés à la racine de la SD. sdfat supporte la gestion des répertoires (que ce soit en lecture, création, suppression)
- sdfat permet bien d'autres opérations, telles que l'écriture en mode raw (permettant des accès plus rapides), et d'autres fonctions poussées, comme la gestion de la carte SD (comme l'analyse de la carte)

Mise en oeuvre des bibliothèques

Initialisation de la carte
  • Lib SD:
#include <SD.h>
  • Lib sdfat:
#include <SdFat.h>
#include <SdFatUtil.h> // l'utilité de cet include reste à vérifier dans le cas d'une utilisation limitée à l'écriture/lecture de données sur la carte SD

Contrôle de l'accès à la carte
  • Lib SD:
if (!SD.begin(4)) {
    Serial.println("Erreur à l'init!");
    return;
}
Serial.println("init Ok.");
  • Lib sdfat:
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

if (!card.init(SPI_HALF_SPEED)) 
{
 Serial.println("Erreur à l'init de carte");
}
// initialize a FAT volume
if (!volume.init(&card)) 
{
 Serial.println("Erreur à l'init du volume");
}
// Ouverture du volume
if (!root.openRoot(&volume)) 
{
 Serial.println("Erreur à l'ouverture du volume");
}


Ouverture d'un fichier et écriture de données

  • Lib SD:
File theFile;
theFile = SD.open("fichier.txt", FILE_WRITE); // ouverture de fichier.txt en écriture

if (theFile) {
    Serial.print("Ecriture de données sur la premiere ligne");
    theFile.println(", fin de la ligne et passage a la ligne suivante");
 // Fermeture du fichier:
    theFile.close();
    Serial.println("C'est écrit !");
  } else {
    // impossible d'ouvrir/créer le fichier:
    Serial.println("Erreur d'ouverture de fichier.txt");
}

  • Lib sdfat:
// ce qui suit est tiré du sketch de l'avertisseur radar /Flash disponible en téléchargement sur ce blog

void writeCRLF(SdFile& f) {
  f.write((uint8_t*)"\r\n", 2);
}

void writeNumber(SdFile& f, uint32_t n) {
  uint8_t buf[10];
  uint8_t i = 0;
  do {
    i++;
    buf[sizeof(buf) - i] = n%10 + '0';
    n /= 10;
  } while (n);
  f.write(&buf[sizeof(buf) - i], i);
}

void writeString(SdFile& f, char *str) {
  uint8_t n;
  for (n = 0; str[n]; n++);
  f.write((uint8_t *)str, n);
}

// Fonction principale:

if (file.open(&root, "fichier.txt", O_CREAT | O_APPEND | O_WRITE)){
    // Crée le fichier s'il n'existe pas, sinon l'ouvre en mode Ajout, en lecture
    writeString(file, "Ecriture d'une chaine de caractères");
    writeNumber(file, millis()); // Ecriture d'un nombre
    writeCRLF(file); // Ecriture d'un retour chariot
}
else
{
    Serial.println("Ouverture impossible du fichier");
}

Ouverture d'un fichier et lecture des données

  • Lib SD:
theFile = SD.open("fichier.txt");
  if (theFile) {
    Serial.println("fichier.txt:");
    // lecture du fichier jusqu'à la fin:
    while (theFile.available()) {
    Serial.write(theFile.read());
  }
  // Fermeture du fichier:
  theFile.close();
} 
else {
  // Ouverture impossible:
  Serial.println("Ouverture impossible de fichier.txt");
}

  • Lib sdfat:
int16_t n;
  uint8_t buf[7];// ce chiffre n'a a priori pas d'importance. Il défini la longueur de la chaine lue à chaque itération
  while ((n = file.read(buf, sizeof(buf))) > 0) {
     for (uint8_t i = 0; i < n; i++) Serial.print(buf[i]);
  }

Voilà.
J'espère que ces quelques exemples vont vous aider à aborder le traitement de fichiers sur carte SD.
Les librairies sont aussi fournies avec des exemples, pour aller plus loin ... au risque de me répéter, la librairie sdfat propose d'autres fonctions expliquées dans ces exemples

Alimenter les réalisations: le LM317

Le LM317 est un régulateur ajustable avec les caractéristiques suivantes:


  • Tension de sortie de 1,2 V à 37 V
  • Tension d'entrée maxi de 40 V
  • Courant de sortie maxi de 1,5 A
Schéma:

La tension de sortie est définie selon la formule suivante:

Vs = 1,25 ( 1 + R2/R1)

La valeur du condensateur C1 est fixée à 100nF
La valeur recommandée de R1 est fixée à 240Ω

Brochage



Mise en oeuvre
Alimentation de l'Arduino

La plage d'alimentation recommandée pour l'Arduino se situe entre 7v et 12v (dixit arduino.cc).
J'ai donc visé à peu près au milieu, soit 9v.
Par exemple, une valeur de R1 à 240Ω et R2 à 1,5KΩ conviennent parfaitement car le LM317 délivre alors la tension désirée.


Alimentation 5v:
Des valeurs de R1 à 240Ω et R2 à 720Ω permettent une alimentation en 5v.

DS1307: Le temps qui passe ...

Depuis un bon moment nous recherchons, ma femme & moi, une horloge qui soit originale et design.

On ne peut pas dire que les différentes marques (ou no-marques) fassent franchement des efforts sur le design dans ce qu'on trouve dans les diverses enseignes, à quelques exceptions près, hors de prix - cela va de soi.

Pas grave: je vais la faire maison.

Je commence donc cette étude par le coeur de ce que sera ma future horloge: le DS1307 RTC.

Présentation du module

Le module DS1307 RTC (pour Real Time Clock) est une horloge en mesure de fournir secondes, minutes, heures, jour, mois & année avec prise en compte des années bisextiles  jusqu'en 2100, ce qui devrait me laisser le temps de finaliser cette horloge ;).
Une pile de sauvegarde peut être mise en place pour conserver les données en cas de coupure de l'alim extérieure.

Le DS1307 s'interface sur un bus I²C, à l'adresse 68.

Il y a donc 2 liaisons data, à relier aux broches 4 (sda) & 5 (scl) de l'Arduino et 2 liaisons pour l'alimentation en 5v du module.

Mise en oeuvre du module
Pour tester le DS1307, je suis parti de l'exemple dispo sur bildr.org.

J'ai écrit un petit sketch permettant d'afficher le temps qui passe sur le port série, avec possibilité de régler les heures et les minutes.
Ca fonctionne, le gros challenge ayant été la gestion des rebonds.

Attention aussi à ne pas faire la même erreur que moi, en plaçant un des inter sur la pin 1, qui est la sortie Tx !

Le montage
Voici la liste des entrées-sorties:

E/S num:
--------

Broche  Signal        Fonction  
|-0      Rx           
|-1      Tx              
|-2      inter          Interrupteur réglage
|-3      PWM/Inter      Interrupteur '+'
|-4      I2C            SDA DS1307
|-5      PWM/I2C        SCL DS1307
|-6      PWM           
|-7      Entree         Interrupteur '-'
|-8      Entree       
|-9      PWM          
|-10     PWM          
|-11     PWM           
|-12     Entree        
|-13     Entree        

Entrees analogiques:
--------------------
|-14    
|-15    
|-16    
|-17    
|-18    
|-19    
|-20    

Le sketch


Lecture des données en provenance du DS1307:

Wire.beginTransmission(DS1307_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
second = bcdToDec(Wire.receive());
minute = bcdToDec(Wire.receive());
hour = bcdToDec(Wire.receive() & 0b111111);
if (hour>12)
{
 hour=hour-12;
 meridian=true;
}
else
{
 meridian=false;
}

Je gère les heures supérieures à 12 car je ne travaillerai pas avec un affichage sur 24 heures.
La récupération est limitée aux heures, minutes, secondes car il n'y aura pas de gestion de la date.

Modification des données dans le DS1307:

Wire.beginTransmission(DS1307_ADDRESS);
Wire.send(0); 
Wire.send(decToBcd(second));
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour));
Wire.send(0);
Wire.endTransmission();
Là encore, seules les heures, minutes, secondes sont traitées

Réglage de l'heure:
while (digitalRead(inter_enter)==HIGH){
 if (digitalRead(inter_moins)==LOW){
  data=data-1;
  if (data>maximum){
   data=maximum;
  }
 }
 if (digitalRead(inter_plus)==LOW){
  data=data+1;
  if (data>maximum){
   data=0;
  }
 }
 if (type_data=="h"){
  hour=data;
 }
 else
 {
  minute=data;
 }
 print_serie();
 delay(900);
  
}

Tant que le bouton Enter n'est pas actionné, on checke l'état des boutons + et - pour modifier la donnée 'data'. En fonction de son type ('h' ou 'm'), on réinitialise la valeur si on dépasse le maximum autorisé (12 pour 'h', 60 pour 'm').
Le réglage des secondes n'est pas prévu: on réinitialise arbitrairement les secondes en fin de réglage.
A l'issue de chaque appui, on affiche l'heure modifie (fonction print-série)

Téléchargement du sketch complet:
Le sketch complet est téléchargeable ici. Comme les autres sketchs de ce blog, il est bien-sûr libre de modifications et de redistribution.

Conclusion
Ca marche, et tout le mérite en revient aux auteurs de bildr.org.
Je reviendrai bientôt pour une mise en oeuvre un peu plus aboutie de l'affichage (parce que sur la console de l'IDE Arduino, c'est quand même pas très bô ...), mais pour le moment, j'attends les composants ...

/Flash: Bilan après quelques 500km

Un bilan s'impose après plus de 500km en compagnie de la dernière release du proto de l'avertisseur radar.

Tout d'abord, je me suis rendu compte que la version 0.83 diffusée n'était pas la bonne ... la faute au fait que je bosse sur plusieurs ordi en parallèle.
Je comptais donc re-uploader le fichier, mais je pense apporter quelques modifs suite à mon petit voyage.

Au titre des évols envisagées:
- le remplacement des LED par un buzzer fait apparaître un pb invisible (et surtout inaudible !) avec les LED: lorsque des trames GPS arrivent sur le port COM, il arrive parfois que ça grésille dans le buzzer. Il faut que je regarde ça. Les premières investigations ne semblent pas mettre en cause des parasitages, mais plutôt des lourdeurs dans les traitements, qui font que le traitement des trames prend trop de temps, et "déborde" sur les temps d'émission des bips.

- Lorsqu'on roule sur des axes rapides urbains (périph, rocades), on se fiche un peu d'être prévenus des radars feu: il y a tout de même rarement des feux sur les axes à 110km/h. Un traitement particulier va être rajouté.

- en complément du point ci-dessus, je vais même peut-être purement ne pas prendre en compte les radar feux si la vitesse GPS est supérieure à un seuil (80km/h par exemple), et forcer des extracts en cas de franchissement du seuil. Un extract de radar de la BDD prend dans les 350m à 130km/h en province (bdd de 1790 radar), il y a donc peu de chance pour qu'un radar passe à la trappe, surtout sur des vitesses inférieures, mais ça m'est arrivé ...

- sur les zones super chargées (IDF surtout), il y a largement plus de 10 radar sur la zone d'extract. Hors actuellement je relance un extract en BDD seulement lorsque la position GPS arrive en limite du bord de zone. Il faut que je modifie le bord de zone afin qu'il soit ramené au 10 ieme radar le plus loin, et pas systématiquement à la valeur théorique.

Je pensais partir sur la version 1 de /Flash après ces quelques km, mais une nouvelle version du proto va voir le jour.

/Flash: les fichiers radar

Voici les fichiers radar:

Nouvelle version de la BDD Ile de France, datée du 27/05.


Liste des radar en Ile de France, daté du 27/05/2011

Liste des radar sur le reste de la France, daté du 04/05/2011

Cette liste est extraite d'une "souche" provenant de la liste des radar fournis par gpspassion.com (base de radar en version standard d'octobre 2010) et disponible ici
De cette base ont été supprimés tous les radar mobiles (il y en a 12000 !), puis quelques-uns ont été rajoutés, au gré de mes besoins.

Dans les 2 listes de radar utilisés dans mon avertisseur, seul le paramètre 'vitesse' est inutilisé aujourd'hui.
Une explication sur le contenu de ces fichiers a été faite dans un billet précédent

/Flash: Explications sur le code

Voici, dans les grandes lignes, l'approche que j'ai retenu pour réaliser mon avertisseur sonore ...

L'exploitation des radar en base de données se fait de la façon suivante:
1- On extrait un nombre de radar max (défini à 10 pour l'Arduino 2009, car l'Arduino plante au dessus. On doit s'approcher du max de consommation de RAM) les plus proches de la position actuelle GPS.

L'extract est limitée à une zone autour de la position actuelle, définie à 0.18° (soit environ 15km²)
et réduite à 0.08° (soit environ 7km²) sur l'Ile de France car il y a beaucoup de radar, ce qui provoque des temps de traitement trop long pour que l'avertisseur soit réactif.
Si la zone d'extract n'entraine pas un extract de 10 radar, on n'aggrandit pas la zone de recherche
(inutile de prévenir le conducteur s'il y a des radar à 50km).
Ce point est traité dans la fonction 'extract_liste_rdr

2- Lorsque la zone est extraite, l'avertisseur calcule en permanence la distance véhicule-radar la plus faible et prévient le conducteur si certaines conditions sont remplies:
- le véhicule se rapproche du radar
- le véhicule se dirige vers le radar, avec un cone d'approximation
- le véhicule est à une distance raisonnable du radar, distance dépendant du type de radar
- le véhicule n'est pas arrêté (histoire de ne pas être inondé de bip lorsque le feu est rouge ou dans les bouchons)
Ce point est traité dans la fonction 'calc_distance_rdr'


3- Lorsque le véhicule se rapproche du bord de la zone d'extraction, une nouvelle extraction est lancée.
Deux critères définissent le déclenchement de ce nouvel extract:
- la distance par rapport au bord de la zone, définie à 2,5km sur l'IDF
- l'écart mini entre la pos actuelle du véhicule et le radar, défini à 1,5km sur l'IDF

Si on passe sous la distance mini ET que l'écart avec le radar le plus proche est supérieur à l'écart min, on lance un nouveau calcul.
Le calcul est effectué dans la fonction 'calc_distance_bord_zone' et la décision est prise dans la fonction 'calc_distance_rdr'

La fonction 'recup_trame_gps' lit le port série pour récupérer la position GPS.
En cas de perte de trame ou de récupération erronée, la fonction attend 10 secondes avant de faire savoir qu'il y a un problème (en arrêtant de prévenir le conducteur de la proximité d'un éventuel radar).
A l'avenir, dans ce cas de figure, la position du véhicule sera rafraîchie par projection. Cela permettra de prévenir d'une éventuelle présence de radar dans un tunnel par exemple.

La fonction 'buzzer' permet de prévenir le conducteur en fonction du type et de la distance du radar

Enfin, les fonctions 'writeString' et 'writeNumber' permettent de logguer des infos sur la carte SD: axe des radar, et, pour contrôle, la liste des radar extraits dans la fonction 'extract_liste_rdrainsi que la position du véhicule lors de l'extraction.

GraarduiCut: Cherche moteurs déserpérément

Comme indiqué dans le premier billet consacré à GraarduiCut, les moteurs de propulsion ne sont pas du tout adaptés: rotation trop rapide, pas assez de couple.

J'ai surfé sur le web, à la recherche de moteurs dans le genre de ce qu'on trouve sur les quads des enfants.
Sur le quad de mon fils, il y a un moteur pas plus grand que ceux actuellement montés sur GraarduiCut, équipés d'un réducteur balèse ...
Résultat, ça traine mon fils de 2 ans et demi, et j'ai même surpris ma fille de 7 ans assise avec mon fils, et le quad arrivait à les trainer (pour combien de temps ?).

J'avais donc pour objectif de me trouver 2 ex de ce genre de moteur.

Je ne peux même pas trainer dans les déchèteries: il me faut 2 moteurs identiques, et les quads n'en ont qu'un :-(


Autre piste:
des moteurs ayant une vitesse de rotation lente, style moteurs de lève-vitre.
Je n'ai par contre aucune idée de la conso de ces moteurs. Les équipements électriques des voitures sont rarement économes en énergie, ça me fait donc un peu peur.


Si vous avez des idées, n'hésitez pas à m'en faire part ...

GraarduiCut:Quelques photos

Mon proto de robot tondeuse est à l'image de la taille de mon jardin: petit :-)

Voici quelques photos de GraarduiCut:

Une vue générale du robot
vue générale du robot GraarduiCut

Les moteurs de propulsion
Vue sur les moteurs de propulsion de GraarduiCut


Les lames
Vue sur les lames de GraarduiCut


La partie électronique avec le moteur de lame en arrière plan
Vue sur le coeur de GraarduiCut: l'Arduino


Quelques chiffres:
GraarduiCut fait 42cm de large, roues comprises
la lame fait 20cm

/Flash: Le code du sketch

Ci-joint le code de l'avertisseur de radar.

La version courante est la 0.83.
Elle reprend donc les principales fonctionnalités décrites dans les billets précédents, et notamment dans celui-ci.

Le code est téléchargeable ici:
Version 0.83

Robot tondeuse: Le concept "GraarduiCut"

GraarduiCut: Grass Arduino Cutter ;-)
L'idée est de concevoir une tondeuse robot autonome, low-cost.
Le coeur du robot est bien-sûr un Arduino (2009, mais un Uno ferait tout aussi bien l'affaire)

Je suis donc parti sur une plateforme toute simple en contre-plaqué, 2 roues motorisées à l'arrière, 2 roues folles à l'avant sur amortisseur, de simples contacts à l'avant, une lame de coupe.

Les moteurs de propulsion sont des moteurs RS-5404SH équipés de réducteurs (il faudrait que je calcule le rapport de réduction)
.
Le moteur de la lame est un moteur de petite perceuse.

Les moteurs sont pilotés par un pont en H intégré: le L298.


La tondeuse fonctionne, si ce n'est que les moteurs de propulsion ont un couple trop faible pour promener le robot lorsque la pelouse est haute (la hauteur étant toute relative). Je contourne le pb en affectant une valeur forte à mon PWM, ce qui fait que le robot trace comme un malade lorsque la pelouse est courte ... et se tape donc les obstacles à une vitesse vertigineuse.


La priorité est donc de mettre la main sur des moteurs avec un facteur de réduction important, et un couple plus adapté, et de changer l'étage de commande, car le pont en H est franchement trop juste ...

Idéalement, des moteurs utilisés dans les quads électriques des gamins seraient tout à fait adaptés: ils doivent avoir un couple tout de même assez important pour pouvoir trainer un mini biker de 20-30kg, et ne pas trop consommer: mon fils à un de ces quads avec un moteur en 6 volts, équipé d'une batterie pas très puissante, et à quand même une bonne autonomie.

Aujourd'hui, le robot se contente d'aller (à peu près) droit devant lui, de rebondir contre les obstacles, et de reprendre sa route.

Les évolutions attendues dès que j'aurai mis la main sur des moteurs:
- détecter la présence de la pelouse, afin d'éviter d'aller se balader sur la terrasse
- détecter le niveau de batterie pour couper le jus à temps dans un premier temps ...
- ... et retrouver sa base dans un second temps (mais là, va y avoir du boulot !)
- détecter une éventuelle averse, pour éviter de sortir quand le temps n'est pas adapté à une tonte
- détecter le niveau de luminosité, afin de programmer des sorties de nuit, quand les enfants sont couchés et ne risquent pas de se mettre les pieds et les doigts dans les lames ...

A bientôt donc pour la suite de l'aventure ...

Finalisation du proto ...

Après pas mal de km de tests, le proto de l'avertisseur de radar a encore bénéficié de quelques modifications.

Pêle-mêle:

  • C'est bien parti pour rester sur un avertisseur de radar à base de buzzer: les LED obligeaient de jeter un oeil permanent pour savoir s'il y avait un risque. Le buzzer prévient désormais de la manière suivante:
    1 bip: avertisseur de radar fixe
    2 bips: avertisseur de radar mobile
    3 bips: avertisseur de radar feu

    Il y a une petite inversion dans l'ordre des radar depuis mon dernier billet. La raison est purement pratique: dans la majorité des cas, j'ai affaire soit à des radar fixe, soit à des radar feux. Distinguer 3 bips d'1 seul est plus simple de que 2.
    J'ai par ailleurs franchement allégé la base de données concernant ces foutus radar mobiles, sinon l'avertisseur n'arrête pas de sonner. En plus, comme je ne fais pas franchement d'excès de vitesse, ça ne me sert pas à grand chose (d'autant que les radar mobiles sont plus tolérants en terme d'excès de vitesse ...)

  • L'avertisseur de radar émet un son sous certaines conditions:
    - il faut rouler (à plus de 7km/h)
    - il faut s'approcher du radar
    - il faut être dans l'axe du radar (à + ou - 10° près, ce qui pourrait bien être revu à la baisse si ça sonne de trop)
    - il faut être à moins de 500m d'un radar feu, et à moins de 1000m d'un radar fixe ou mobile

    Pb résiduel: un radar fixé situé sur une route parallèle à moins de 1000 mètres provoquera une alerte. Il faudrait rajouter un contrôle sur le relèvement

  • Pour améliorer les performances sur l'Ile de France (où il y a pas mal de radar), la base de données à été séparée en 2.

  • Pour permettre de mettre à jour les caps des radar sans trop se prendre la tête, tous les radar "croisés" sur la route sont sauvegardés dans un fichier, avec le cap GPS.
Voilà pour les dernières news ... bientôt le code !

/Flash: Affichage, changement de technique

Après quelques temps à faire des essais, il apparait que les LED, c'est pas le sommum: il faut avoir les yeux rivés au truc si on ne veut pas louper une info, et c'est d'autant plus marquant si les LED clignotent.

Je viens donc de faire une petite transfo: j'ai remplacé une des LED par un petit buzzer.
C'est plus facile à appréhender, et le type de radar est plus simple à identifier:

  • un bip: radar fixe
  • deux bips: radar feu
  • trois bips: radar mobile
La période entre 2 (groupes de) bips est directement liée à la distance entre le véhicule et le radar:
700m: 700ms, 1km: 1s

Je commence les essais et si ça convient, je nettoie un peu le code et le mets en ligne

/Flash: la base de données

Voici un extrait de la base de données des radar:

6.54937;48.96629;0;50;361;1213;XXX
1.74705;48.96686;0;110;361;2312;XX
2.09068;48.97220;0;90;361;13224;XX
2.23332;48.97715;0;110;361;10476;X

Dans l'ordre:
- longitude sur 7 digits, point compris
- latitude sur 8 digits, point compris
- type de radar sur 1 digit:
  • 0 pour un radar fixe
  • 1 pour un radar mobile
  • 2 pour un radar feu
- vitesse de contrôle sur 3 digit maxi
- cap de radar sur 3 digits maxi (1 cap à 361° indique que le cap du radar est inconnu)
- identifiant unique, sur 5 digits max
- complément de chaine, pour avoir des chaines de longueur constante de 36 caractères

Les données en rouge ne sont pas utilisées actuellement:
- J'ai dernièrement retiré le contrôle du respect de la vitesse car ça alourdissait l'affichage, en rajoutant des séquences de clignotement
- un petit bug empêche de déterminer avec exactitude les cohérences de cap entre le véhicule et le radar. J'espère trouver une solution. Cela permettrait d'affiner les avertissements.

/Flash: Schéma électrique

/Flash: Affichage

Mon choix de LED s'est porté sur des modèles diamètre 5mm, de couleurs rouge, orange, jaune.
En fonction de la distance restant à parcourir pour rejoindre le radar, la LED allumée change de couleur: jaune, puis orange, puis rouge.

Les paliers sont modifiés en fonction de la vitesse de déplacement. Les voici:

SeuilV<80km/hv>80km/h
S long1000m2000m
S moy500m1000m
S min250m5000m

En fonction du type de radar et de la distance, l'allumage des LED est le suivant:
Type radar              D<S min           D<S moy         D<S long

Fixe / mobile                                                   

Feu                                                                        

Un radar feu situé à plus de 500m ne sera pas détecté différemment d'un radar feu situé à 1000m. Ce n'est pas génant car ces radar sont en ville et une détection si éloignée est sans intérêt.


En complément, d'autres séquences sont prévues en fonction du statut de fonctionnement:

Erreur de lecture carte SD
Recherche des radars en BDD
Trame GPS invalide ou GPS hors portée

/Flash: modules logiciels

/Flash se base sur plusieurs librairies externes:
- TinyGPS pour la mise en oeuvre du GPS sur port série
- SDFATlib pour la mise en oeuvre du lecteur SD
- NewSoftSerial, permettant de définir plusieurs ports série (GPS, terminal pour debugger)

Le déroulement séquentiel s'approche de ceci:

Acquisition d'une trame valide
Véhicule dans zone géo ?
non         .
          oui
Calcul d'une nouvelle zone avec VHL au centre
Calcul/affichage distance radar le plus proche
Retour début

La seule contrainte imposée lors du calcul de la distance avec le radar le plus proche est la suivante: le radar le plus proche de la liste n'est pris en compte que si la distance diminue entre 2 calculs (véhicule se rapproche effectivement du radar)

/Flash: présentation ...

/Flash ... (lire flash barre)

Je viens partager ma première réalisation ayant une "utilité", dans le sens où c'est un produit, pas un embryon de truc roulant vers la lumière, ou vers l'obscurité, ou je ne sais quoi d'autre encore ...

/Flash est censé protéger de la lumière ... pas de celle du soleil: une bonne paire de lunettes appropriées devrait suffire, mais ce celle des flashs, qui bordent de plus en plus les côtés de nos chaussées, ou le pied de nos feux de circulation. /flash est un avertisseur de radar ...

J'habite dans le 95, qui est le département le plus peuplé en terme de radar feu. Je dois vous dire que c'est hallucinant: on en voit partout !

Ayant un vieux GPS série, je me suis dit qu'en le couplant avec un Arduino, un lecteur de carte SD et 2-3 LED, ça devrait donner quelque chose de potable.
C'est pas que je vais en avoir une utilité folle: je me déplace exclusivement en électrique, à 50km/h, en silence ... Je vous invite d'ailleurs à visiter LE forum de référence en terme de véhicule électrique.
Enfin, revenons-en à /Flash ...
Le but est donc de réaliser un avertisseur de radar grâce à un GPS embarqué, et de prévenir lorsque "la menace" s'approche.

Le matériel
  1. La base de données:
    La liste des radar est stockée sur carte SD. Cette liste est issue de celle mise à disposition gratuitement sur gpspassion. J'ai cependant supprimé beaucoup de radar mobiles pour l'alléger, puis je l'ai mis manuellement à jour, surtout sur les zones qui m'intéressent.
    Il en ressort une liste de radar fixes & feu (et quelques radar mobiles) avoisinant les 2000 !
  2. Le contrôleur:
    L'Arduino utilisé est un '2009'. Un Uno fonctionnerait tout autant. Un Mega serait largement plus approprié aux futures évolutions. Vu la quantité de données à traiter, j'ai été obligé de tailler dans les fonctions proposées, pour n'en garder que le minimum
  3. L'affichage:
    Réduit à son plus strict minimum: 3 LED 1 buzzer
L'approche logicielle
  • A partir des coordonnées actuelles du véhicule, effectuer une recherche sur une zone de proximité de tous les radar présents. La capacité en RAM de l'Arduino m'a vite imposée de limiter la liste des radar pris en considération en la limitant à 10.
  • Vérifier en permanence la distance entre le véhicule et chacun des 10 radar, et remonter une info en fonction de la distance et du type de radar: le comportement 'préventif' à adopter n'est pas le même entre un radar en bord de route et un radar feu: dans un cas il vaut mieux anticiper un changement de la couleur des feux, dans l'autre vérifier qu'on respecte la limitation de vitesse
  • Lorsque le véhicule qui la zone de recherche, relancer une nouvelle recherche par rapport à la position actuelle ...

Les évolutions possibles

Moyennant une évolution matérielle, soit en passant sur un Arduino Mega, soit en mettant 2 '2009' en parallèle, il serait intéressant:
  • de virer les LED buzzer au profit d'un LCD: les LED qui clignotent c'est joli, mais au bout d'un moment, on n'a plus vraiment la logique en tête: radar fixe, mobile, feu, en fonction de la distance, du respect de la vitesse ... ça fait beaucoup de combinaisons pour pas beaucoup de LED
  • de pouvoir rajouter des radar en live, au moyen d'un petit poussoir par exemple
  • d'affiner le calcul de l'approche véhicule-radar. Actuellement, le radar peut être en contresens, dans une rue perpendiculaire ... on est tout de même prévenu.

Formulaire de contact



Nom *



Email *



Votre blog / site web:



Sujet *



Message *




Image Verification

captcha

Saisissez le texte correspondant à celui de l'image ...:

[Changer de code] [C'est quoi ? (in english)]

Powered byEMF Form Builder
Report Abuse