/****************************************************************************************
 *  Code is based on Blynk USB-Serial Example
 *  Make sure you go to C:\Users\Your Username\Documents\Arduino\libraries\Blynk\scripts
 *  Press CTRL + LMouse Button and select Open Command Windows Here
 *  Then type in command windws >> blynk-ser.bat -c COM2 and click enter
 *  Enjoy the Virtual IoT !!!
 ****************************************************************************************/
#include <BlynkSimpleStream.h>
#include <SimpleTimer.h> //Timer to update encoder count

// Pin Assignments
int  pinMotor=10;                                   // PWM Pin for Motor Speed.
int  pinEncoder=2;                                 //  Pin to receive XORed (double resolution) encoder pulses.
volatile unsigned int counter=0;                  //   Counter to hold counted pulses.
unsigned int motorSpeedRPM=0;                    //    Calculated motor speed from encoder value.
SimpleTimer timer;                              //     Timer object for polling counter value every 1 sec.
const long udpateInterval=1000L;               //      Timer update value (1000 ms)
const float pulsesPerRevolution=24*2.0;  //       Pulses per revolution (Servo Motor-Proteus)

//Your app authentication token (can be fetched from your blynk app
char auth[] = "2273348720d2405c92584041e6914e5b";

// This function sends Arduino's up time every 1 second to Virtual Pin (2).
// In the app, Widget's reading frequency should be set to PUSH. This means
// that you define how often to send data to Blynk App.
void updateSpeedEvent()
{
  motorSpeedRPM=((counter/(udpateInterval/1000.0))*60.0)/pulsesPerRevolution; //RPM speed
  Blynk.virtualWrite(V2, motorSpeedRPM); //send RPM value to gauge
  counter=0; //reset counter;
}


void setup()
{
  //Set the Motor pin as output
  pinMode(pinMotor,OUTPUT);
  //Set Encoder pin as input
  pinMode(pinEncoder,INPUT);
   
  // Blynk will work through Serial
  Serial.begin(9600);
  Blynk.begin(auth, Serial);

  // Setup a function to be called every 1 sec.
  timer.setInterval(udpateInterval, updateSpeedEvent);

  // Interrupt for accurate counting of encoder pulses
  attachInterrupt(digitalPinToInterrupt(pinEncoder), encoderCounter, RISING);
}

// This function corresponds to changes in slider 
// Which will change motor speed via PWM
BLYNK_WRITE(V1)
{
  int motorSpeed = param.asInt(); // assigning incoming value from pin V1 to a variable
  analogWrite(pinMotor,map(motorSpeed,0,100,0,255)); //Map motor slider (0-100)==>(0-255)
}

void loop()
{
  // All the magic is here
  Blynk.run();
  timer.run(); // Initiates SimpleTimer
}

// Interrupt Service Routine (ISR)
void encoderCounter()
{
    counter+=1; //a pulse received
}
