Émission de données (RTC)/Réception et affichage des données : Différence entre versions

De Wiki L.A.B
Aller à : navigation, rechercher
 
(35 révisions intermédiaires par 2 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
 
Tout d'abord nous allons mettre en œuvre le breakout Tiny RTC et un afficheur LCD avec une liaison I2C, puis dans un second temps nous allons mettre en œuvre le bus CAN en deux arduinos Uno.le breakout Tiny RTC sera branché sur le premier arduino Uno, l'afficheur RTC sera branché sur un second arduino Uno qui pourra afficher les données émises par le RTC.
 
Tout d'abord nous allons mettre en œuvre le breakout Tiny RTC et un afficheur LCD avec une liaison I2C, puis dans un second temps nous allons mettre en œuvre le bus CAN en deux arduinos Uno.le breakout Tiny RTC sera branché sur le premier arduino Uno, l'afficheur RTC sera branché sur un second arduino Uno qui pourra afficher les données émises par le RTC.
  
[[Fichier:Canbus.jpg|vignette|droite]]
 
 
== Présentation et objectifs ==
 
== Présentation et objectifs ==
 +
 
Le but de ce tutoriel est de tester le fonctionnement de l’horloge RTC sur l’écran LCD à l’aide d’une carte Arduino UNO.  La manipulation permet de faire communiquer l’horloge avec l’écran LCD afin que ce dernier affiche l’heure et la date.
 
Le but de ce tutoriel est de tester le fonctionnement de l’horloge RTC sur l’écran LCD à l’aide d’une carte Arduino UNO.  La manipulation permet de faire communiquer l’horloge avec l’écran LCD afin que ce dernier affiche l’heure et la date.
 
Ce tutoriel nécessite une connaissance minimale de la plateforme Arduino. La page Formation Arduino du wiki contient toutes les ressources nécessaires pour découvrir la programmation avec Arduino.
 
Ce tutoriel nécessite une connaissance minimale de la plateforme Arduino. La page Formation Arduino du wiki contient toutes les ressources nécessaires pour découvrir la programmation avec Arduino.
  
Le premier montage que nous allons faire utilisera le connecteur à souder sur le shield :  
+
Le montage utilise donc :  
 +
*une carte Arduino UNO
 +
*une horloge RTC avec module i2c
 +
*un écran LCD avec module i2c
 +
*des fils de liaison
 +
*une breadboard
 +
*un câble d’alimentation USB
  
[[Fichier:Shield connecteur externe.png]]
+
[[Fichier:Arduino_RTC.PNG]]
  
L'utilisation de ce connecteur permet d'accéder directement aux signaux ''CAN_H'' et ''CAN_L'' sans passer par la prise ''DB-9''.
+
== Etape 1 : tester l’écran LCD avec la carte Arduino ==
  
Le montage final devrait ressembler à cela :
+
On souhaite réaliser un code pour afficher un texte sur notre écran LCD branché à notre carte Arduino UNO afin de tester l’écran.
  
[[Fichier:CAN_essai1.jpg|500px|Présentation du montage]]
+
[[Fichier:Arduino_LCD.PNG]]
  
== Pré-requis ==
+
On a donc besoin de 4 fils :
Ce tutoriel nécessite une connaissance minimale de la plateforme Arduino. La page [[:Catégorie:Formation_Arduino|Formation Arduino]] contient toutes les ressources nécessaires pour découvrir la programmation avec Arduino.
+
*GND LCD => GND Arduino
 +
*VCC LCD => 5V Arduino
 +
*SDA LCD => pin analogique A4 Arduino
 +
*SCL LCD => pin analogique A5 Arduino
  
La bibliothèque [https://github.com/Seeed-Studio/CAN_BUS_Shield ''CAN_BUS_Shield''] devra être ajouté à votre installation Arduino pour faire fonctionner les programmes ci-après.
+
Une fois le montage réalisé, sur le programme Arduino nous pouvons donc ajouter ce code:
  
=== Matériel ===
+
<syntaxhighlight lang="cpp" enclose="div">
Matériel nécessaire :
+
#include <Wire.h>
* 2 Arduino Uno
+
#include <LiquidCrystal_I2C.h> // pour télécharger la librairie: croquis - include library - manage libraries - LiquidCrystal_I2C.h de Frank de Brabander
* 2 [https://www.sparkfun.com/products/10039 shield CAN-BUS Sparkfun]
+
LiquidCrystal_I2C lcd(0x27,16,2); //écran LCD 0x27 avec 16 colonnes et 2 lignes (ligne 0 et ligne 1)
* 2 Résistances de 120 Ohms
+
* Straps ou fils de liaison
+
  
== Émission/Réception simple ==
+
void setup()
==== Etape 1 : Cablage ====
+
{
Pour cette étape, il suffit de brancher les shields sur les Arduinos et de relier les signaux ''CAN_H'', ''CAN_L'' et ''GND'' par des straps comme sur la photo suivante :
+
lcd.init(); //initialisation de l'écran LCD
 +
lcd.cursor_on();
 +
lcd.blink_on();
 +
lcd.backlight();
 +
lcd.setCursor(5,0); // écriture du texte sur la ligne 1 colonne 5 (centré)
 +
lcd.print("Hello!"); // texte "hello" sur ligne 1 colonne 5
 +
lcd.setCursor(7,1); // écriture du texte sur la ligne 2 colonne 7 (centré)
 +
lcd.print("ok"); // texte "ok" sur ligne 2 colonne 7
 +
delay(1000);
 +
lcd.cursor_off();
 +
lcd.blink_off();
 +
}
  
[[Fichier:CAN_essai1.jpg|500px|Présentation du montage]]
+
void loop()
 +
{
 +
}
  
Pour atteindre des vitesses de transmission supérieures à 40Kbit/s, il faut rajouter une résistance de 120 Ohms entre ''CAN_H'' et ''CAN_L''.
+
</syntaxhighlight>
 +
 
 +
Une fois la compilation et le téléversement du code réalisé vers la carte arduino, les textes s’affichent sur l’écran LCD. Pour notre exemple, on obtient :
 +
 
 +
[[Fichier:Arduino_LCD1.PNG]]
 +
 
 +
Le texte affiché sur l’écran peut être modifié et les effets également comme le défilement du texte par exemple. Ne pas hésiter à regarder les exemples proposés par la librairie LiquidCristal_I2C pour faire évoluer le code.
 +
Notre écran LCD avec un module i2c fonctionne donc correctement.
 +
Nous pouvons tester maintenant notre second appareil : l’horloge RTC avec module i2c.
 +
 
 +
== Etape 2 : tester l’horloge RTC avec la carte Arduino ==
 +
 
 +
On souhaite réaliser un code pour afficher l’heure et la date sur notre ordinateur à partir d’une horloge RTC avec module i2c branchée à notre carte Arduino UNO.
 +
Notre modèle de RTC est la DS1307.
 +
[[Fichier:ARDUINO_rtc1.PNG]]
 +
 
 +
On a donc besoin de 4 fils (mêmes branchements que pour l’afficheur LCD):
 +
*GND RTC => GND Arduino
 +
*VCC RTC => +5V Arduino
 +
*SDA RTC => pin analogique A4 Arduino
 +
*SCL RTC => pin analogique A5 Arduino
 +
 
 +
Une fois le montage réalisé, sur le programme Arduino nous pouvons donc ajouter ce code. Il faut aussi télécharger la librairie RTClib, disponible sur le github.
  
==== Etape 2 : Programmation de l'émetteur ====
 
Sur l'Arduino émetteur téléverser le programme ci-après. Ce programme va envoyer sans cesse un message standard contenant les données "0, 1, 2, 3, 4, 5, 6, 7" avec l'identifiant 0.
 
 
 
 
<syntaxhighlight lang="cpp" enclose="div">
 
<syntaxhighlight lang="cpp" enclose="div">
/*
+
//Heure et date en utilisant un RTC DS1307 connecté via un I2C
  Ce programme envoie un tableau de donnée sur le bus CAN
+
#include <Wire.h> //librairie déjà disponible sur Arduino
*/
+
#include <RTClib.h> //librairie à télécharger en ZIP sur https://github.com/jcw/rtclib
#include <mcp_can.h>
+
 
#include <SPI.h>
+
RTC_DS1307 RTC; //modèle de la clock(RTC)
const int SPI_CS_PIN = 10;
+
 
 +
void setup () {
 +
    Serial.begin(57600); //nombre de bauds: définir le même nombre sur le moniteur série (Ctrl - Maj - M)
 +
    Wire.begin();
 +
    RTC.begin();
 +
   
 +
 
 +
  RTC.adjust(DateTime(__DATE__, __TIME__)); //Ajuster l'heure et la date de la clock avec celles de l'ordinateur
 +
}
 +
 
 +
void loop () {
 +
    DateTime now = RTC.now();
 +
   
 +
    Serial.print(now.year(), DEC);
 +
    Serial.print('/');
 +
    Serial.print(now.month(), DEC);
 +
    Serial.print('/');
 +
    Serial.print(now.day(), DEC);
 +
    Serial.print(' ');
 +
    Serial.print(now.hour(), DEC);
 +
    Serial.print(':');
 +
    Serial.print(now.minute(), DEC);
 +
    Serial.print(':');
 +
    Serial.print(now.second(), DEC);
 +
    Serial.println();
 +
   
 +
    Serial.print(" since 2000 = ");
 +
    Serial.print(now.get());
 +
    Serial.print("s = ");
 +
    Serial.print(now.get() / 86400L);
 +
    Serial.println("d");
 +
 
 +
    DateTime future (now.get() + 7 * 86400L + 30); //Calculer et afficher une date/heure avec 7 jours et 30 secondes de plus que celles de l'ordinateur
 +
   
 +
    Serial.print(" now + 7d + 30s: ");
 +
    Serial.print(future.year(), DEC);
 +
    Serial.print('/');
 +
    Serial.print(future.month(), DEC);
 +
    Serial.print('/');
 +
    Serial.print(future.day(), DEC);
 +
    Serial.print(' ');
 +
    Serial.print(future.hour(), DEC);
 +
    Serial.print(':');
 +
    Serial.print(future.minute(), DEC);
 +
    Serial.print(':');
 +
    Serial.print(future.second(), DEC);
 +
    Serial.println();
 +
   
 +
    Serial.println();
 +
    delay(3000);
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
Une fois la compilation et le téléversement du code vers la carte arduino, on ouvre le moniteur série (Ctrl – Maj – M) et notre ordinateur affiche le résultat du code : soit l’heure et la date actuelle. Ne pas oublier de régler le nombre de bauds sur le moniteur série avec celui du code, ici 57600.
 +
 
 +
[[Fichier:Moniteur_série_arduino_rtc.PNG]]
 +
 
 +
Notre horloge RTC avec un module i2c fonctionne donc correctement.
 +
Nous pouvons tester maintenant l’ensemble : l’horloge RTC avec module i2c et l’écran LCD avec module i2c. L’ensemble branché en parallèle sur la carte Arduino UNO.
 +
 
 +
== Etape 3 : afficher l'heure et la date sur l'écran ==
 +
 
 +
On souhaite réaliser un code pour afficher l’heure et la date, à partir de l’horloge RTC, directement sur notre écran LCD.
 +
 
 +
[[Fichier:Montage_arduino_rtc_et_lcd.PNG]]
 +
 
 +
On a donc besoin de 12 fils et d’une bread board. Les 3 éléments (RTC, LCD et Arduino UNO) sont branchés en parallèle.
 +
 
 +
Une fois le montage réalisé, sur le programme Arduino nous pouvons donc ajouter le code ci-dessous. Les librairies sont les mêmes que celles téléchargées et ajoutées précédemment donc pas besoin de les inclure à nouveau.
 +
 
 +
<syntaxhighlight lang="cpp" enclose="div">
 +
#include <Wire.h> //librairie déjà sur arduino
 +
#include <LiquidCrystal_I2C.h> //pour télécharger la librairie: croquis - include library - manage libraries - LiquidCrystal_I2C.h de Frank de Brabander
 +
#include <RTClib.h> //librairie à télécharger en ZIP sur https://github.com/jcw/rtclib
 +
 +
#if defined(ARDUINO) && ARDUINO >= 100
 +
#define printByte(args)  write(args);
 +
#else
 +
#define printByte(args)  print(args,BYTE);
 +
#endif
 +
 +
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
 +
RTC_DS1307 RTC;
 +
LiquidCrystal_I2C lcd(0x27,16,2); // Adresse du LCD 0x27 avec 16 colonnes et 2 lignes
 +
 +
void setup()
 +
{
 +
  lcd.init();  // initialisation du LCD
 +
  lcd.backlight();
 +
  lcd.print("Initialising..."); //afficher un message sur l'afficheur LCD
 +
  lcd.createChar(2, clock);
 +
  Wire.begin();
 +
  RTC.begin();
 +
  RTC.adjust(DateTime(__DATE__, __TIME__)); //Ajuster la clock avec l'heure et la date de l'ordinateur
 +
}
 +
 +
void loop()
 +
{
 +
  lcd.clear(); //code pour afficher heure et date de la clock (du RTC) sur l'écran LCD
 +
  DateTime now = RTC.now();
 +
  lcd.printByte(2);
 +
  lcd.print(" ");
 +
  lcd.print(now.hour(), DEC);
 +
    lcd.print(':');
 +
    lcd.print(now.minute(), DEC);
 +
    lcd.print(':');
 +
    lcd.print(now.second(), DEC);
 +
  lcd.setCursor(0, 1);
 +
  lcd.print(now.day(), DEC);
 +
    lcd.print('/');
 +
    lcd.print(now.month(), DEC);
 +
    lcd.print('/');
 +
    lcd.print(now.year(), DEC);
 +
    lcd.print(' ');
 +
  delay(1000);
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
Une fois la compilation et le téléversement du code réalisé vers la carte arduino, l’heure et la date s’affichent correctement sur l’écran LCD. Pour notre exemple, on obtient :
 +
 
 +
[[Fichier:Résultat_arduino_rtc_et_lcd.PNG]]
 +
 
 +
== Etape 4 : communication entre deux bus CAN ==
 +
 
 +
Le but de cette étape est d’établir la communication entre deux CAN Bus Shields, une horloge RTC et un écran LCD. Pour cela, nous branchons le RTC sur un premier shield Can (émetteur) et l’afficheur LCD sur le second shield (récepteur). Nous cherchons donc à récupérer les données du RTC, date et heure, à partir d’un bus Can et à les afficher sur l’écran avec le second bus Can.
 +
Le montage utilise donc :
 +
*deux cartes Arduino UNO
 +
*deux CAN Bus Shields v1.2
 +
*une horloge RTC avec module i2c
 +
*un écran LCD avec module i2c
 +
*des fils de liaison
 +
*deux câbles d’alimentation USB
 +
 
 +
Pour réaliser le montage il faut d’abord brancher les deux CAN Bus Shields ensemble : il suffit de brancher les shields sur les Arduinos et de relier les signaux CAN_H et CAN_L.
 +
 
 +
[[Fichier:Montage_communication_entre_2_CAN_Bus_Shields.PNG]]
 +
 
 +
Une fois les deux shields branchés, nous pouvons les faire communiquer. Sur le wiki L.A.B dans « découverte du bus Can », le document "Emission/Réception simple" nous permet de mettre en œuvre cette communication.
 +
 
 +
Dans notre cas, nous allons compléter ce montage en ajoutant un RTC avec module i2c sur le shield Can émetteur et en ajoutant un écran LCD avec module i2c sur le shield Can récepteur.
 +
 
 +
[[Fichier:Montage_2_shields_can,_rtc_et_lcd.PNG ‎]]
 +
 
 +
En tout, on a besoin de 10 fils :
 +
*Entre les CAN-Bus Shields :
 +
**CAN H émetteur => CAN H récepteur
 +
**CAN L émetteur => CAN L récepteur
 +
*Pour le CAN-Bus Shield émetteur :
 +
**GND RTC => GND Shield
 +
**VCC RTC => +5V Shield
 +
**SDA RTC => SDA Shield
 +
**SCL RTC => SCL Shield
 +
*Pour le CAN-Bus Shield récepteur :
 +
**GND LCD => GND Shield
 +
**VCC LCD => +5V Shield
 +
**SDA LCD => SDA Shield
 +
**SCL LCD => SCL Shield
 +
 
 +
Une fois le montage réalisé, sur le programme Arduino nous pouvons donc ajouter les deux codes.
 +
 
 +
 
 +
Code émetteur à téléverser sur le shield avec le RTC :
 +
 
 +
<syntaxhighlight lang="cpp" enclose="div">
 +
//code du Bus CAN émetteur
 +
 
 +
#include <mcp_can.h> // télécharger cette librairie en ZIP sur https://github.com/Seeed-Studio/CAN_BUS_Shield et l'ajouter à notre logiciel Arduino
 +
#include <SPI.h> //librairie déjà disponible sur Arduino
 +
#include <LiquidCrystal_I2C.h> // pour télécharger la librairie: croquis - include library - manage libraries - LiquidCrystal_I2C.h de Frank de Brabander
 +
#include <Wire.h>  //librairie déjà disponible sur Arduino
 +
#include <RTClib.h> //librairie à télécharger en ZIP sur https://github.com/jcw/rtclib
 +
 
 +
#if defined(ARDUINO) && ARDUINO >= 100
 +
#define printByte(args)  write(args);
 +
#else
 +
#define printByte(args)  print(args,BYTE);
 +
#endif
 +
 +
const int SPI_CS_PIN = 9;
 
MCP_CAN CAN(SPI_CS_PIN);
 
MCP_CAN CAN(SPI_CS_PIN);
 +
 +
RTC_DS1307 RTC; //modèle de la clock(RTC)
 +
LiquidCrystal_I2C lcd(0x27,16,2); //écran LCD 0x27 avec 16 colonnes et 2 lignes (ligne 0 et ligne 1)
  
 
void setup()
 
void setup()
 
{
 
{
     Serial.begin(115200);
+
     Serial.begin(57600); //nombre de bauds: définir le même nombre sur le moniteur série (Ctrl - Maj - M)
 +
    Wire.begin();
 +
    RTC.begin();
 +
    RTC.adjust(DateTime(__DATE__, __TIME__)); //Ajuster l'heure et la date de la clock avec celles de l'ordinateur
  
 
START_INIT:
 
START_INIT:
     if(CAN_OK == CAN.begin(CAN_500KBPS))                   // init can bus : baudrate = 500k
+
     if(CAN_OK == CAN.begin(CAN_500KBPS)) // initialisation du bus can : baudrate = 500k
 
     {
 
     {
         Serial.println("Initialisation du CAN BUS Shield ok!");
+
         Serial.println("Initialisation du CAN BUS Shield ok!"); // si le bus can s'initialise correctement alors le moniteur série (Ctrl-Maj-M) affiche cela
 
     }
 
     }
 
     else
 
     else
 
     {
 
     {
         Serial.println("Initialisation du CAN BUS Shield en echec");
+
         Serial.println("Initialisation du CAN BUS Shield en echec"); //si l'initialisation du Can échoue il tente de se réinitialiser jusqu'à ce que ça fonctionne
 
         Serial.println("Réinitialisation CAN BUS Shield");
 
         Serial.println("Réinitialisation CAN BUS Shield");
         delay(100);
+
         delay(1000);
 
         goto START_INIT;
 
         goto START_INIT;
 
     }
 
     }
 +
   
 
}
 
}
 
+
unsigned char stmp[6] = {0, 0, 0, 0, 0, 0}; //permet de créer un tableau de 6 caractères (dans notre cas : année, mois, jour, heure, minutes et secondes)
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+
  
 
void loop()
 
void loop()
{
+
{  
    // send data:  id = 0x00, standard frame, data len = 8, stmp: data buf
+
      DateTime now = RTC.now();
    CAN.sendMsgBuf(0x00, 0, 8, stmp);
+
      stmp[0] = now.year()-2000; //1er caractère du tableau qui correspond à l'année actuelle
    delay(100);
+
      stmp[1] = now.month();//2eme caractère qui correspond au mois
 +
      stmp[2] = now.day();//caractère 3 qui correspond au jour
 +
      stmp[3] = now.hour();//caractère 4 qui correspond à l'heure
 +
      stmp[4] = now.minute();//caractère 5 qui correspond aux minutes
 +
      stmp[5] = now.second();//caractère 6 qui correspond aux secondes
 +
     
 +
      CAN.sendMsgBuf(0x00, 0, 6, stmp); //permet d'envoyer une donnée.Ici, envoie le tableau créé avec année, mois, jour, heure, minutes et secondes
 +
      delay(1000);
 +
 
 
}
 
}
 +
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==== Etape 3 : programmation du récepteur  ====
+
 
Sur l'Arduino récepteur téléverser le programme suivant :
+
 
 +
Code récepteur à téléverser sur le shield avec l’afficheur LCD :  
 +
 
 
<syntaxhighlight lang="cpp" enclose="div">
 
<syntaxhighlight lang="cpp" enclose="div">
/*
+
//code du Bus CAN récepteur
  Ce programme reçois les messages transmis sur le bus CAN et les affiches sur la console série.
+
*/
+
#include <SPI.h>
+
#include <mcp_can.h>
+
  
const int SPI_CS_PIN = 10;
+
#include <SPI.h> //librairie déjà disponible sur Arduino
 +
#include <mcp_can.h> // télécharger cette librairie en ZIP sur https://github.com/Seeed-Studio/CAN_BUS_Shield et l'ajouter à notre logiciel Arduino
 +
#include <Wire.h> //librairie déjà disponible sur Arduino
 +
#include <LiquidCrystal_I2C.h> // pour télécharger la librairie: croquis - include library - manage libraries - LiquidCrystal_I2C.h de Frank de Brabander
 +
#include <RTClib.h> //librairie à télécharger en ZIP sur https://github.com/jcw/rtclib
 +
#if defined(ARDUINO) && ARDUINO >= 100
 +
#define printByte(args)  write(args);
 +
#else
 +
#define printByte(args)  print(args,BYTE);
 +
#endif
 +
 
 +
const int SPI_CS_PIN = 9;
 
MCP_CAN CAN(SPI_CS_PIN);
 
MCP_CAN CAN(SPI_CS_PIN);
 +
LiquidCrystal_I2C lcd(0x27,16,2); //écran LCD 0x27 avec 16 colonnes et 2 lignes (ligne 0 et ligne 1)
  
 
void setup()
 
void setup()
 
{
 
{
     Serial.begin(115200);
+
     Serial.begin(57600); //nombre de bauds: définir le même nombre sur le moniteur série (Ctrl - Maj - M)
 +
    lcd.init();
 +
    lcd.backlight();
 +
   
 +
    lcd.print("Initialisation..."); // l'écran LCD affiche qu'il s'initialise
  
 +
    Wire.begin();
 +
 
 
START_INIT:
 
START_INIT:
     if(CAN_OK == CAN.begin(CAN_500KBPS))                   // init can bus : baudrate = 500k
+
     if(CAN_OK == CAN.begin(CAN_500KBPS)) //initialisation du bus can : baudrate = 500k
 
     {
 
     {
         Serial.println("Initialisation du CAN BUS Shield ok!");
+
         Serial.println("Initialisation du CAN BUS Shield ok!"); // si le bus can s'initialise correctement alors le moniteur série (Ctrl-Maj-M) affiche cela
 
     }
 
     }
 
     else
 
     else
 
     {
 
     {
         Serial.println("Initialisation du CAN BUS Shield en echec");
+
         Serial.println("Initialisation du CAN BUS Shield en echec"); //si l'initialisation du Can échoue il tente de se réinitialiser jusqu'à ce que ça fonctionne
 
         Serial.println("Réinitialisation CAN BUS Shield");
 
         Serial.println("Réinitialisation CAN BUS Shield");
         delay(100);
+
         delay(1000);
 
         goto START_INIT;
 
         goto START_INIT;
 
     }
 
     }
 +
  lcd.clear();
 
}
 
}
  
 
void loop()
 
void loop()
 
{
 
{
    unsigned char len = 0;
+
  unsigned char buf[8];
    unsigned char buf[8];
+
  lireDonneesSurBusCan(buf);//les différentes fonctions sont décrites ci-dessous
 +
  DateTime now = transformerDonneesEnDate(buf);
 +
  afficherDateSurLcd(now);
 +
  delay(1000);
 +
}
  
     if(CAN_MSGAVAIL == CAN.checkReceive())           // vérifie l'arrivée d'un message
+
DateTime transformerDonneesEnDate(unsigned char buf[]){
 +
  DateTime now(buf[0]+2000,
 +
                buf[1],
 +
                buf[2],
 +
                buf[3],
 +
                buf[4],
 +
                buf[5]);
 +
  return now;
 +
}
 +
 
 +
void lireDonneesSurBusCan(unsigned char buf[]){
 +
    unsigned char len = 0;
 +
     if(CAN_MSGAVAIL == CAN.checkReceive()) // vérifie l'arrivée d'un message
 
     {
 
     {
        CAN.readMsgBuf(&len, buf);   // read data,  len: data length, buf: data buf
+
      CAN.readMsgBuf(&len, buf);  
  
        unsigned char canId = CAN.getCanId();
+
      unsigned char canId = CAN.getCanId();
 
          
 
          
 
         Serial.println("-----------------------------");
 
         Serial.println("-----------------------------");
Ligne 121 : Ligne 388 :
 
         Serial.println(canId);
 
         Serial.println(canId);
  
        for(int i = 0; i<len; i++)    // affiche les données
+
      for(int i = 0; i<len; i++)    // affiche les données
 
         {
 
         {
            Serial.print(buf[i]);
+
          Serial.print(buf[i]);
            Serial.print("\t");
+
          Serial.print("\t");
 
         }
 
         }
 
         Serial.println();
 
         Serial.println();
 
     }
 
     }
 
}
 
}
</syntaxhighlight>
+
void afficherDateSurLcd(DateTime now){
==== Etape 4 : essai de la communication  ====
+
  lcd.setCursor(0, 0);
Brancher les deux Arduinos. Ouvrez la console série du récepteur et vérifier que les données émises sont bien reçues :  
+
  lcd.print(now.hour(), DEC);
[[Fichier:CAN BUS message.jpg]]
+
  lcd.print(':');
 +
  lcd.print(now.minute(), DEC);
 +
  lcd.print(':');
 +
  lcd.print(now.second(), DEC);
 +
  lcd.print(' ');
 +
  lcd.setCursor(0, 1);
 +
  lcd.print(now.day(), DEC);
 +
  lcd.print('/');
 +
  lcd.print(now.month(), DEC);
 +
  lcd.print('/');
 +
  lcd.print(now.year(), DEC);
 +
  lcd.print(' ');
 +
 
 +
    Serial.println();
 +
  Serial.print(now.year(), DEC);
 +
  Serial.print('/');
 +
  Serial.print(now.month(), DEC);
 +
  Serial.print('/');
 +
  Serial.print(now.day(), DEC);
 +
  Serial.print(' ');
 +
  Serial.print(now.hour(), DEC);
 +
  Serial.print(':');
 +
  Serial.print(now.minute(), DEC);
 +
  Serial.print(':');
 +
  Serial.print(now.second(), DEC);
 +
}</syntaxhighlight>
  
=== Conseils ===
+
Une fois la compilation et le téléversement des deux codes vers leur shield Can, on a :
Si jamais vous n'arrivez pas à recevoir vos données, essayez de baisser la vitesse sur l'émetteur et le récepteur. Si jamais vous n'avez pas de résistances de 120 Ohms, la communication devrait quand-même fonctionner pour des vitesses inférieures à 40Kbit/s.
+
*En ouvrant le moniteur série (Ctrl – Maj – M) : l’initialisation du CAN Bus shield ainsi que l’heure et la date exacte transmise par la clock qui se synchronise régulièrement. Ne pas oublier de régler le nombre de bauds sur le moniteur série avec celui du code, ici 57600.
 +
*L’écran LCD qui affiche bien l’heure et la date, soit les données transmises par la clock.
 +
Nos deux CAN Bus Shields communiquent donc correctement car les données transmises par l’un sont récupérées et affichées par l’autre.
  
== Pour aller plus loin ==
+
[[Fichier:Moniteur_série_2_shields_can,_rtc_et_lcd.PNG]]
Si vous disposez d'un cable DB-9 Droit, vous pouvez remplacer les straps par ce câble. D'après nos premiers essais, il semblerait que
+
le cablage de la prise sur le shield de Sparkfun soit différent du standard. Les différents signaux sont câblés comme suit :
+
* ''CAN_L'' : 5
+
* ''CAN_H'' : 3
+
* ''GND'' : 2
+
  
alors que le câblage standard est le suivant :
 
* ''CAN_L'' : 2
 
* ''CAN_H'' : 7
 
* ''GND'' : 3
 
  
 
== Bibliographie ==
 
== Bibliographie ==
  
 
* https://github.com/Seeed-Studio/CAN_BUS_Shield
 
* https://github.com/Seeed-Studio/CAN_BUS_Shield
* http://www.seeedstudio.com/wiki/CAN-BUS_Shield
+
* https://github.com/jcw/rtclib
* http://skpang.co.uk/catalog/arduino-canbus-shield-with-usd-card-holder-p-706.html
+
 
  
  

Version actuelle en date du 18 juillet 2017 à 09:47

Tout d'abord nous allons mettre en œuvre le breakout Tiny RTC et un afficheur LCD avec une liaison I2C, puis dans un second temps nous allons mettre en œuvre le bus CAN en deux arduinos Uno.le breakout Tiny RTC sera branché sur le premier arduino Uno, l'afficheur RTC sera branché sur un second arduino Uno qui pourra afficher les données émises par le RTC.

Présentation et objectifs

Le but de ce tutoriel est de tester le fonctionnement de l’horloge RTC sur l’écran LCD à l’aide d’une carte Arduino UNO. La manipulation permet de faire communiquer l’horloge avec l’écran LCD afin que ce dernier affiche l’heure et la date. Ce tutoriel nécessite une connaissance minimale de la plateforme Arduino. La page Formation Arduino du wiki contient toutes les ressources nécessaires pour découvrir la programmation avec Arduino.

Le montage utilise donc :

  • une carte Arduino UNO
  • une horloge RTC avec module i2c
  • un écran LCD avec module i2c
  • des fils de liaison
  • une breadboard
  • un câble d’alimentation USB

Arduino RTC.PNG

Etape 1 : tester l’écran LCD avec la carte Arduino

On souhaite réaliser un code pour afficher un texte sur notre écran LCD branché à notre carte Arduino UNO afin de tester l’écran.

Arduino LCD.PNG

On a donc besoin de 4 fils :

  • GND LCD => GND Arduino
  • VCC LCD => 5V Arduino
  • SDA LCD => pin analogique A4 Arduino
  • SCL LCD => pin analogique A5 Arduino

Une fois le montage réalisé, sur le programme Arduino nous pouvons donc ajouter ce code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h> // pour télécharger la librairie: croquis - include library - manage libraries - LiquidCrystal_I2C.h de Frank de Brabander
LiquidCrystal_I2C lcd(0x27,16,2); //écran LCD 0x27 avec 16 colonnes et 2 lignes (ligne 0 et ligne 1)

void setup()
{
lcd.init(); //initialisation de l'écran LCD
lcd.cursor_on();
lcd.blink_on();
lcd.backlight();
lcd.setCursor(5,0); // écriture du texte sur la ligne 1 colonne 5 (centré)
lcd.print("Hello!"); // texte "hello" sur ligne 1 colonne 5
lcd.setCursor(7,1); // écriture du texte sur la ligne 2 colonne 7 (centré)
lcd.print("ok"); // texte "ok" sur ligne 2 colonne 7
delay(1000);
lcd.cursor_off();
lcd.blink_off();
}

void loop()
{
}

Une fois la compilation et le téléversement du code réalisé vers la carte arduino, les textes s’affichent sur l’écran LCD. Pour notre exemple, on obtient :

Arduino LCD1.PNG

Le texte affiché sur l’écran peut être modifié et les effets également comme le défilement du texte par exemple. Ne pas hésiter à regarder les exemples proposés par la librairie LiquidCristal_I2C pour faire évoluer le code. Notre écran LCD avec un module i2c fonctionne donc correctement. Nous pouvons tester maintenant notre second appareil : l’horloge RTC avec module i2c.

Etape 2 : tester l’horloge RTC avec la carte Arduino

On souhaite réaliser un code pour afficher l’heure et la date sur notre ordinateur à partir d’une horloge RTC avec module i2c branchée à notre carte Arduino UNO. Notre modèle de RTC est la DS1307. ARDUINO rtc1.PNG

On a donc besoin de 4 fils (mêmes branchements que pour l’afficheur LCD):

  • GND RTC => GND Arduino
  • VCC RTC => +5V Arduino
  • SDA RTC => pin analogique A4 Arduino
  • SCL RTC => pin analogique A5 Arduino

Une fois le montage réalisé, sur le programme Arduino nous pouvons donc ajouter ce code. Il faut aussi télécharger la librairie RTClib, disponible sur le github.

//Heure et date en utilisant un RTC DS1307 connecté via un I2C
#include <Wire.h> //librairie déjà disponible sur Arduino
#include <RTClib.h> //librairie à télécharger en ZIP sur https://github.com/jcw/rtclib

RTC_DS1307 RTC; //modèle de la clock(RTC)

void setup () {
    Serial.begin(57600); //nombre de bauds: définir le même nombre sur le moniteur série (Ctrl - Maj - M)
    Wire.begin();
    RTC.begin();
    

   RTC.adjust(DateTime(__DATE__, __TIME__)); //Ajuster l'heure et la date de la clock avec celles de l'ordinateur
}

void loop () {
    DateTime now = RTC.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    Serial.print(" since 2000 = ");
    Serial.print(now.get());
    Serial.print("s = ");
    Serial.print(now.get() / 86400L);
    Serial.println("d");

    DateTime future (now.get() + 7 * 86400L + 30); //Calculer et afficher une date/heure avec 7 jours et 30 secondes de plus que celles de l'ordinateur
    
    Serial.print(" now + 7d + 30s: ");
    Serial.print(future.year(), DEC);
    Serial.print('/');
    Serial.print(future.month(), DEC);
    Serial.print('/');
    Serial.print(future.day(), DEC);
    Serial.print(' ');
    Serial.print(future.hour(), DEC);
    Serial.print(':');
    Serial.print(future.minute(), DEC);
    Serial.print(':');
    Serial.print(future.second(), DEC);
    Serial.println();
    
    Serial.println();
    delay(3000);
}

Une fois la compilation et le téléversement du code vers la carte arduino, on ouvre le moniteur série (Ctrl – Maj – M) et notre ordinateur affiche le résultat du code : soit l’heure et la date actuelle. Ne pas oublier de régler le nombre de bauds sur le moniteur série avec celui du code, ici 57600.

Moniteur série arduino rtc.PNG

Notre horloge RTC avec un module i2c fonctionne donc correctement. Nous pouvons tester maintenant l’ensemble : l’horloge RTC avec module i2c et l’écran LCD avec module i2c. L’ensemble branché en parallèle sur la carte Arduino UNO.

Etape 3 : afficher l'heure et la date sur l'écran

On souhaite réaliser un code pour afficher l’heure et la date, à partir de l’horloge RTC, directement sur notre écran LCD.

Montage arduino rtc et lcd.PNG

On a donc besoin de 12 fils et d’une bread board. Les 3 éléments (RTC, LCD et Arduino UNO) sont branchés en parallèle.

Une fois le montage réalisé, sur le programme Arduino nous pouvons donc ajouter le code ci-dessous. Les librairies sont les mêmes que celles téléchargées et ajoutées précédemment donc pas besoin de les inclure à nouveau.

#include <Wire.h> //librairie déjà sur arduino
#include <LiquidCrystal_I2C.h> //pour télécharger la librairie: croquis - include library - manage libraries - LiquidCrystal_I2C.h de Frank de Brabander
#include <RTClib.h> //librairie à télécharger en ZIP sur https://github.com/jcw/rtclib
 
#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args)  write(args);
#else
#define printByte(args)  print(args,BYTE);
#endif
 
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0}; 
RTC_DS1307 RTC;
LiquidCrystal_I2C lcd(0x27,16,2); // Adresse du LCD 0x27 avec 16 colonnes et 2 lignes
 
void setup()
{
  lcd.init();  // initialisation du LCD
  lcd.backlight();
  lcd.print("Initialising..."); //afficher un message sur l'afficheur LCD
  lcd.createChar(2, clock);
  Wire.begin();
  RTC.begin();
  RTC.adjust(DateTime(__DATE__, __TIME__)); //Ajuster la clock avec l'heure et la date de l'ordinateur
}
 
void loop()
{
  lcd.clear(); //code pour afficher heure et date de la clock (du RTC) sur l'écran LCD
   DateTime now = RTC.now();
   lcd.printByte(2);
   lcd.print(" ");
  lcd.print(now.hour(), DEC);
    lcd.print(':');
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    lcd.print(now.second(), DEC);
   lcd.setCursor(0, 1);
   lcd.print(now.day(), DEC);
    lcd.print('/');
    lcd.print(now.month(), DEC);
    lcd.print('/');
    lcd.print(now.year(), DEC);
    lcd.print(' ');
  delay(1000);
}

Une fois la compilation et le téléversement du code réalisé vers la carte arduino, l’heure et la date s’affichent correctement sur l’écran LCD. Pour notre exemple, on obtient :

Résultat arduino rtc et lcd.PNG

Etape 4 : communication entre deux bus CAN

Le but de cette étape est d’établir la communication entre deux CAN Bus Shields, une horloge RTC et un écran LCD. Pour cela, nous branchons le RTC sur un premier shield Can (émetteur) et l’afficheur LCD sur le second shield (récepteur). Nous cherchons donc à récupérer les données du RTC, date et heure, à partir d’un bus Can et à les afficher sur l’écran avec le second bus Can. Le montage utilise donc :

  • deux cartes Arduino UNO
  • deux CAN Bus Shields v1.2
  • une horloge RTC avec module i2c
  • un écran LCD avec module i2c
  • des fils de liaison
  • deux câbles d’alimentation USB

Pour réaliser le montage il faut d’abord brancher les deux CAN Bus Shields ensemble : il suffit de brancher les shields sur les Arduinos et de relier les signaux CAN_H et CAN_L.

Montage communication entre 2 CAN Bus Shields.PNG

Une fois les deux shields branchés, nous pouvons les faire communiquer. Sur le wiki L.A.B dans « découverte du bus Can », le document "Emission/Réception simple" nous permet de mettre en œuvre cette communication.

Dans notre cas, nous allons compléter ce montage en ajoutant un RTC avec module i2c sur le shield Can émetteur et en ajoutant un écran LCD avec module i2c sur le shield Can récepteur.

Montage 2 shields can, rtc et lcd.PNG

En tout, on a besoin de 10 fils :

  • Entre les CAN-Bus Shields :
    • CAN H émetteur => CAN H récepteur
    • CAN L émetteur => CAN L récepteur
  • Pour le CAN-Bus Shield émetteur :
    • GND RTC => GND Shield
    • VCC RTC => +5V Shield
    • SDA RTC => SDA Shield
    • SCL RTC => SCL Shield
  • Pour le CAN-Bus Shield récepteur :
    • GND LCD => GND Shield
    • VCC LCD => +5V Shield
    • SDA LCD => SDA Shield
    • SCL LCD => SCL Shield

Une fois le montage réalisé, sur le programme Arduino nous pouvons donc ajouter les deux codes.


Code émetteur à téléverser sur le shield avec le RTC :

//code du Bus CAN émetteur

#include <mcp_can.h> // télécharger cette librairie en ZIP sur https://github.com/Seeed-Studio/CAN_BUS_Shield et l'ajouter à notre logiciel Arduino
#include <SPI.h> //librairie déjà disponible sur Arduino
#include <LiquidCrystal_I2C.h> // pour télécharger la librairie: croquis - include library - manage libraries - LiquidCrystal_I2C.h de Frank de Brabander
#include <Wire.h>  //librairie déjà disponible sur Arduino
#include <RTClib.h> //librairie à télécharger en ZIP sur https://github.com/jcw/rtclib

#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args)  write(args);
#else
#define printByte(args)  print(args,BYTE);
#endif
 
const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN);

RTC_DS1307 RTC; //modèle de la clock(RTC)
LiquidCrystal_I2C lcd(0x27,16,2); //écran LCD 0x27 avec 16 colonnes et 2 lignes (ligne 0 et ligne 1)

void setup()
{
    Serial.begin(57600); //nombre de bauds: définir le même nombre sur le moniteur série (Ctrl - Maj - M)
    Wire.begin();
    RTC.begin(); 
    RTC.adjust(DateTime(__DATE__, __TIME__)); //Ajuster l'heure et la date de la clock avec celles de l'ordinateur

START_INIT:
    if(CAN_OK == CAN.begin(CAN_500KBPS)) // initialisation du bus can : baudrate = 500k
    {
        Serial.println("Initialisation du CAN BUS Shield ok!"); // si le bus can s'initialise correctement alors le moniteur série (Ctrl-Maj-M) affiche cela
    }
    else
    {
        Serial.println("Initialisation du CAN BUS Shield en echec"); //si l'initialisation du Can échoue il tente de se réinitialiser jusqu'à ce que ça fonctionne
        Serial.println("Réinitialisation CAN BUS Shield");
        delay(1000);
        goto START_INIT;
    }
     
}
unsigned char stmp[6] = {0, 0, 0, 0, 0, 0}; //permet de créer un tableau de 6 caractères (dans notre cas : année, mois, jour, heure, minutes et secondes)

void loop()
{    
      DateTime now = RTC.now();
      stmp[0] = now.year()-2000; //1er caractère du tableau qui correspond à l'année actuelle 
      stmp[1] = now.month();//2eme caractère qui correspond au mois
      stmp[2] = now.day();//caractère 3 qui correspond au jour
      stmp[3] = now.hour();//caractère 4 qui correspond à l'heure
      stmp[4] = now.minute();//caractère 5 qui correspond aux minutes
      stmp[5] = now.second();//caractère 6 qui correspond aux secondes
      
      CAN.sendMsgBuf(0x00, 0, 6, stmp);  //permet d'envoyer une donnée.Ici, envoie le tableau créé avec année, mois, jour, heure, minutes et secondes
      delay(1000);

}


Code récepteur à téléverser sur le shield avec l’afficheur LCD :

//code du Bus CAN récepteur

#include <SPI.h> //librairie déjà disponible sur Arduino
#include <mcp_can.h> // télécharger cette librairie en ZIP sur https://github.com/Seeed-Studio/CAN_BUS_Shield et l'ajouter à notre logiciel Arduino
#include <Wire.h> //librairie déjà disponible sur Arduino
#include <LiquidCrystal_I2C.h> // pour télécharger la librairie: croquis - include library - manage libraries - LiquidCrystal_I2C.h de Frank de Brabander
#include <RTClib.h> //librairie à télécharger en ZIP sur https://github.com/jcw/rtclib
#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args)  write(args);
#else
#define printByte(args)  print(args,BYTE);
#endif

const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN);
LiquidCrystal_I2C lcd(0x27,16,2); //écran LCD 0x27 avec 16 colonnes et 2 lignes (ligne 0 et ligne 1)

void setup()
{
    Serial.begin(57600); //nombre de bauds: définir le même nombre sur le moniteur série (Ctrl - Maj - M)
    lcd.init();
    lcd.backlight();
    
    lcd.print("Initialisation..."); // l'écran LCD affiche qu'il s'initialise

    Wire.begin();
   
START_INIT:
    if(CAN_OK == CAN.begin(CAN_500KBPS)) //initialisation du bus can : baudrate = 500k
    {
        Serial.println("Initialisation du CAN BUS Shield ok!"); // si le bus can s'initialise correctement alors le moniteur série (Ctrl-Maj-M) affiche cela
    }
    else
    {
        Serial.println("Initialisation du CAN BUS Shield en echec"); //si l'initialisation du Can échoue il tente de se réinitialiser jusqu'à ce que ça fonctionne
        Serial.println("Réinitialisation CAN BUS Shield");
        delay(1000);
        goto START_INIT;
    }
   lcd.clear();
}

void loop()
{
   unsigned char buf[8];
   lireDonneesSurBusCan(buf);//les différentes fonctions sont décrites ci-dessous
   DateTime now = transformerDonneesEnDate(buf);
   afficherDateSurLcd(now);
   delay(1000);
}

DateTime transformerDonneesEnDate(unsigned char buf[]){
   DateTime now(buf[0]+2000,
                buf[1],
                buf[2],
                buf[3],
                buf[4],
                buf[5]);
   return now;
}

void lireDonneesSurBusCan(unsigned char buf[]){
    unsigned char len = 0;
    if(CAN_MSGAVAIL == CAN.checkReceive()) // vérifie l'arrivée d'un message
    {
      CAN.readMsgBuf(&len, buf); 

      unsigned char canId = CAN.getCanId();
        
        Serial.println("-----------------------------");
        Serial.println("get data from ID: ");
        Serial.println(canId);

       for(int i = 0; i<len; i++)    // affiche les données
        {
          Serial.print(buf[i]);
          Serial.print("\t");
        }
        Serial.println();
    }
}
void afficherDateSurLcd(DateTime now){
   lcd.setCursor(0, 0);
   lcd.print(now.hour(), DEC);
   lcd.print(':');
   lcd.print(now.minute(), DEC);
   lcd.print(':');
   lcd.print(now.second(), DEC);
   lcd.print(' ');
   lcd.setCursor(0, 1);
   lcd.print(now.day(), DEC);
   lcd.print('/');
   lcd.print(now.month(), DEC);
   lcd.print('/');
   lcd.print(now.year(), DEC);
   lcd.print(' ');
   
    Serial.println();
   Serial.print(now.year(), DEC);
   Serial.print('/');
   Serial.print(now.month(), DEC);
   Serial.print('/');
   Serial.print(now.day(), DEC);
   Serial.print(' ');
   Serial.print(now.hour(), DEC);
   Serial.print(':');
   Serial.print(now.minute(), DEC);
   Serial.print(':');
   Serial.print(now.second(), DEC);
}

Une fois la compilation et le téléversement des deux codes vers leur shield Can, on a :

  • En ouvrant le moniteur série (Ctrl – Maj – M) : l’initialisation du CAN Bus shield ainsi que l’heure et la date exacte transmise par la clock qui se synchronise régulièrement. Ne pas oublier de régler le nombre de bauds sur le moniteur série avec celui du code, ici 57600.
  • L’écran LCD qui affiche bien l’heure et la date, soit les données transmises par la clock.

Nos deux CAN Bus Shields communiquent donc correctement car les données transmises par l’un sont récupérées et affichées par l’autre.

Moniteur série 2 shields can, rtc et lcd.PNG


Bibliographie