Skip to content

Instantly share code, notes, and snippets.

@cibomahto
Created December 9, 2020 13:37
Show Gist options
  • Save cibomahto/021a3b777d9fcc0ed1abbd077ac35076 to your computer and use it in GitHub Desktop.
Save cibomahto/021a3b777d9fcc0ed1abbd077ac35076 to your computer and use it in GitHub Desktop.
plot.pde
// Modified sensor code for Arduino
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
/*
* Macro Definitions
*/
#define SPEC_TRG A0
#define SPEC_ST A1
#define SPEC_CLK A2
#define SPEC_VIDEO A3
#define WHITE_LED A4
#define LASER_404 A5
#define SPEC_CHANNELS 288 // New Spec Channel
uint16_t data[SPEC_CHANNELS];
inline void __attribute__((always_inline)) clockPulse() {
// digitalWrite(SPEC_CLK, HIGH);
// delayMicroseconds(delayTime);
// digitalWrite(SPEC_CLK, LOW);
// delayMicroseconds(delayTime);
// see: https://docs.google.com/spreadsheets/d/1zFkrNUWS6-ow6kGBxUObfnzK1ZsuW7VK3vRO1FoV8fc/edit#gid=0
bitSet(PORTF, PIN5);
bitClear(PORTF, PIN5);
}
void setup(){
//Set desired pins to OUTPUT
pinMode(SPEC_CLK, OUTPUT);
pinMode(SPEC_ST, OUTPUT);
pinMode(LASER_404, OUTPUT);
pinMode(WHITE_LED, OUTPUT);
//digitalWrite(WHITE_LED, HIGH); // Set SPEC_CLK High
digitalWrite(SPEC_CLK, HIGH); // Set SPEC_CLK High
digitalWrite(SPEC_ST, LOW); // Set SPEC_ST Low
Serial.begin(115200); // Baud Rate set to 115200
// Fast ADC clock (http://r6500.blogspot.com/2015/01/fast-adc-on-arduino-leonardo.html)
// ADCSRA=(ADCSRA&0xF80)|0x04;
}
/*
* This functions reads spectrometer data from SPEC_VIDEO
* Look at the Timing Chart in the Datasheet for more info
*/
void readSpectrometer(){
int delayTime = 1; // delay time
// Start clock cycle and set start pulse to signal start
digitalWrite(SPEC_CLK, LOW);
clockPulse();
// digitalWrite(SPEC_ST, HIGH);
// delayMicroseconds(delayTime);
bitSet(PORTF, PIN6);
//Sample for a period of time
for(int i = 0; i < 2500; i++){
clockPulse();
}
//Set SPEC_ST to low
// digitalWrite(SPEC_ST, LOW);
bitClear(PORTF, PIN6);
//Sample for a period of time
for(int i = 0; i < 85; i++){
clockPulse();
}
//One more clock pulse before the actual read
clockPulse();
//Read from SPEC_VIDEO
for(int i = 0; i < SPEC_CHANNELS; i++){
data[i] = analogRead(SPEC_VIDEO);
clockPulse();
}
digitalWrite(SPEC_CLK, HIGH);
delayMicroseconds(delayTime);
}
/*
* The function below prints out data to the terminal or
* processing plot
*/
void printData(){
for (int i = 0; i < SPEC_CHANNELS; i++){
Serial.print(data[i]);
Serial.print(',');
}
Serial.print("\n");
}
void loop(){
readSpectrometer();
printData();
delay(10);
}
//Processing sketch to display data + simple peak detector
import processing.serial.*;
Serial myPort;
String val;
int[] data;
float[] summed;
int sum_count = 0;
boolean draw_sum = false;
final int dc_offset = 100; // Correct for the DC offset in the measurement
final int POINT_COUNT = 289;
// Given calibration data and a sample, determine the wavelength
float wavelength(int pix) {
// Note; Replace these with the values for your sensr
final double A0 = 3.062951791E+02;
final double B1 = 2.720613040E+00;
final double B2 = -1.302773396E-03;
final double B3 = -7.101037823E-06;
final double B4 = 8.279199710E-09;
final double B5 = 5.742926217E-12;
//wavelength resolution = 9.2nm
double wavelength = A0 + B1*pix + B2*(pix^2) + B3*(pix^3) + B4*(pix^4) + B5*(pix^5);
return (float)wavelength;
}
float val(int i) {
if(draw_sum)
return summed[i]/sum_count;
else
return data[i];
}
void plotdata()
{
if(sum_count == 0)
return;
background(0);
stroke(255);
for (int i=0; i<data.length-1; i++) {
line(i, height, i, height-val(i));
}
final int window = 10;
final float noise_floor = 40;
int peak_count = 0;
stroke(255,0,0);
fill(255,0,0);
for (int i=window; i<(data.length-1-window); i++) {
boolean top = true;
for (int j = i-window; j < i+window; j++) {
if ((i != j) && (val(j) >= val(i))) {
top = false;
}
}
if (top && (val(i) > noise_floor)) {
ellipse(i, height-val(i),4,4);
text(wavelength(i), 20, 20+20*peak_count);
peak_count+=1;
}
}
}
void setup()
{
println(Serial.list());
String portName = Serial.list()[1]; //This is the index into the serial list, if you only have one serial device the index is 0
myPort = new Serial(this, portName, 115200);
summed = new float[POINT_COUNT];
for (int i = 0; i < POINT_COUNT; i++)
{
summed[i] = 0;
}
// Processign design bug: can't use a constant here.
size(289, 750);
}
void draw()
{
if ( myPort.available() <= 0)
return;
val = myPort.readStringUntil('\n'); // read it and store it in val
if (val == null)
return;
data = int(split(val, ','));
for(int i = 0; i < data.length; i++) {
data[i] = data[i] - dc_offset;
}
// Discard first frame if it is the wrong size
if(data.length != POINT_COUNT)
return;
for (int i = 0; i < data.length; i++) {
if (i<summed.length) {
summed[i] += data[i];
}
}
sum_count++;
plotdata();
}
void keyPressed() {
if (key == 'c' )
{
for (int i = 0; i < summed.length; i++)
{
summed[i] = 0;
}
sum_count = 0;
} else if (key == 't' )
{
draw_sum = !draw_sum;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment