4 Software Architecture

This project implements a hierarchical approach from the software point of view. The main function represents the entry point for the code and calls the application’s principal function, Application_Run, which handles the system’s initialization and includes the main application loop.

Upon power-up or Reset, the system clock, pins and peripherals are initialized using the application programming interface (API) provided by the MCC by effectively calling the SYSTEM_Initialize function. Therefore the PWM, CWG, CLC, OPA, FVR, DAC, CMP, UTMR and UART peripherals, along with the system clock and pins are configured just by using the generated code provided by the MCC with no further intervention necessary. Further on, the ISR callbacks needed for the distance measurements’ acquisition are registered by the InitializeCallbacks function. The CMP1’s callback (CaptureCounterCallback) captures the UTMR’s counter value when a reflected echo is detected, disables the CMP1 interrupt to avoid detecting a false echo and signals to the main context that a new data point is available. On the other hand, the PWM2 callback (ResetComparatorInterruptCallback) clears the CMP1 interrupt flag and re-enables its interrupt to adjust it for a new acquisition. Furthermore, the function also enables global interrupts.

After the initialization step ends, the main application loop starts running. This code continuously checks if a new data point is available and, if applicable, it also verifies that it’s within valid bounds (selected empirically with regards to the physical limits of the ultrasonic transducer). If the counter value falls within those constraints, it’s added to a moving average and the current mean distance is printed on the console. The moving average, also called rolling or running average, is a type of Finite Impulse Response (FIR) low-pass filter effectively attenuating high-frequency variations from the input. To make the implementation of the filter’s algorithm reasonably fast, the output of the moving average is not computed using a weighted sum of coefficients and values, instead it uses internally what is called a ring or circular buffer. Essentially, the static allocated circular buffer behaves like a queue of N elements and the system keeps track of the sum of the current queue configuration. When a new sample is available, the buffer’s front element is subtracted from the sum and the new data point is pushed on to the queue and added to the sum, thus a new average can be computed.

Figure 4-1. System Flowchart Diagram
Note: The configuration of this application in MPLAB® Code Configurator and its source code can be found here: