Dernière révision : septembre 2023










Projet Arduino n° 7

Philippe Notez (philippe.notez@musee-info.fr)





Sommaire

Introduction

L’électronique et l’informatique ont profondément modifié notre société. C’est certainement la révolution industrielle la plus rapide de l’histoire de l’humanité. En effet, l’ordinateur que nous connaissons aujourd’hui était tout simplement inimaginable il y a seulement une cinquantaine d’années. Et avec les Arduino, les ESP8266 ou les Raspberry Pi Pico, l'aventure est loin d'être terminée.

L’auteur ne pourra en aucun cas être tenu responsable des dommages qui résulteraient de l’utilisation des informations publiées sur ce site, sous licence Creative Commons BY-NC-SA. Toute reproduction ou modification d'un document, même partielle, est autorisée à condition que son origine et le nom de l'auteur soient clairement indiqués (BY), qu'il soit utilisé à des fins non commerciales (NC), que son mode de diffusion soit identique au document initial (SA), et que cela ne porte pas atteinte à l’auteur.

Ce document présente un projet utilisant deux cartes Arduino, en espérant toujours être le plus clair et précis possible. Malgré tout le soin apporté à la rédaction, l'auteur vous remercie de bien vouloir le contacter si vous relevez la moindre erreur ou omission, et vous souhaite une agréable lecture.

Si vous avez apprécié ce document, vous pouvez faire un don ici. Merci pour votre soutien.


Objectif

Envoyer et recevoir des informations via une communication sans fil (module nRF24L01),
les enregistrer sur carte µSD et les afficher sur un écran LCD I2C.


Niveau




Matériel utilisé (émetteur)
  • un support pour Arduino Nano ou une plaque d'essai (breadboard) 170 / 400 / 830 points
  • une carte Arduino Nano
  • un module nRF24L01 avec adaptateur
  • un module GPS GY-NEO6MV2 (date, heure, latitude, longitude, altitude, vitesse)
  • un module DS1302 pour sauvegarder la date et l'heure (non obligatoire)
  • un module BME280 (température, humidité, pression)
  • des câbles Dupont
  • un câble USB pour la liaison avec l'ordinateur
Matériel utilisé (récepteur)
  • un support pour Arduino Nano ou une plaque d'essai (breadboard) 170 / 400 / 830 points
  • une carte Arduino Nano
  • un module nRF24L01 avec adaptateur
  • un module et une carte µSD
  • un afficheur LCD I2C 20 x 4
  • des câbles Dupont
  • un câble USB pour la liaison avec l'ordinateur

Programme (émetteur)

wifi-e_2.ino
// wifi (module nRF24L01) : émetteur

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <SparkFunBME280.h>
#include <SPI.h>
#include <SD.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

#define CLK 3
#define DAT 4
#define CE 5
#define reception 6
#define emission 7
#define temps 10 // 1 Mb/s -> 1 kb/ms -> 125 octets/ms

TinyGPSPlus gps;
SoftwareSerial liaison_gps(reception,emission);
BME280 capteur;

unsigned char nom_fic[13],mem_min[3];
unsigned char date_ds1302[11],heure_ds1302[9],date_gps[11],heure_gps[9];
unsigned char tab_lat[11],tab_lon[12],tab_vit[8],tab_alt[9];
unsigned char tab_temp[4],tab_humi[3],tab_pression[8];

void setup()
  {
  File num_fic;

  liaison_gps.begin(9600);
  Wire.begin();
  capteur.settings.I2CAddress=0x76; // 0x77 si SDO = 1
  capteur.settings.runMode=3;
  capteur.settings.tStandby=5;      // une mesure par seconde
  capteur.settings.filter=0;
  capteur.settings.tempOverSample=1;
  capteur.settings.pressOverSample=1;
  capteur.settings.humidOverSample=1;
  capteur.begin();
  SPI.begin();
  SD.begin(10); // CS
  strcpy(nom_fic,"gps-thp.csv");
  // FILE_READ -> lecture seule, curseur en début de fichier
  // FILE_WRITE -> lecture et écriture, curseur en fin de fichier
  num_fic=SD.open(nom_fic,FILE_WRITE);
  num_fic.write("Date");
  num_fic.write(',');
  num_fic.write("Heure");
  num_fic.write(',');
  num_fic.write("Latitude (°)");
  num_fic.write(',');
  num_fic.write("Longitude (°)");
  num_fic.write(',');
  num_fic.write("Vitesse (km/h)");
  num_fic.write(',');
  num_fic.write("Altitude (m)");
  num_fic.write(',');
  num_fic.write("Température (°C)");
  num_fic.write(',');
  num_fic.write("Humidité (%)");
  num_fic.write(',');
  num_fic.write("Pression (hPa)");
  num_fic.write(13);
  num_fic.write(10);
  num_fic.close();
  Mirf.cePin=8;     // CE
  Mirf.csnPin=9;    // CS
  Mirf.spi=&MirfHardwareSpi;
  Mirf.init();
  Mirf.channel=101;  // 128 canaux disponibles (0 à 127)
  Mirf.payload=1;   // taille d'un message (octets)
  // RF_SETUP=0000abc0 :
  //  - a = 0 –> 1 Mb/s
  //  - a = 1 –> 2 Mb/s
  //  - bc = 00 –> -18 dBm
  //  - bc = 01 –> -12 dBm
  //  - bc = 10 –> -6 dBm
  //  - bc = 11 –> 0 dBm
  Mirf.configRegister(RF_SETUP,0x06); // 1 Mb/s et 0 dBm (puissance max.)
  Mirf.config();
  Mirf.setRADDR((byte *)"adr-2");     // adresse de l'émetteur (5 octets)
  Mirf.setTADDR((byte *)"adr-1");     // adresse du récepteur (5 octets)
  delay(5000);
  mem_min[0]=0;
  }

void loop()
  {
  int test;
  unsigned char tab_min[3];

  lire_date_heure();
  lire_gps();
  test=strcmp(date_gps,"00/00/2000\0");
  if (test!=0)
    {
    test=strcmp(date_gps,date_ds1302);
    if (test!=0) ecrire_date_heure();
    }
  tab_min[0]=heure_ds1302[3];
  tab_min[1]=heure_ds1302[4];
  tab_min[2]=0;
  test=strcmp(tab_min,mem_min);
  if (test!=0)
    {
    lire_bme280();
    ecrire_sd();
    ecrire_wifi();
    strcpy(mem_min,tab_min);
    }
  }

void ecrire_date_heure()
  {
  unsigned char adr_reg,valeur;

  // disable Write Protect
  adr_reg=0x8E;
  ecrire_ds1302(adr_reg,0);
  // pas de circuit de charge (pile CR2032)
  adr_reg=0x90;
  ecrire_ds1302(adr_reg,0);
  // jour du mois
  adr_reg=0x86;
  valeur=date_gps[0]-48;
  valeur<<=4;
  valeur+=date_gps[1]-48;
  ecrire_ds1302(adr_reg,valeur);
  // mois
  adr_reg=0x88;
  valeur=date_gps[3]-48;
  valeur<<=4;
  valeur+=date_gps[4]-48;
  ecrire_ds1302(adr_reg,valeur);
  // année
  adr_reg=0x8C;
  valeur=date_gps[8]-48;
  valeur<<=4;
  valeur+=date_gps[9]-48;
  ecrire_ds1302(adr_reg,valeur);
  // heures
  adr_reg=0x84;
  valeur=heure_gps[0]-48;
  valeur<<=4;
  valeur+=heure_gps[1]-48;
  ecrire_ds1302(adr_reg,valeur);
  // minutes
  adr_reg=0x82;
  valeur=heure_gps[3]-48;
  valeur<<=4;
  valeur+=heure_gps[4]-48;
  ecrire_ds1302(adr_reg,valeur);
  // secondes
  adr_reg=0x80;
  valeur=heure_gps[6]-48;
  valeur<<=4;
  valeur+=heure_gps[7]-48;
  ecrire_ds1302(adr_reg,valeur);
  // enable Write Protect
  adr_reg=0x8E;
  ecrire_ds1302(adr_reg,128);
  }

void lire_date_heure()
  {
  unsigned char adr_reg,valeur;

  // jour du mois
  adr_reg=0x87;
  valeur=lire_ds1302(adr_reg);
  date_ds1302[0]=(valeur>>4)+48;
  date_ds1302[1]=(valeur&0x0F)+48;
  date_ds1302[2]='/';
  // mois
  adr_reg=0x89;
  valeur=lire_ds1302(adr_reg);
  date_ds1302[3]=(valeur>>4)+48;
  date_ds1302[4]=(valeur&0x0F)+48;
  date_ds1302[5]='/';
  // année
  date_ds1302[6]='2';
  date_ds1302[7]='0';
  adr_reg=0x8D;
  valeur=lire_ds1302(adr_reg);
  date_ds1302[8]=(valeur>>4)+48;
  date_ds1302[9]=(valeur&0x0F)+48;
  date_ds1302[10]=0;
  // heures
  adr_reg=0x85;
  valeur=lire_ds1302(adr_reg);
  heure_ds1302[0]=(valeur>>4)+48;
  heure_ds1302[1]=(valeur&0x0F)+48;
  heure_ds1302[2]=':';
  // minutes
  adr_reg=0x83;
  valeur=lire_ds1302(adr_reg);
  heure_ds1302[3]=(valeur>>4)+48;
  heure_ds1302[4]=(valeur&0x0F)+48;
  heure_ds1302[5]=':';
  // secondes
  adr_reg=0x81;
  valeur=lire_ds1302(adr_reg);
  heure_ds1302[6]=(valeur>>4)+48;
  heure_ds1302[7]=(valeur&0x0F)+48;
  heure_ds1302[8]=0;
  }

void ecrire_ds1302(unsigned char adr_reg,unsigned char valeur)
  {
  unsigned char car;
  int i=1;

  digitalWrite(CE,HIGH); // démarrer le transfert
  // adresse du registre
  pinMode(DAT,OUTPUT);
  do
    {
    digitalWrite(CLK,LOW);
    car=adr_reg&i;
    if (car==i) digitalWrite(DAT,HIGH);
    else digitalWrite(DAT,LOW);
    digitalWrite(CLK,HIGH);
    i*=2;
    }
  while (i<=128);
  // valeur
  i=1;
  do
    {
    digitalWrite(CLK,LOW);
    car=valeur&i;
    if (car==i) digitalWrite(DAT,HIGH);
    else digitalWrite(DAT,LOW);
    digitalWrite(CLK,HIGH);
    i*=2;
    }
  while (i<=128);
  digitalWrite(CE,LOW);  // arrêter le transfert
  }

unsigned char lire_ds1302(unsigned char adr_reg)
  {
  unsigned char car,valeur=0;
  int i=1;

  digitalWrite(CE,HIGH); // démarrer le transfert
  // adresse du registre
  pinMode(DAT,OUTPUT);
  do
    {
    digitalWrite(CLK,LOW);
    car=adr_reg&i;
    if (car==i) digitalWrite(DAT,HIGH);
    else digitalWrite(DAT,LOW);
    digitalWrite(CLK,HIGH);
    i*=2;
    }
  while (i<=128);
  // valeur
  pinMode(DAT,INPUT);
  i=1;
  do
    {
    digitalWrite(CLK,LOW);
    car=digitalRead(DAT);
    if (car==HIGH) valeur+=i;
    digitalWrite(CLK,HIGH);
    i*=2;
    }
  while (i<=128);
  digitalWrite(CE,LOW);  // arrêter le transfert
  return valeur;
  }

void lire_gps()
  {
  double val_lat,val_lon,vit,alt;

  while (!gps.date.isUpdated()) if (liaison_gps.available()>0) gps.encode(liaison_gps.read());
  // jour du mois
  if (gps.date.day()<10)
    {
    date_gps[0]='0';
    date_gps[1]=gps.date.day()+48;
    }
  else itoa(gps.date.day(),date_gps,10);
  date_gps[2]='/';
  // mois
  if (gps.date.month()<10)
    {
    date_gps[3]='0';
    date_gps[4]=gps.date.month()+48;
    }
  else itoa(gps.date.month(),date_gps+3,10);
  date_gps[5]='/';
  // année
  itoa(gps.date.year(),date_gps+6,10);
  date_gps[10]=0;
  // heures
  if (gps.time.hour()<10)
    {
    heure_gps[0]='0';
    heure_gps[1]=gps.time.hour()+48;
    }
  else itoa(gps.time.hour(),heure_gps,10);
  heure_gps[2]=':';
  // minutes
  if (gps.time.minute()<10)
    {
    heure_gps[3]='0';
    heure_gps[4]=gps.time.minute()+48;
    }
  else itoa(gps.time.minute(),heure_gps+3,10);
  heure_gps[5]=':';
  // secondes
  if (gps.time.second()<10)
    {
    heure_gps[6]='0';
    heure_gps[7]=gps.time.second()+48;
    heure_gps[8]=0;
    }
  else itoa(gps.time.second(),heure_gps+6,10);
  // latitude
  val_lat=gps.location.lat();
  dtostrf(val_lat,10,6,tab_lat);
  sup_esp(tab_lat);
  // longitude
  val_lon=gps.location.lng();
  dtostrf(val_lon,11,6,tab_lon);
  sup_esp(tab_lon);
  // vitesse
  vit=gps.speed.kmph();
  dtostrf(vit,7,2,tab_vit);
  sup_esp(tab_vit);
  // altitude
  alt=gps.altitude.meters();
  dtostrf(alt,8,2,tab_alt);
  sup_esp(tab_alt);
  }

void sup_esp(unsigned char *tab)
  {
  unsigned char car,i=0,j=0;

  if (tab[0]!=32) return;
  do car=tab[i++];
  while (car==32);
  do
    {
    tab[j++]=car;
    car=tab[i++];
    }
  while (car!=0);
  tab[j]=0;
  }

void lire_bme280()
  {
  int temperature;
  float humidite,pression;

  temperature=capteur.readTempC();
  itoa(temperature,tab_temp,10);
  humidite=capteur.readFloatHumidity();
  dtostrf(humidite,2,0,tab_humi);
  pression=capteur.readFloatPressure();
  pression/=100.0;  // hPa
  dtostrf(pression,7,2,tab_pression);
  }

void ecrire_sd()
  {
  File num_fic;

  num_fic=SD.open(nom_fic,FILE_WRITE);
  num_fic.write(date_ds1302,strlen(date_ds1302));
  num_fic.write(',');
  num_fic.write(heure_ds1302,strlen(heure_ds1302));
  num_fic.write(',');
  num_fic.write(tab_lat,strlen(tab_lat));
  num_fic.write(',');
  num_fic.write(tab_lon,strlen(tab_lon));
  num_fic.write(',');
  num_fic.write(tab_vit,strlen(tab_vit));
  num_fic.write(',');
  num_fic.write(tab_alt,strlen(tab_alt));
  num_fic.write(',');
  num_fic.write(tab_temp,strlen(tab_temp));
  num_fic.write(',');
  num_fic.write(tab_humi,strlen(tab_humi));
  num_fic.write(',');
  num_fic.write(tab_pression,strlen(tab_pression));
  num_fic.write(13);
  num_fic.write(10);
  num_fic.close();
  }

void ecrire_wifi()
  {
  unsigned char car,i=0;

  // début de trame
  car=255;
  Mirf.send(&car);
  delay(temps);
  // date
  do
    {
    car=date_ds1302[i++];
    Mirf.send(&car);
    delay(temps);
    }
  while (car!=0);
  // heure
  i=0;
  do
    {
    car=heure_ds1302[i++];
    Mirf.send(&car);
    delay(temps);
    }
  while (car!=0);
  // latitude
  i=0;
  do
    {
    car=tab_lat[i++];
    Mirf.send(&car);
    delay(temps);
    }
  while (car!=0);
  // longitude
  i=0;
  do
    {
    car=tab_lon[i++];
    Mirf.send(&car);
    delay(temps);
    }
  while (car!=0);
  // vitesse
  i=0;
  do
    {
    car=tab_vit[i++];
    Mirf.send(&car);
    delay(temps);
    }
  while (car!=0);
  }


Programme (récepteur)

wifi-r_2.ino
// wifi (module nRF24L01) : récepteur

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define temps 1

LiquidCrystal_I2C lcd(0x27,20,4);

unsigned char tab_date[11],tab_heure[9],tab_lat[11],tab_lon[12],tab_vit[8];

void setup()
  {
  SPI.begin();
  Mirf.cePin=9;     // CE
  Mirf.csnPin=10;   // CS
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.channel=101; // 128 canaux disponibles (0 à 127)
  Mirf.payload=1;   // taille d'un message (octets)
  // RF_SETUP=0000abc0 :
  //  - a = 0 –> 1 Mb/s
  //  - a = 1 –> 2 Mb/s
  //  - bc = 00 –> -18 dBm
  //  - bc = 01 –> -12 dBm
  //  - bc = 10 –> -6 dBm
  //  - bc = 11 –> 0 dBm
  Mirf.configRegister(RF_SETUP,0x06); // 1 Mb/s et 0 dBm (puissance max.)
  Mirf.config();
  Mirf.setRADDR((byte *)"adr-1");     // adresse du récepteur (5 octets)
  Mirf.setTADDR((byte *)"adr-2");     // adresse de l'émetteur (5 octets)
  lcd.begin();
  lcd.backlight();
  delay(5000);
  }

void loop()
  {
  unsigned char i=0,car=1;

  // date
  do if (Mirf.dataReady())
    {
    Mirf.getData(&car);
    delay(temps);
    if (car==255) return;
    tab_date[i++]=car;
    }
  while (car!=0);
  lcd.setCursor(0,0);
  lcd.print((char*)tab_date);
  // heure
  i=0;
  car=1;
  do if (Mirf.dataReady())
    {
    Mirf.getData(&car);
    delay(temps);
    if (car==255) return;
    tab_heure[i++]=car;
    }
  while (car!=0);
  lcd.setCursor(12,0);
  lcd.print((char*)tab_heure);
  // latitude
  i=0;
  car=1;
  do if (Mirf.dataReady())
    {
    Mirf.getData(&car);
    delay(temps);
    if (car==255) return;
    tab_lat[i++]=car;
    }
  while (car!=0);
  lcd.setCursor(0,1);
  lcd.print("Lat. : ");
  lcd.setCursor(7,1);
  lcd.print((char*)tab_lat);
  // longitude
  i=0;
  car=1;
  do if (Mirf.dataReady())
    {
    Mirf.getData(&car);
    delay(temps);
    if (car==255) return;
    tab_lon[i++]=car;
    }
  while (car!=0);
  lcd.setCursor(0,2);
  lcd.print("Lon. : ");
  lcd.setCursor(7,2);
  lcd.print((char*)tab_lon);
  // vitesse
  i=0;
  car=1;
  do if (Mirf.dataReady())
    {
    Mirf.getData(&car);
    delay(temps);
    if (car==255) return;
    tab_vit[i++]=car;
    }
  while (car!=0);
  lcd.setCursor(0,3);
  lcd.print("Vit. : ");
  lcd.setCursor(7,3);
  lcd.print((char*)tab_vit);
  lcd.print(" km/h");
  }




Haut de page