/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 ...