'+-------------------------------------------------------------+ '| | '| BACKPACK TRACKER | '| | '| 10-2019 Volhout @ TheBackShed.com | '+-------------------------------------------------------------+ ' Curve tracer type huntron tracker ' For ILI9341 LCD backpack on 28 pin MX170 ' Uses pin 24 as analog input ' Uses pin 4 as pwm output ' Uses pin 9 and 10 to set amplifier gain ' all values scaled to 'resolution' ' there are 'samples' measurements per period ' V11 has support for ARMmiteF4 '------------------------- Version History ------------------ ' V00 Proof of concept with 640 samples 100 resolution ' V01 Increase resolution to 1000, decrease samples to 200 ' V02 Implemented touch for REF and ZOOM buttons, REF added ' V03 Optimized main loop from 400msec to 300msec ' V04 Implemented support for HW zoom ' V05 Zoom implemented in SW ' V06 Restructure code to support samples and resolution as constants ' V07 Tune performance on MX170 ( 8 frames / second ) ' V08 Improved code for readability, remove obsolete DIM's ' V09 Screen resolution independent (untested), added header ' V10 Add dynamic measurement values ' V11 Support for ArmiteF4 (untested with hardware) '------------------------------ init ------------------------ Option explicit init: If MM.Device$ = "ARMmite F407" Then 'STM32F407VET6 initialisation 'OPTION LCDPANEL ILI9341_16, LANDSCAPE 'TOUCH PB12, PC5 Const ADC_PIN = 15 ' 15/PC0 for F4 Const HI_GAIN_HI = 1 ' switch to high gain, PE2/pin1 for F4 Const HI_GAIN_LO = 5 ' switch to high gain, PE6/pin5 for F4 GUI interrupt Touch_Int Else 'PIC32MX170 initialisation 'OPTION LCDPANEL ILI9341, L, 2, 23, 6 'OPTION TOUCH 7, 15 CPU 48 ' max speed - not needed in ARM F4 Const ADC_PIN = 24 ' 24 for MX170 Const HI_GAIN_HI = 10 ' switch to high gain, 10 for MX Const HI_GAIN_LO = 9 ' switch to high gain, 9 for MX ' enable touch SetPin 15, INTL, Touch_Int End If 'start board SetPin ADC_PIN,ain ' voltage input ADC1-ch10 (at pin 15) PWM 1,120000,50 ' set PWM to 50% (0Vdc amplifier out) ' pin 31/PA6 on F4, pin 4 on MX170 amp_high_gain ' set amplifier gain ' Define samples each scan Const samples = 64 Const resolution = 1000 ' external ADC divider (R15=47k into R10=12k//R11=15k) Const R10_R11 = 12000*15000/(12000+15000) Const resistor_divider = (47000 + R10_R11)/R10_R11 ' Declare variables ------------------------------------------------- ' Declare defaults for scaling ADC to 'resolution', these values ' are fine tuned in calibration (at powerup) Dim integer lowgain=resolution/3.3, highgain=2*lowgain Dim gain=lowgain Dim integer lowoffset=0, highoffset=-resolution/2 Dim offset=lowoffset ' for user interface, xt/yt are touch coordinates Dim integer xt,yt ' generic i,j,h are counters, ADC is scaled adc value, adc10 and adc90 ' are used in calibration Dim integer i,j,h,ADC Dim float adc10,adc90 ' display waveform, x/y are measured waveform, xr/yr are memory reference Dim integer x0,y0,x(samples),y(samples),xr(samples),yr(samples) ' init coordinates with values that fit the screen For i=1 To samples xr(i)=MM.HRes-3:yr(i)=MM.VRes/2:x(i)=MM.HRes-3:y(i)=MM.VRes/2 Next i x0=MM.HRes-3:y0=MM.VRes/2 ' display numerics, xnl/ynl for left side, xnr/ynr for right side Dim integer xnr=100,xnl=100,ynr=100,ynl=100,yor=0,yol=0 Dim float vr,ir,vl,il ' generate waveform, pw = pwm value, pc = pwm value scaled to 'resolution' Dim pw(samples), pc(samples) ' fill waveform with triange wave 0...100% For i=1 To samples / 2 pw(i) = 100 - ( 200 / samples ) * i pc(i) = resolution * pw(i) / 100 pw(i + samples / 2) = ( 200 / samples ) * i pc(i + samples / 2) = resolution * pw(i + samples / 2) / 100 Next ' graphics scaling to resolution Dim float Vstep = MM.VRes / resolution, Hstep = MM.HRes / resolution Dim center = resolution / 2 ' buttons and line colors Dim integer membuttoncolor = RGB(blue), zoombuttoncolor = RGB(blue) Dim integer memcolor = RGB(black), linecolor = RGB(yellow) 'debug Memory ' initialize screen draw_window ' timed interrupts SetTick 1000, Time_Int, 1 ' calibrate analog circuits calibrate '------------------------------ MAIN ------------------------ main: ' all comments removed from main loop to speed it up ' cycle through all pwm values using pointers i (actual) and j (last) ' erase last segment ' allways draw memory line, but color decides if it is visible ' draw memory line first so actual overwrites memory ' measure input value ' recalculate new segment (huntron method) ' draw new segement Do Timer = 0 For i = 1 To samples j = i - 1 : If j = 0 Then j = samples PWM 1,120000,pw(i) Line x0,y0,x(i),y(i),1,0 Line xr(j),yr(j),xr(i),yr(i),1,memcolor x0 = x(i) : y0 = y(i) ADC=(Pin(ADC_PIN) * gain) + offset y(i)=(ADC - pc(i) + center) * Vstep x(i)= ADC * Hstep Line x(j),y(j),x(i),y(i),1,linecolor Next i Print Timer Loop '--------------------------- SUBS --------------------------- Sub Touch_Int xt = Touch(x) : yt = Touch(y) 'check for MEM button if we should display memory If xt < ( MM.HRes / 4 ) And yt < ( MM.VRes / 4 ) Then If memcolor = RGB(black) Then For h = 1 To samples 'copy live to REF line yr(h) = y(h) xr(h) = x(h) Next memcolor = RGB(red) membuttoncolor = RGB(red) Else memcolor = RGB(black) membuttoncolor = RGB(Blue) End If RBox 10,10,60,30,2,RGB(white),membuttoncolor Text 30,18,"MEM",,,,RGB(white),membuttoncolor End If 'check for ZOOM button to see if we should zoom in If xt > (3 * MM.HRes / 4 ) And yt > (3 * MM.VRes / 4) Then If zoombuttoncolor = RGB(blue) Then zoombuttoncolor = RGB(red) adc_high_gain amp_low_gain Else zoombuttoncolor = RGB(Blue) adc_low_gain amp_high_gain End If RBox MM.HRes-70,MM.VRes-40,60,30,2,RGB(white),zoombuttoncolor Text MM.HRes-55,MM.VRes-32,"ZOOM",,,,RGB(white),zoombuttoncolor End If draw_frame Pause 300 'prevent double touch End Sub Sub amp_high_gain SetPin HI_GAIN_LO,dout : Pin(HI_GAIN_LO)=0 SetPin HI_GAIN_HI,dout : Pin(HI_GAIN_HI)=1 End Sub Sub amp_low_gain SetPin HI_GAIN_LO,din SetPin HI_GAIN_HI,din End Sub Sub adc_high_gain gain = highgain offset = highoffset End Sub Sub adc_low_gain gain = lowgain offset = lowoffset End Sub Sub draw_window 'clear screen CLS 'draw outside lines draw_frame 'draw buttons RBox 10,10,60,30,2,RGB(white),membuttoncolor Text 30,18,"MEM",,,,RGB(white),membuttoncolor RBox MM.HRes-70,MM.VRes-40,60,30,2,RGB(white),zoombuttoncolor Text MM.HRes-55,MM.VRes-32,"ZOOM",,,,RGB(white),zoombuttoncolor End Sub Sub calibrate 'calibrate standard mode ------------ amp_high_gain adc_low_gain 'measure 10% and 90% points PWM 1,120000,10 Pause 1 adc10 = Pin(ADC_PIN) PWM 1,120000,90 Pause 1 adc90 = Pin(ADC_PIN) 'calculate ADC low gain and offset lowgain = 80 * resolution / (100 * (adc90 - adc10)) lowoffset = - lowgain * (adc10 - ((adc90 - adc10)/8)) Print lowgain , lowoffset 'calibrate zoom mode -------------- amp_low_gain adc_high_gain 'measure 10% and 90% values PWM 1,120000,10 Pause 1 adc10 = Pin(ADC_PIN) PWM 1,120000,90 Pause 1 adc90 = Pin(ADC_PIN) 'calculate ADC high gain and offset highgain = 80 * resolution / (100 * (adc90 - adc10)) highoffset = - highgain * (adc10 - ((adc90 - adc10)/8)) Print highgain , highoffset 'back to standard mode amp_high_gain adc_low_gain End Sub Sub draw_frame 'draw outside lines Line 1,1,1,MM.VRes-2,2,RGB(white) Line 1,MM.VRes-2,MM.HRes-2,MM.VRes-2,2,RGB(white) Line MM.HRes-2,MM.VRes-2,MM.HRes-2,1,2,RGB(white) Line MM.HRes-2,1,1,1,2,RGB(white) End Sub Sub Time_Int 'check if left marker needs update If ynl <> y(samples/2) Then 'erase old text Text xnl+12,ynl+yol," ",l,,,0,0 'write markers Box xnl-5,ynl-5,10,10,,0 ' calculate voltage xnl = x(samples/2): ynl = y(samples/2) vl = resistor_divider * ((xnl - MM.HRes / 2) / Hstep) / gain ' repair corrupted frame draw_frame 'write markers Box xnl-5,ynl-5,10,10,,RGB(cyan) 'get new coordinates for writing text, and write If ynl > MM.VRes-30 Then yol=-20 Else yol=5 Text xnl+12,ynl+yol,Str$(vl,0,2)+"V",l,,,RGB(white),0 End If ' check if right marker needs an update If ynr <> y(samples) Then 'erase old text Text xnr-12,ynr+yor," ",r,,,0,0 'write markers Box xnr-5,ynr-5,10,10,,0 ' calculate voltage xnr = x(samples): ynr = y(samples) vr = resistor_divider * ((xnr - MM.HRes / 2) / Hstep) / gain ' repair corrupted frame draw_frame 'write markers Box xnr-5,ynr-5,10,10,,RGB(cyan) 'get new coordinates for writing text, and write If ynr < 30 Then yor=5 Else yor=-20 Text xnr-12,ynr+yor,Str$(vr,0,2)+"V",r,,,RGB(white),0 End If End Sub