﻿// COMPTEUR DE VITESSE POUR LE MODÉLISME FERROVIAIRE - VERSION 7 - MAJ 04-03-2023

// LES ÉCHELLES TRAITEES : N (1/160), TT (1/120), HO (1/87), 0 (1/45) et I (1/32).
// LA DISTANCE DE MESURE PEUT SE FAIRE SUR 20cm, 40cm, 60cm, 80cm ou 100cm

// LA DÉTECTION DES PASSAGES SE FAIT PAR COUPURE D'UN RAYON LASER.
// LES ÉMETTEURS LASER SONT RÉGLAGLES :
//      - EN INTENSITE PAR VARIATION DE LEUR TENSION D'ALIMENTATION
//      - EN NETTETE PAR UNE FOCALE A VIS.

// LE CHOIX DES ÉCHELLES ET DISTANCES SE FAIT PAR BASCULE DE MICRO-SWITCHES.
// CHOIX DE L'ÉCHELLE : 5 MICRO-SWITCHES (BASCULE ON/OFF) ; DE 1/160 A 1/35 - DE GAUCHE A DROITE.
// CHOIX DE LA DISTANCE : 5 MICRO-SWITCHES (BASCULE ON/OFF) POUR LES DISTANCES - DE GAUCHE A DROITE.

// FAIRE UN RESET APRÈS CHAQUE MODIFICATION DE L'ÉCHELLE ET/OU DE LA DISTANCE DE MESURE.
// UN BOUTON POUSSOIR RÉALISERA CE RESET PAR MISE A 0V DE LA BROCHE RST DE L'ARDUINO.

// LA MESURE DE VITESSE EST FAITE QUELQUE SOIT LE SENS DE PASSAGE DU TRAIN
// LE DÉTECTEUR B PEUT ÊTRE ACTIVÉ AVANT LE A OU LE A AVANT LE B.
// LE REPÉRAGE DES DÉTECTEURS NE DONNE PAS D'ORDRE DE PRIORITÉ.


// DECLARATION DES VARIABLES

#include <LiquidCrystal.h>
const uint8_t rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7; // Broches pour NANO et UNO
LiquidCrystal lcd (rs, en, d4, d5, d6, d7);

const int Detecteur_A = A6;
int Etat_Detecteur_A;

const int Detecteur_B = A7;
int Etat_Detecteur_B;

const int Echelle_160 = 8;
const int Echelle_120 = 9;
const int Echelle_87 = 10;
const int Echelle_45 = 11;
const int Echelle_32 = 12;
int Echelle_Choisie;
float Coefficient;

const int Distance_20cm = 18;
const int Distance_40cm = 17;
const int Distance_60cm = 16;
const int Distance_80cm = 15;
const int Distance_100cm = 14;
int Distance_Choisie;
int Valeur_Distance_choisie;

unsigned long Temps_Au_Detecteur_Entree= millis();
unsigned long Temps_Au_Detecteur_Sortie= millis();
unsigned long Temps_De_Parcours;
float Vitesse_De_Parcours;

int Vitesse_Reelle;
// Le int de Vitesse_Reelle permet de récupérer la valeur entière du nombre.


void setup()
{
  pinMode (Detecteur_A, INPUT);
  pinMode (Detecteur_B, INPUT);
  digitalWrite (Detecteur_A, LOW);
  digitalWrite (Detecteur_B, LOW);

  pinMode (Echelle_160, INPUT);
  pinMode (Echelle_120, INPUT);
  pinMode (Echelle_87, INPUT);
  pinMode (Echelle_45, INPUT);
  pinMode (Echelle_32, INPUT);

  digitalWrite (Echelle_160, LOW);
  digitalWrite (Echelle_120, LOW);
  digitalWrite (Echelle_87, LOW);
  digitalWrite (Echelle_45, LOW);
  digitalWrite (Echelle_32, LOW);

  pinMode (Distance_20cm, INPUT);
  pinMode (Distance_40cm, INPUT);
  pinMode (Distance_60cm, INPUT);
  pinMode (Distance_80cm, INPUT);
  pinMode (Distance_100cm, INPUT);

  digitalWrite (Distance_20cm, LOW);
  digitalWrite (Distance_40cm, LOW);
  digitalWrite (Distance_60cm, LOW);
  digitalWrite (Distance_80cm, LOW);
  digitalWrite (Distance_100cm, LOW);

  lcd.begin (16,2);
  lcd.clear();
}


void loop()
{
  Test_Choix_Echelle();
}


void Test_Choix_Echelle()
{

  Echelle_Choisie = digitalRead (Echelle_160);
  if ( Echelle_Choisie == HIGH )
  { Coefficient = 5.760;
  lcd.clear(); lcd.setCursor (0,0);  lcd.print ("E=1/160");}

  Echelle_Choisie = digitalRead (Echelle_120);
  if ( Echelle_Choisie == HIGH )
  { Coefficient = 4.320;
  lcd.clear(); lcd.setCursor (0,0);  lcd.print ("E=1/120"); }

  Echelle_Choisie = digitalRead (Echelle_87);
  if ( Echelle_Choisie == HIGH )
  { Coefficient = 3.132;
  lcd.clear(); lcd.setCursor (0,0);  lcd.print ("E=1/87"); }

  Echelle_Choisie = digitalRead (Echelle_45);
  if ( Echelle_Choisie == HIGH )
  { Coefficient = 1.620;
  lcd.clear(); lcd.setCursor (0,0);  lcd.print ("E=1/45"); }

  Echelle_Choisie = digitalRead (Echelle_32);
  if ( Echelle_Choisie == HIGH )
  { Coefficient = 1.152;
  lcd.clear(); lcd.setCursor (0,0);  lcd.print ("E=1/32"); }

  Test_Distance_De_Mesure();
}
  
void Test_Distance_De_Mesure()
{
  Distance_Choisie = digitalRead (Distance_20cm);
  if ( Distance_Choisie == HIGH )
  { Valeur_Distance_choisie = 20;
  lcd.setCursor (9,0);  lcd.print ("D=20cm"); }
  
  Distance_Choisie = digitalRead (Distance_40cm);
  if ( Distance_Choisie == HIGH )
  { Valeur_Distance_choisie = 40;
  lcd.setCursor (9,0);  lcd.print ("D=40cm"); }
  
  Distance_Choisie = digitalRead (Distance_60cm);
  if ( Distance_Choisie == HIGH )
  { Valeur_Distance_choisie = 60;
  lcd.setCursor (9,0); lcd.print ("D=60cm"); }
  
  Distance_Choisie = digitalRead (Distance_80cm);
  if ( Distance_Choisie == HIGH )
  { Valeur_Distance_choisie = 80;
  lcd.setCursor (9,0);  lcd.print ("D=80cm"); }
  
  Distance_Choisie = digitalRead (Distance_100cm);
  if ( Distance_Choisie == HIGH )
  { Valeur_Distance_choisie = 100;
  lcd.setCursor (9,0);  lcd.print ("D=100cm"); }

  Attente_Du_Passage_Sur_Le_Detecteur_A_Ou_Sur_Le_Detecteur_B();
}


void Attente_Du_Passage_Sur_Le_Detecteur_A_Ou_Sur_Le_Detecteur_B()
{
  do
  {
    Etat_Detecteur_A = analogRead (Detecteur_A);
    Etat_Detecteur_B = analogRead (Detecteur_B);
    Temps_Au_Detecteur_Entree = millis();
  }
  while ((Etat_Detecteur_A <= 200) && (Etat_Detecteur_B <= 200));

  if (Etat_Detecteur_A >= 500)
    { lcd.setCursor (2,1); lcd.print ("DETECTEUR A");
      Attente_Du_Passage_Sur_Le_Detecteur_B(); }
  else
    if (Etat_Detecteur_B >= 500)
      { lcd.setCursor (2,1); lcd.print ("DETECTEUR B");
      Attente_Du_Passage_Sur_Le_Detecteur_A(); }
}


void Attente_Du_Passage_Sur_Le_Detecteur_B()
{
  do
  {
    Etat_Detecteur_B = analogRead (Detecteur_B);
    Temps_Au_Detecteur_Sortie = millis();
  }
  while (Etat_Detecteur_B <= 200);
  lcd.setCursor (2,1); lcd.print ("DETECTEUR B");
  delay (2000);
  Calcul_Affichage_Vitesse ();
}


void Attente_Du_Passage_Sur_Le_Detecteur_A()
{
  do
  {
    Etat_Detecteur_A = analogRead (Detecteur_A);
    Temps_Au_Detecteur_Sortie = millis();
  }
  while (Etat_Detecteur_A <= 200);
  lcd.setCursor (2,1); lcd.print ("DETECTEUR A");
  delay (2000);
  Calcul_Affichage_Vitesse ();
}


void Calcul_Affichage_Vitesse ()
{
  Temps_De_Parcours = ((Temps_Au_Detecteur_Sortie - Temps_Au_Detecteur_Entree) / 1000);
  // Vitesse en cm/s
  Vitesse_De_Parcours = (Valeur_Distance_choisie / Temps_De_Parcours);
  // Vitesse en km/h
  Vitesse_Reelle = ( Vitesse_De_Parcours * Coefficient);

  lcd.setCursor (0,1);
  lcd.print ("               ");
  delay (1000);

  lcd.setCursor (2,1);
  lcd.print ("V = ");     lcd.print (Vitesse_Reelle);     lcd.print (" km/h");

  delay (10000);

  Test_Choix_Echelle();
}

