伺服馬達控制


         Joseph Chen
360° Servo

 伺服馬達控制主要利用PWM控制轉的方向
 與轉速
 360° servo 需要50Hz的脈波週期訊號 並藉由0.5~2.5ms HIGH PULSE做
 控制
 等於1.5ms HIGH PULSE是位於停止的狀態
 小於1.5ms 順時針轉動, 若值愈小轉速可愈快
 大於1.5ms 逆時針轉動,若值愈大轉速可愈快。
The S3C6410X RISC microprocessor comprises of
five 32-bit timers. These timers are used to
generate internal interrupts to the ARM
subsystem.
Timers 0 and 1 include a PWM function (Pulse
Width Modulation), which can drive an external
I/O signal. The PWM for timer 0 and 1 have an
optional dead-zone generator capability, which
can be utilized to support a large current device.
Timer 2, 3 and 4 are internal timers with no
output pins.
Clock Generation Scheme for PWM
PWM Function Block


                            TCNTB     TCMPB
                                               Manual Update=1
                                               Auto reload=1
PCLK   Prescaler   Divder                      when TCNT reaches 0
                            TCNT        TCMP   TCNT=TCNB
                                               TCMP=TCMPB
                             TCNTO

                             TCFG       TCON



                            Double Buffering
PWM waveform
REGISTER MAP
S3C6410 的PWM 如何設定?
 得到20ms的週期 (50HZ)
 如果 PCLK=83MHZ, 8-bit prescaler=255 and 4-bit divider=16
 Frequency=PCLK/(255+1)/16 => 20.2KHz
 週期=>1/20.2K=0.0495ms

 20ms/0.0495=404 --> TCNTB                     TOUT
                             Pulse Width



 TCMPB setting?:
 Get 2ms High Pulse width: 2ms/0.0495=40
 Get 1.5ms High Pulse width: 1.5ms/0.0495=30
 Get 1ms High Pulse width: 1ms/0.0495=20
dc_motor.c


 static int __init dcm_init(void)
 {
             int retval;
             retval = register_chrdev(DCM_MAJOR,dcm_name,&dcm_fops);
             if(retval < 0)
             {
                         printk(KERN_WARNING"Can't get major %dn",DCM_MAJOR);
                         return retval;
             }
             s3c6410_timer_setup(0,10,100,0);
             pwm_init(PERIOD); //unit: 20000us
             printk("Serveo_motor driver register success!n");
             return 0;
 }
static void pwm_init(unsigned long period)
{
                                                             Period=20000us
    // initial the timer period
               unsigned long tcnt;
                                                             時間(週期)
                                                             = Y HZ (Y次/s)* period
     hi_pulse=0;
                                                             =次/s *(us/106)
     tcnt=(period*(( PCLK )/((255+1)*16 )))/1000000;

     printk(KERN_WARNING"%s:tcnt=%ldn",__func__,tcnt);

//           tcnt =( 96000000 )/( FREQ_PWM1 *16 );
             __raw_writel(tcnt, S3C_TCNTB(0));
             __raw_writel(((tcnt*(0))/100), S3C_TCMPB(0));

}
s3c6410_timer_setup

 int s3c6410_timer_setup (int channel, int usec,
 unsigned long g_tcnt, unsigned long g_tcmp)
 Parameters:
  1)   channel: PWM channel 0/1
  2)   usec: unused
  3)   g_tcnt: unused
  4)   g_tcmp: unused
/* set gpio as PWM TIMER0 to signal output*/
s3c_gpio_cfgpin(S3C64XX_GPF(14), S3C64XX_GPF14_PWM_TOUT0);
s3c_gpio_setpull(S3C64XX_GPF(14), S3C_GPIO_PULL_NONE);
tcfg1 &= ~S3C_TCFG1_MUX0_MASK;
tcfg1 |= 4; // set divider 16 , by jospeh

tcfg0 &= ~S3C_TCFG_PRESCALER0_MASK;
tcfg0 |= (PRESCALER) << S3C_TCFG_PRESCALER0_SHIFT;
tcon &= ~(7<<0);
tcon |= S3C_TCON_T0RELOAD;
User space Code

 232, 0 /dev/pwm0
 232,1 /dev/pwm1
 fd_l=open(“/dev/pwm0”);
  ioctl(fd_l,cmd,arg);
 fd_r=open(“dev/pmm1”);
 Ioctl(fd_r,cmd,arg)

伺服馬達控制

  • 1.
  • 2.
    360° Servo 伺服馬達控制主要利用PWM控制轉的方向 與轉速 360° servo 需要50Hz的脈波週期訊號 並藉由0.5~2.5ms HIGH PULSE做 控制 等於1.5ms HIGH PULSE是位於停止的狀態 小於1.5ms 順時針轉動, 若值愈小轉速可愈快 大於1.5ms 逆時針轉動,若值愈大轉速可愈快。
  • 4.
    The S3C6410X RISCmicroprocessor comprises of five 32-bit timers. These timers are used to generate internal interrupts to the ARM subsystem. Timers 0 and 1 include a PWM function (Pulse Width Modulation), which can drive an external I/O signal. The PWM for timer 0 and 1 have an optional dead-zone generator capability, which can be utilized to support a large current device. Timer 2, 3 and 4 are internal timers with no output pins.
  • 5.
  • 6.
    PWM Function Block TCNTB TCMPB Manual Update=1 Auto reload=1 PCLK Prescaler Divder when TCNT reaches 0 TCNT TCMP TCNT=TCNB TCMP=TCMPB TCNTO TCFG TCON Double Buffering
  • 7.
  • 8.
  • 10.
    S3C6410 的PWM 如何設定? 得到20ms的週期 (50HZ) 如果 PCLK=83MHZ, 8-bit prescaler=255 and 4-bit divider=16 Frequency=PCLK/(255+1)/16 => 20.2KHz 週期=>1/20.2K=0.0495ms 20ms/0.0495=404 --> TCNTB TOUT Pulse Width TCMPB setting?: Get 2ms High Pulse width: 2ms/0.0495=40 Get 1.5ms High Pulse width: 1.5ms/0.0495=30 Get 1ms High Pulse width: 1ms/0.0495=20
  • 11.
    dc_motor.c static int__init dcm_init(void) { int retval; retval = register_chrdev(DCM_MAJOR,dcm_name,&dcm_fops); if(retval < 0) { printk(KERN_WARNING"Can't get major %dn",DCM_MAJOR); return retval; } s3c6410_timer_setup(0,10,100,0); pwm_init(PERIOD); //unit: 20000us printk("Serveo_motor driver register success!n"); return 0; }
  • 12.
    static void pwm_init(unsignedlong period) { Period=20000us // initial the timer period unsigned long tcnt; 時間(週期) = Y HZ (Y次/s)* period hi_pulse=0; =次/s *(us/106) tcnt=(period*(( PCLK )/((255+1)*16 )))/1000000; printk(KERN_WARNING"%s:tcnt=%ldn",__func__,tcnt); // tcnt =( 96000000 )/( FREQ_PWM1 *16 ); __raw_writel(tcnt, S3C_TCNTB(0)); __raw_writel(((tcnt*(0))/100), S3C_TCMPB(0)); }
  • 13.
    s3c6410_timer_setup int s3c6410_timer_setup(int channel, int usec, unsigned long g_tcnt, unsigned long g_tcmp) Parameters: 1) channel: PWM channel 0/1 2) usec: unused 3) g_tcnt: unused 4) g_tcmp: unused
  • 14.
    /* set gpioas PWM TIMER0 to signal output*/ s3c_gpio_cfgpin(S3C64XX_GPF(14), S3C64XX_GPF14_PWM_TOUT0); s3c_gpio_setpull(S3C64XX_GPF(14), S3C_GPIO_PULL_NONE); tcfg1 &= ~S3C_TCFG1_MUX0_MASK; tcfg1 |= 4; // set divider 16 , by jospeh tcfg0 &= ~S3C_TCFG_PRESCALER0_MASK; tcfg0 |= (PRESCALER) << S3C_TCFG_PRESCALER0_SHIFT; tcon &= ~(7<<0); tcon |= S3C_TCON_T0RELOAD;
  • 15.
    User space Code 232, 0 /dev/pwm0 232,1 /dev/pwm1 fd_l=open(“/dev/pwm0”); ioctl(fd_l,cmd,arg); fd_r=open(“dev/pmm1”); Ioctl(fd_r,cmd,arg)