您好!
我正在尝试将伺服电机(sg90)实现到 MSP430的电位器中。 我希望伺服电机由电位器控制、即转动电位器将使电机旋转。 我有 ADC 代码、但我正在努力处理实现此代码所需的其他代码。 非常感谢您提供任何帮助。 非常感谢!
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
您好!
我正在尝试将伺服电机(sg90)实现到 MSP430的电位器中。 我希望伺服电机由电位器控制、即转动电位器将使电机旋转。 我有 ADC 代码、但我正在努力处理实现此代码所需的其他代码。 非常感谢您提供任何帮助。 非常感谢!
我想您的意思是 A/D、而不是"电位器"。
对于伺服、您需要将 PWM 设置为特定的频率并调整占空比。 您能向我们展示您拥有的产品吗? 我们不想为您做家庭作业。
尝试 timer_a_ex4_pwmMultipleUpDown 示例。
下面是伺服教程:
https://learn.sparkfun.com/tutorials/basic-servo-control-for-beginners/servo-motor-basics
对于伺服驱动器、您需要20毫秒的周期和从5%(1ms 脉冲)到10%(2ms 脉冲)不等的占空比
尊敬的 Keith、感谢您的回复。 这是我的代码现在看起来的样子、我不确定如何调整它。
#包含
#包含
#包含
void configureADC()
{
//ADC 设置
SYSCFG2 |= ADCPCTL9;//打开模拟引脚9,使其不是 GPIO
ADCCTL0 |= ADCON;//打开 ADC
ADCCTL1 |= ADCSHP;//选择位9
ADCCTL1 |= ADCSSEL_2;//选择 SMCLK
ADCCTL2 |= ADCRES_2;//时钟分辨率
ADCMCTL0 |= ADCSREF_7;//+ve 和-ve 基准引脚
ADCMCTL0 |= ADCINCH_9;// A9作为输入
ADCIFG &&~0x01;//清除中断标志
ADCIE |= ADCIE0;//启用 ADC 转换完成中断
}
void initPWM(){
TA0CCTL1 = OUTMOD_7;// CCR1复位/设置
TA0CTL = TASSEL_2 + MC_1 + TACLR;// SMCLK、向上计数模式、清除 TAR
TA0CCR0 = 20000-1;// 20ms (50Hz)的 PWM 周期
TA0CCR1 = 1000;// 1ms 脉冲的初始占空比
P1DIR |= BIT2;// P1.2作为 PWM 的输出
P1SEL0 |= BIT2;// P1.2选项选择
}
void main (void){
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
configureADC ();//设置 ADC
initPWM ();//设置伺服的 PWM
__ bis_SR_register (GIE);//启用全局中断以启动 ADC
while (1){
ADCCTL0 |= ADCENC | ADCSC;//开始采样/转换
__ bis_SR_register (LPM0_bits + GIE);//进入 LPM0、ADC_ISR 将强制退出
}
}
// ADC 中断服务例程
#pragma vector=adc_vector
__interrupt void ADC_ISR (void){
if (ADCIFG & ADCIFG0){//检查转换是否完成
unsigned int adcValue = ADCMEM0;//获取 ADC 转换结果
无符号 int dutyCycle = 1000 +(adcValue * 1000 / 4095);//将 ADC 值映射到占空比范围
TA0CCR1 =占空比;//更新 PWM 占空比以调整伺服位置
ADCIFG &&~ADCIFG0;//清除中断标志
__ bic_SR_register_on_exit (LPM0_bits);//退出 LPM0
}
}
一个问题是1.2并未连接到定时器、它被 USCI 使用。
您需要使用1.6或1.7、如示例所示:
//
// MSP430FR4133
//-------------------------------------------------------
// /|\|
// |||
// --|RST |
// |
// | P1.7/TA0.1|--> CCR1 - 75% PWM
// | P1.6/TA0.2|--> CCR2 - 25% PWM
//
这是我的代码现在看起来的样子:
#包含
#包含
#包含
void configureADC(){
// ADC 设置
SYSCFG2 |= ADCPCTL9;//为 ADC 输入启用 A9
ADCCTL0 |= ADCON;//打开 ADC
ADCCTL1 |= ADCSHP;//采样保持脉冲模式选择
ADCCTL1 |= ADCSSEL_2;// SMCLK 作为 ADC 时钟源
ADCCTL2 |= ADCRES_2;// 12位转换结果
ADCMCTL0 |= ADCSREF_7;//基准电压为 V (R+)= VREF+和 V (R-)= VREF-
ADCMCTL0 |= ADCINCH_9;// A9作为输入
ADCIFG &&~0x01;//清除中断标志
ADCIE |= ADCIE0;//启用 ADC 转换完成中断
}
void initPWM(){
//配置 GPIO
P1DIR |= BIT7;//将 P1.7设置为输出
P1SEL0 |= BIT7;//为 P1.7选择 TA0.1选项
//针对 PWM 的计时器 A0配置
TA0CCTL1 = OUTMOD_7;// CCR1复位/设置
TA0CTL = TASSEL_2 + MC_1 + TACLR;// SMCLK、向上计数模式、清除 TAR
TA0CCR0 = 20000-1;// PWM 周期:20ms (对于50Hz)
TA0CCR1 = 1500;//开始使用中性占空比(例如、在1.5ms 脉宽下为~7.5%)
//注意:根据 ADC_ISR 中的 ADC 读数调整 TA0CCR1值
}
void main (void){
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
configureADC ();//设置 ADC
initPWM ();//设置伺服的 PWM
__ bis_SR_register (GIE);//启用全局中断以启动 ADC
while (1){
ADCCTL0 |= ADCENC | ADCSC;//开始采样/转换
__ bis_SR_register (LPM0_bits + GIE);//进入 LPM0、ADC_ISR 将强制退出
}
}
// ADC 中断服务例程
#pragma vector=adc_vector
__interrupt void ADC_ISR (void){
if (ADCIFG & ADCIFG0){//检查转换是否完成
unsigned int adcValue = ADCMEM0;//获取 ADC 转换结果
//将 ADC 值映射到 PWM 占空比范围(对于5%、为1000到10%)
无符号 int dutyCycle = 1000 +(adcValue * 1000/4095);
TA0CCR1 =占空比;//更新 PWM 占空比以调整伺服位置
ADCIFG &&~ADCIFG0;//清除中断标志
__ bic_SR_register_on_exit (LPM0_bits);//退出 LPM0
}
}
> unsigned int dutyCycle = 1000 +(adcValue * 1000/4095);
FR4133具有一个10位 ADC。 此外、乘法极有可能会溢出。 总体结果是您相对于1000的偏移(完全正确?) 电流将在非常小的范围内变化。 您可以在以下方面做得更好:
> unsigned int dutyCycle = 1000 +(adcValue * 1000UL/1024);
----------------
> ADCMCTL0 |= ADCSREF_7;//基准电压为 V (R+)= VREF+和 V (R-)= VREF-
我预计您没有连接外部 VREF 引脚、因此我不确定结果会是什么。 SREF= 0 (VCC)或=1 (内部 VREF)可能会获得更好的结果。
----------------
你设置(省略) ADCSHT=0,这是一个很短的时间,特别是来自电阻分压器电路——它们通常具有很高的阻抗。 您没有太着急、于是将 ADCSHT 设置为相当大的值、例如、
> ADCCTL0 |= ADCSHT_6; // 128个 ADC 采样/保持时钟
我只有2311可用、但此代码有效-我更改了数字、以获得您的20ms 周期。
这是 MSP430fr231X_tb0_16示例。
我建议您从一个简单的 PWM 示例开始、以便在连接 ADC 之前使其正常工作。
(噢、请使用代码插入工具使您的代码可读)
int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT P1DIR |= BIT6 | BIT7; // P1.6 and P1.7 output P1SEL1 |= BIT6 | BIT7; // P1.6 and P1.7 options select // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; TB0CCR0 = 20000; // PWM Period TB0CCTL1 = OUTMOD_7; // CCR1 reset/set TB0CCR1 = 15000; // CCR1 PWM duty cycle TB0CCTL2 = OUTMOD_7; // CCR2 reset/set TB0CCR2 = 5000; // CCR2 PWM duty cycle TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR; // SMCLK, up mode, clear TBR __bis_SR_register(LPM0_bits); // Enter LPM0 __no_operation(); // For debugger }