4570|4

6366

帖子

4929

TA的资源

版主

楼主
 

在MSP430 Launchpad下利用PWM控制舵机 [复制链接]

RC Servos are pretty useful devices, they allow us to move things in a mechanical manner. They are cheap and readily available, so it only makes sense to use them!

A quick intro:

Servos are actually rather simple to interface with, they merely require a pulse of a certain width to determine the next position.

Because of this, we can use hardware PWM to generate these pulses. The frequency is typically 50Hz, which means we’ll be able to obtain a great deal of granularity with regard to the duty cycle, given our clock speed of 1MHz. Which is required since we’ll be dealing with pulses ranging ~1mS to ~2mS (typically)

Different servos will require a different minimum and maximum duty cycle, however in general the given code should just-work, in case your servo goes off range simply find the best minimum and maximum values for it

 

 

 

 

 

#include "msp430g2553.h" // make sure you change the header to suit your particular device.
 
// Connect the servo SIGNAL wire to P1.2 through a 1K resistor.
 
#define MCU_CLOCK 1000000
#define PWM_FREQUENCY 46 // In Hertz, ideally 50Hz.
 
#define SERVO_STEPS 180 // Maximum amount of steps in degrees (180 is common)
#define SERVO_MIN 650 // The minimum duty cycle for this servo
#define SERVO_MAX 2700 // The maximum duty cycle
 
unsigned int PWM_Period = (MCU_CLOCK / PWM_FREQUENCY); // PWM Period
unsigned int PWM_Duty = 0; // %
 
void main (void){
 
unsigned int servo_stepval, servo_stepnow;
unsigned int servo_lut[ SERVO_STEPS+1 ];
unsigned int i;
 
// Calculate the step value and define the current step, defaults to minimum.
servo_stepval = ( (SERVO_MAX - SERVO_MIN) / SERVO_STEPS );
servo_stepnow = SERVO_MIN;
 
// Fill up the LUT
for (i = 0; i < SERVO_STEPS; i++) {
servo_stepnow += servo_stepval;
servo_lut[i] = servo_stepnow;
}
 
// Setup the PWM, etc.
WDTCTL = WDTPW + WDTHOLD;     // Kill watchdog timer
TACCTL1 = OUTMOD_7;            // TACCR1 reset/set
TACTL = TASSEL_2 + MC_1;     // SMCLK, upmode
TACCR0 = PWM_Period-1;        // PWM Period
TACCR1 = PWM_Duty;            // TACCR1 PWM Duty Cycle
P1DIR |= BIT2;               // P1.2 = output
P1SEL |= BIT2;               // P1.2 = TA1 output
 
// Main loop
while (1){
 
// Go to 0°
TACCR1 = servo_lut[0];
__delay_cycles(1000000);
 
// Go to 45°
TACCR1 = servo_lut[45];
__delay_cycles(1000000);
 
// Go to 90°
TACCR1 = servo_lut[90];
__delay_cycles(1000000);
 
// Go to 180°
TACCR1 = servo_lut[179];
__delay_cycles(1000000);
 
// Move forward toward the maximum step value
for (i = 0; i < SERVO_STEPS; i++) { TACCR1 = servo_lut[i]; __delay_cycles(20000); } // Move backward toward the minimum step value for (i = SERVO_STEPS; i > 0; i--) {
TACCR1 = servo_lut[i];
__delay_cycles(20000);
}
 
   }
 

 

The actual code was written for a quick and dirty servo testing unit I put together, however it could easily be expanded to other uses.

By using a LUT (Look-Up Table) we are able to position the servo on a per-degree basis, which makes the code a lot more intuitive and readable.

A bunch of notes and tips:

  1. Filter your servo power supply properly; servos are electrically noisy!
  2. Make sure your micro-controller is protected from external devices, such as the servos. For instance never connect the signal wire directly to the GPIO pins. Instead, use a buffer or at least a resistor. For this example we used a 1k Resistor, but since the “signal” interface is relatively high impedance, we could even use 4k7 or higher without much hassle.
  3. As long as you keep sending a signal to the servo, the servo will keep it’s position due to it’s internal feedback. However this consumes power so if you’ve got a very lightweight load or no load at all, you can always stop the PWM output for the periods of inactivity to save power.
  4. If you aren’t sure about your servo connections, here’s a small diagram to help you find the pinouts. In my case I had a couple cheap “Tower Pro” blue servos that use the JR pinout — These work fine at both 5v and 3.3v, however do not power them from the Launchpad power supply pins! — Servos consume a lot of current, always use an external PSU.
  5. Only one connection is required to interface the servo with the launchpad, find the pin P1.2 and connect it to the SIGNAL wire from your servo.

最新回复

for (i = 0; i < SERVO_STEPS; i++) {这一段好像是错的  详情 回复 发表于 2012-8-13 14:16
 
点赞 关注

回复
举报

216

帖子

0

TA的资源

纯净的硅(初级)

沙发
 
哇咔咔~这个可以尝试实践下!谢谢楼主分享!
 
 

回复

1972

帖子

1

TA的资源

五彩晶圆(初级)

板凳
 
我现在还看不懂,还得学习啊
 
 
 

回复

7172

帖子

195

TA的资源

五彩晶圆(高级)

4
 
牛啊 谢谢马哥分享
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(中级)

5
 

for (i = 0; i &lt; SERVO_STEPS; i++) {这一段是错的好像

for (i = 0; i &lt; SERVO_STEPS; i++) {这一段好像是错的
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表