Legacy Forum: Preserving Nearly 20 Years of Community History - A Time Capsule of Discussions, Memories, and Shared Experiences.

Continuous PWM

Based on DMP's Vortex processor / SoC this board is a full computer capable of running a standard Windows and Linux installation on the backpack of your robot.
9 postsPage 1 of 1
9 postsPage 1 of 1

Continuous PWM

Post by Lost Tourist » Thu Oct 21, 2010 12:31 pm

Post by Lost Tourist
Thu Oct 21, 2010 12:31 pm

I have been messing around with the RB100 using the standard rcservo commands and got them working fine however I am now trying to get a continuous PWM signal set up to run a standard servo in C++. (for now I am only setting a single channel)

I have gone through all the training material, the rcservo.cpp, pwm.cpp and pwmdx.cpp files and looked through this forum for a basic run down of how to set it up, the best I can find is RN1AsOf091407's post on his Roboard experience.

Please correct my understanding below.

From the training files I know I should not simply override the pwm_SetCountingMode while using the rcservo functions to do the rest of the work (although this is sort of successful)

So from looking in pwmdx.cpp I see that I should configure the South Bridge PWM Setting register and the PWM Control register although I'm not sure in which order or exactly how.

For the South Bridge register i have

pwm_SetBaseAddress(0xffff); // from rcservo_SetServo , i'm work out exactly what this is later
pwm_SetBaseClock(PWMCLOCK_50MHZ); // from rcservo_SetServo , i'm work out exactly what this is later
pwm_EnablePin(channel); // sets GPIO for PWM
pwm_EnableINT(channel); // sets interrupt mask
pwm_ClearMultiFLAG(0xffffffffL); // clears all interrupt flags
pwm_SetIRQ(PWMIRQ_DISABLE); // sets south bridge register
// pwm_SetIRQ doesn't accept PWMIRQ_ENABLE and I can't find the source

For the PWM control register I have

pwm_EnablePWM(channel); // enable single channel
pwm_SetCountingMode(channel, PWM_CONTINUE_MODE); // Set mode for channel to be continous
pwm_SetWaveform(channel, PWM_WAVEFORM_NORMAL); // Set waveform normal
pwm_SetPulse(channel, 20000L, 1500L); // set pulse 20mS period, 1.5mS duty

I also have

pwm_UnlockMulti(0xffffffffL);

from RN1AsOf091407's post Which sets the servo sync register but i'm not sure what the sync register's purpose is.


I'm getting nothing showing on the CRO, I assume the PWM output will start after the PWM control register is set or when pwm_SetPulse is updated.

The setup is simply XP pro on an RB100

Any help would be appreciated
I have been messing around with the RB100 using the standard rcservo commands and got them working fine however I am now trying to get a continuous PWM signal set up to run a standard servo in C++. (for now I am only setting a single channel)

I have gone through all the training material, the rcservo.cpp, pwm.cpp and pwmdx.cpp files and looked through this forum for a basic run down of how to set it up, the best I can find is RN1AsOf091407's post on his Roboard experience.

Please correct my understanding below.

From the training files I know I should not simply override the pwm_SetCountingMode while using the rcservo functions to do the rest of the work (although this is sort of successful)

So from looking in pwmdx.cpp I see that I should configure the South Bridge PWM Setting register and the PWM Control register although I'm not sure in which order or exactly how.

For the South Bridge register i have

pwm_SetBaseAddress(0xffff); // from rcservo_SetServo , i'm work out exactly what this is later
pwm_SetBaseClock(PWMCLOCK_50MHZ); // from rcservo_SetServo , i'm work out exactly what this is later
pwm_EnablePin(channel); // sets GPIO for PWM
pwm_EnableINT(channel); // sets interrupt mask
pwm_ClearMultiFLAG(0xffffffffL); // clears all interrupt flags
pwm_SetIRQ(PWMIRQ_DISABLE); // sets south bridge register
// pwm_SetIRQ doesn't accept PWMIRQ_ENABLE and I can't find the source

For the PWM control register I have

pwm_EnablePWM(channel); // enable single channel
pwm_SetCountingMode(channel, PWM_CONTINUE_MODE); // Set mode for channel to be continous
pwm_SetWaveform(channel, PWM_WAVEFORM_NORMAL); // Set waveform normal
pwm_SetPulse(channel, 20000L, 1500L); // set pulse 20mS period, 1.5mS duty

I also have

pwm_UnlockMulti(0xffffffffL);

from RN1AsOf091407's post Which sets the servo sync register but i'm not sure what the sync register's purpose is.


I'm getting nothing showing on the CRO, I assume the PWM output will start after the PWM control register is set or when pwm_SetPulse is updated.

The setup is simply XP pro on an RB100

Any help would be appreciated
Lost Tourist
Newbie
Newbie
Posts: 4
Joined: Tue Sep 28, 2010 1:59 am

Re: Continuous PWM

Post by roboard » Fri Oct 22, 2010 7:21 am

Post by roboard
Fri Oct 22, 2010 7:21 am

Hi,

you should call pwm_EnableINT() only if you are writing XP driver for PWM and are wanting to use interrupt control.

PWM pulses would be sent out immediatly when pwm_EnablePWM() is called (except that you lock PWM channels first).

Servo Sync Register can lock/unlock PWM pulse output of all channels at the same time, and is used to synchronize all PWM pulse output.

:)
Hi,

you should call pwm_EnableINT() only if you are writing XP driver for PWM and are wanting to use interrupt control.

PWM pulses would be sent out immediatly when pwm_EnablePWM() is called (except that you lock PWM channels first).

Servo Sync Register can lock/unlock PWM pulse output of all channels at the same time, and is used to synchronize all PWM pulse output.

:)
roboard
Savvy Roboteer
Savvy Roboteer
Posts: 302
Joined: Fri Jul 03, 2009 4:44 am

PWM sample code

Post by andrewmerrill » Sat Oct 23, 2010 12:13 am

Post by andrewmerrill
Sat Oct 23, 2010 12:13 am

The following code seems to work for me for setting a continuous PWM signal, but I would appreciate feedback from others about how this could be improved.

Code: Select all
int pin = 0;
int period = 1000;
int duty = 500;
pwm_Initialize(0xFFFF, PWMCLOCK_50MHZ, PWMIRQ_DISABLE);
pwm_EnablePin(pin);
pwm_EnablePWM(pin);
pwm_SetWaveform(pin, PWM_WAVEFORM_NORMAL);
pwm_SetCountingMode(pin, PWM_CONTINUE_MODE);
pwm_SetPulse(pin, period, duty);
// do stuff...
pwm_DisablePWM(pin);
pwm_Close();
The following code seems to work for me for setting a continuous PWM signal, but I would appreciate feedback from others about how this could be improved.

Code: Select all
int pin = 0;
int period = 1000;
int duty = 500;
pwm_Initialize(0xFFFF, PWMCLOCK_50MHZ, PWMIRQ_DISABLE);
pwm_EnablePin(pin);
pwm_EnablePWM(pin);
pwm_SetWaveform(pin, PWM_WAVEFORM_NORMAL);
pwm_SetCountingMode(pin, PWM_CONTINUE_MODE);
pwm_SetPulse(pin, period, duty);
// do stuff...
pwm_DisablePWM(pin);
pwm_Close();
andrewmerrill
Newbie
Newbie
Posts: 5
Joined: Fri Oct 22, 2010 3:09 am

Post by Lost Tourist » Sat Oct 23, 2010 8:57 am

Post by Lost Tourist
Sat Oct 23, 2010 8:57 am

Thanks for the quick replies.

Roboard I’m not sure what your instructions are, I have removed pwm_EnableINT() (as I’m not trying to do anything fancy) with no success.

Are you saying that I have locked the pwm channel first or that I should lock the channel first, regardless of which why is there only an unlocking function in pwm_initialize if locking is required here?

As for the sync register are you saying it is used to start all pwm channels at once if required?

As all I am trying to do it write a new pwm_initialize that sets the counting mode as continuous can you correct the following steps and set the correct order to setup the PWM for continuous operation. (These steps being the steps and sequence used in pwm_initialize)
1 - Set base address to 0xffff
2 - Set the base clock using pwm_SetBaseClock(PWMCLOCK_50MHZ)
3 - Set interrupt mode with pwm_SetIRQ(PWMIRQ_DISABLE)
4 - Disable the pwm mode using pwm_DisablePin(channel)
5 - Disable the pwm interrupts using pwm_DisableINT(channel)
6 - Clear all PWM flags using pwm_ClearMultiFLAG(0xffffffffL)
7 - Set the counting mode using pwm_SetCountingMode(channel, PWM_CONTINUE_MODE)
8 - Set the waveform using pwm_SetWaveform (channel, PWM_WAVEFORM_NORMAL)
9 - Set the PWM pulse using pwm_SetPulse(channel, period, duty)
10 - Unlock the channel using pwm_Unlock(channel)
11 - Call pwm_EnablePWM(channel) to start the waveform
Because this does not seem to work.

Andrewmerrill thanks for your code as it works fine, although I don’t like double setting things so I wouldn’t normally use pwm_initialize to set the counting mode, waveform and pulse and then set them again separately unless there was a clear reason but I can’t argue with your results :)

Thanks
Thanks for the quick replies.

Roboard I’m not sure what your instructions are, I have removed pwm_EnableINT() (as I’m not trying to do anything fancy) with no success.

Are you saying that I have locked the pwm channel first or that I should lock the channel first, regardless of which why is there only an unlocking function in pwm_initialize if locking is required here?

As for the sync register are you saying it is used to start all pwm channels at once if required?

As all I am trying to do it write a new pwm_initialize that sets the counting mode as continuous can you correct the following steps and set the correct order to setup the PWM for continuous operation. (These steps being the steps and sequence used in pwm_initialize)
1 - Set base address to 0xffff
2 - Set the base clock using pwm_SetBaseClock(PWMCLOCK_50MHZ)
3 - Set interrupt mode with pwm_SetIRQ(PWMIRQ_DISABLE)
4 - Disable the pwm mode using pwm_DisablePin(channel)
5 - Disable the pwm interrupts using pwm_DisableINT(channel)
6 - Clear all PWM flags using pwm_ClearMultiFLAG(0xffffffffL)
7 - Set the counting mode using pwm_SetCountingMode(channel, PWM_CONTINUE_MODE)
8 - Set the waveform using pwm_SetWaveform (channel, PWM_WAVEFORM_NORMAL)
9 - Set the PWM pulse using pwm_SetPulse(channel, period, duty)
10 - Unlock the channel using pwm_Unlock(channel)
11 - Call pwm_EnablePWM(channel) to start the waveform
Because this does not seem to work.

Andrewmerrill thanks for your code as it works fine, although I don’t like double setting things so I wouldn’t normally use pwm_initialize to set the counting mode, waveform and pulse and then set them again separately unless there was a clear reason but I can’t argue with your results :)

Thanks
Lost Tourist
Newbie
Newbie
Posts: 4
Joined: Tue Sep 28, 2010 1:59 am

Post by roboard » Tue Oct 26, 2010 3:56 am

Post by roboard
Tue Oct 26, 2010 3:56 am

Lost Tourist wrote: 1 - Set base address to 0xffff
...


Hi,

you can't call pwm_SetBaseAddress(0xffff) to set 0xffff as the base address (0xffff is an invalid base address). Please call pwm_SetBaseAddress(0xfe00) instead; then your code should work normally.

:)
Lost Tourist wrote: 1 - Set base address to 0xffff
...


Hi,

you can't call pwm_SetBaseAddress(0xffff) to set 0xffff as the base address (0xffff is an invalid base address). Please call pwm_SetBaseAddress(0xfe00) instead; then your code should work normally.

:)
roboard
Savvy Roboteer
Savvy Roboteer
Posts: 302
Joined: Fri Jul 03, 2009 4:44 am

Post by Lost Tourist » Mon Nov 01, 2010 11:51 am

Post by Lost Tourist
Mon Nov 01, 2010 11:51 am

Roboard,

Still no joy. I have experimented with the order of things, removed bits added bits all to no avail.

AndrewMerill's code work's fine in it's place.

My code is :-

pwm_SetBaseAddress(0xfe00);
pwm_SetBaseClock(PWMCLOCK_50MHZ);
pwm_SetIRQ(PWMIRQ_DISABLE);
pwm_DisablePin(channel);
pwm_DisableINT(channel);
pwm_ClearMultiFLAG(0xffffffffL);
pwm_Unlock(channel);
pwm_SetCountingMode(channel, PWM_CONTINUE_MODE);
pwm_SetWaveform(channel, PWM_WAVEFORM_NORMAL);
pwm_SetPulse(channel, 20000L, 1500L);
pwm_EnablePin(channel);
pwm_EnableINT(channel);

pwm_EnablePWM(channel);

What am I doing wrong?

Thanks
Roboard,

Still no joy. I have experimented with the order of things, removed bits added bits all to no avail.

AndrewMerill's code work's fine in it's place.

My code is :-

pwm_SetBaseAddress(0xfe00);
pwm_SetBaseClock(PWMCLOCK_50MHZ);
pwm_SetIRQ(PWMIRQ_DISABLE);
pwm_DisablePin(channel);
pwm_DisableINT(channel);
pwm_ClearMultiFLAG(0xffffffffL);
pwm_Unlock(channel);
pwm_SetCountingMode(channel, PWM_CONTINUE_MODE);
pwm_SetWaveform(channel, PWM_WAVEFORM_NORMAL);
pwm_SetPulse(channel, 20000L, 1500L);
pwm_EnablePin(channel);
pwm_EnableINT(channel);

pwm_EnablePWM(channel);

What am I doing wrong?

Thanks
Lost Tourist
Newbie
Newbie
Posts: 4
Joined: Tue Sep 28, 2010 1:59 am

Post by roboard » Mon Nov 01, 2010 12:59 pm

Post by roboard
Mon Nov 01, 2010 12:59 pm

Lost Tourist wrote:Roboard,

Still no joy. I have experimented with the order of things, removed bits added bits all to no avail.



Hi,

the line "pwm_EnableINT(channel)" should be removed. And "channel" should be an integer between 0~23.

Please try the following code to see whether PWM channel 0 sends PWM pulses. :)

Code: Select all
int channel = 0;

pwm_SetBaseAddress(0xfe00);
pwm_SetBaseClock(PWMCLOCK_50MHZ);
pwm_SetIRQ(PWMIRQ_DISABLE);
pwmdx_DisablePin(channel);
pwmdx_DisableINT(channel);
pwmdx_ClearMultiFLAG(0xffffffffL);
pwmdx_Unlock(channel);
pwmdx_SetCountingMode(channel, PWM_CONTINUE_MODE);
pwmdx_SetWaveform(channel, PWM_WAVEFORM_NORMAL);
pwmdx_SetPulse(channel, 20000L, 1500L);
pwmdx_EnablePin(channel);

pwmdx_EnablePWM(channel);


In RoBoIO 1.61, it is necessary to call pwm_Initialize() for getting the PWM lib work. If you don't want to call pwm_Initialize(), then you should use the PWM primitive functions pwmdx_... for operating the PWM H/W; but using pwmdx_... functions is not a recommended approach (unless you understand the Vortex86DX's PWM module and the H/W design of RB-100 in detail).

:)
Lost Tourist wrote:Roboard,

Still no joy. I have experimented with the order of things, removed bits added bits all to no avail.



Hi,

the line "pwm_EnableINT(channel)" should be removed. And "channel" should be an integer between 0~23.

Please try the following code to see whether PWM channel 0 sends PWM pulses. :)

Code: Select all
int channel = 0;

pwm_SetBaseAddress(0xfe00);
pwm_SetBaseClock(PWMCLOCK_50MHZ);
pwm_SetIRQ(PWMIRQ_DISABLE);
pwmdx_DisablePin(channel);
pwmdx_DisableINT(channel);
pwmdx_ClearMultiFLAG(0xffffffffL);
pwmdx_Unlock(channel);
pwmdx_SetCountingMode(channel, PWM_CONTINUE_MODE);
pwmdx_SetWaveform(channel, PWM_WAVEFORM_NORMAL);
pwmdx_SetPulse(channel, 20000L, 1500L);
pwmdx_EnablePin(channel);

pwmdx_EnablePWM(channel);


In RoBoIO 1.61, it is necessary to call pwm_Initialize() for getting the PWM lib work. If you don't want to call pwm_Initialize(), then you should use the PWM primitive functions pwmdx_... for operating the PWM H/W; but using pwmdx_... functions is not a recommended approach (unless you understand the Vortex86DX's PWM module and the H/W design of RB-100 in detail).

:)
roboard
Savvy Roboteer
Savvy Roboteer
Posts: 302
Joined: Fri Jul 03, 2009 4:44 am

Post by Lost Tourist » Thu Nov 11, 2010 10:59 pm

Post by Lost Tourist
Thu Nov 11, 2010 10:59 pm

Roboard,

For some reason I do not seem to have access to the pwmdx commands you listed even when I include the pwmdx.h header file.

As I wrote above I'm not trying to do anything the fancy so if using PWM_Initialise is the recommended way then I will use AndrewMerrill's code.

Thanks for your help.
Roboard,

For some reason I do not seem to have access to the pwmdx commands you listed even when I include the pwmdx.h header file.

As I wrote above I'm not trying to do anything the fancy so if using PWM_Initialise is the recommended way then I will use AndrewMerrill's code.

Thanks for your help.
Lost Tourist
Newbie
Newbie
Posts: 4
Joined: Tue Sep 28, 2010 1:59 am

Post by roboard » Fri Mar 25, 2011 6:37 am

Post by roboard
Fri Mar 25, 2011 6:37 am

Hi,

we have added (high-level) continuous PWM functions (rcservo_SendCPWM(), rcservo_StopPWM(), ...) into RC servo lib of RoBoIO 1.7. It is now unnecessary to apply the low-level PWM lib for using
continuous PWM.

:)
Hi,

we have added (high-level) continuous PWM functions (rcservo_SendCPWM(), rcservo_StopPWM(), ...) into RC servo lib of RoBoIO 1.7. It is now unnecessary to apply the low-level PWM lib for using
continuous PWM.

:)
roboard
Savvy Roboteer
Savvy Roboteer
Posts: 302
Joined: Fri Jul 03, 2009 4:44 am


9 postsPage 1 of 1
9 postsPage 1 of 1