/*This is the V3.01 turret control program for the DAV5 3D printable Raman Spectrometer.

  it utilizes a KY-040 encoder to control the holographic diffraction grating
  at steps of 4 & -4, full project details can be found here @ https://hackaday.io/project/18126-dav5-v301-raman-spectrometer
  This program is also in the public domain @ http://playground.arduino.cc/Main/KY-040EncodeUsedToControlAHolographicDiffractionGratingForARamanSpectrometer */

  1. include <Wire.h>
  2. include <LiquidCrystal_I2C.h>
  3. include "Stepper.h"
  4. define STEPS 1024 // Number of steps for one revolution of Internal shaft

// 2048 steps for one revolution of External shaft

  1. define outputA 2
  2. define outputB 3

int counter = 0; int aState; int aLastState;

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address

volatile boolean TurnDetected; // need volatile for Interrupts volatile boolean rotationdirection; // CW or CCW rotation

const int PinCLK = 2; // Generating interrupts using CLK signal const int PinDT = 3; // Reading DT signal const int PinSW = 4; // Reading Push Button switch

int RotaryPosition = 0; // To store Stepper Motor Position

int PrevPosition; // Previous Rotary position Value to check accuracy int StepsToTake; // How much to move Stepper

// Setup of proper sequencing for Motor Driver Pins // In1, In2, In3, In4 in the sequence 1-3-2-4 Stepper small_stepper(STEPS, 8, 10, 9, 11);

// Interrupt routine runs if CLK goes from HIGH to LOW void isr () {

  delay(5);  // delay for Debouncing
  if (digitalRead(PinCLK))
    rotationdirection = digitalRead(PinDT);
  else
    rotationdirection = !digitalRead(PinDT);
  TurnDetected = true;

}

void setup () {

  lcd.begin(20, 4);        // initialize the lcd for 20 chars 4 lines, turn on backlight
  // ------- Quick 3 blinks of backlight  -------------
  for (int i = 0; i < 3; i++)
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight(); // finish with backlight on
  // set up the LCD's number of columns and rows:
  lcd.begin(20, 4);
  // Print a message to the LCD.
  lcd.print("SYS RDY:");
  lcd.setCursor(8, 0);
  lcd.print(" Mega 2560");
  lcd.setCursor(0, 1);
  lcd.print("CurrentPosition:");//CCW or CC
  lcd.setCursor(0, 2);
  lcd.print("ShaftPostion:");//4th line for version display
  lcd.setCursor(0, 3);
  lcd.print("V3.01 Turret Control");
  Serial.begin(115200);

  pinMode (outputA, INPUT);
  pinMode (outputB, INPUT);

  // Reads the initial state of the outputA
  aLastState = digitalRead(outputA);

  pinMode(PinCLK, INPUT);
  pinMode(PinDT, INPUT);
  pinMode(PinSW, INPUT);
  digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
  attachInterrupt (0, isr, FALLING); // interrupt 0 always connected to pin 2 on Arduino UNO

}

void loop () {

  aState = digitalRead(outputA); // Reads the "current" state of the outputA
  // If the previous and the current state of the outputA are different, that means a Pulse has occured
  if (aState != aLastState) {
    // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
    if (digitalRead(outputB) != aState) {
      counter ++;
    } else {
      counter --;
    }
    lcd.setCursor(16, 1);
    lcd.print(counter ++);//CCW or CC

  }
  aLastState = aState; // Updates the previous state of the outputA with the current state

  small_stepper.setSpeed(10); //Max seems to be 700
  if (!(digitalRead(PinSW))) {   // check if button is pressed
    if (RotaryPosition == 0) {  // check if button was already pressed
    } else {
      small_stepper.step(-(RotaryPosition * 10));
      RotaryPosition = 0; // Reset position to ZERO
      lcd.setCursor(14, 2);
      lcd.print(-(RotaryPosition * 10));
    }
  }

  // Runs if rotation was detected
  if (TurnDetected)  {
    PrevPosition = RotaryPosition; // Save previous position in variable
    if (rotationdirection) {
      RotaryPosition = RotaryPosition - 1;
    } // decrase Position by 1
    else {
      RotaryPosition = RotaryPosition + 1;
    } // increase Position by 1

    TurnDetected = false;  // do NOT repeat IF loop until new rotation detected

    // Which direction to move Stepper motor
    if ((PrevPosition + 1) == RotaryPosition) { // Move motor CW
      StepsToTake = 4;
      small_stepper.step(StepsToTake);
    }

    if ((RotaryPosition + 1) == PrevPosition) { // Move motor CCW
      StepsToTake = -4;
      small_stepper.step(StepsToTake);
    }
  }

}

Share