Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

DSPIC30F4011 PWM Control

Status
Not open for further replies.

hedryn

New Member
Hi,

I am trying to figure out how to use the PWM Motor Control Mode for my dsPic30F4011. I am trying to send a signal with a period of 2 microseconds. The problem is I have no idea how. I've poured through the dsPic manual and the motor pwm module manual, but the documentation is just not making the process clear. So my questions are:

1) How do I "activate" the motor control module? Do I need to write to a certain register or something? I have written to the PTPER and PTCON register, but I am not getting a PWM signal.

2) How do I set the period to 2 microseconds? I have tried to do the math using equation 15-1 in the dsPIC30F4011 manual, but I do not know what Tcy is. What is Tcy?

3) How do I set a different period for PWM1, PWM2, and PWM3?

Thanks for everyone's help so much! Microchip's support is...lacking. I will soon update this post with the little bit of code I've written.

PS. If you're curious, I am building a highly mobile hexapedal robot, and need to send PWM signals to the Victor 884s I have connected to each of the 6 dc motors I am using to make it walk. The mechanical design and building is finished, and the "nervous system" (speed controllers to motors) is more or less complete. But I've gotten complete stuck at the "brain" programming.

Edit// Code so far. Hope to have it filled with lines that make it, you know, work, quite soon:

//title "Project Zero"


#include <dspic.h>

//PORTB will be the hall effect sensors.
void init(void)
{
TRISB = 1;
PORTB = 0;
PORTD = 0;
TRISD = 0;
PORTE = 0;
}

void main(void)
{
init();
PTCON= 0b1000000000000000; //set PWM mode
PTPER = 0b0000000000010001; //set pwm period

}
 
Last edited:
I've never looked at the dsPIC's before, but I took a look at the datasheets because I found it odd that the documentation would not be that good. The description of the PWM motor control module seems to be complete and detailed. You are right, Tcy is not mentioned around the actual formula, but searching Tcy in the datasheet found this pretty easily:

Instruction cycle period (TCY) equals four times the input oscillator time base period. All specified values
are based on characterization data for that particular oscillator type under standard operating conditions
with the device executing code. Exceeding these specified limits may result in an unstable oscillator
operation and/or higher than expected current consumption. All devices are tested to operate at “min.”
values with an external clock applied to the OSC1/CLKI pin. When an external clock input is used, the
“Max.” cycle time limit is “DC” (no clock) for all devices

Table 24-16 seems to have a list of Tcy values based on crystal frequencies.
 
Thanks a lot, I'm not sure how I didn't find that. This will help. I'll start reading through the manual to figure out what the input oscillator time base period is.

I should clarify. The documentation is very in depth on the individual registers, and what bits control what, etc. What I am having difficulty with - and my professor does not know either - is putting the pieces together into a code. The documentation has information, but not instructions. Does just writing to the registers that control frequency "start" pwm mode? How do I control the individual duty cycles? These are the questions I haven't been able to answer from the documentation.
 
Last edited:
The chip specific dspic manuals are only supplemental to the more comprehensive family reference manual shared by all dspics (30F and 33F have their own). Is that why you can't find certain things?
 
Last edited:
Hi,

I am trying to figure out how to use the PWM Motor Control Mode for my dsPic30F4011. I am trying to send a signal with a period of 2 microseconds. The problem is I have no idea how. I've poured through the dsPic manual and the motor pwm module manual, but the documentation is just not making the process clear. So my questions are:
Isn't the Victor884 looking for a servo signal (even though they call it PWM), which would be a 2ms period, not 2us?

Is a Vex RC Transmiter/receiver being used? If not, then what controller, and Tx protocol, is being used?

Don't have the dspic30f4011 data sheet. IF the motor module is setup like the motor module of the PIC18f1330, then here is some snippets of code I made for some rgb leds. It is in GCBasic, turning on the various bits in the 8-bit registers, so those are most likely merged from the PDC0H and PDC0L into PDC0 etc for the 16-bit dspic.

It was kind of pain, even from the data sheet as I remember. Please forgive for what may be inaccurate commenting, the code was never polished up. Hope this helps to understand the power module register control.

Code:
#chip 18f1330,4
#config osc=INTIO2,HPOL=HIGH,LPOL=High 'set PWM polarity bit for active low (CA led)

#define Red PortB.1	'PWM1, PWM 1/3/5 are main PWM 0/2/4 are compimentary
#define Green PortB.4	'PWM3
#define Blue PortB.6	'PWM5
#define WaitLed wait 1 s
dim Level as word	
dir Red out
dir Green out
dir Blue out
dir PortB out
init_PowerPWM


Level = 16384
Main:
;Yellow
	PDC0H = ! Level_H	
	PDC0L = ! Level
	PDC1H = ! Level_H/2
	PDC1L = ! Level
	PDC2H = ! 0XFF
	PDC2L = ! 0XFF
	waitled
;Purple
	PDC0H = ! Level_H	
	PDC0L = ! Level
	PDC1H = ! 0X00
	PDC1L = ! 0X00
	PDC2H = ! Level_H/2
	PDC2L = ! Level
	waitled
goto Main

sub init_PowerPWM
	Set PTEN On
		'set UDIS Off
	PTCKPSO = 0
	PTCKPSO = 0
	Set PMOD2 Off
	Set PMOD1 Off
	Set PMOD0 Off	;independent mode
	Set PTMOD1 Off
	set PTMOD0 Off
		'no dead time required!
		'DTCON = b;01010100'
	PTCON0 = 0X00
		'PTCON1 = 0XC0
	SET PTEN ON	;PWM TIME BASE IS ON
	SET PTDIR ON ;PWM TIME BASE COUNTS DOWN
		'PWMCON0 = 0X37
	Set PWMEN2 On ;PWM1,3,5 enabled
	set PWMEN1 ON
	Set PWMEN0 On
		'PWMCON1 = 0
	PTPERL = 0XAA
	PTPERH = 0X01
	PDC0H = 0x00
	PDC0L = 0X00	'PWM1 DUTY CYCLE
	PDC1H = 0X00
	PDC1L = 0X00
	PDC2H = 0X00
	PDC2L = 0X00
end sub
 
YOu need to look at the motor control specific datassheet. That has the specific information on the MC-PWM module.
 
Okay, interesting. I'll try writing the code a bit more like you do. You set a PWMEN2 On, which you comment turns on the PWMs. Do you know if there is something analogous for the dspic30f? One of my above questions was whether there was something I needed to write to to enable the pwm registers. I tried also writing to the ptmr and pwmcon1 registers, but still no signal. I'll repost my own code in a bit after I do a little work on it.

And yes, I meant 2ms, not us. I'm not using a Vex RC transmitter/receiver - as of now I'm not attempting tele-op. My only hardware is dsPic30f4011 --> Victor --> DC motor.
 
Last edited:
Okay, interesting. I'll try writing the code a bit more like you do. You set a PWMEN2 On, which you comment turns on the PWMs. Do you know if there is something analogous for the dspic30f? One of my above questions was whether there was something I needed to write to to enable the pwm registers. I tried also writing to the ptmr and pwmcon1 registers, but still no signal. I'll repost my own code in a bit after I do a little work on it.
The PWMEN2 bit is part of the PWMCON0 register for the 18f1330, so I would think you would be looking for a PWMCON register for the 16bit dspic? Please note that three bits need to be set to determine which PWM pins are enabled. Notice in my code all three PWMEN2:pWMEN0 are set, meaning all odd numbered PWM outputs are enabled (i.e. 1, 3,and 5) per the 18f1330 data sheet.

Same goes for the PMOD2:pMOD0 bits, all on for independent mode in the same PWMCON register. You will have to verify whether these bits are valid for the dspic. Usually(?), Microchip keeps the same bit definitions even if the register names change. While my code is more universal in nature, poor commenting does not associate their respective registers.

It is not entirely clear to me whether you can actually write to the PTMR register? In my case, the PTPER registers were written to instead.
 
You have to write to the P1DC1, P1DC2, P1DC3 registers to set the duty cycle for each PWM output. I'm not sure how to do it with the <dspic.h> headers, but here is a basic setup for a ds33 device. Should be the same, although the actual period and duty cycle numbers will need to be changed to be specific to your setup.

You need to include the device specific header. In this case #include <p33FJ32MC202.h> for MPLABc30

Code:
	// Init PWM1 for dual pair output.
	PWM1CON1bits.PEN1L 	= 1;
	PWM1CON1bits.PEN1H 	= 1;
	PWM1CON1bits.PEN2L 	= 1;
	PWM1CON1bits.PEN2H 	= 1;

	// Setup the dead time periods
	P1DTCON1bits.DTBPS 	= 0;
	P1DTCON1bits.DTB	= 63;
	P1DTCON1bits.DTAPS 	= 0;
	P1DTCON1bits.DTA 	= 63;
	
	// Set which transitions get which dead times.
	P1DTCON2bits.DTS1I	= 1;
	P1DTCON2bits.DTS1A	= 0;
	P1DTCON2bits.DTS2I	= 1;
	P1DTCON2bits.DTS2A	= 0;

	P1TPER = 1999;

	// Enable PWM1
	P1TCONbits.PTEN = 1;

        // Set the initial duty cycle;
        P1DC1 = 1000;
        P1DC2 = 1000;
 
Last edited:
Thanks a lot smanches, I think this is going to be really useful. I'd add the include file, write to the P1DC1 registers, make sure to enable PWM1 by writing to the PTEN bit, and see where this takes me and let you guys know the result.
 
//title "Project Zero"


#include <dspic30f4011.h>

//PORTB will be the hall effect sensors.
void init(void)
{
TRISB = 0b111111111111111;
PORTB = 0b0000000000000000;
PORTD = 0b0000000000000000;
TRISD = 0b0000000000000000;
TRISE = 0b0000000000000000;
}

void main(void)
{
init();
PTCON = 0B1000000000000000; //set PWM mode - free running, time base is on.
PTPER = 0B1001110000111111 //set pwm period to 39999, which should be 2 ms
PWMCON1 = 0B111111111111; //should enable all pins for PWM output
PDC1 = 0b1000; //should set PMW1 duty cycle.

}



Okay, I've got to be close. I realized my chip wasn't powered correctly, fixed that and thought it must work, but still nothing.

  • Include file is chip-specific.
  • PTCon is set to free running.
  • I used equation 15-1 to calculate that PTPER should be 39,999 for a period of 2 ms, which the Victor needs. This is assuming Fcy = 20MHZ, which the example says, yet which I have no idea.
  • PWMCON1 is set so that PWM1L and PWM1H should be enabled.
  • Though I'm not certain about this, TRISE is set to output. PDC1 is set so it should be giving me something: I'm not certain what binary value to set it to, in order to vary the duty cycle from 0 to 100%. Is all pins on 100%, all pins off 0%?

With this code in place, I expect to put the digital pin on my oscilloscope to Pin 38, PWM1L, and see some square wave/pwm action. But still nothing - it just remains at ground. Do I need to set the dead time values? Frankly I'm not certain what the dead time is, but I can read through the manuals and hopefully figure it out.
 
Last edited:
hedryn:

I just realized that maybe we are starting from scratch here. Have you got a basic blinky led going yet? If not then what is missing is the config and basic setup statements describing the type of oscillator used, speed, watchdog timer, PLL, etc. etc.

If starting from scratch, the Microchip C30 compiler page should have some basic sample code folder/zip file, for various library's like the blinky led, usart, I2C, etc. Grab a blinky led program and get that going if you haven't already.

Next, describe the hardware setup. Is it a breadboard?, are all the grounds tied together, same for the Vdd, 0.1uf across each supply rail. Or is it a demo board? and if so which model? Is there an external crystal and what value, or will the internal osc be used? If the MCLR is enabled in config, then that pin needs a 10k pullup to Vdd.

Instead of enabling all the PWM pins, how about just setting for a single output. For some odd reason, I vaguely remember having an issue with this, and having to write the duty cycle to all the enabled ones at the same time. Don't trust my memory as fact though, could easily be explained by my goof.
 
Hi Nickelflippr,

WHen you say a basic blinky LED, do you mean one turned on and off by a PWM signal - because that would be great. If I could get that happening, I would see whatever code I am missing to make PWM work, and probably be able to modify it to get the frequency/duty cycle I need. You'll have to forgive me for new to this - I'm more of a mechanical engineer with basic abilities in electrical and coding. Would you mind linking me to this page?

The hardware setup is a breadboard. Right now it's very simple. The dsPic30f4011 chip on a breadboard, powered and grounded, and a hopeful oscilloscope probe at pin 38 (PWM1), still hoping to see some pulse width modulation. The grounds and power are tied together with a capacitor across the supply rail. I'll modify the code to just output to PWM1 once I'm in the lab.
 
Hi hedryn:

I can sympathize. Here is a link to the getting started with dsPIC 30F, there is a basic blinky led (no PWM) example at the end. Code without all the extra error stuff is shown below. It uses the internal osc with 4xPLL, and gives you the Fcy needed for the PTPER calculation.

In the example, the device include file needs to be changed to the "p.30F4011.h". The config bits sets up important stuff like the type and speed of the osc, along with the watch dog timer, mclr etc. You can disable the mclr so no pullup resistor would be required. Also the LATX, TRISX is important to initialize the port pins and setting the pin direction as an output, or input.

I ran across an excellent site on the dsPIC30F4011; With a servo code tutorial no less!

Got my 18f1330 (power control pwm) servo code going late last night, and runs a Futaba 3003 just fine. It took the longest time to figure out (it's right there in the data sheet) that the duty cycle for the "18f" needed to be multiplied by 4!

EDIT: PS. here is the product code link for the dsPIC30F4011. All manner of information.

My 18f1330 calcs for period and dutycycle:
Code:
	;PTPER = (Fcy/Fpwm*(PTMRPrescaler))-1
	;Fcy = Fosc/4
	;for 20ms or 18ms servo update
	;Fpwm = 1/.020 or 1/.018 = 50 or 55.55Hz
	;PTPER = (1000000/(50*16))-1 = 1249 (12 bit (i.e. 0xFFF) is max for 18f1330)
	PTPER = 1249

	;Servo duty cycle is 1-2ms over the 20ms period or,
	;1/20*4*(PTPER+1) 'full reverse', 1.5/20*4*(PTPER+1) 'neutral', 2/20ms*4*(PTPER+1) 'full forward'
	;to get the correct duty cycle must multiply by 4 because of Q1:Q0 in PTMR register
	;PDCx (PDCxH and PDCxL) will be forward = 500, neutral = 375, reverse = 250
 
Last edited:
Wow, this is amazing. Finally able to get back in the lab and test this out. It's possible my code isn't working because I wasn't doing any configuring like he does in his PWM code. I'll also try individually writing to the bits he wants to turn on, instead of writing to the entire register. I also have to alter the syntax because I'm using a HIGH-TECH C compiler - that's a bit of a pain. As soon as I can rewrite it I'll see if I can't finally get a PWM signal out of this chip. I'll keep you guys updated.
 
Last edited:
Edit//Update:

Man. I was CERTAIN it was going to work this time. I rewrote my code, effectively transferring this guy's complete code into Hi-Tech C. I rechecked all the connections on my microcomputer. I replaced the microcomputer, just in case. My code now looks like this:

//title "Project Zero"


#include <dspic30f4011.h>
#define FOSC 10000000 // 10Mhz
#define FCY (FOSC / 4) // 1 inscruction cycle = 4 clock cycles


void initpwm(void)
{
PTEN = 0; //Disable MCPWM
PWMCON1_PEN1H = 1; //PWM1H enabled for PWM output
PWMCON1_PEN2H = 1; //PWM2H enabled for PWM output
PTCKPS0 = 1; //PTCKPS<1:0> set to 01. 1:4 Prescale.
PTCKPS1 = 0;
PTOPS0 = 0; //PTOPS<3:0> set to 0s. 1:1 Postscale
PTOPS1 = 0;
PTOPS2 = 0;
PTOPS3 = 0;
PTSIDL = 1; // STOP in Idle Mode: Yes
PTMOD0 = 0; //PTMOD<1:0> set to 00. Free running mode.
PTMOD1 = 0;
PTEN = 1; //ENABLE MCPWM

PTPER = 11250;
}

void main(void)
{
initpwm();


while(1) //Infinite loop
{
PDC1 = 1875; //should set PMW1 duty cycle.
}

}

And still, no pulse width modulation. I don't even know what the problem could be. I see no reason why I cannot put my oscilloscope to pin 37 or 35 and see PWM. I set the watch dog timer off in the "Configuration Bits" in MPLAB - does anyone know how to actually write that in the code. Besides that, I am completely out of ideas. I do notice one thing though - in RoboticsGuy's code, he has the INIT_PWM code after his Main code. I thought in C your Main(void) code had to be at the bottom. I don't know if this is significant. I'm scrounging for ideas at this point. I'll include a picture of my setup after I get it off my cell phone.
 
Still not seeing any configuration settings, nor the Hitech include file.

Really, the first thing to be done is verify proper function and setup, is to blink an led, NOT PWM!!!

Below is the config for HI-TECH v9.61 and an extended range dsPIC30f1010, the only dsPIC in my possession. The extended range matters with this device, because it runs at a different internal osc speed for the industrial, and extended range designations (e.g. I/P and E/P), weird.

The example config sets up the high speed internal oscillator, and provides a clock signal on the clkout pin, to check with a scope. It is not directly applicable to the dsPIC30F4011, but should be similar.

What type of oscillator is being used? What speed? Look to the HI-TECH manual, and the device xxxx_cfgs.h (from the HI-TECH dsPIC include folder), for setting up the correct oscillator and other config settings. The config register alias (e.g. FOSC) and that registers associated bits need to be on their own separate lines apparently with HI-TECH.
Code:
#include <htc.h>
//-----------------------------------------------------------------------------
//Configuration bits
//should be 9.7 mips frc for extended range device dsPIC30F1010, FRC_PLL and FRC_HI_RANGE
__CONFIG (FOSC, CLKSWDIS & FSCMDIS & RANGEH & CLKOACT);
__CONFIG (FOSCEL, FRCPLL); 
__CONFIG (FWDT, WDTDIS);
 
Definitely right, my proff just said the same thing. Going to try bit banging to see if I can't at least get an LED to blink/pin to go high.

A question about the hitech include file - we need that on top of the individual device include file? Also, I had configured the settings in the "Configuration Bits" window in MPLAB and thought that covered that. I'll try to add the include and the config bits, get a pin going high/low, and see where that takes me.
 
The hitech include file htc.h must be for the newest compiler version(s??). If the device include file is all that is needed for your particular (or earlier) version, then fine. That's why I prefaced which compiler version I used.

Including the config settings in code helps when sharing with others from afar, otherwise no one knows what's happening behind the scenes. Config settings are a hassle when first starting out, when changing to a new device, or even a different compiler.
 
Backing up a lot, as it turns out I can't even get even turn an LED on and off - namely, I can't turn a pin high and lo. I attempted to tell PORT B Pin 0 to go high, and I couldn't even do that - in the MPLAB simulator (MPLAB SIM), let alone on the protoboard itself. Wow. I guess there is some configuration settings in my code I'm not doing. Whether the ports have to be initialized or its my configuration bits, I am not certain.

Also, I'm trying to find some information on configuration bits syntax for the hi-tech c compiler so I can have that in my code and not just use the configuration bits setting. Just trying to eliminate variables at this point.

EDIT: After some troubleshooting it looks like I have to set up my clock..I just wish I knew what this meant.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top