Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of scoreLight_Advanced by
lockin.cpp
00001 #include "lockin.h" 00002 00003 Lockin lockin=Lockin();//pre-instanciation of object lockin with inter-file scope (declared extern in .h file) 00004 00005 00006 // NOTE: the ADC interrupt catching function is not a method of the Lockin class, hence the use of the pre-instantiated object "lockin": 00007 void catchInterupt(uint32_t value){ 00008 lockin.buffer_pos=(lockin.buffer_pos+1)%BUFFER_SIZE; 00009 lockin.buffer[lockin.buffer_pos] = (value>>4)&0xFFF; // this is 12 bit precision ADC (0 to 4095), can be stored in an "unsigned short" (two bytes) 00010 } 00011 00012 // PWM generation is configure as double edge 00013 // MR0 (Match Register 0) control the frequency 00014 // 'pwm2' uses MR1 and MR2 (rising and falling edges) 00015 // 'pwm4' uses MR3 and MR4 (rising and falling edges) 00016 // 'pwm1' and 'pwm3' cannot be used since they share the same Match Register 00017 // for the moment, all PWM pin are set as output: 00018 //PwmOut pwm1(p26); 00019 PwmOut pwm2(LOCKIN_LASER_PIN); //USED: this is pin p25, the LOCKIN_LASER_PIN 00020 PwmOut pwm3(p24); 00021 PwmOut pwm4(LOCKIN_REF_PIN); //USED: this is pin p23, the LOCKIN_REF_PIN 00022 //PwmOut pwm5(p22); 00023 //PwmOut pwm6(p21); 00024 00025 //Lockin::Lockin(){} 00026 00027 void Lockin::init(){ 00028 00029 //configure PWM for the laser and the Lockin 00030 refFreq = 147; 00031 offsetRef = 40; 00032 halfRefFreq = refFreq / 2; 00033 00034 refFrequency = 653; //init the lock-in frequency at 653 kHz 00035 phaseShiftLaser = 0.546; //offset of 54% for the laser signal 00036 phaseShiftLockin = 0; //no offset for the lock-in reference 00037 initPWM(); 00038 00039 //configure ADC: 00040 clearBuffer(); 00041 00042 // SET ADC IN BURST MODE: 00043 lockin.setADC_forLockin(1); 00044 } 00045 00046 void Lockin::setADC_forLockin(int mode) { 00047 if (mode>0) { // ADC BURST MODE: 00048 adc.startmode(0,0); 00049 adc.burst(1); 00050 adc.setup(LOCKIN_ADC_PIN, 1); 00051 adc.select(LOCKIN_ADC_PIN); 00052 adc.interrupt_state(LOCKIN_ADC_PIN, 1); 00053 adc.append(LOCKIN_ADC_PIN, catchInterupt); 00054 } else { 00055 // unset the lockin pin: 00056 adc.burst(0); 00057 adc.setup(LOCKIN_ADC_PIN, 0); 00058 adc.interrupt_state(LOCKIN_ADC_PIN, 0); 00059 } 00060 } 00061 00062 void Lockin::initPWM(){ 00063 00064 float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; // half shared periof 00065 _currentMR[0] = int(1.0 * MBEDFREQUENCY / refFrequency); //save the current value of MR0 (shared periof) //147 00066 _currentMR[1] = int(phaseShiftLaser * halfPeriod); //save the current value of MR1 //40 00067 _currentMR[2] = int(_currentMR[1] + halfPeriod); //save the current value of MR2 //40+73 00068 _currentMR[3] = int(phaseShiftLockin * halfPeriod); //save the current value of MR1 //0 00069 _currentMR[4] = int(_currentMR[3] + halfPeriod); //save the current value of MR2 //73 00070 00071 00072 // set PWM: 00073 LPC_PWM1->TCR = (1 << 1); // Reset counter, disable PWM 00074 LPC_SC->PCLKSEL0 &= ~(0x3 << 12); 00075 LPC_SC->PCLKSEL0 |= (1 << 12); // Set peripheral clock divider to /1, i.e. system clock 00076 00077 LPC_PWM1->PCR |= 0x0014; // Double edge PWM for PWM2,4 00078 00079 LPC_PWM1->MR0 = _currentMR[0]; // Match Register 0 is shared period counter for all PWM1 00080 00081 LPC_PWM1->MR1 = _currentMR[1]; // Match Register 1 is laser rising edge counter 00082 LPC_PWM1->MR2 = _currentMR[2]; // Match Register 2 is laser falling edge counter 00083 LPC_PWM1->MR3 = _currentMR[3]; // Match Register 3 is lock-in rising edge counter 00084 LPC_PWM1->MR4 = _currentMR[4]; // Match Register 4 is lock-in falling edge counter 00085 00086 LPC_PWM1->LER |= 1; // Start updating at next period start 00087 LPC_PWM1->TCR = (1 << 0) || (1 << 3); // Enable counter and PWM 00088 } 00089 00090 //change the frequency of the PWM after initPWM() 00091 void Lockin::setPWMFrequency(float freq){ 00092 refFrequency = freq; 00093 _currentMR[0] = int(MBEDFREQUENCY / refFrequency); //save the current value of MR0 00094 LPC_PWM1->MR0 = _currentMR[0]; //update PWM shared period register 00095 LPC_PWM1->LER |= 1; //update PWM 00096 } 00097 00098 //change the phase shift of the sensing laser after initPWM() 00099 void Lockin::setLaserPhaseShift(float phaseShift){ 00100 phaseShiftLaser = phaseShift; 00101 float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; 00102 _currentMR[1] = int(phaseShiftLaser * halfPeriod); //save the current value of MR1 00103 _currentMR[2] = _currentMR[1] + halfPeriod; //save the current value of MR2 00104 00105 LPC_PWM1->MR1 = _currentMR[1]; //update Laser rising edge match register 00106 LPC_PWM1->MR2 = _currentMR[2]; //update Laser faling edge match register 00107 } 00108 00109 //change the phase shift of the lock-in after initPWM() 00110 void Lockin::setLockinPhaseShift(float phaseShift){ 00111 phaseShiftLockin = phaseShift; 00112 float halfPeriod = 0.5 * MBEDFREQUENCY / refFrequency; 00113 _currentMR[3] = int(phaseShiftLockin * halfPeriod); //save the current value of MR1 00114 _currentMR[4] = _currentMR[3] + halfPeriod; //save the current value of MR2 00115 00116 LPC_PWM1->MR3 = _currentMR[3]; //update lock-in rising edge match register 00117 LPC_PWM1->MR4 = _currentMR[4]; //update lock-in faling edge match register 00118 } 00119 00120 00121 void Lockin::setLaserPower(bool power){ 00122 if(power){ 00123 LPC_PWM1->MR1 = _currentMR[1]; 00124 LPC_PWM1->MR2 = _currentMR[2]; 00125 LPC_PWM1->LER |= 1; // update PWM at the next period 00126 } 00127 else{ 00128 LPC_PWM1->MR1 = 0; //set rising edge at 0 00129 LPC_PWM1->MR2 = 0; //set falling edge at 0 00130 LPC_PWM1->LER |= 1; // update PWM at the next period 00131 } 00132 } 00133 00134 void Lockin::clearBuffer(){ 00135 for(int i=0; i<BUFFER_SIZE; i++){ 00136 buffer[i] = 0; 00137 } 00138 buffer_pos = BUFFER_SIZE; 00139 } 00140 00141 /* 00142 void Lockin::catchInterupt(uint32_t value){ 00143 buffer_pos++; 00144 buffer_pos%=BUFFER_SIZE; 00145 buffer[buffer_pos] = value; 00146 } 00147 */ 00148 00149 //****** aquisition method *****// 00150 unsigned short Lockin::getLastValue(){ 00151 return buffer[buffer_pos]; 00152 } 00153 00154 unsigned short Lockin::getSmoothValue(){ 00155 unsigned short smoothValue = buffer[0]; 00156 for(int i=1; i<BUFFER_SIZE; i++){ 00157 smoothValue += buffer[i]; 00158 } 00159 smoothValue = (unsigned short)(smoothValue/BUFFER_SIZE); // note: we could have more precision (sub-12 bit), but it's not required and would imply using a float as output 00160 00161 return smoothValue; 00162 } 00163 00164 unsigned short Lockin::getMedianValue(){ 00165 //this method applies a median filter to the buffer 00166 //It reduces the salt-and-pepper noise 00167 //It seems that this noise is very strong on certain mBed board, but not all... 00168 00169 // unsigned short orderedBuffer[BUFFER_SIZE_MEDIAN]; 00170 00171 //sort half of the buffer: 00172 00173 //copy buffer 00174 for(int i=0; i<BUFFER_SIZE_MEDIAN; i++){ 00175 orderedBuffer[i] = buffer[(buffer_pos+BUFFER_SIZE-i+DELAY_BUFFER_MEDIAN)%BUFFER_SIZE]; 00176 } 00177 00178 //order buffer 00179 for(int i=0; i<BUFFER_SIZE_MEDIAN-1; i++){ 00180 int minPos = i; 00181 00182 //get min 00183 for(int j=i+1; j<BUFFER_SIZE_MEDIAN; j++){ 00184 if(orderedBuffer[j] < orderedBuffer[minPos]) minPos = j; 00185 } 00186 00187 //swap min to the right position 00188 if(minPos != i){ 00189 int tmpMin = orderedBuffer[minPos]; 00190 orderedBuffer[minPos] = orderedBuffer[i]; 00191 orderedBuffer[i] = tmpMin; 00192 } 00193 } 00194 00195 return orderedBuffer[BUFFER_SIZE_MEDIAN/2]; 00196 }
Generated on Tue Jul 12 2022 18:50:27 by
1.7.2
