- Provide insight and a guide on how to generate a Pulse-Width-Modulation (PWM) signal using the MPLABX IDE and the MPLAB Code Configurator after spending two months trying to figure it out on my own and being told on the Mircochip fourms to "read the datasheets"
- (1) dspic33CH512MP508 Curiosity development board
- (4) 100 Ohm resistors, or any value resistors you have
- (5) Jumper cables
- Open MPLAB Code Configurator by clicking on the icon circled in red.
- Enable the PWM and UART2 peripherals that are listed under 'Device Resources. Enabling the UART peripheral will allow us to monitor the PWM signal being generated in real time.
- Double click on the 'PWM' Peripheral and you'll see the 'Hardware Settings' window pop up
- Under 'Select Required PWM Generators' enable all the PWM_Generators that are listed by clicking on them
-
Make sure :
- 'Enable PWM Generator' is checked
- 'PWM Operation Mode' is set to Independent Edge
- 'PWM Output Mode' is set to Complementary
-
Under PWM Frequency Settings :
- Set PWM Input Clock Selection to 4000000
- Under the Period settings set :
- Requested frequency : 235.29412 kHz
- Requested period : 4.25 us
- Under Duty Cycle set :
- PWM Duty Cycle : 0
- PWM Phase : 0 ns
- Under Trigger Control Settings set :
- Start of Cycle Trigger : Self-Trigger
- Trigger Output Selection : EOC event
- Under ADC Trigger set :
- ADC Trigger 1/2 : None
- Trigger A/B/C compare : 0 ns
- Under Dead Time and Override Settings set :
- PWM L/H Dead Time Delay : 0 ns
- PWM L/H Override : disabled
- Under Data Update Settings set :
- Update Trigger : Manual
- Update Mode : SOC Update
Here's also a screenshot that you can also follow along with the mentioned settings
The most crucial step is to ensure that the 'Redirect Printf to UART' is enabled so we can check/watch the values being generated for the PWM signal
Under 'Project Resources' click 'Generate' to, quite literally, generate the code we've configurated for through the MCC GUI.
While the MPLABX Code Configurator is still open, on the right hand side of the IDE is the 'Pin Manager : Package View' window.
Since we're controlling four EXTERNAL LEDs and the on-board RGB LED, right click on the corresponding green boxes as indicated on the screenshot below and change them to the values listed.
For example, when you right click on port RB10 a drop down menu will pop up and will allow you to designate that port as PWM3-H
If you go to the project folder --> Header Files --> MCC Generated Files --> There's a pwm.h file that shows what each function does and the parameters needed per function.
For example, the following code snippet is to change the PWM duty cycle
/**
@Summary
Enables the specific PWM generator.
@Description
This routine is used to enable the specific PWM generator selected by the argument PWM_GENERATOR.
@Param
genNum - PWM generator number.
@Returns
None
@Example
<code>
PWM_GeneratorEnable(PWM_GENERATOR_1);
</code>
*/
PWM_GeneratorEnable(PWM_GENERATOR genNum)
{
switch(genNum) {
case PWM_GENERATOR_1:
PG1CONLbits.ON = 1;
break;
case PWM_GENERATOR_2:
PG2CONLbits.ON = 1;
break;
case PWM_GENERATOR_3:
PG3CONLbits.ON = 1;
break;
case PWM_GENERATOR_4:
PG4CONLbits.ON = 1;
break;
default:break;
}
}
My intial thoughts was that the PWM_GeneratorEnable() function was all that I needed.
After spending two months and reading any datasheet that was related to generating a PWM signal, I was dead wrong.
I posted my woes in the Microchip fourms and was forunate enough to have a solution provided to me by @GettinBetter whom used the 'MasterPWM' settings to change the duty cycle of the blue on-board RGB LED.
The TL;DR version of his post is as follows
- In pwm.h has a section that outlines how to use the 'Master PWM' settings which will be used as a guide to generate a PWM signal from one of the four PWM generators
- An outline of the mentioned Master PWM settings can be found below
@Summary
Initializes PWM module.
@Description
This routine initializes PWM module, using the given initialization data.
@Param
None.
@Returns
None
@Example
<code>
uint16_t masterPeriod,masterDutyCycle,masterPhase;
masterPeriod = 0xFFFF;
masterDutyCycle = 0xFF;
masterPhase = 0xF;
PWM_Initialize();
PWM_GeneratorDisable();
PWM_MasterPeriodSet(masterPeriod);
PWM_MasterDutyCycleSet(masterDutyCycle);
PWM_MasterPhaseSet(masterPhase);
PWM_GeneratorEnable(PWM_GENERATOR_1);
</code>
- So in order to use the PWM_Generator_1 to generate the PWM signal, you just have to swap the following functions
- PWM_MasterPeriodSet(masterPeriod) --> PWM_PeriodSet(PWM_GENERATOR_1,0x4E20)
This snippet of code will dim an LED that's attached to Pin RB14 in accordance to the hex value being passed in the PWM_DutyCycleSet() function.
- Decimal values such as Unsigned Ints up to 32500 can be used instead of Hex values
while(true)
{
PWM_PeriodSet(PWM_GENERATOR_1,0x4E20); //Decimal value : 20000
PWM_GeneratorDisable(PWM_GENERATOR_1); //Pin : RB14
PWM_DutyCycleSet(PWM_GENERATOR_1, 0x4FB0); //Decimal value : 20400
PWM_GeneratorEnable(PWM_GENERATOR_1);
__delay_ms(300);
PWM_GeneratorDisable(PWM_GENERATOR_1);
PWM_DutyCycleSet(PWM_GENERATOR_1, 0x27D8); //Decimal value : 10200
PWM_GeneratorEnable(PWM_GENERATOR_1);
__delay_ms(300);
PWM_GeneratorDisable(PWM_GENERATOR_1);
PWM_DutyCycleSet(PWM_GENERATOR_1, 0x64); //Decimal value : 100
PWM_GeneratorEnable(PWM_GENERATOR_1);
__delay_ms(300);
}
The pins corresponding to the on-board RGB LED are :
- RB14 : BLUE
- RD5 : RED
- RD7 : Green
When we enable PWM_GENERATOR_1 and PWM_GENERATOR_4 we can send a PWM signal to pin(s) RB14, RD5 and RD7.
However when right clicking pins like RB14, I'm currently not sure what the difference is between PWM4H and PWM4L
- As of 9/22/2021 I'm under the assumption that the designated pin will 'Start' the PWM signal high or low depending if it's assigned PWM4H or PWM4L
- Example : If RB14 was designated as PWM4H, the PWM signal will start HIGH at 3.3 volts
- If the same pin was assigned PWM4L, the PWM signal will start LOW, or at 0 volts
- Example : If RB14 was designated as PWM4H, the PWM signal will start HIGH at 3.3 volts
For troulbeshooting/sanity checks, we'll be using the printf() function to ensure the PWM signal is being generated when the fade_LEDs() function is enabled/uncommented in the main function loop
For the dsPIC33CH512MP508 Curiosity board pin(s) RC10/RC11 are the perspective TX/RX pins.
To enable them :
- Go to the pin manager
- Right click on pin RC11 and set it to U2TX
- Under the pin module, ensure RC11 the box for 'Start High' is checked
- Do the same with pin RC10 and set it to U2RX
Since there was no sort of documentation on how to generate a basic PWM signal and reading the High-Resolution PWM with Fine Edge Placement or the High-Speed PWM Module raised more questions than answers lead/motivated me to creating this repository with hopes of helping others.