/*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 @ https://playground.arduino.cc/Main/KY-040EncodeUsedToControlAHolographicDiffractionGratingForARamanSpectrometer */
// 2048 steps for one revolution of External shaft
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); } }
}