// Shaft encoder tester
// determines frequency of each single output, stepped through by button
// direction indication from external logic circuit
// Requires external power source to operate circuit and attached encoder
//
// R. Parnell
// 28/8/21
// further work 29/3/22

//1/9/21 - read direction inputs. If both zero, then display stopped" and cycle through
// until one goes high



#include <FreqCount.h>//https://github.com/PaulStoffregen/FreqCount/archive/master.zip
#include <LiquidCrystal.h>

// A, not A, B, not B selector outputs - Arduino D7, D8, D9, D10
// selector button to D13
// D5 is digital frequency input to measure
//

int button = 0; // button value 0 or 1
int selection = 1; // selection of inputs D7 to D10 to be cycled through. (Values 1 to 4)
int but = 13; // D13 input for button
int Dir1 = 4; // analogue A4 for direction input 1
int Dir2 = 5; // analogue A5 for direction input 2
int DirF = 0; // variable value for Forward direction input (analogue A4)
int DirR = 0; // variable value Reverse direction input (analogue A5)

// D5 is frequency input pin to read from. This is apparently the only pin that can be used.
// Therefore, externally switch one of four inputs to D5 via external logic, interfaced with Nano. 28/3/22 
// quad input AND gate - each input to one AND gate input. Nano D7-11 outputs to other respective AND gate inputs.
// 4x AND gate outputs fed to 4input OR gate, output to D5 input on Nano?

// read button value. If pressed, increment quadrature input by 1 and loop through all 4 inputs

LiquidCrystal lcd(12, 11, 6, 4, 3, 2);// Arduino D12, D11, D6, D4, D3, D2 to LCD ARS,E,D4,D5,D6,D7
void setup() {
  lcd.begin(16, 2);// LCD 16X2
  
  // initialise
  lcd.setCursor(0,0); 
  lcd.print("  Quadrature    ");
  lcd.setCursor(0,1);
  lcd.print(" encoder tester ");
  delay (3500);
  lcd.setCursor(0,0); 
  lcd.print(" Robert Parnell ");
  lcd.setCursor(0,1);
  lcd.print("* August 2021  *");
  delay (3500);
  lcd.setCursor(0,0); 
  lcd.print("                ");
  lcd.setCursor(0,1); 
  lcd.print("                ");
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(but,INPUT);
  pinMode(but,INPUT_PULLUP);
  FreqCount.begin(1000);
  
}
unsigned long f;float f0;
int x,n=3,r;
int speed;

void loop() {
  
  // read input selector button
  
  button = digitalRead(but);
  
  if (button == 0){ // button has been pressed, active LOW
    selection = selection + 1;
    if (selection == 5) {(selection = 1);}
   }
    if (selection == 1){
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      digitalWrite(10, LOW);
      digitalWrite(7, HIGH);
      
    }
    if (selection == 2){
      digitalWrite(9, LOW);
      digitalWrite(10, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, HIGH);
      
    }
    if (selection == 3){
      digitalWrite(8, LOW);
      digitalWrite(10, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, HIGH);
      
    }
    if (selection == 4){
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      digitalWrite(7, LOW);
      digitalWrite(10, HIGH);
      
    }
    
  // read direction status
 DirF = analogRead(Dir1); // these are active HIGH
 DirR = analogRead(Dir2);

//if (DirF < 500 && DirR < 500){
  if (DirF < 500 && DirR < 500 && f<=10){ // added 28/3/22. Only show idle if frequency is effectively zero.
    // both direction inputs are low, nothing is happening or a fault
    // both cannot be high
     lcd.setCursor(9,1);
  lcd.print(" <IDLE>");
    
  }
  if (DirF > 500){
    lcd.setCursor(9,1);
  lcd.print("Dir=FOR");
    
  } else 
  if (DirR > 500){
    lcd.setCursor(9,1);
  lcd.print("Dir=REV");
    
  }
  
  //if(digitalRead(selection)==HIGH){n++;x=0;delay(100);}
  //  lcd.setCursor(0,1);
  if(n==1){x++;if(x==1){FreqCount.begin(100);}r=-1;}
  if(n==2){x++;if(x==1){FreqCount.begin(10000);}r=1;}
  if(n==3){x++;if(x==1){FreqCount.begin(1000);}r=0;}
  if(n>3){n=1;} // 
    lcd.setCursor(0,0);
    lcd.print("F");
    lcd.print(selection); //the input selected (1-4) of D7 to D10
    lcd.print("= ");
    speed = (f/157823)*150; // calculate rough speed 
  if(f>=1000000 && n==3){f0=f/1000000.0;lcd.print(f0,6+r);lcd.print(" MHz");}
  if(f<1000000 && n==3){f0=f/1000.0;lcd.print(f0,3+r);lcd.print(" kHz");}
  if(f>=100000 && n==1){f0=f/100000.0;lcd.print(f0,6+r);lcd.print(" MHz");}
  if(f<100000 && n==1){f0=f/100.0;lcd.print(f0,3+r);lcd.print(" kHz");}
  if(f>=10000000 && n==2){f0=f/10000000.0;lcd.print(f0,6+r);lcd.print("MHz");}
  if(f<10000000 && n==2){f0=f/10000.0;lcd.print(f0,3+r);lcd.print(" kHz");}

  
  lcd.setCursor(0,1);
  lcd.print(speed);
  lcd.print("km/h");
  
  
  
  
  if (FreqCount.available()) { 
   
    f = FreqCount.read(); 
    
   //lcd.setCursor(10,1);lcd.print("***");
  }
   delay(200);
   lcd.clear();
}