You are on page 1of 4

/* When you turn the rotary encoder clockwise, the angular

displacement is increased;
when you turn it counterclockwise, the displacement is decreased.
If you press the switch on the rotary encoder, the readings will return to zero
Original code can be found here://Email: support@sunfounder.com
//Website: www.sunfounder.com
//2015.5.7/
**Although this is in the Public Domain, I have created a "Creative Commons
License" for this work,
the reason is, I made enough mod's and put in many hours of work to make this
program accurate and
efficient as part of a much larger project @ Hackaday.com, the DAV5 3D Printable
Raman Spectrometer.
There are individuals there that have engaged in "intellectual theft" and not
bothered to give credit
where credit was certainly due, so I believe I have no choice but to go this
route since I have put in
2 years of very hard work on this.**
The creative commons license can be viewed here: http://thequantumhub.blog/
I have modified this code to accomodate my diffraction grating turret for
the DAV5 Raman 3D printable Spectrometer (http://hackaday.io/project/18126-dav5-
v301-raman-
spectrometer)
Written and modified by David H Haffner SR 10/18/2017
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
It utilizes a KY-040 encoder to control the holographic diffraction grating
at steps of 1 & -1, each pin (SW,DT and CLK) has a 0.1uf ceramic cap for
decoupling,
this is more effective for rise time spike removal. There are 2 LED indicators, a
red for encoder step
movements and
a yellow for home position indication that will light when the shaft docks back
to a pre-determined home
position,(I'm still
working on it,)This is accomplished by adjusting both "StepsToTake and
RotoryPosition," they are in direct
relation to steps per revolution
of the internal shaft according to the type of stepper motor you are using (mine
is a 28-YBJ-48).Fine tuning
can be done by playing between
STEPS (per revolution of shaft) and Speed, this will ensure smoother transitions
when turning the encoder
for fewer misses.
If you press the switch on the rotary encoder, the readings will return to approx
zero (+/- 0.71) 0.21 percent
error.
a 0.1uf ceramic Cap is placed @ PinSW (4) to GND (the reason for the pin pullup
The formula in this sketch is derived from the specifications of the 28-YBJ-48
stepper MTR
which has a step angle of 5.62deg, to convert degrees into nanometers you 1st
have to convert
degrees into radians {RAD}, we do this for the 1st specification which is
5.625deg = 0.09817474 {RAD}
this # is then divided by the equitorial radius of the Earth which is 3,963.2
miles.
Our new value would then be, 0.000024772 miles (NM)
Now with this #, we mutiply it by the constant of 1 (NM) = 1609344e+012 miles
*(Variable)/56.5
gives us our converting factor from encoder position count to nanometer counts.
* /
1. include <Wire.h>
2. include <LiquidCrystal_I2C.h>
3. include "Stepper.h"
4. define STEPS 64 // Number of steps for one revolution of Internal
shaft
// 2048 steps for one revolution of External shaft LiquidCrystal_I2C
lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the
LCD I2C address
double double_x = .000024772 * 1609344E+012 * 0 / 56.5;
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(7); // delay for Debouncing
if (digitalRead(PinCLK))
rotationdirection = digitalRead(PinDT);
else
rotationdirection = !digitalRead(PinDT);
digitalWrite(12, HIGH); // Tracks the detents of the encoder
delay(1);
digitalWrite(12, LOW);
delay(1);
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("SYSTEM RDY");
lcd.setCursor(10, 0);
lcd.print(" Mega 2560");// system ready wired to Pin#13 built-in LED (blinks
twice to indicate "system
ready.")
lcd.setCursor(0, 1);
lcd.print("ShaftPOS:");//CCW or CC
lcd.setCursor(0, 2);
lcd.print("WVLngth[NM]");// Previous shaft position
lcd.setCursor(0, 3);
lcd.print("Correctd");// Float Position corrected
Serial.begin(115200);
delay(1000);
pinMode(12, OUTPUT);// tracks the detent pins of the KY_040 encoder/turns off
when button is pressed
pinMode(PinCLK, INPUT);
pinMode(PinDT, INPUT);
pinMode(PinSW, INPUT_PULLUP);// pullup resistor needed for switch stability
digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
attachInterrupt (0, isr, FALLING); // interrupt 0 always connected to pin 2 on
Arduino UNO
}
void loop () {
small_stepper.setSpeed(100); //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 * 0.711);
RotaryPosition = 0; // Reset position to ZERO
lcd.setCursor(14, 2);
lcd.print(.000024772 * 1609344 * PrevPosition / 56.5);
}
}
// Runs if rotation was detected
if (TurnDetected) {
PrevPosition = RotaryPosition; // Save previous position in variable
if (rotationdirection) {
RotaryPosition = RotaryPosition - 1;
lcd.setCursor(14, 1);
lcd.print(RotaryPosition);
} // decrase Position by 1
else {
RotaryPosition = RotaryPosition + 1;
lcd.setCursor(14, 1);
lcd.print(RotaryPosition);
} // 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 = 1;
small_stepper.step(StepsToTake);
lcd.setCursor(15, 3);
lcd.print(fabs(+(PrevPosition) * 0.712)); // absolute value of a float, steps
in + direction
delay(1);
}
if ((RotaryPosition + 1) == PrevPosition) { // Move motor CCW
StepsToTake = -1;
small_stepper.step(StepsToTake);
lcd.setCursor(9, 3);
lcd.print(fabs(-(PrevPosition) * 0.712)); // absolute value of a float, steps
in - direction
delay(1);
}
}
}

You might also like