0
\$\begingroup\$

Hello there I have experienced some really weird behavior from servo motor wheni try to control it with pwm. I am using dspic30f4013 and servo motor sg90 tower mini. I configured my pic with 10Mhz input crystal with PLL4. Here is datasheet for sg90 tower mini servo motor and here is datasheet for my dspic. So to steer servo to position "0" 1.5 ms pulse, "90" ~2ms pulse, is all the way to the right, "-90" ~1ms pulse is all the way to the left. I configured my pwm like this:

void initPWM()
{
  TRISDbits.TRISD1 = 0; // to clear port
  PR3 = 2899; // inserting value for TMR3 period
  OC2CONbits.OMC = 0; 
  OC2R = 0;
  OC2RS = 658; //initial duty cycle (This value steers servo to the right)
  OC2CONbits.OCTSEL = 1; // TMR3 is selected
  OC2CONbits.OCFLT = 0; // no flt pin
  OC2CONbits.OCSIDL = 1;
  OC2CONbits.OCM = 0b101; // Continues pwm mode

  T3CONbits.TCKPS = 1; // prescaler 1:8
  IEC0bits.T3IE = 1; // enable interrupt
  T3CONbits.TON = 1; // turn on timer module
 }

When i power on initial value of pwm loaded in OC2RS register steers servo to the right which is ok. Then i load value of 250 in while just to see what will happen and it steers servo motor to the left which is also fine. But when i make simple program to steer it from left to right just for fun to see if it works as it suppose to do, it doesn't. So what happens is that after initial value steers it to right it suppose to go to left and than right and vice versa but it just goes to one side and that's all, and it simply just stay in that position and do nothing, not even a sound of servo tryin to move. I don't understand what is happening, it's like PWM value doesn't get updated or something. Here is my main file:

  #include <xc.h>
  #include <p30fxxxx.h>

 _FOSC(CSW_FSCM_OFF & XT_PLL4);
 _FWDT(WDT_OFF);
 _FBORPOR(MCLR_EN);

 void __attribute__((interrupt, no_auto_psv)) _T3Interrupt(void)
 {
   TMR3 = 0;
   IFS0bits.T3IF = 0;
 }

 int main(void)
 {
   ADPCFG = 0b1111111111111111; // all pins as digital
   initPWM()

   delay_ms(1000); // 1s delay
   while(1)
   {
     for(i = 0; i < 20; i++)
     {
       OC2RS = 250; // to the left
     }
     delay_ms(200);
     for(i = 0; i < 20; i++)
     {
       OC2RS = 658; // to the right
     }
   }
   return 0;
 }

That part above is not working, but when i do it like this it works:

 while(1)
 {
   OC2R = 0
   OC2RS = 250;
   OC2R = 0;
   OC2RS = 658;
 }

But after it does left to right it stops and that's all. I don't know what am I missing. Someone please explain it to me what is happening and why?

\$\endgroup\$
1
\$\begingroup\$

Try eliminating the useless for loop and add delay_ms(); after OC2RS = 658;

 while(1)
   {
     OC2RS = 250; // to the left
     delay_ms(200);
     OC2RS = 658; // to the right
     delay_ms(200);
   }

After OC2RS switches to 658, without the delay, it will switch back to 250 almost immediately. Thus, there will be no observable effect at all.

\$\endgroup\$
  • 1
    \$\begingroup\$ I have tried that and it didn't work then, but it works now... Anyway thanks a lot. \$\endgroup\$ – A.F. Jan 26 at 15:43
  • \$\begingroup\$ @Long Pham, You have told A.F. what is wrong but you could explain a bit more why it is wrong. \$\endgroup\$ – Dan1138 Jan 28 at 23:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.