Last active
February 16, 2016 02:31
-
-
Save pietroartoni/943137046d610120658b to your computer and use it in GitHub Desktop.
Spectrumino: an Arduino Due based tool for spectroscopy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*This sketch is for Arduino Due and is made for getting fast spectra in vivo. | |
The software asks for the first wavelength of the spectrum, the wavelength step, the length of the spectrum and for the laser intensity during the spectrum. | |
Imaging is triggered by the ECG signal, to be in phase with the heartbeat. | |
Feel free to fork it! Comments and suggestions are appreciated. | |
*/ | |
//global variables | |
double alpha; | |
int nframes = 10; //number of frames to be mediated for each wavelength | |
int lambdamin; //first lambda | |
int deltalambda; //lambda step | |
int n_scansioni; //number of wavelengths | |
int LEDred = 12; //activity led (busy) | |
int LEDgreen = 13; //activity led (free) | |
double potmisuratamW; //instantaneous measured power in mW | |
double potmisuratadouble; | |
double mediapotmisuratamW;//mediated measured power in mW | |
double epsilonS; | |
int TRIGGER_prairie = 3; | |
int SHUTTER = 4; //shutter of the microscope | |
int CHAMELEON = 9; //shutter of the chameleon laser | |
int i = 0; | |
int k = 0; | |
int epsilon = 5; | |
//boolean control flow variables | |
boolean pippo = false ; | |
boolean pippo2 = false ; | |
boolean pippo3 = true ; | |
boolean pippo4 = true ; | |
boolean pippo5 = true ; | |
boolean pippo6 = true ; | |
boolean pippo7 = true ; | |
//analog I/O | |
int pinpotmisurata = A0; //indicates the measured power | |
int heartbeat = A3; | |
int pinpotimposta = DAC0; | |
int potimposta; | |
int potmisurata; | |
double targetpower; | |
int powermax = 4090; //maximum voltage allowed by the pockels cell amplifier, is 2.00v but can be boosted to 2.25v. 16 bit value | |
int memo910 = 0; | |
int t0; | |
int t1; | |
double ratio; //ratio between measured power and target power | |
//setup section, this happens only once | |
void setup() { | |
//serial initialization | |
Serial.begin(19200); //debug | |
Serial1.begin(19200); //serial communication with the pc (termite serial monitor) | |
Serial3.begin(19200); //serial communication with the laser | |
//digital and analog pin definition | |
pinMode(potmisurata, INPUT); | |
pinMode(heartbeat, INPUT); | |
pinMode(TRIGGER_prairie, OUTPUT); | |
pinMode(SHUTTER, OUTPUT); | |
pinMode(CHAMELEON, OUTPUT); | |
pinMode(LEDred, OUTPUT); | |
pinMode(LEDgreen, OUTPUT); | |
pinMode(pinpotimposta, OUTPUT); | |
digitalWrite(CHAMELEON, HIGH); | |
} | |
//heartbeat synchronization function | |
void synchroheartbeat(void) | |
{ | |
int data = 0; | |
int trigger = 300; | |
int nbeat = 0; | |
int nbeatmax = 2; | |
bool pippolo = false; | |
delay(100); | |
while (nbeat < (nbeatmax + 1)) { | |
// dataold=data; | |
data = analogRead(heartbeat); | |
Serial.println(data); | |
if ((data > trigger) && (pippolo == false)) | |
{ nbeat++; | |
pippolo = true; | |
digitalWrite(LEDgreen, HIGH);//switch on the green led | |
delay(15); | |
} | |
if (data <= trigger) { | |
digitalWrite(LEDgreen, LOW); | |
//switch off the green led | |
pippolo = false; | |
} | |
} | |
digitalWrite(LEDgreen, LOW); | |
digitalWrite(CHAMELEON, HIGH); | |
digitalWrite(TRIGGER_prairie, HIGH); //send the trigger to the microscope | |
delayMicroseconds (20); | |
digitalWrite(TRIGGER_prairie, LOW); | |
delay (360); //time necessary for scanning + time necessary for measurements | |
digitalWrite(CHAMELEON, LOW); | |
} | |
//loop section, this happens continuosly | |
void loop() { | |
epsilonS = 0.002; | |
//12 bit resolution for reading and writing through A/D and D/A converters | |
analogReadResolution(12); | |
analogWriteResolution(12); | |
digitalWrite(LEDred, LOW); | |
digitalWrite(LEDgreen, LOW); | |
digitalWrite(SHUTTER, LOW); | |
analogWrite(pinpotimposta, 0); | |
if (pippo == true) { | |
t0 = millis(); | |
delay (100); | |
digitalWrite(TRIGGER_prairie, LOW); | |
digitalWrite(LEDred, HIGH); | |
digitalWrite(LEDgreen, LOW); | |
digitalWrite(SHUTTER, LOW); | |
potimposta = 0; | |
analogWrite(pinpotimposta, potimposta); | |
Serial1.println("Start spectrum (type q to stop acquisition)"); | |
for (i = 0; i < n_scansioni; i++) | |
{ | |
Serial1.print("\nlambda "); | |
Serial1.print(lambdamin + i * deltalambda); | |
Serial3.print("VW="); | |
Serial3.println(lambdamin + i * deltalambda); | |
delay (2000); //time needed by the laser to change the wavelength | |
if (i == 0) { | |
potimposta = 0; | |
mediapotmisuratamW = 0; | |
analogWrite(pinpotimposta, potimposta); | |
} | |
else { | |
//power measurement | |
mediapotmisuratamW = 0; | |
for (k = 0; k < 200; k++) | |
{ | |
potmisurata = analogRead(pinpotmisurata); | |
potmisuratadouble = potmisurata; | |
potmisuratamW = potmisuratadouble * 30 / 1186; | |
mediapotmisuratamW = potmisuratamW + mediapotmisuratamW; | |
} | |
mediapotmisuratamW = mediapotmisuratamW / 200; | |
Serial.println(mediapotmisuratamW); | |
} | |
alpha = 1; | |
if (lambdamin + i * deltalambda >= 900) { | |
alpha = 2 * (lambdamin + i * deltalambda - 900) / 100 + 1; | |
} | |
while ((abs(mediapotmisuratamW - targetpower) / targetpower) > epsilonS) | |
{ | |
//3 step algorithm for setting the power of the laser | |
ratio = mediapotmisuratamW / targetpower; | |
//decreases the power if too high | |
if ((ratio >= 1.0) && (ratio < 1.1)) | |
{ | |
potimposta = potimposta - alpha * 5; | |
} | |
if ((ratio >= 1.1) && (ratio < 1.40)) | |
{ | |
potimposta = potimposta - alpha * 10; | |
} | |
if (ratio >= 1.40) | |
{ | |
potimposta = potimposta - alpha * 50; | |
} | |
//increases the power if too low | |
if (ratio < 0.6) | |
{ | |
potimposta = potimposta + alpha * 50; | |
} | |
if ((ratio >= 0.6) && (ratio < 0.9)) | |
{ | |
potimposta = potimposta + alpha * 10; | |
} | |
if ((ratio >= 0.9) && (ratio < 1.0)) | |
{ | |
potimposta = potimposta + alpha * 5; | |
} | |
delay (50); | |
analogWrite(pinpotimposta, potimposta); | |
delay (100); //let the power meter do the measurement | |
//give 50 ms extra for the voltage rise, due to the low pass filter | |
//power measurement | |
mediapotmisuratamW = 0; | |
for (k = 0; k < 200; k++) | |
{ | |
potmisurata = analogRead(pinpotmisurata); | |
potmisuratadouble = potmisurata; | |
potmisuratamW = potmisuratadouble * 30 / 1186; | |
mediapotmisuratamW = potmisuratamW + mediapotmisuratamW; | |
} | |
mediapotmisuratamW = mediapotmisuratamW / 200; | |
Serial.println(mediapotmisuratamW); | |
//end of power measurement | |
if (potimposta > powermax) { | |
targetpower = 0; //for Pockels cell protection | |
Serial1.println("Error - too high power on the pockel cell"); | |
//exits the loop | |
}//exit from the if | |
if (Serial1.read() == 'q') { | |
Serial1.print("\nstopped "); | |
i = n_scansioni; | |
} //if the loop doensn't converge | |
}//exit from while | |
if ((lambdamin + i * deltalambda) == 900) { | |
memo910 = potimposta; | |
} | |
digitalWrite(SHUTTER, HIGH); | |
delay(200); | |
Serial1.print("frame n "); | |
for (int conta = 0; conta < nframes; conta++) { | |
synchroheartbeat(); //synchronization to the heartbeat, and image triggering | |
delay(300); | |
Serial1.print(""); | |
Serial1.print(conta + 1); | |
} | |
Serial1.println(""); | |
digitalWrite(CHAMELEON, HIGH); | |
Serial1.print(" - power = "); | |
Serial1.print(mediapotmisuratamW); | |
Serial1.println(" mW"); | |
digitalWrite(SHUTTER, LOW); | |
// event, if something is not right and the user wants to exit the scan | |
if (Serial1.read() == 'q') { | |
Serial1.print("\nstopped "); | |
i = n_scansioni; | |
} //exit from the if loop | |
} //exit from the for loop | |
digitalWrite(SHUTTER, LOW); | |
digitalWrite(LEDred, LOW); | |
digitalWrite(LEDgreen, HIGH); | |
potimposta = 0; | |
analogWrite(pinpotimposta, potimposta); | |
t1 = millis(); | |
Serial1.print("\n\n...finished! \nTime elapsed = "); | |
Serial1.print((t1 - t0) / 60000); | |
Serial1.print(" min and "); | |
Serial1.print(((t1 - t0) % 60000) / 1000); | |
Serial1.print(" s \n"); | |
pippo = false; | |
pippo2 = false; | |
pippo3 = true; | |
pippo4 = true; | |
pippo5 = true; | |
pippo6 = true; | |
pippo7 = true; | |
} | |
/*In this part of the sketch the Arduino Due asks the user for the parameters of the spectrum, and then gets the parameters | |
from the PC. The protocol used is the serial communication port 1 of the Arduino Due. | |
When the code is looped in these queries, waiting the parameters from the user, | |
the Arduino Due leaves the user taking control of the microscope, | |
seeking another field to image, for example. Wavelength is tuned at 910 nm automatically. | |
Termite, or any other software for serial communication, has to be run on the PC. | |
The settings for the serial communication are as follows: | |
port: comXX, or dev/ttyXX (the one used by the operative system, usually changes if different serial devices are connected) | |
Baud rate: 19200 | |
data bits: 8 | |
stop bits: 1 | |
parity: none | |
flow control: none | |
forward: none | |
append: nothing | |
local echo: off. | |
*/ | |
else { | |
digitalWrite(SHUTTER, HIGH); | |
digitalWrite(LEDred, LOW); | |
digitalWrite(LEDgreen, HIGH); | |
digitalWrite(TRIGGER_prairie, LOW); // just to be sure | |
analogWrite(pinpotimposta, memo910); | |
delay(200); | |
if (pippo7 == true) { | |
Serial3.println("VW=910"); | |
} | |
pippo7 = false; | |
if (pippo2 == false) { | |
Serial1.println("Spectrum parameters"); | |
Serial1.print("first lambda = "); | |
while (pippo3 == true) { | |
if (Serial1.available() > 0) { | |
int var4 = Serial1.parseInt(); | |
if ((var4 >= 760) && (var4 <= 1039)) { | |
lambdamin = var4; | |
Serial1.println(lambdamin); | |
pippo3 = false; | |
} | |
} | |
} | |
Serial1.print("step nm = "); | |
while (pippo5 == true) { | |
if (Serial1.available() > 0) { | |
deltalambda = Serial1.parseInt(); | |
Serial1.println(deltalambda); | |
pippo5 = false; | |
} | |
} | |
Serial1.print("number of wavelengths = "); | |
while (pippo4 == true) { | |
if ((Serial1.available() > 0)) { | |
int var2 = Serial1.parseInt(); | |
if (lambdamin + (var2 - 1)*deltalambda < 1040) { | |
n_scansioni = var2; | |
Serial1.println(n_scansioni); | |
pippo4 = false; | |
} | |
} | |
} | |
Serial1.print("power (mW) = "); | |
while (pippo6 == true) { | |
if ((Serial1.available() > 0)) { | |
double var3 = Serial1.parseInt(); | |
if (var3 <= 28) { | |
targetpower = var3; | |
Serial1.println(targetpower); | |
pippo6 = false; | |
} | |
} | |
} | |
Serial1.println("\nStart T-Series on Prarie, then, press s to start!"); | |
Serial1.println("Press n for new parameters\n"); | |
pippo2 = true; | |
} | |
char lettera = Serial1.read(); | |
switch (lettera) { | |
case 's': | |
pippo = true; | |
break; | |
case 'n': | |
pippo = false; | |
pippo2 = false; | |
pippo3 = true; | |
pippo4 = true; | |
pippo5 = true; | |
pippo6 = true; | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment