//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////TRUEHEME CODE V0.1.3 - BETA Version (Tested)///////////////////////////////////////////////////////////////////// //////////NEW Changes: All LED warmup function Added; Limit Switch added;EEPROM storage of DAC values; Stray light sensing; Turing on any one LED/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "ADS1X15.h" #include #include #include /////////////////////////////////////////////////////////////////////PLEASE UPDATE DEVICE ID BEFORE UPLOADING TO ANY DEVICE///////////////////////////////////////////////////////////////// String Device_ID = "SNS HCV-001-0012 SNE"; // Device ID //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const int LED_available[] = {1,2,3,4}; // List of LEDs available. All Variables with 4 columns (other than ones controlling the LED turning ON sequence) must be filled in this order int LED_sequence[] = {1,2,3,4}; // LED turning ON sequence int Detector_sequence[] = {1,1,1,1}; // Detector sequence (if hardware supports dual pathlength) int LED_dac[] = {1792,2304,2040,1920}; // Preset DAC values for the device int LED_sample_size[] = {50,50,50,50}; // No. of ADC readings to use for Average ADC calculation int LED_DS_threshold[] = {22000,18000,18000,22000}; // DAC sweep upperlimit for each LED int LED_settling_time[] = {20000,20000,20000,20000}; // Settling time given to each LED int ADC_reading_delay[] = {0,0,0,0}; // Delay for each ADC reading while averaging int led_warmup_DAC[] = {3000,3000,3000,3000}; // DAC value at which all the LEDs will be powered during LED warmup int DAC_Sweep_start_limit[] = {1000,1000,1000,1000}; // Lower limit for DAC sweep int DAC_Sweep_end_limit[] = {4000,4000,4000,4000}; // Upper limit for DAC sweep int DacSweep_gain_combinations[] = {0,0,0,0}; // Gain to be used for DAC sweep int incr=8; // DAC sweep increment int del=1000; // Delay between each interval of the DAC sweep int appmode=1; // if =1, it removes most of the unwanted serial prints int raw_ADC_print=0; // if =1, it will serialprint raw ADC values (even during LED warmup and settling) int timestamp_printer=0; // if =1, will print timestamp at regular intervals int limit_switch_active=0; // If there is a limit switch in the device, make it 1 int Blank_gain_combinations[] = {0,0,0,0}; // Programmable gain to be used while blanking int Sample_gain_combinations[5][4] = {{0,0,0,0},{1,1,1,1},{2,2,2,2},{4,4,4,4},{8,8,8,8}}; // Programmable gain to be used while taking sample readings ///////////////////////////////////////////DO NOT CHANGE ANY VALUES BELOW ////////////////////////////////////////////////////////////////////////////////////////////// const int PIN_CS_DAC1 = 10; // Chip select pin for DAC 1 const int PIN_CS_DAC2 = 9; // Chip select pin for DAC 2 const int GAIN_1 = 0x1; // DAC 1X gain (output between 0 - 2.048 Volts) const int GAIN_2 = 0x0; // DAC 2X gain (output between 0 - 4.096 Volts) const int PD1G1 = 6; // Programmable gain resistor _______ohm const int PD1G2 = 8; // Programmable gain resistor _______ohm const int PD2G1 = 5; // Programmable gain resistor _______ohm const int PD2G2 = 7; // Programmable gain resistor _______ohm const int LEDR = A2; // Red indicator LED const int LEDB = A0; // Blue indicator LED const int LEDG = A1; // Green indicator LED const int Limit_Switch = 2; // Limit switch for cuvette sensing const int Buzzer_pin = 3; // Buzzer connection for alert ADS1115 ADS(0x48); ///////////////////////////////////////////DO NOT CHANGE ANY VALUES ABOVE ////////////////////////////////////////////////////////////////////////////////////////////// const char compile_date[] = __DATE__ " " __TIME__; //Stores date and time when the firmware was uploaded on the arduino String Firmware_location_Auto=__FILE__; //Stores location of the firmware on the computer used for uploading String Firmware_version_Auto=__FILE__; //Stores the firmware version uploaded int DAC_lower_limit[]= {0,0,0,0}; int DAC_upper_limit[]= {4096,4096,4096,4096}; unsigned long long intensity_storage = 0; int temp_counter = 0; const int detector_settling_time=2000; const int detector_settling_time_DACsweep=1000; float avg_storage = 0; float avg_green = 0; float avg_blue = 0; float old_green = 0; float old_blue = 0; int initialRGBstate=0; int split_counter = 0; int intensity_display = 1; int plotter = 0; int j = 0; float average_readings = 0; float avg_blank[]={0,0,0,0}; float avg_air_blank[]={0,0,0,0}; float avg_sample[]={0,0,0,0}; int LED_on_status[]={0,0,0,0}; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setup() { Serial.begin(9600); pinMode(PIN_CS_DAC1, OUTPUT); pinMode(PIN_CS_DAC2, OUTPUT); pinMode(PD1G1, OUTPUT); pinMode(PD1G2, OUTPUT); pinMode(PD2G1, OUTPUT); pinMode(PD2G2, OUTPUT); pinMode(LEDR, OUTPUT); pinMode(LEDG, OUTPUT); pinMode(LEDB, OUTPUT); pinMode(Limit_Switch, INPUT); pinMode(Buzzer_pin, OUTPUT); digitalWrite(LEDR, LOW); digitalWrite(LEDG, HIGH); digitalWrite(LEDB, HIGH); SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV2); ADS.begin(); if(appmode==0) { Serial.print("Initial DAC Settings: "); for (int i =0; i<4;i++) { Serial.print("\t");Serial.print(LED_dac[i]); } Serial.println(); } if(appmode==0) { Serial.print("Process: Setup End; Timestamp: ");Serial.println(millis()); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void buzzer(int mode) { if(mode==1) { tone(Buzzer_pin, 2730, 1000); } else if (mode==2) { tone(Buzzer_pin, 2730, 5000); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void all_LEDs_turnoff() { setOutput(GAIN_1, 0, 1); //LED 1 setOutput(GAIN_1, 0, 2); //LED 2 setOutput(GAIN_1, 0, 3); //LED 3 setOutput(GAIN_1, 0, 4); //LED 4 } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void secondary_gain_select(int gain_combo) { bool gain_choice1=bitRead(gain_combo, 0); bool gain_choice2=bitRead(gain_combo, 1); bool gain_choice3=bitRead(gain_combo, 2); bool gain_choice4=bitRead(gain_combo, 3); digitalWrite(PD1G1, gain_choice1); digitalWrite(PD1G2, gain_choice2); digitalWrite(PD2G1, gain_choice3); digitalWrite(PD2G2, gain_choice4); if(appmode==0) { Serial.print("Gains Used\t G1:");Serial.print(gain_choice1);Serial.print("\t G2:");Serial.print(gain_choice2);Serial.print("\t G3:");Serial.print(gain_choice3);Serial.print("\t G4:");Serial.println(gain_choice4); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setOutput(byte gain, unsigned int val, int LEDselect) { byte channel=0; byte shutdown=1; if(LEDselect%2==0) { channel=1; } else { channel=0; } byte lowByte = val & 0xff; byte highByte = ((val >> 8) & 0xff) | channel << 7 | gain << 5 | shutdown << 4; if (LEDselect <= 2) { PORTB &= 0xfb; SPI.transfer(highByte); SPI.transfer(lowByte); PORTB |= 0x4; } else { PORTB &= 0xfd; SPI.transfer(highByte); SPI.transfer(lowByte); PORTB |= 0x2; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void indicator_LED(char statusLED) { digitalWrite(LEDR,LOW); digitalWrite(LEDG,LOW); digitalWrite(LEDB,LOW); digitalWrite(LEDR,(statusLED=='R')); digitalWrite(LEDG,(statusLED=='G')); digitalWrite(LEDB,(statusLED=='B')); /* if(statusLED=='R') { digitalWrite(LEDR,HIGH); digitalWrite(LEDG,LOW); digitalWrite(LEDB,LOW); //Serial.println("RED"); } else if(statusLED=='G') { digitalWrite(LEDR,LOW); digitalWrite(LEDG,HIGH); digitalWrite(LEDB,LOW); //Serial.println("G"); } else if(statusLED=='B') { digitalWrite(LEDR,LOW); digitalWrite(LEDG,LOW); digitalWrite(LEDB,HIGH); //Serial.println("B"); } else { digitalWrite(LEDR,LOW); digitalWrite(LEDG,LOW); digitalWrite(LEDB,LOW); } */ } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int setDAC_LED() { int LED_flags[]={0,0,0,0}; int flags_combined=0; if(appmode==0) { Serial.println("#DAC Sweep Start"); } all_LEDs_turnoff(); delay(1000); ////////////////////////////////////////FIRST FORLOOP TO DISCARD STARTS///////////////////////////////////////////////// for (int i=3000;i<4096;i+=incr) { setOutput(GAIN_1, i, 1); delay(del); int16_t val_0 = ADS.readADC(0); if((val_0>24000)) { break; } } all_LEDs_turnoff(); delay(1000); ////////////////////////////////////////FIRST FORLOOP TO DISCARD ENDS///////////////////////////////////////////////// for (int j=0;j<4;j++) { all_LEDs_turnoff(); secondary_gain_select(DacSweep_gain_combinations[j]); for (int i=DAC_Sweep_start_limit[j];iLED_DS_threshold[j])&&(LED_flags[j]==0)) { LED_dac[j]=i; LED_flags[j]=1; break; } } all_LEDs_turnoff(); if (appmode==0) { Serial.print("LED ");Serial.print(j+1);Serial.print(" DACsweep Completed");Serial.print("\t");Serial.print("NEW DAC VALUE : ");Serial.println(LED_dac[j]); } delay(1000); } all_LEDs_turnoff(); flags_combined=(LED_flags[3]*1)+(LED_flags[2]*10)+(LED_flags[1]*100)+(LED_flags[0]*1000); if(appmode==0) { Serial.println("#DAC Sweep End"); } return flags_combined; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void eeprom_DAC_write() { int led_dac_split[]= {0,0,0,0,0,0,0,0}; Serial.println("#WS"); led_dac_split[0] = LED_dac[0]/100; led_dac_split[1] = LED_dac[0]-(led_dac_split[0]*100); led_dac_split[2] = LED_dac[1]/100; led_dac_split[3] = LED_dac[1]-(led_dac_split[2]*100); led_dac_split[4] = LED_dac[2]/100; led_dac_split[5] = LED_dac[2]-(led_dac_split[4]*100); led_dac_split[6] = LED_dac[3]/100; led_dac_split[7] = LED_dac[3]-(led_dac_split[6]*100); if(appmode==0) { Serial.print(led_dac_split[0]);Serial.print("\t");Serial.println(led_dac_split[1]); Serial.print(led_dac_split[2]);Serial.print("\t");Serial.println(led_dac_split[3]); Serial.print(led_dac_split[4]);Serial.print("\t");Serial.println(led_dac_split[5]); Serial.print(led_dac_split[6]);Serial.print("\t");Serial.println(led_dac_split[7]); } for (int i=0;i<8; i++) { EEPROM.write(i, led_dac_split[i]); } Serial.println("#WC"); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void eeprom_DAC_read() { int led_dac_split[]= {0,0,0,0,0,0,0,0}; Serial.println("#RS"); for(int i=0;i<8;i++) { led_dac_split[i] = EEPROM.read(i); } for(int i=0;i<4;i++) { LED_dac[i] = (led_dac_split[i*2]*100)+led_dac_split[(i*2)+1]; } if(appmode==0) { Serial.print(led_dac_split[0]);Serial.print("\t");Serial.println(led_dac_split[1]); Serial.print(led_dac_split[2]);Serial.print("\t");Serial.println(led_dac_split[3]); Serial.print(led_dac_split[4]);Serial.print("\t");Serial.println(led_dac_split[5]); Serial.print(led_dac_split[6]);Serial.print("\t");Serial.println(led_dac_split[7]); Serial.print(LED_dac[0]);Serial.print("\t");Serial.print(LED_dac[1]);Serial.print("\t");Serial.print(LED_dac[2]);Serial.print("\t");Serial.println(LED_dac[3]); } Serial.println("#RC"); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void LED_warmup(int warmup_time) { int warmup_start=millis(); int current_time=millis(); while((current_time-warmup_start) 10)&&(appmode==0)) { Serial.println("Error: stray light interference or LED partly ON "); } int flag=0; secondary_gain_select(DacSweep_gain_combinations[j]); for (int i = 0; i <=4096; i+= reading_increment) { setOutput(GAIN_1, i, j+1); int start_time=millis(); int current_time=millis(); while ((current_time-start_time)LED_DS_threshold[LED_sequence[j]-1])&&(flag==0)) { lowerlimit_dac= i-(reading_increment*2); upperlimit_dac= i+(reading_increment*2); if (lowerlimit_dac<0) { lowerlimit_dac=0; } if(upperlimit_dac>4095) { upperlimit_dac=4095; } DAC_lower_limit[j]=lowerlimit_dac; DAC_upper_limit[j]=upperlimit_dac; flag=1; } Serial.print("LED:");Serial.print(j+1);Serial.print("__DAC:");Serial.print(i);Serial.print("__ADC:");Serial.println(val_0); } if (appmode==0) { Serial.print("LED:");Serial.print(j+1);Serial.print("__DAC LOWER LIMIT:");Serial.println(DAC_lower_limit[j]); Serial.print("LED:");Serial.print(j+1);Serial.print("__DAC UPPER LIMIT:");Serial.println(DAC_upper_limit[j]); } secondary_gain_select(0); all_LEDs_turnoff(); } Serial.println("#DC"); all_LEDs_turnoff(); delay(1000); if((appmode==0)&&(timestamp_printer==1)) { Serial.print("Process: Diagnostics end; Timestamp: ");Serial.println(millis()); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void startTask4() { if((appmode==0)&&(timestamp_printer==1)) { Serial.print("Process: Buffer start; Timestamp: ");Serial.println(millis()); } all_LEDs_turnoff(); delay(100); all_LEDs_turnoff(); Serial.println("#BS"); for (int i=0;i<4;i++) { setOutput(GAIN_1, 0, LED_sequence[i]); delay(100); avg_blank[i] = detector(LED_sample_size[LED_sequence[i]-1], Detector_sequence[LED_sequence[i]-1], Blank_gain_combinations[LED_sequence[i]-1], 2000, ADC_reading_delay[LED_sequence[i]-1]); all_LEDs_turnoff(); delay(1000); } if (appmode==0) { Serial.print(millis());Serial.print("\t");Serial.print("LED1B : "); Serial.print(avg_blank[0]); Serial.print("\t"); Serial.print("LED2B : "); Serial.print(avg_blank[1]); Serial.print("\t"); Serial.print("LED3B : "); Serial.print(avg_blank[2]); Serial.print("\t"); Serial.print("LED4B : "); Serial.println(avg_blank[3]); } Serial.println("#BC"); if((appmode==0)&&(timestamp_printer==1)) { Serial.print("Process: Buffer end; Timestamp: ");Serial.println(millis()); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////