SLAAE78 August 2024 MSPM0G1105 , MSPM0G1106 , MSPM0G1107 , MSPM0G1505 , MSPM0G1506 , MSPM0G1507 , MSPM0G3105 , MSPM0G3106 , MSPM0G3107 , MSPM0G3505 , MSPM0G3506 , MSPM0G3507 , MSPM0L1105 , MSPM0L1106 , MSPM0L1303 , MSPM0L1304 , MSPM0L1304-Q1 , MSPM0L1305 , MSPM0L1305-Q1 , MSPM0L1306 , MSPM0L1306-Q1 , MSPM0L1343 , MSPM0L1344 , MSPM0L1345 , MSPM0L1346
This example demonstrates how to convert an analog signal to a 4kHz PWM output. The analog input signal is sampled using the MSPM0 integrated ADC. The duty cycle of the PWM output gets updated based on the ADC reading. Two timers are required for this example; one to trigger the ADC reading and another to generate the PWM output. Download the code for this example.
Figure 1-1 displays a functional block diagram of the peripherals used in this example.
This application requires 2 timers, an integrated ADC, and 2 device pins.
Sub-block functionality | Peripheral usage | Notes |
---|---|---|
Sample triggering | (1x) Timer G | Called TIMER_0_INST in code |
PWM generation | (1x) Timer G | Called PWM_0_INST in code |
Analog signal capture | 1 ADC channel | Called ADC12_0_INST in code |
IO | 2 pins | (1x) ADC input (1x) PWM output |
Based on the requirements in ,Table 1-1 this example is compatible with the devices in Table 1-2. The corresponding EVM can be used for prototyping.
MSPM0Lxxx |
EVM |
MSPM0Lxxx |
|
MSPM0Lxxx |
Determine the required PWM output frequency and resolution. These two parameters are the starting point when calculating other design parameters. In this example we chose an PWM output frequency of 4kHz and a PWM resolution of 10bits.
Calculate the timer clock frequency. The equation F_clock = F_pwm x resolution can be used to calculate the timer clock frequency.
Determine the ADC sampling rate. The sampling rate is related to the output PWM frequency. In this example, a single ADC sample determines the duty cyle. F_adc = F_pwm. However, filtering or averaging may require the application to choose a different sampling rate.
Configure peripherals in SysConfig. Select which timer instances will be used. Configure which device pins will be used for ADC input and PWM output. This example uses PA17 for the PWM output (which is connected to Timer G4) and A0.4 for the analog input.
Write application code. The remaining piece of this application is to transfer the ADC samples to the PWM timer. This is accomplished in software. See Software Flowchart for an overview of the application or browser the code directly.
Max output frequency: Fundamentally, the max PWM output frequency is limited by the IO speed. However, the duty cycle resolution also affect the max output frequency. More resolution requires more timer counts which increases the output period.
Clocking: Deciding which clocks to use and what clock division ratios to use is an important design consideration for this application.
Select a resolution that is a power of 2 so scaling operations can use shifts instead of multiplies and divides b.
In general, don't divide a slower clock down to a lower frequency. Instead pick a slower clock to reduce power consumption 3.
Race conditions on gCheckADC: This application takes care to clear gCheckADC as soon as possible. If the application waits too long to clear gCheckADC it may inadvertently miss new data.
Pipelining: The PWM timer selected in this application supports pipelining the timer compare value. Pipelining allows the application to schedule an update to the timer compare value without causing a glitch on the output. Techniques exist to mitigate glitches on timers without support for pipelining. However, this is beyond the scope of this document.
Figure 1-2 shows the operations performed by application to convert an ADC reading into a PWM output.
This application's PWM output has 10bits of resolution. However, the ADC samples are 12bits, so we must convert the 12 bit ADC readings into 10 bit values that can be used to set the compare value of the PWM timer. Depending on an applications requirements different scaling can be required.
Additionally, more advanced signal processing of the incoming data can be required. For example limiting, averaging or other filtering may be important in different scenarios. These type of operations can be performed in the function below.
void updatePWMfromADCvalue(uint16_t adcValue) {
// Check to see if the adc value is above our minimum threshold
if (adcValue > PWM_DEADBAND)
{
// Convert 12bit adcValue into 10bit value by right
// shifting by 2 because the PWM resolution is 10bit
uint16_t adcValue_10bit = adcValue >> 2;
// PWM timer is configured as a down counter (i.e it
// starts counting down from PWM_LOAD_VAL) and its
// initial state is high therefore we must perform
// the following operation so that small values of
// adcValue_10bit result in small duty cycles
uint16_t ccv = PWM_LOAD_VAL - adcValue_10bit;
// Write the new ccv value into the corresponding timer
// register
DL_TimerG_setCaptureCompareValue(PWM_0_INST,
ccv,
DL_TIMER_CC_0_INDEX);
// Start the timer if it is not already running
if ( !DL_TimerG_isRunning(PWM_0_INST) ) {
DL_TimerG_startCounter(PWM_0_INST);
}
}
else {
// If adcResult is not above deadband value then disable timer
DL_TimerG_stopCounter(PWM_0_INST);
}
}
When the input voltage is below a preset deadband value the output is disabled, as shown in figure 1-3.
In figure 1-4 the input voltage is 2.26V. The measured duty cycle is 67.93%. A quick calculation confirms that the expected duty cycle is 68.4%.