Embedded Signal
Processing
Project 5: Buterworth Filter, Ticker Interrupt-Driven
Code, Digital Resistor
Overview
M.S. students randomized
groups of two each week, never working with same student, unless
otherwise directed by instructor.
Ph.D. students have option to choose their groups (all Ph.D. or
mix), with or without randomization.
The objective of this project is to become familiar with:
- Programming a Butterworth filter
using the 16-bit ADC and 12-bit DAC on the FRDMK64F using mbed.org online IDE
- Using the Ticker.h mbed library
to create interrupt-driven timing
for the filter
NOTE: Use the Project Report Template and see below
for minimum required data content
your reports and demos.
IN NO CASE may code or files or data or pictures be exchanged
between student groups, there is to be NO COPYING of group
reports!
Also, each student must be able to independently
answer any questions themselves during demos.
All students are expected to learn all aspects of every project.
Nevertheless, students are encouraged to collaborate (not copy)
during the lab sessions.
- Some technical notes:
- The FRDMK64F board uses the 100-pin MK64FN1M0VLL12
MCU, with
- maximum operation frequency of 120 MHz, 1 MB of flash, 256
KB RAM,
- full-speed USB controller, Ethernet controller
- 12-bit DAC (see pin DAC0_out on the Arduino header)
- 16-bit ADC (see pins A0 to A5 on the Arduino header)
- 68 GPIO (see pins AD0 to AD15 on the Arduino header)
- The 100-pin package on the FRDMK64F has one DAC module, the 121-pin and
144-pin packages have two DAC modules.
- For more ADC information, see:
Part 1, A Buterworth Lowpass Filter Using mbed Ticker Interrupt
- See below for minimum required data
content for your reports and your demos
- In this part, the 16-bit ADC and 12-Bit DAC are used to
implement a Butterworth filter on the FRDMK64F using mbed
IDE
- ADC and filter timing is set using the mbed Ticker.h library
- First, create and run the code as follows:
- Log into your mbed.org
account
- Go to the mbed
compiler view
- Create a new program using Mbed::MenuBar::NewProgram (blue
arrow below) and
- selecting the FRDM-K64F platform,
- gpio example program template,
- and name frdm_adcTickerInterrupt01 (blue circle below) as
shown below
Fig. 1
- Open the Program Folder and double-click main.cpp (blue
arrow below) to open the main program file as shown below
Fig. 2
- Inspect the main.cpp program code (use main.cpp tab in blue
circle above)
- Click the Mbed::MenuBar::Compile button (red arrow above)
- Make sure that you observe
"success" for the compilation at the bottom of the mbed
window, as before
- Also, note that the file "frdm_whateverYourFileName.bin"
should have been downloaded to your computer
- At this point, you have just confirmed that everything is
working normally as in previous projects
- Plug in your FRDM-K64F board
- Create and run the project code as follows:
- Delete any .bin file that was compiled above and downloaded
to your computer, since we will next replace the default
gpio_example with our own code
- Next: edit the code in the main.cpp frame of the mbed
compiler, as follows
#include "mbed.h"
DigitalOut gpo(D0);
DigitalOut led(LED_RED);
AnalogOut dac0out(DAC0_OUT);
AnalogIn adc0in(A0); //A0 = PTB2
//Serial pc(USBTX, USBRX);
Ticker timer1;
volatile float y=0,yold=0,x=0,xold=0;
void myDsp()// this dsp code will run off a timer interrupt
{
volatile uint32_t mask16=1<<16;
volatile uint32_t dat1=(PTC->PDOR) |
mask16; //set Port Data Output Register
volatile uint32_t dat0=(PTC->PDOR) &
(!mask16); //clear
volatile uint16_t tpAdc0in=1,yout=0;
extern volatile float y, yold,x,xold;
(PTC->PDOR)=dat0; //clear
(PTC->PDOR)=dat1; //set ADD BREAKPOINT HERE
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat0; //clear
tpAdc0in=adc0in.read_u16();
x=(float)tpAdc0in;
y=0.16412f*(x+xold)+0.67175f*yold;
yold=y;
xold=x;
yout=(uint16_t)y;
(PTC->PDOR)=dat0; //clear
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
(PTC->PDOR)=dat1; //set
DAC0->DAT[0].DATL =
(uint8_t)((uint16_t)(yout>>4)
& 0xFF);
DAC0->DAT[0].DATH = (uint8_t)(((uint16_t)(yout>>4)
>> 8) & 0x0F);
(PTC->PDOR)=dat0; //clear
}
int main()
{
if(1) {
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(0); //divide clock 0=/1, 1=/2, 2=/4, 3=/8
}
DAC0->C0 = 0; DAC0->C1 = 0; //reset
DAC state
DAC0->C0 = DAC_C0_DACEN_MASK |
DAC_C0_DACSWTRG_MASK| DAC_C0_DACRFS_MASK;
extern volatile float y,yold,x,xold;
timer1.attach(&myDsp,12.5e-6f); //
calls the myDsp function every 12.5 microseconds
uint32_t cntr=0;
while (true) {
cntr=cntr+1; //does
nothing, jst waiting for timer to call DSP code
if(cntr>1000000)
cntr=0;
}
}
- Note
- The line "timer1.attach(&myDsp,12.5e-6f);
" is used to set a timer interrupt that calls the subtourine
myDsp every 12.5 microseconds
- The resulting sample rate should then be 80,000 samples/s
- For more on interrupts, see Section 3.2.2 Nested Vectored
Interrupt Controller (NVIC) on page 74 of the
Freescale K64
Sub-Family Reference Manual, Rev. 2, January 2014
- Visit mbed-src
to see the details of Ticker.h, AnalogIn.h, DigitalOut.h, and
other items which reside in the mbed library
- Even more instructive to see DigitalOut.h:
- Export your project as a zip archive using right-click the
program folder in mbed, exportProgram, k64fTarget,
toolchainZipArchiveWithRepositories
- Unzip the archive that is downloaded
- Navigate to the mbed folder to inspect all the header
files and definitions within them
- The above code implements a first-order butterworth lowpass
filter, as follows
Fig. 3
- Next, set up a signal generator in the lab:
- First, connect the signal generator output to an
oscilloscope
- Connect the "gnd" pin on the signal generator to the
oscilloscope ground clip
- Set the signal generator to a 2 KHz sine wave, with offset
and peak voltages such that the signal lies between 0.5 and
2.5 volts as shown below (Note: different
equipment may require different settings!)
Fig. 4
- Check that the sine wave is correct, using the
oscilloscope, as follows:
Fig. 5
- Make sure the signal is between 0 and 3 Volts, to avoid damaging your board!
- Plug in your FRDM-K64F board
- Connect the "gnd" pin on the Arduino header to the
oscilloscope ground clip and to the signal generator ground
clip
- Load and run the program that was created above
- Only AFTER you make sure that the
signal is between 0 and 3 volts, connect the signal generator
to Arduino-header pin A0 (PTB2), the 16-bit ADC pin
- Connect the oscilloscope to the DAC output:
- Connect the "gnd" pin on the Arduino header to the channel
2 oscilloscope ground clip
- Connect channel 2 of the oscilloscope to the Arduino
header DAC0_out pin
- NOTE: some slower boards do
not appear to work properly at 80KHz,
- if your board has odd behavior near 20-30 KHz, see the
instructor first, then change the timer to 50 KHz as follows
timer1.attach(&myDsp, 20e-6f); // calls the myDsp
function every 12.5 microseconds
- Also, beware: if you make this
change, how will your filter response change?
- Compile and load the program
- Press reset and run the program
- Press the "single" button on the oscilloscope to capture a
single trace as shown below
- You should see a digital signal as follows:
Fig. 6
- Adjust the signal generator to 20 KHz and observe waveforms
as follows:
Fig. 7
- What is the sampling frequency of the system in sample/s as
computed from your oscilloscope trace as illustrated above?
(this is sample rate R1 in your
report)
- If your output looks like the figure above, Timer.h appears
to be properly setting the interrupt timing for the filter
- Plot the output in your report as the "Butterworth first-order filter",
and you must show both traces as above
- What is the
theoretical impulse response h[n] of the filter?
- What is the
theoretical z-transform H(z) of the filter?
- What is the
theoretical frequency response H(w) of the filter?
- For the sample
rate above, at what frequency in
radians/sample do you expect the null (see
magenta arrow in picture below) in the frequency response
of the filter?
- For the sample
rate above, at what frequency in
Hertz do you expect the null in the frequency
response of the filter?
- Why should a
null occur at half the sample rate?
- Change the input frequency of the sine wave to measure your
predicted null frequency, and do you observe a null (zero)
output? Adjust the frequency to measure the frequency
where the output signal null occurs. (this is null frequency F1 in your report)
- Use the signal
generator to measure frequencey response with a
sine wave function (FUNC button)
- Vary the input frequency from 2 KHz to 50 KHz in 2 KHz
steps, and plot the measured and
theoretical frequency response in dB,
20*log10(Vout/Vin), using the ratio of the peak-peak voltages
at each frequency, as below:
Fig. 8
- You may use (after fixing the errors in this file) the excel
template p05butterPlotTemplate.xlsx
You must fix the data and theory
in this template file
- Does your measured frequency response match the theoretical
response?
- This plot is " Butterworth
first-order filter"
, to be included in your project report,
and you must show both traces as above
- Change the code to implement a
new filter as follows:
- Return your signal generator to the
original settings including the input frequency that
was changed
- Compile and load the program
- Press reset and run the program
- Press the "single" button on the oscilloscope to capture a
single trace
- Plot the output in your report as the " Butterworth
second-order filter", and you must show both traces as above
- Does it roll off faster and provide sharper filtering
than the first-order filter?
- For the sample
rate above, at what frequency in
Hertz do you expect the first null in the
frequency response of an 8-point moving average filter?
- Change the input frequency of the sine wave to measure your
predicted null frequency, and do you observe a null (zero)
output? Adjust the frequency to measure the frequency
where the output signal null occurs. (this is null frequency F2 in your report)
- Does your measured frequency response match the theoretical
response?
Part 2, Digital Resistor
- See below for minimum required data
content for your reports and your demos
- In this part, a digital resistor is created on the FRDMK64F
using mbed IDE or KDS/KSDK
IDE or improvised Eclipse/Platformio
IDE
- Create the digital resistor and follow the instructions as
follows
- NOTE: some slower boards do
not appear to work properly at 80KHz:
- see the note in Part 1 above
to adjust timer for digital resistor below, if needed
- Download the instructions for the digital resistor
experiment (see instructor for password)
- Follow the instructions, and add results to your report as
indicated below
Report Data
- Minimum required data content for
your report and demos
- Required theory content:
- For a second-order Butterworth lowpass filter with 5 KHz
bandwidth and 80,000 samples/s, provide:
- the z-transform H(z) as in Fig. 3 above
- Required software code excerpt content:
- The single most important line
of code in main.cpp to do the Butterworth
second-order filter
- Something similar to
"y=0.16412f*(x+xold)+0.67175f*yold;" in above Butterworth
example
- The single most important line
of code in main.cpp to do the Rin=2000 digital
resistor
- Something similar to "y=0.75f*x;" in above digital
resistor example
- Required tabular data content:
- The values for:
- Measured Butterworth sample rate
R1 in samples/second as defined above
- Measured first-order Butterworth
null frequency F1 in Hz
- Measured second-order
Butterworth null frequency F2 in Hz
- Measured peak current I1 in
milliamps for Rin=2000
- Required pictures/photos content:
- Legible picture (if pdf of your report is
"zoomed/magnified") oscilloscope photo showing ADC
input and DAC output voltages for " Butterworth first-order filter"
similar to Fig. 7 above
- Legible picture (if pdf of your report is
"zoomed/magnified") showing "Butterworth
first-order
filter frequency
response" similar to Fig. 8 above
- Legible picture (if pdf of your report is
"zoomed/magnified") showing "Butterworth
second-order
filter frequency
response" similar to Fig. 8 above
- Legible picture (if pdf of your report is
"zoomed/magnified") oscilloscope photo
showing "Rin=2000, 0-2V input ADC, DAC
output, plus Math-mode" similar to Fig. A5 of
Digital Resistor section above
- Project Demos
- Be prepared to demonstrate and discuss items such as:
- Demonstrate sine wave response first-order Butterworth
filter as Fig. 7
- Demonstrate sine wave response second-order Butterworth
filter as Fig. 7
- Change the sampling period and sampling rate
- Demonstrate an Rin=2000 digital resistor
- Measure the current in an Rin=2000 digital resistor using
oscilloscope MATH mode
- Change Rin for a digital resistor
- Set breakpoints
- Start and stop the debugger
- Demonstrate a full clean/build
- Be prepared to answer questions such as:
- What is impulse response of the filters?
- What is frequency response of the filters?
- What is z-transform of the filters?
- What is dc response of the filters?
- What port number is ADC (PT???)
- What port number is DAC(PT???)
- How can the value of the digital resistor be changed?
- How can the 3 dB point of the Butterworth filter be
changed?
- What happens if the sample rate changes for the
Butterworth code?
- Which line of code sets up the interrupt/timer?
- How does myDsp() subroutine code get executed, if it is
not called inside of main{}?
- What is an interrupt?
- How many clock cycles are used in serviceing an interrupt?
- What is the sp register and stack pointer?
- what is interrupt latency? interrupt priority? see https://community.arm.com/docs/DOC-2607
- What is stack overflow? see https://en.wikipedia.org/wiki/Stack_overflow
- What is bilinear transform?
Report:
- See above project description for required
report data content.
- NOTE Report Template Use the Project Report Template
( embDspProjTemplate.docx) for your report.
- One pdf-format must be emailed to the instructor at the
beginning of the class meeting of the demo.
- One hardcopy per student, plus
one extra hardcopy for the instructor, should be brought to
class for the demo.
- Do not add extraneous pages or put explanations on separate
pages unless specifically directed to do so. The instructor will
not read extraneous pages!
- YOU MUST ADD CAPTIONS AND FIGURE NUMBERS TO ALL FIGURES!!
Copyright 2015-2016 T. Weldon
Freescale, Kinetis are registered trademarks of Freescale
Semiconductor, Inc. Texas Instruments, TI, C2000, and
Code Composer Studio are a registered trademarks of Texas
Instruments Incorporated. Adafruit is a registered
TradeMark of Limor Fried. ARM, Cortex and Keil are
registered trademarks of ARM Limited (or its subsidiaries).
Apple, Yosemite, Mac OS, iPhone, iPad, MacBook, Mac, iTunes, and
Xcode are trademarks of Apple inc. All other product or service
names are the property of their respective owners. Arduino
is a registered trademark of Arduino.