/* This code uses functions derived from an open-source Texas Instruments OPT3002 Light to Digital Sensor Arduino Library developed for the ClosedCube OPT3002 Light to Digital Sensor breakout module. Those functions were written by AA for ClosedCube on 12-Oct-2016. The rest of the code was written by Jackson Coole (jbc7@rice.edu) for the article "Open-Source Miniature Fluorimeter to Monitor Real-Time Isothermal Nucleic Acid Amplification Reactions in Resource-Limited Settings" submitted to Journal of Visualized Experiments. Date: December 16th, 2020 Hardware connections for Arduino Nano: VDD to 3.3V DC SDA to A4 SCL to A5 GND to common ground */ // --------------- LIBRARIES -------------------- #include #include "ClosedCube_OPT3002.h" // --------CONSTANTS and USER INPUTS--------------- const int led_A_Pin = 3; // Define the digital pin used to modulate the LED const int ExposureTime = 3400; // number of millisecs LED is on const int led_A_Interval = 5000; //20000; // number of millisecs between exposures const float led_Power = .5; // percentage of power between 0 and 1. O being the highest and 1 being the lowest #define OPT3002_P1_ADDRESS 0x44 // Define I2C address of first photodiode ( with R4 Resistor ) #define OPT3002_P2_ADDRESS 0x45 // Define I2C address of second photodiode ( with jumper wire ) //------------ VARIABLES--------------------- byte led_A_State = HIGH; // LOW = on / HIGH = off unsigned long currentMillis = 0; // stores the value of millis() in each iteration of loop() unsigned long previousLed_A_Millis = 0; ClosedCube_OPT3002 opt3002_P1; // Initialize the first photodiode ClosedCube_OPT3002 opt3002_P2; // Initialize the second photodiode void setup() { Serial.begin(9600); // Begin serial connection pinMode(led_A_Pin, OUTPUT); // sets the digital pin as output Serial.println("ClosedCube OPT3002 Arduino Test"); opt3002_P1.begin(OPT3002_P1_ADDRESS); // Beging connection to the OPT3002_P1 opt3002_P2.begin(OPT3002_P2_ADDRESS); // Beging connection to the OPT3002_P2 configureSensor(opt3002_P1); configureSensor(opt3002_P2); Serial.println("----"); } void loop() { currentMillis = millis(); // captures the latest value of millis() updateLed_A_State(); switchLeds(); TakeMeasurement(); } //==============Functions========================== void printResult(String text, OPT3002 result) { if (result.error == NO_ERROR) { Serial.print(text); Serial.print(": "); Serial.print(result.lux); Serial.println(" nW/cm2"); } else { printError(text, result.error); } } void printError(String text, OPT3002_ErrorCode error) { Serial.print(text); Serial.print(": [ERROR] Code #"); Serial.println(error); } //====================================== void switchLeds() { // this is the code that actually switches the LEDs on and off // If LED should be off if (led_A_State == HIGH) { digitalWrite(led_A_Pin,led_A_State); } // If LED should be on, you can turn it to a percentage of being on to avoid photobleaching else { analogWrite(led_A_Pin, 255*led_Power); delay(10); } } //====================================== void updateLed_A_State() { if (led_A_State == HIGH) { if (currentMillis - previousLed_A_Millis >= led_A_Interval) { led_A_State = LOW; previousLed_A_Millis += led_A_Interval; } } else { if (currentMillis - previousLed_A_Millis >= ExposureTime) { led_A_State = HIGH; previousLed_A_Millis += ExposureTime; } } } //======================================== void TakeMeasurement() { // if (led_A_State == LOW) { OPT3002 result_P1 = opt3002_P1.readResult(); printResult("OPT3002_P1", result_P1); OPT3002 result_P2 = opt3002_P2.readResult(); printResult("OPT3002_P2", result_P2); } } //======================================== void configureSensor(ClosedCube_OPT3002 opt3002) { OPT3002_Config newConfig; newConfig.RangeNumber = B1100; newConfig.ConvertionTime = B1; newConfig.Latch = B1; newConfig.ModeOfConversionOperation = B11; OPT3002_ErrorCode errorConfig = opt3002.writeConfig(newConfig); if (errorConfig != NO_ERROR) printError("OPT3002 configuration", errorConfig); else { OPT3002_Config sensorConfig = opt3002.readConfig(); Serial.println("OPT3002 Current Config:"); Serial.println("------------------------------"); Serial.print("Conversion ready (R):"); Serial.println(sensorConfig.ConversionReady, HEX); Serial.print("Conversion time (R/W):"); Serial.println(sensorConfig.ConvertionTime, HEX); Serial.print("Fault count field (R/W):"); Serial.println(sensorConfig.FaultCount, HEX); Serial.print("Flag high field (R-only):"); Serial.println(sensorConfig.FlagHigh, HEX); Serial.print("Flag low field (R-only):"); Serial.println(sensorConfig.FlagLow, HEX); Serial.print("Latch field (R/W):"); Serial.println(sensorConfig.Latch, HEX); Serial.print("Mask exponent field (R/W):"); Serial.println(sensorConfig.MaskExponent, HEX); Serial.print("Mode of conversion operation (R/W):"); Serial.println(sensorConfig.ModeOfConversionOperation, HEX); Serial.print("Polarity field (R/W):"); Serial.println(sensorConfig.Polarity, HEX); Serial.print("Overflow flag (R-only):"); Serial.println(sensorConfig.OverflowFlag, HEX); Serial.print("Range number (R/W):"); Serial.println(sensorConfig.RangeNumber, HEX); Serial.println("------------------------------"); } }