DIY Spectrometer) Explore the Unknown ->

by simonfrfr in Circuits > Arduino

118705 Views, 668 Favorites, 0 Comments

DIY Spectrometer) Explore the Unknown ->

IMG_0735 (1).JPG
figure_1.png
DIY Spectrometer Explore the Unknown
SpectrometerSchematic.PNG
SpectrometerBoard.PNG

Hey Guys! A Spectrometer is useful for detecting impurities in water and in other substances, or even just telling us what wavelength something is! If you have a mystery laser and you want to know the wavelength, you grab a laser with a known wavelength, and calibrate the Spectrometer, simply by taking measurements and then poof, a scan is done and then you know the wavelength. Spectrometers are super useful in optics, and you can tell the different wavelengths of light.

**Please click on the orange vote ribbon in the upper right-hand corner of this page if you enjoy this Instructable.**

I have attached at the end of this tutorial documents related to the construction and development of this spectrometer. Also, a special thanks to Altium for sponsoring the project! Altium provides circuit design software and you can visit their website at http://www.Altium.com/

Also Altium will be releasing their new Hobby Software for FREE, check it out at: circuitmaker.com!

Now you can download the files for this PCB on the Second Last Step of this Instructable!

What You Will Need

IMG_0702.JPG
IMG_0661.JPG
IMG_0671.JPG
545adce5ec8d83da1a000001.jpeg
12287-01.jpg
IMG_0726.JPG
IMG_0751.JPG
IMG_0767.JPG
IMG_0768.JPG
09567-01-Working.jpg
00718-01.jpg

There a various supplies that you will need for this project; this project takes about an hour or two to build. You Will need:

A CD Drive to take apart appx. $20 (Example: http://www.newegg.com/Product/Product.aspx?Item=N8... )

MSP430 or Arduino ($10 MSP430 or $10 Arduino Pro Mini [or equivalent e.g. Leonardo, Mega, UNO])

EasyDriver Stepper Motor Driver $15

A CD/DVD (Example: http://www.newegg.com/Product/Product.aspx?Item=N8... )

Two 90 Degree surfaces (Can be even be two small boxes)

PhotoTransistor/LDR to detect light $1.50->$5.00 (I used a phototransistor and a photodiode)

Lots of Breadboard Wires/Jumpers (Male and Female or Male/Female

A USB Serial Converter or even just your Arduino/MSP Board $15 (I prefer a Serial Converter)

Several Screwdrivers (One needs to be the tiny sort used for eyeglasses repair $1)

Male Headers (Better to have more of these than you need for just this project)

Solder

A Soldering Iron

Hot Glue Gun

Double Sided Tape

A USB mini-B cord

Small BreadBoard

Tweezers or Xacto-Knife

Twist Ties

Reminder: You can probably get all of these items for a much lower price at Amazon and/or Ebay, but these are some of the distributors which will most likely have these products for some time.

Now to Take Apart the CD Drive

IMG_0702 (1).JPG

First you will need to take apart the CD Drive to use the parts for the project. There are many valuable parts in the disk drive and I'd recommend keeping all of the extra harvested motors, optics and parts (There is even a Laser Diode)

So all you need for now is the CD Drive and a Phillips Screw Driver

Unscrew the First Set of Screws

IMG_0703.JPG
IMG_0704.JPG

On the Bottom of the CD Drive there should be a set of four screws to allow for one to access the drive.

Take the Top Off

IMG_0708.JPG

Now that you have removed the screws, you can now simply take off the Panel. This Flat(ish) panel will be used at a later time to mount all of the parts.

Note: You may not actually have to pry off the top, but in my two cases I needed to.

Now Start Taking Out the Circuit Boards

IMG_0709.JPG
IMG_0711.JPG
IMG_0712.JPG

Now start removing the circuit boards inside of the CD Drive. It should be relatively easy; mine did not have any screws, but only clips. Depending on the CD drive that you have will be dependent on what you actually need to do to take out the circuit board. You can also start disconnecting the wires. Try not to break the wires. (I know sometimes it is hard not to accidentally break a wire, but is not really a requirement, but do not break the stepper Motor wire)

Now to Get the Metal Frame Off...

IMG_0714.JPG
IMG_0713.JPG
IMG_0715.JPG
IMG_0716.JPG
IMG_0717.JPG

Now very simply get a screwdriver to push the two tabs on each side of the disk drive, then you should be able to pry the drive open from the top side. Take the metal frame off; you will not need this for the project (unless you want to use it as a 90 degree mount...) It might be a little hard at first to take off, but if you try to pry if off and it starts coming out, it might just a bit hard to take off.

Now Make the Disk Drive Go Out.

IMG_0718.JPG
IMG_0719.JPG
IMG_0720.JPG

Take a battery and attach it to the two leads of the DC motor. This will allow for the motor to spin in a direction. If the motor is running and the disk tray is not coming out, then try switching the Polarity (+ and - of the the Battery on the motor) The tray should come out.

Take Out the Sensor Bay

IMG_0721.JPG
IMG_0722.JPG

Unscrew screws mounting down the Sensor Bay. Then Take out the Sensor bay.

Unscrew the Brushless Motor

IMG_0724.JPG
IMG_0725.JPG

Unscrew the Brushless Motor. You will not need this for this project, but you can save it for later. In this case though, the Stepper motor is attached to the brushless motor subassembly and you will need to desolder the connector at a later time to wire the Stepper Motor.

Grab Your Small Screwdriver

IMG_0726 (1).JPG

Now you need to grab your small screwdriver to take out the current sensor and laser array.

Take Out the Sensor/Laser Array

IMG_0727 (1).JPG
IMG_0729 (1).JPG
IMG_0730 (1).JPG
IMG_0728 (1).JPG
IMG_0731 (1).JPG
IMG_0732 (1).JPG
IMG_0733 (1).JPG
IMG_0736 (2).JPG
IMG_0737 (1).JPG

Start unscrewing all of the screws that are holding down the sensor array and Laser diode. Then pry the boards off, because they are glued to the assembly. Be careful it might be a good idea to not break any of the connections just in case you want to use some of the parts for another project.

Take Out the Rubbery Things and the Beamsplitter Lens

IMG_0738.JPG
IMG_0739.JPG

First take out all of the large rubber things in the mounting holes, then take out the beamsplitter inside of the assembly head.

Glue Your Sensor

54609cb5ec8d83fe61000133.jpeg
IMG_0742.JPG

Depending on what intensity you are expecting, and the angles that you want to hit your sensor, you can either mount it on the front, where there is a greater chance of being hit by light, or inside of the assembly head where there are less chances of being hit by a beam of light.

Mount the Linear Assembly

IMG_0743.JPG
IMG_0704 (1).JPG
IMG_0744.JPG
54609e47ec8d83dbc8000031.jpeg

Grab your 90 Degree mount and the base that you took off before and then the assembly. Glue all of the parts together in such a fashion that the long-ways of the assembly is up and the short-ways of the assembly is parallel to the short-ways of the base-plate.

Grab Your CD/DVD and Tweezers

IMG_0751 (2).JPG

Get your CD and tweezers because its time to take apart a CD/DVD!

Taking Apart the CD/DVD

IMG_0752 (1).JPG
IMG_0754 (1).JPG
IMG_0756.JPG

First grab your tweezers or X-acto knife and a CD/DVD. Simply separate the disk into two by placing the tweezers between the two layers from the center hole of the disk. Then go all the way though and soon you will have two disks.

Getting Your Diffraction Grating

IMG_0757.JPG
IMG_0759.JPG
IMG_0760.JPG
IMG_0761.JPG

Now get the disk that does not have the picture on it, and cut a part of the disk that does not have any silvery material on it. This will be your diffraction Grating. (It might not be purple, it depends on the CD/DVD)

Placing the Grating

IMG_0763.JPG
IMG_0762.JPG
IMG_0768 (1).JPG
IMG_0769.JPG
IMG_0771.JPG
IMG_0772.JPG

Grab your second mounting block and put double sided sticky tape on the diffraction grating and the and 90 Degree mount. Then in order to be able to adjust the location of the mount put double sided sticky tape on the bottom too so that the grating can be moved for one position to another.

Starting With the Electronics

IMG_0725 (1).JPG
IMG_0645.JPG
IMG_0648.JPG
IMG_0650.JPG
IMG_0651.JPG
IMG_0654.JPG
IMG_0655.JPG
IMG_0656.JPG

Remember that Connector that I told you to hold onto? Well now you need the Stepper Motor connector so that you can interface with the Stepper Motor. So desolder the connector and solder it to Four header leads so that it can be accessed more easily. After soldering, then reattach the connector to the Stepper Motor.

Set Up the Stepper Controller

IMG_0649 (2).JPG
IMG_0658.JPG
IMG_0659.JPG
IMG_0660.JPG

Grab the Stepper Motor controller and some header that are One 1x4 pin One 1x3 pin and Two 1x2 pin headers. Solder these headers onto the Motor Ports A and B; M+ and GND; GND, DIR and STEP; and 5V pins. VERY IMPORTANT: IF YOU ARE USING THE MSP430 THEN YOU WILL NEED TO ALSO SHORT THE 3/5V JUMPPER SO THAT THE MSP430 IS SAFE.

Readying the Chip and the Stepper Controller

IMG_0661 (1).JPG
IMG_0662.JPG

Put the MSP430G2553 and Stepper Driver on a Breadboard. Mount the breadboard to the base plate.

Wire the Stepper Motor

IMG_0664.JPG
IMG_0665.JPG

Now wire the Stepper Motor. Read the pictures for a better description, but basically you just need to attach wires from the stepper to the Stepper A ports and Stepper B ports.

Wire the GNDs and VCCs

IMG_0666.JPG
IMG_0668.JPG
IMG_0669.JPG
IMG_0674.JPG
IMG_0676.JPG
IMG_0677.JPG
IMG_0687.JPG

Now just wire each GND to the Negative Rail and M+ to the right positive rail and All of the rest of the VCCs to the left Positive Rail.

Wire the Stepper Control to MSP430

IMG_0679.JPG
IMG_0683.JPG
IMG_0686.JPG

Connect STEP to P2_4 and DIR to P2_5. Then the control for the Stepper is established.

Attaching the Sensor

IMG_0693.JPG
IMG_0694.JPG
IMG_0697.JPG

Now attach one of the two wires to the GND or VCC (User Preference) and the other to P1_3.

Attach the Serial Conveter

IMG_0701.JPG

Connect RX from the Serial Converter to the fourth pin on the left of the MSP430G2553 (P1_2) and TX to the Third pin on the left of the MSP430G2553 (P1_1). And attach GND to one of the - rails.

Calibrate Your Machine!

546188b7ec8d835113000002.jpeg
IMG_0772 (1).JPG
546188ceec8d830bba000031.jpeg

Grab your calipers or measuring utensil and measure two distances: Distance between the center dot and the diffracted dot and the distance from the grating to the assembly (X Axis). First measure the distance to the Assembly head. Next shine your laser at the diffraction grating and mark where the bottom dot is and move the assembly head to where to top dot is. Measure this distance; make sure to record these distances, you will need them in the next step.

The Code

Energia-Spectrometer.PNG

This code can be ported to Arduino IDE From Energia and works perfectly on both platforms.

You can download energia here: http://energia.nu/download/

CHANGE THE x AND THE D AND THE nm VARIABLES TO MATCH YOUR RESULTS FROM THE LAST STEP! Otherwise your calibration will be my calibration for my machine, not yours. It will then fail to provide accurate data.

The Below Code is for use with an SD card and Live stream.

#include "SPI.h" 
#include "pfatfs.h"

#define cs_pin      10             // chip select pin 
#define read_buffer 128             // size (in bytes) of read buffer 

  unsigned short int bw, br;//, i;
  char buffer[read_buffer];
  int rc;
  DIR dir;				/* Directory object */
  FILINFO fno;			/* File information object */

//I/O Below

const int StepperMotor = P2_4;
const int StepperDirection = P2_5;
const int Sensors[] = {P1_3}; // Add more sensors here!\

//Constants for calibration below!

const double nm = 405; // Known Calibration source Frequency
const double x = 33.28; // Distance of point above the "Screen"
const double D = 48.78; // distance to the "Screen"
const double degreesperstep = 18; // Degrees per step for the stepper motor
const double microstepping = 8; // This allows for you to determine how often you want the Sample to be taken (inverse microstep)
const double mmPerRotation = 2.76; // This is the distance between the two teeth of the spindle which moves the sensor up and down
const double heightofTray = 38.00; // Under estimate this a bit
const double starty = 32.35;
const boolean SDCARD = false;

/////////////////////////Fiddle with the below at your own risk!///////////////////////////////////////////
const double stepsperrotation = 360/degreesperstep;
const double microstepsuntilend = heightofTray/mmPerRotation * stepsperrotation * (microstepping);
const double d = (nm*1e-9)/sin(atan(x/D));
//const double d = 720e-9;
//const double x = (nm*1e-9*d);
int wavelengthvIntensity[sizeof(Sensors)-1];
int datafile = 0;
double cnt = 0;
char buf[30];
double tempnm = 0;
double currenty = 0;
const double zero = starty-x;
char ksk = '0';

void setup() {                
  pinMode(PUSH2, INPUT_PULLUP);
  pinMode(StepperMotor, OUTPUT);     
  pinMode(StepperDirection, OUTPUT);
  digitalWrite(StepperMotor, LOW);
  digitalWrite(StepperDirection, LOW);
  Serial.begin(9600);            // initialize the serial terminal
  if (SDCARD == true){
  FatFs.begin(cs_pin);             // initialize FatFS library calls
  }
   for (int i=0;i<sizeof(wavelengthvIntensity);i++) {
     pinMode(Sensors[i], INPUT);
   }
   for (int i = 0; i < microstepsuntilend; i++) {
    digitalWrite(StepperMotor, HIGH);
    delayMicroseconds(250);          
    digitalWrite(StepperMotor, LOW); 
    delayMicroseconds(250);   
   }
   digitalWrite(StepperDirection, HIGH);
}
void die (int pff_err){
         Serial.println();Serial.print("Failed with rc=");Serial.print(pff_err,DEC);
         for (;;) ;
  }
void writedata() {
        rc = FatFs.open("Data.csv");
	if (rc) die(rc);

	Serial.println();
        Serial.println("Writing scan Data");
        delay(100);
        bw=0;
        for (int i=0;i<sizeof(wavelengthvIntensity);i++) {
                sprintf( buf, "%lu, ",wavelengthvIntensity[i]);
                int StringLength =  strlen(buf);
		rc = FatFs.write(buf, StringLength, &bw);
                if (rc || !bw) break;
	}
        
        sprintf( buf, "%lu\n\r",tempnm);
        int StringLength =  strlen(buf);
	rc = FatFs.write(buf, StringLength, &bw);
	if (rc) die(rc);
	rc = FatFs.write(0, 0, &bw);  //Finalize write
        if (rc) die(rc);
        rc = FatFs.close();  //Close file
	if (rc) die(rc);
}
void loop() {
  if (ksk == '1') {
    ksk = 0;
    cnt = 0;
 while (cnt < microstepsuntilend) {
  for (int i=0;i<sizeof(wavelengthvIntensity)-1;i++) {
    wavelengthvIntensity[i] = analogRead(Sensors[i]);
    Serial.print(wavelengthvIntensity[i]);
    Serial.print(", ");
  }
  Serial.println(tempnm);
  if (SDCARD == true) {
    writedata();
  }
  digitalWrite(StepperMotor, HIGH);
  delayMicroseconds(1);          
  digitalWrite(StepperMotor, LOW); 
  delayMicroseconds(1);       
  cnt++;
  //Serial.println(currenty);
  currenty = zero+((cnt/microstepsuntilend)  * heightofTray);
  tempnm = d*sin(atan((x+currenty)/D))*(1e9);
  }
  digitalWrite(StepperDirection, LOW);
  for (int i = 0; i < microstepsuntilend; i++) {
    digitalWrite(StepperMotor, HIGH);
    delayMicroseconds(250);          
    digitalWrite(StepperMotor, LOW); 
    delayMicroseconds(250);   
   }
   digitalWrite(StepperDirection, HIGH);
  Serial.println("$");
  }
  ksk = Serial.read();
}

The Code Below is the Code for the spectrometer: Live Mode Only.

//I/O Below

const int StepperMotor = P2_4;
const int StepperDirection = P2_5;
const int Sensors[] = {P1_3}; // Add more sensors here!\

//Constants for calibration below!

const double nm = 405; // Known Calibration source Frequency
const double x = 37.65; // Distance of point above the "Screen"
const double D = 50.00; // distance to the "Screen"
const double degreesperstep = 18; // Degrees per step for the stepper motor
const double microstepping = 8; // This allows for you to determine how often you want the Sample to be taken (inverse microstep)
const double mmPerRotation = 2.76; // This is the distance between the two teeth of the spindle which moves the sensor up and down
const double heightofTray = 38.00; // Under estimate this a bit
const double starty = 32.35;

/////////////////////////Fiddle with the below at your own risk!///////////////////////////////////////////
const double stepsperrotation = 360/degreesperstep;
const double microstepsuntilend = heightofTray/mmPerRotation * stepsperrotation * (microstepping);
const double d = (nm*1e-9)/sin(atan(x/D));
//const double d = 720e-9;
//const double x = (nm*1e-9*d);
int wavelengthvIntensity[sizeof(Sensors)-1];
int datafile = 0;
double cnt = 0;
char buf[30];
double tempnm = 0;
double currenty = 0;
const double zero = starty-x;
char ksk = '0';

void setup() {                
  pinMode(PUSH2, INPUT_PULLUP);
  Serial.begin(9600);  // Hah, I forgot to add this in Special thanks to tommy_goh1997 for spotting the bug!
  pinMode(StepperMotor, OUTPUT);     
  pinMode(StepperDirection, OUTPUT);
  digitalWrite(StepperMotor, LOW);
  digitalWrite(StepperDirection, LOW);
   for (int i=0;i<sizeof(wavelengthvIntensity);i++) {
     pinMode(Sensors[i], INPUT);
   }
   for (int i = 0; i < microstepsuntilend; i++) {
    digitalWrite(StepperMotor, HIGH);
    delayMicroseconds(250);          
    digitalWrite(StepperMotor, LOW); 
    delayMicroseconds(250);   
   }
   digitalWrite(StepperDirection, HIGH);
}
void loop() {
  if (ksk == '1') {
    ksk = 0;
    cnt = 0;
 while (cnt < microstepsuntilend) {
  for (int i=0;i<sizeof(wavelengthvIntensity)-1;i++) {
    wavelengthvIntensity[i] = analogRead(Sensors[i]);
    Serial.print(wavelengthvIntensity[i]);
    Serial.print(", ");
  }
  Serial.println(tempnm);
  digitalWrite(StepperMotor, HIGH);
  delayMicroseconds(1);          
  digitalWrite(StepperMotor, LOW); 
  delayMicroseconds(1);       
  cnt++;
  //Serial.println(currenty);
  currenty = zero+((cnt/microstepsuntilend)  * heightofTray);
  tempnm = d*sin(atan((x+currenty)/D))*(1e9);
  }
  digitalWrite(StepperDirection, LOW);
  for (int i = 0; i < microstepsuntilend; i++) {
    digitalWrite(StepperMotor, HIGH);
    delayMicroseconds(250);          
    digitalWrite(StepperMotor, LOW); 
    delayMicroseconds(250);   
   }
   digitalWrite(StepperDirection, HIGH);
  Serial.println("$");
  }
  ksk = Serial.read();
}

Python

figure_1.png

First download python: https://www.python.org/downloads/. The packages that you will need for Matplotlib (to Graph) are: (Matplotlib), numpy, libpng, freetype, six, serial, dateutil, and pyparsing. If you are running debian/ubuntu you can apt-get them with sudo apt-get build-dep python-matplotlib If you are running windows then you can download all of them from http://www.lfd.uci.edu/~gohlke/pythonlibs/ That is what I use because of convince. All of the packages for windows are practically all on the same page, just do a ctrl+F and then you can find any of the packages you need.

Then you should be able to use my code for Graphing the information.

Edit the COM port in "Write Data.py" and run test6.py to run the Spectrometer. Press Rescan to read from the spectrometer.

Enjoy!

IMG_0646.JPG

Now you should have a working Spectrometer!

Enjoy!

If you need help or if I didn't explain something well, feel free to ask and I shall happily help you!

Thanks

Have a Great Day!

PCB Files

SpectrometerGerber.PNG

Attached are the Altium Project files and in the "Project Outputs for Spectrometer" Folder are the Drill Files and Gerber files for the 1 Layer board. This board consolidates all of the wiring steps into a simple PCB board that you just have to solder basic connectors on. You can get some here: https://oshpark.com/ or any other PCB manufacturer.

Downloads

References