The project is a fast lock in amplifier (LIA) which can update its output at rate of 1000 measurements/s. It performs digital dual mixing and filtering to obtain a DC value proportional to the AC input signal.
main.cpp
- Committer:
- Nikollao
- Date:
- 2017-08-21
- Revision:
- 0:4e20939af8bb
- Child:
- 1:bf693859586c
File content as of revision 0:4e20939af8bb:
#include "main.h" int main() { pc.baud(115200); dref.rise(&voltageRise); /// set interrupt to calculate reference frequency setupK64Fclocks(); /// initialise DAC output dac0_out while (ref_freq < 1e2) { sleep(); } //ref_freq = 5e3; /// make sure frequency is read before we go to the program /// cancel event-triggered rise interrupt, not to interfere with program dref.rise(NULL); pc.printf("Ref_Freq is:%.2f kHz\n\r",ref_freq*0.001); //constant sample_freq = 6*samples16*ref_freq; sample_time = 1/sample_freq; initDAC(); delay_freq = ref_freq*amp_points; amplitude_delay = 1/delay_freq; offset_ticker.attach(&offset_isr,0.001); while (offset == 0) { if (g_offset_flag == 1) { g_offset_flag = 0; offset = mavg_filter(filter_points); } sleep(); } offset_ticker.detach(); output_ticker.attach(&output_isr,0.00099); while (true) { // gpo = !gpo; digitalMix(offset); while (g_output_flag == 0) {sleep();} if (g_output_flag == 1) { g_output_flag = 0; //aout = max(samples16); aout = 2*max(samples16); } } } double max(int points) { double amp = 0; for (int i = 0; i < points; i++) { if (amp < R[i]) amp = R[i]; //wait(amplitude_delay); } return amp; } double mavg_filter(int filt_points) { double avg = 0, signal = 0; double delay = 0.9/(1*ref_freq*filter_points); for (int i = 0; i < filter_points; i++) { signal = ain.read(); avg = avg + signal; wait((float)(5e-5)); } avg = avg/filter_points; return avg; } void digitalMix(double remove_offset) { /// perform mixing of input and reference signals double input = 0; for (int i = 0; i < samples16;i++) { /// remove the offset before doing the multiplication of signals input = ain.read()-remove_offset; /// find the X component by multiplying with sine 17 values array double refX = input*sin_array16[i]; /// find the Y component by multiplying with cosine 17 values array double refY = input*cos_array16[i]; //double XY = exp(2*log(refX))+exp(2*log(refY)); double XY = (refX*refX)+(refY*refY); /// R square //double R = exp(0.5*log(XY))/4; R[i] = pow(XY,0.5); /// R //aout = (1+sin_array16[i])/4; //aout = R[i]/2; wait(sample_time); /// sample time } } void voltageRise() { if (g_counter == 1) { /// first time function is called is the first rise /// start timer period_timer.start(); /// increase counter so next time function is called we calculate freq. g_counter++; } else if (g_counter == 2) { /// second time function is called is the second rise /// stop timer period_timer.stop(); /// calculate the time taken between the two rises to find period ref_period = period_timer.read(); /// frequency is the inverse of the signal period ref_freq = 1/ref_period; /// reset timer period_timer.reset(); /// increase counter because we only want to calculate once per cycle /// if we want to actively track the ref_freq we should decrease counter g_counter++; } } void setupK64Fclocks() { if(1) { uint32_t div1=0,div2=0,busClk=0,adcClk=0; SystemCoreClockUpdate(); pc.printf("SystemCoreClock= %u \r\n",SystemCoreClock); /// System Core Clock: 120 MHz div1=( (SIM->CLKDIV1) & SIM_CLKDIV1_OUTDIV1_MASK)>>SIM_CLKDIV1_OUTDIV1_SHIFT; div1=1+div1; div2=1+( (SIM->CLKDIV1) & SIM_CLKDIV1_OUTDIV2_MASK)>>SIM_CLKDIV1_OUTDIV2_SHIFT; busClk=SystemCoreClock*div1/div2; pc.printf("Divider1== %u div2=%u \r\n",div1,div2); pc.printf("MCGOUTCLK= %u, busClk = %u \r\n",SystemCoreClock*div1,busClk); /// MCGOUTCLK 120 MHz, Bus Clock = 120 MHz ADC0->SC3 &= ~ADC_SC3_AVGE_MASK;//disable averages ADC0->CFG1 &= ~ADC_CFG1_ADLPC_MASK;//high-power mode ADC0->CFG1 &= ~0x0063 ; //clears ADICLK and ADIV ADC0->CFG1 |= ADC_CFG1_ADIV(2); //divide clock 0=/1, 1=/2, 2=/4, 3=/8 //ADC0->SC3 |= 0x0007;//enable 32 averages if (((ADC0->CFG1)& 0x03) == 0) adcClk = busClk/(0x01<<(((ADC0->CFG1)&0x60)>>5)); if (((ADC0->SC3)& 0x04) != 0) adcClk = adcClk/(0x01<<(((ADC0->SC3)&0x03)+2)); pc.printf("adcCLK= %u \r\n",adcClk); /// ADC Clock: 60 MHz } } void offset_isr() { g_offset_flag = 1; } void output_isr() { g_output_flag = 1; } void initDAC() { DAC0->C0 = 0; DAC0->C1 = 0; //reset DAC state DAC0->C0 = DAC_C0_DACEN_MASK | DAC_C0_DACSWTRG_MASK| DAC_C0_DACRFS_MASK; }