Final Project Report
B12901148 Kuan-Yu, Chou, B11901100 Chun-Ping, Wang
A.Motivation
1. For individuals like students, oscilloscopes are not quite affordable.
2. Oscilloscopes are not portable for analyzing signals anywhere.
3. The functions of analyzing input signals of traditional oscilloscopes may be
limited.
B. Methodology
We introduce a portable mini oscilloscope with functions of oscilloscope, filter,
and signal generator using stm32f746g discovery kit.
1. Tasks
There are six tasks:
a. Main: manage the states like oscilloscope/filter/signal generator mode
and the UI menu.
b. ADC_process: control the ADCs to operate at a desired sampling
frequency, organize the raw data from ADCs, and find the trigger point.
c. Filter_process: If filter is used, filter the input signal collected by
ADC_process and calculate the filter output.
d. DAC_process: Configure the output rate of DAC and compute the
output signal by the parameters of signal generator or the output of the
filter determined by the use of signal generator or filter.
e. User_input: Capture the user input from touch screen to update the
parameters like: sampling rate, use of filter, cutoff frequency of the
filter, etc.
f. Render: By the current menu, display the icons, data points, characters
onto the screen.
2. ADC process
a. ADCs Cooperation
To achieve a high sampling rate, we make the 3 ADC instances
(ADC1, ADC2, ADC3) operate in cooperation. We set up three output
compare events (OC1, OC2, and OC3) triggered by timer1 with CCR1
= ARR/3, CCR2 = ARR*2/3, and CCR3 = 0 are configured. Where
ARR is the auto reload register, also the period of timer1. Each of these
three events trigger the conversion of ADC1, ADC2, ADC3
respectively. Therefore, the ADCs convert in pipelined reaching the
maximum 3x throughput rate, also the sampling rate of a single ADC.
Note that the reason why the CCR1 is ARR/3 but not 0 is if the timer
starts with CNT value 0, the output compare event for 0 would not be
triggered instantaneously but output compare events with CCR>0 will
be triggered first, as a result, to make ADC1 convert first, we should set
CCR1 as ARR/3.
By the configuration mentioned above, the sampling rate can be
derived by:
3·𝐻𝐶𝐿𝐾
𝑓𝑆 = 𝑃𝑆𝐶·𝐴𝑅𝑅
The typical value of HCLK is 216MHz for stm32f746g discovery. By
adjusting the prescaler and the period of the timer1, we can achieve a
variable sampling rate.
b. Data Acquisition
We configure three DMA streams for the transfer of the raw data of
the three ADCs to three buffers respectively as shown in Figure 1. To
reconstruct the real ADC data sequence in the order of time, we should
go through the three DMA buffers in the order of the gray arrows shown
in Figure 1, and then copy to a new buffer array.
c. Finding Trigger
The trigger is a critical function of an oscilloscope. It can be noticed
that we should preserve the data before the trigger point as the trigger
point is centered in general; hence, we regard the databuffer as a circular
buffer. We find the trigger point while copying the ADC data from the
three adc_buff to the data buffer. On finding the trigger, we tag the
trigger point by noting its index and keep copying half the length of the
databuffer which makes the trigger point center the circular databuffer.
Figure 1. Data Acquisition from DMA buffer
Figure 2. Circular Databuffer
3. Filter process
a. Design
Our oscilloscope includes a real-time digital filter running on the
STM32 microcontroller. The filter supports four common types:
Low-Pass Filter, High-Pass Filter, Band-Pass Filter, and Band-Stop
Filter, each with selectable cutoff frequencies.
For simplicity and performance, we use an FIR (Finite Impulse
Response) filter. Instead of complex or computationally expensive
algorithms like Minimax or Least Mean Squares Error (MSE), we chose
a straightforward and efficient approach.
To design the FIR filter, we start with an ideal square-shaped frequency
response. This is then converted into a time-domain sinc function using
an inverse Fourier transform. Since the sinc function has infinite length
and causes ripple effects when truncated, we apply a Hamming window
to smooth it out and reduce sidelobes, resulting in a more practical and
stable filter.
This method is equivalent to the way MATLAB’s fir1() function
generates FIR filters. To verify our implementation, we compared the
generated coefficients with those from MATLAB, and confirmed that
the error was below 1e-3, ensuring high accuracy. (Experiment done on
fc = 0.4. In bandpass and bandstop cases, the second cutoff frequency is
at 0.2.) Please note that MATLAB normalizes the cutoff frequency to
the Nyquist frequency. This means the normalized frequency used in
fir1() is twice the actual cutoff frequency relative to the sampling rate.
b. Implementation with CMSIS DSP
The filter is implemented using the CMSIS-DSP library provided for
ARM Cortex-M processors. Specifically, we use arm_fir_instance_f32
to create a filter instance, and the function arm_fir_f32() is used to
process real-time signal data.
Filtering only runs when the digital filter function is enabled by the
user via the touch interface. This saves processing power when filtering
is
not needed.
Overall, this design provides a balance between performance and
simplicity, making it ideal for real-time embedded applications like our
DIY oscilloscope.
4. DAC process
a. Timer Triggered
We use timer2 for generating the event to load DAC data from the
DMA buffer. The update rate of the DAC is determined by the
following,
𝐻𝐶𝐿𝐾
𝑓𝑈 = 𝑃𝑆𝐶·𝐴𝑅𝑅
,
which can be also variably adjusted. For our application, the update rate
of the DAC is the sampling rate of ADCs in filter mode or decided by
the desired output signal in signal generator mode.
b. Buffer Management
In signal generator mode, we set our minimum sampling factor to be
128. That is, there are at least 128 samples in a period. To generate a
continuous signal, the total buffer length should be integer multiple of
the sampling factor. For example, if the buffer length is 1024, and the
sampling factor is 128, there would be 8 periods of the signal in the
buffer. Once the desired signal for the signal generator is set, we
compute the lookup table and store into the DMA buffer, and then start
DMA transfer.
In filter mode, the DMA buffer is filled by the filter process task and
thus is able to output the filtered signal.
5. User input
The user interface of our oscilloscope is implemented using the
STM32F746’s built-in LCD touchscreen, supported by the STM32 BSP
(Board Support Package). Touch input is handled through hardware
interrupts: whenever the user interacts with the screen, an external interrupt
is triggered, notifying the corresponding task within the RTOS.
Upon each touch event, we call
BSP_TS_GetState(&touch_screen_state); to
retrieve the coordinates of the touch. Based
on the current state or active page of the
oscilloscope interface, we use conditional
logic to determine the appropriate
response—such as switching modes,
adjusting filter parameters, or changing
display settings.
6. Render
a. Determine Updates
Check if the state is altered, if true, collect all the icons/characters
that should be updated.
b. Display
Draw the icons which should be updated and the data points of the
oscilloscope input or filter output by the board support package
functions in the correct order of the layers.
C. Results
1. We find the output of the on board DAC is not quite accurate and stable, and a
high throughput DAC module is expensive. Therefore, we deprecate the
functions about it, which are the signal generator and the output signal of the
filter.
2. When trying to use the ADC process and Render together, we find some
significant but hard to be noticed factors that may disable the transfer of the
DMA of the ADC.
a. DMA Stream
In cubeMX, we can choose the stream for DMA to transfer the
data from ADC. However, we didn’t notice that the LCD screen,
used with BSP, depends on the peripherals LTDC+DMA2D, where
the LTDC manages the layers, screen buffers, and the pixel format in
the screen buffers and the DMA2D performs the pixel format
conversion and render different layers. They also use DMA2 stream0
for transfer. Hence, we need to avoid using DMA2 stream0 for
transferring our ADC data in cubeMX.
b. Use of SDRAM
The LTDC peripheral takes use of the SDRAM for storing the
screen buffer and it seems like it also uses DMA to access the screen
buffer in SDRAM. If the three DMA buffers of the ADCs are too
large to allocate in SRAM, they will be allocated onto SDRAM by
the compiler which can also lead to the DMA access failure. As a
consequence, we allocate short enough ADC buffers to be placed in
SRAM.
3. After resolving the above issues, we successfully integrate the functions
together. We show some photos of our end product in the following.
Figure 3. (a), (b) The UI menu for selecting oscilloscope, signal generator, or filter mode.
Figure 4. The lowpass filtered signal shown with original signal together
D.References
1. STM32f746ng MCU datasheet
2. STM32f746gdisco datasheet
3. Mathworks FIR Filter Design