首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使伺服马达启动然后停止

如何使伺服马达启动然后停止
EN

Stack Overflow用户
提问于 2022-07-29 04:09:07
回答 1查看 49关注 0票数 0

我想让马达运行1s,然后停下来。它被用来推送物品。这将在一个for循环中用来确定马达推送的项目数。我使用的电机是FS90R,芯片是pic18f4550。电机需要1.5毫秒的脉冲才能停止,并需要1毫秒的脉冲才能前进。

代码语言:javascript
复制
/* TimerPWM.c Program to generate PWM at RC2
 *  Use Timer2
 *  Frequency of OSC = 48 MHz, Prescaler = 16
 *  PR2 register set the frequency of waveform
 *  CCPR1L with CP1CONbits.DC1B0, CCP1CONbits.DC1B1 set the On-Time 
 *  Use Timer0 for the one second delay function
 */
#include <xc.h>
#include "delays.h"

void Delay1sec(void); //Function to provide 1 sec delay using Timer0

void Delay1sec(void) {
    TMR0H = 0X48; //Starting count value
    TMR0L = 0XE5;

    INTCONbits.TMR0IF = 0; //Clear flag first
    T0CONbits.TMR0ON = 1; //Turn on Timer 0

    while (INTCONbits.TMR0IF == 0); //Wait for time is up when TMR0IF=1 
    T0CONbits.TMR0ON = 0; //Turn off Timer 0 to stop counting
}

void motorgo(){
    TRISC = 0x00; //PortC RC2 connects to motor
    TRISD = 0x00; //PortD connected to 8 LEDs
    T0CON = 0b00000111; //Off Timer0, 16-bits mode, prescaler to 256

    T2CON = 0b00000111; //Timer2 is On, Prescaler is 16

    CCP1CON = 0b00001100; //Turn on PWM on CCP1, output at RC2
    
    PR2 = 149;
    CCPR1L = 37;
    
}

void motorstop(){
    TRISC = 0x00; //PortC RC2 connects to motor
    TRISD = 0x00; //PortD connected to 8 LEDs
    T0CON = 0b00000111; //Off Timer0, 16-bits mode, prescaler to 256

    T2CON = 0b00000111; //Timer2 is On, Prescaler is 16

    CCP1CON = 0b00001100; //Turn on PWM on CCP1, output at RC2
    
    PR2 = 1124;
    CCPR1L =1124;
    
}

void main(void) {
    ADCON1 = 0x0F;
    CMCON = 0x07;
    TRISC = 0x00; //PortC RC2 connects to motor
    TRISD = 0x00; //PortD connected to 8 LEDs
    T0CON = 0b00000111; //Off Timer0, 16-bits mode, prescaler to 256

    T2CON = 0b00000111; //Timer2 is On, Prescaler is 16

    CCP1CON = 0b00001100; //Turn on PWM on CCP1, output at RC2
     //Load period of PWM 0.2msec for 5KHz

    while (1) //Repeatedly
    {   
        motorgo();
        Delay1sec();
        //Delay1sec();
 
        motorstop();

    }
}
EN

回答 1

Stack Overflow用户

发布于 2022-08-01 07:14:32

LucK发布的代码看起来不太可能工作。

在我看来,我认为海报不理解PIC18F4550控制器中脉宽调制的局限性。

下面是一个完整的应用程序,它应该让FeeTech FS90R伺服运行1秒,停止9秒,然后重复:

代码语言:javascript
复制
/*
 * File:     main.c
 * Author:   dan1138
 * Target:   PIC18F4550
 * Compiler: XC8 v1.45
 * IDE:      MPLAB v8.92
 *
 * Description:
 * 
 * See: https://stackoverflow.com/questions/73161548/how-to-make-servo-moto-to-start-then-stop
 *
 *                               PIC18F4550
 *                       +----------:_:----------+
 *             VPP ->  1 : MCLR/VPP      PGD/RB7 : 40 <> PGD
 *                 <>  2 : RA0/AN0       PGC/RB6 : 39 <> PGC
 *                 <>  3 : RA1/AN1       PGM/RB5 : 38 <> 
 *                 <>  4 : RA2/AN2      AN11/RB4 : 37 <> 
 *                 <>  5 : RA3/AN3       AN9/RB3 : 36 <> 
 *                 <>  6 : RA4           AN8/RB2 : 35 <> 
 *                 <>  7 : RA5/AN4       SCL/RB1 : 34 <> 
 *                 <>  8 : RE0/AN5       SDA/RB0 : 33 <> 
 *                 <>  9 : RE1/AN6           VDD : 32 <- PWR
 *                 <> 10 : RE2/AN7           VSS : 31 <- GND
 *             PWR -> 11 : VDD               RD7 : 30 <> 
 *             GND -> 12 : VSS               RD6 : 29 <> 
 *           20MHZ -> 13 : OSC1              RD5 : 28 <> 
 *           20MHZ <- 14 : OSC2              RD4 : 27 <> 
 *                 <> 15 : RC0         RX/DT/RC7 : 26 <> 
 *                 <> 16 : RC1/CCP2    TX/CK/RC6 : 25 <> 
 *          SERVO1 <> 17 : RC2/CCP1       D+/RC5 : 24 <-
 *             3v3 <> 18 : VUSB           D-/RC4 : 23 <-
 *                 <> 19 : RD0               RD3 : 22 <> 
 *                 <> 20 : RD1               RD2 : 21 <> 
 *                       +-----------------------:
 *                                DIP-40
 *  
 *
 * Created on July 30, 2022, 8:42 PM
 */
#pragma config PLLDIV = 5           /* PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input)) */
#pragma config CPUDIV = OSC1_PLL2   /* System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2]) */
#pragma config USBDIV = 2           /* USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes from the 96 MHz PLL divided by 2) */
#pragma config FOSC = INTOSC_HS     /* Oscillator Selection bits (Internal oscillator, HS oscillator used by USB (INTHS)) */
#pragma config FCMEN = OFF          /* Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) */
#pragma config IESO = OFF           /* Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled) */
#pragma config PWRT = OFF           /* Power-up Timer Enable bit (PWRT disabled) */
#pragma config BOR = OFF            /* Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software) */
#pragma config BORV = 3             /* Brown-out Reset Voltage bits (Minimum setting 2.05V) */
#pragma config VREGEN = ON          /* USB Voltage Regulator Enable bit (USB voltage regulator enabled) */
#pragma config WDT = OFF            /* Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit)) */
#pragma config WDTPS = 32768        /* Watchdog Timer Postscale Select bits (1:32768) */
#pragma config CCP2MX = ON          /* CCP2 MUX bit (CCP2 input/output is multiplexed with RC1) */
#pragma config PBADEN = OFF         /* PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset) */
#pragma config LPT1OSC = OFF        /* Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation) */
#pragma config MCLRE = ON           /* MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled) */
#pragma config STVREN = ON          /* Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) */
#pragma config LVP = OFF            /* Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) */
#pragma config ICPRT = OFF          /* Dedicated In-Circuit Debug/Programming Port (ICPORT) Enable bit (ICPORT disabled) */
#pragma config XINST = OFF          /* Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode)) */
#pragma config CP0 = OFF            /* Code Protection bit (Block 0 (000800-001FFFh) is not code-protected) */
#pragma config CP1 = OFF            /* Code Protection bit (Block 1 (002000-003FFFh) is not code-protected) */
#pragma config CP2 = OFF            /* Code Protection bit (Block 2 (004000-005FFFh) is not code-protected) */
#pragma config CPB = OFF            /* Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected) */
#pragma config CPD = OFF            /* Data EEPROM Code Protection bit (Data EEPROM is not code-protected) */
#pragma config WRT0 = OFF           /* Write Protection bit (Block 0 (000800-001FFFh) is not write-protected) */
#pragma config WRT1 = OFF           /* Write Protection bit (Block 1 (002000-003FFFh) is not write-protected) */
#pragma config WRT2 = OFF           /* Write Protection bit (Block 2 (004000-005FFFh) is not write-protected) */
#pragma config WRTC = OFF           /* Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected) */
#pragma config WRTB = OFF           /* Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected) */
#pragma config WRTD = OFF           /* Data EEPROM Write Protection bit (Data EEPROM is not write-protected) */
#pragma config EBTR0 = OFF          /* Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks) */
#pragma config EBTR1 = OFF          /* Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks) */
#pragma config EBTR2 = OFF          /* Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks) */
#pragma config EBTRB = OFF          /* Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks) */

/*   Specify the System clock frequency in Hz */
#define FSYS (8000000UL)
    
/*   Specify the Peripheral clock frequency in Hz */
#define FCY  (FSYS/4UL)

#define _XTAL_FREQ FSYS

#include <xc.h>

void PIC_Init(void) {
    INTCON = 0;     /* disable interrupts */
    INTCON2 = 0xF5;
    INTCON3 = 0xC0;
    PIE1 = 0;
    PIE2 = 0;

    OSCCON = 0x70;      /* set internal oscillator to 8 MHz */

    RCONbits.IPEN = 0;  /* use legacy interrupt model */

    ADCON1 = 0x0F;      /* Disable ADC inputs  */

    CMCON  = 0x07;      /* disable Comparators */

    LATA   = 0x00;
    TRISA  = 0xC0;      /*  */
    LATB   = 0x00;
    TRISB  = 0x00;      /*  */
    LATC   = 0x00;
    TRISC  = 0x60;      /*  */
    LATD   = 0x00;
    TRISD  = 0x00;
    LATE   = 0x00;
    TRISE &= ~0x03;     /*  */
}

/* global variable to hold pulse width for servo */
volatile unsigned short ServoPulse;
volatile unsigned char  ServoRefreshCount;
volatile unsigned char  OneSecondTimeoutRunning;

/* High priority interrupt handled here */
void __interrupt(high_priority) ISR_High (void)
{
    if (PIE1bits.TMR2IE)   // test if TMR2 interrupt is enabled
    { 
        if (PIR1bits.TMR2IF) // test if TMR2 interrupt is asserted
        {
            PIR1bits.TMR2IF = 0;  // reset T2 assertion
            if(ServoRefreshCount)
            {
                ServoRefreshCount--;
                CCP1CON = 0b00001100;   // PWM mode
                CCPR1L  = 0;
            }
            else
            {
                ServoRefreshCount = 9;
                CCPR1L = (unsigned char)(ServoPulse >> 2);
                if(ServoPulse & 2) CCP1CONbits.DC1B1 = 1;
                if(ServoPulse & 1) CCP1CONbits.DC1B0 = 1;
                if (OneSecondTimeoutRunning) OneSecondTimeoutRunning--;
            }
        }
    }
} 

/* Low priority interrupt handled here */
void __interrupt(low_priority) ISR_Low (void)
{
}    
// initialize the PWM and interrupt on T2 overflow
void Init_PWM( void )
{ 
    PIE1bits.TMR2IE = 0;    // turn off TMR2 interrupt
    TRISC &= (0b11111011);  // make RC2 output for PWM
    
    T2CON = 0b00000010;     // postscaler 1:1
                            // TMR2 off
                            // prescaler 1:16
    
    PR2 = 250-1;            // set PWM period
    TMR2 = 0;
    
    CCP1CON = 0b00001100;   // PWM mode
    CCPR1L  = 0;
    ServoPulse = 0;
    ServoRefreshCount = 0;
    IPR1bits.TMR2IP  = 1;   // use high priority interrupt handler
    T2CONbits.TMR2ON = 1;   // turn on TMR2
    PIE1bits.TMR2IE  = 1;   // turn on TMR2 interrupt
}
/* Set PWM to stop motor */
void MotorStop (void)
{
    PIE1bits.TMR2IE  = 0;
    ServoPulse = 750;       // Set PWM for 1500 microsecond pulse
    PIE1bits.TMR2IE  = 1;
}
/* Set PWM to run motor clockwise */
void MotorRunCW (void)
{
    PIE1bits.TMR2IE  = 0;
    ServoPulse = 500;       // Set PWM for 1000 microsecond pulse
    PIE1bits.TMR2IE  = 1;
}
/* Set PWM to run motor counterclockwise */
void MotorRunCCW (void)
{
    PIE1bits.TMR2IE  = 0;
    ServoPulse = 1000;       // Set PWM for 2000 microsecond pulse
    PIE1bits.TMR2IE  = 1;
}
/* Start one second timeout */
void StartOneSecondTimeout(void)
{
    OneSecondTimeoutRunning = 50;
}
/* Check if timeout is running */
unsigned char OneSecondTimeoutIsRunning(void)
{
    if(OneSecondTimeoutRunning) return 1;
    return 0;
}
/*
 * Main application
 */
void main(void) 
{
    unsigned char DemoState;

    /* Initialize application*/
    PIC_Init();
    Init_PWM();
    
    GIEL = 1;   /* enable low priority interrupts */
    GIEH = 1;   /* enable global interrupts */

    /*
     * Demo application.
     * 
     * After Power-On-Reset start motor for one second.
     * 
     * Repeat sequence every 10 seconds.
     * 
     */
    MotorStop();
    DemoState = 0;
    /* Process loop for application */
    for(;;)
    {
        if(!OneSecondTimeoutIsRunning())
        {
            StartOneSecondTimeout();
            DemoState++;
            if(DemoState ==  1) 
                MotorRunCW();

            if(DemoState ==  2) 
                MotorStop();

            if(DemoState == 10) {
                DemoState = 0;
                Nop();
            }
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73161548

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档