单个舵机控制程序,越简单越好

具体要求,当传感器检测实际液位低于最低最低液位是开始工作,具体可以询问
或者结合这两个也行

https://www.bilibili.com/video/BV1Zk4y1z7fg?share_source=copy_web


#include <reg51.h>
#include <intrins.h>    
#include "main.h"     
uchar code TabNumASCII[10] =    {'0','1','2','3','4','5','6','7','8','9'};
bool    g_flag = isNo;        
bool    g_flag05s = isNo;    
uchar     ucCount = 0;                
uint    uiH = 80;            
uint    uiL = 30;            
uint    uiD = 100;             
bool    g_flagSwitch = isNo;    
bool    g_flagBeepTimer = isNo;            
void delay10us(void)        
{
    unsigned char i;
    _nop_();
    i = 2;
    while (--i);
}
void delay100us(void)        
{
    uchar i;
    _nop_();
    i = 47;
    while (--i);
}
void delay125us(void)        
{
    unsigned char i;
    i = 60;
    while (--i);
}
void delay5ms(void)        
{
    unsigned char i, j;
    i = 10;
    j = 183;
    do
    {
        while (--j);
    } while (--i);
}
void delay500ms(void)        
{
    unsigned char i, j, k;
    _nop_();
    i = 4;
    j = 205;
    k = 187;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}            
void initIO(void)                    
{
    P0 = 0xff;
    P1 = 0xff;
    P2 = 0xff;
    P3 = 0xff;
}
void initTimer0(void)        
{
    TMOD &= 0xF0;        
    TMOD |= 0x01;        
    TL0 = 0;                
    TH0 = 0;            
    //TR0 = 1;               
    ET0 = 1;              
    EA = 1;                     
}
void initTimer1(void)        
{    
    TMOD &= 0x0F;        
    TMOD |= 0x10;        
    TL1 = 0xB0;        
    TH1 = 0x3C;        
    TR1 = 1;        
    ET1 = 1;      
}
void zd0(void) interrupt 1          
{
    g_flag = isYes;                            
    if(++ucCount >= 8)
    {
        ucCount = 0;
        g_flag05s = isYes;                    
    }
    TL0 = 0;        
    TH0 = 0;            
}
void tm1_isr() interrupt 3 using 1
{
    static uchar count = DATA_switchTime;
    static uchar uiCount = 1200;                    
    static uint uiCount_BeepTimer = DATA_BeepTimer;
    TL1 = 0xB0;        
    TH1 = 0x3C;    
    if (g_flagSwitch == isNo)
    {
        if (count-- == 0)             
        {
            count = DATA_switchTime;
            g_flagSwitch = isYes;
            // TR1 = 0;
        }
    }    
    if(g_flagBeepTimer == isNo)
    {
        if (uiCount-- == 0)               
        {
            uiCount = 1200;
            if(uiCount_BeepTimer-- == 0)
            {
                uiCount_BeepTimer = DATA_BeepTimer; 
                g_flagBeepTimer = isYes;
                // TR1 = 0;
            }                
        }
    }
}
void exint1() interrupt 2 
{
    EX1 = 0;             
    TR0 = 0;                   
}  
void LCD_waitNotBusy(void)
{
    uchar sta;
    IO_LCD_Data = 0xFF; 
    io_LCD_RS = 0;
    io_LCD_RW = 1;
    do
    {
        io_LCD_E = 1;
        _nop_();
        _nop_();
        sta = P0;     
        io_LCD_E = 0;        
    }while(sta & 0x80); 
}
void LCDWriteCommand(uchar command,bool ifReadBusy) 
{
    if (ifReadBusy == isReadBusy) LCD_waitNotBusy(); 
    io_LCD_RS = 0;
    io_LCD_RW = 0;    
    IO_LCD_Data = command;    
    io_LCD_E = 1;
    _nop_();
    _nop_();
    io_LCD_E = 0;    
}
void LCDWriteData(uchar dat) 
{
    LCD_waitNotBusy(); 
    io_LCD_RS = 1;
    io_LCD_RW = 0;
    IO_LCD_Data = dat;    
    io_LCD_E = 1; 
    _nop_();
    _nop_();
    io_LCD_E = 0;
}
void initLCD1602(void) 
{
    uchar    i;    
    IO_LCD_Data = 0;                            
    for(i = 0; i < 3; i++)                    
    {
        LCDWriteCommand(0x38,isNotReadBusy);    
        delay5ms();
    }
    
    LCDWriteCommand(0x38,isReadBusy); 
    LCDWriteCommand(0x08,isReadBusy); 
    LCDWriteCommand(0x01,isReadBusy); 
    LCDWriteCommand(0x06,isReadBusy); 
    LCDWriteCommand(0x0F,isReadBusy); 
}
void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
{
    line &= DATA_LineMax;
    position &= DATA_PositionMax;
    if (line == DATA_LineTow) position |= 0x40;         
    position |= 0x80;                                     
    LCDWriteCommand(position, isReadBusy);     
    LCDWriteData(ucData);     
}
void putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)
{
    uchar i;
    for(i = 0; i < count; i++)    
    {
        putOneCharToLCD1602(line, position + i, ucData[i]);    
    }
}
void    putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)
{
    uiNumber %= 1000;
    putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);
    putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);
    putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);        
}    
uchar GetKey(void)
{    
    uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);
    if( KeyTemp != DATA_KEY_Null )
    {
        uchar CountTemp = 0;
        do
        {
            delay125us();
            if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;                
        } while(++CountTemp > Data_Key20msCountMax);             
        while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);         
        return KeyTemp;    
    }
    return 0;
}
uchar  INC_Number(uchar Number, uchar Min, uchar Max)
{
    if(Number >= Max) return Min; else return (++ Number);    
}
uchar  DEC_Number(uchar Number, uchar Min, uchar Max)
{
    if(Number <= Min) return Max; else return (-- Number);    
}    
void execute_key_task(uchar ucKeyValue)    
{
    uchar state = 0;
    uchar keyValue = 0;    
    if(ucKeyValue != DATA_KEY_Set) return;    
    putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");        
    putThreeCharToLCD1602(lineOne, 8 + 2, uiD);    
    while(1)
    {
        keyValue = GetKey();    
        if(keyValue == 0) continue;
        switch(keyValue)
        {
            case DATA_KEY_Set:
            {
                            switch(state)
                {
                    case 0:            
                    {
                        state = 1;                        
                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);                
                    }
                    break;
                    case 1:
                    {
                        uchar tempMax = uiD - DATA_uiD_Min;
                        if(tempMax < 2 + 2) tempMax = 2 + 2;                        
                        if(uiH > tempMax) 
                        {
                            uiH = tempMax;
                            putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
                        }
                        else if(uiH < 2 + 2)
                        {
                            uiH = 2 + 2;    
                            putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
                        }                            
                        state = 2;
                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
                    }
                    break;
                    case 2:
                    {
                        if(uiL > uiH - 2) 
                        {
                            uiL = uiH - 2;
                            putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
                        }
                        return;        
                    }
                    break;
                }    
            }
            break;
            case DATA_KEY_INC:
            {
                switch(state)
                {
                    case 0:
                    {
                        uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);
                        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);            
                    }
                    break;
                    case 1:
                    {
                        uchar tempMax = uiD - DATA_uiD_Min;
                        if(tempMax < 2 + 2) tempMax = 2 + 2;
                        uiH = INC_Number(uiH, 2, tempMax);                        
                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);    
                    }
                    break;
                    case 2:
                    {
                        uiL = INC_Number(uiL, 0, uiH - 2);    
                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);    
                    }
                    break;
                }
            }
            break;
            case DATA_KEY_DEC:
            {
                switch(state)
                {
                    case 0:
                    {
                        uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);                    
                        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
                    }
                    break;
                    case 1:
                    {
                        uchar tempMax = uiD - DATA_uiD_Min;
                        if(tempMax < 2 + 2) tempMax = 2 + 2;
                        uiH = DEC_Number(uiH, 2, tempMax);                        
                        putThreeCharToLCD1602(lineOne, 0 + 2, uiH);    
                    }
                    break;
                    case 2:
                    {
                        uiL = DEC_Number(uiL, 0, uiH - 2);    
                        putThreeCharToLCD1602(lineTow, 0 + 2, uiL);    
                    }
                    break;
                }
            }
            break;
        }
    }
}
void buzzerCall(void)
{
    uchar    i;    
    for(i = 0; i < 90; i++)
    {
        io_Buzzer = 0;
        delay100us();
        io_Buzzer = 1;
        delay100us();
        delay100us();        
    }
    delay100us();    
    delay100us();    
}
bool CalculatedWaterLevel(void)
{
    uchar     i = 8 + 2;                    
    uint      uiTime;                        
    ulong     ulDis;                            
    uiTime = TH0 << 8 | TL0;    
    ulDis = (uiTime * 3.40) / 200;         
    TH0 = 0;
    TL0 = 0;    
    if((ulDis > uiD) || (g_flag == isYes )) 
        ioLed_Red = ! ioLed_Red;                            
        ioLed_Green = ! ioLed_Green;
        ioLed_Yellow = ! ioLed_Yellow;
        if(buzzerCallFlag == isCall)
        {
            buzzerCall();                
        }
        return isNo;                                
    }
    else
    {
        ulDis = uiD - ulDis;                    
        if(ulDis > uiH)                        
        {
            io_Control_Inlet = isio_Control_Inlet_OFF;
            io_Control_Outlet = isio_Control_Outlet_ON;    
            g_flagSwitch = isNo;
            ioLed_Red = ! ioLed_Red;            
            ioLed_Green = isLedOFF;        
            ioLed_Yellow = isLedOFF;                
            if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient) 
            {
                buzzerCall();                    
            }
        }
        else if(ulDis < uiL)                
            if(g_flagSwitch == isYes)
            {        
                io_Control_Outlet = isio_Control_Outlet_OFF;    
                io_Control_Inlet = isio_Control_Inlet_ON;    
                g_flagSwitch = isNo;
            }    
            ioLed_Red = isLedOFF;
            ioLed_Green = isLedOFF;
            ioLed_Yellow = ! ioLed_Yellow;                
            if( uiL - ulDis > uiL / DATA_alarmCoefficient)/
            {
                buzzerCall();                    
            }    
        }
        else                                    
        {    
            ioLed_Red = isLedOFF;
            ioLed_Green = ! ioLed_Green;
            ioLed_Yellow = isLedOFF;        
        }
        putThreeCharToLCD1602(lineTow, i, ulDis);
        return isYes;    
    }
}
void main(void)
{
    initIO();        
    delay500ms();         
    initLCD1602();     »¯    
    putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm ");        putThreeCharToLCD1602(lineOne, 8 + 2, uiD);        
    putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");    
    putThreeCharToLCD1602(lineOne, 0 + 2, uiH);        
    putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");    
    putThreeCharToLCD1602(lineTow, 0 + 2, uiL);        
    putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");    
    initTimer0();        
    initTimer1();
    io_Control_Inlet = isio_Control_Inlet_OFF;    
    io_Control_Outlet = isio_Control_Outlet_ON;
    g_flagSwitch = isNo;    
    while(1)
    {
        io_US_TX = 1;                  
        delay10us();
        io_US_TX = 0;
        while(io_US_RX == 0);            
        TR0 = 1;                            
        IT1 = 1;                         
        EX1 = 1;                       
        while(EX1 == 1 && g_flag == isNo)
        {
            uchar ucKeyValue = GetKey();                    
            if(ucKeyValue) execute_key_task(ucKeyValue);    
        }
        if(CalculatedWaterLevel() == isNo) continue;                
        TR0 = 0;    
        TL0 = 0;        
        TH0 = 0;        
        g_flag = isNo;
        ucCount = 0;
        g_flag05s = isNo;
        TR0 = 1;                    
        while(g_flag05s == isNo)    
        {            
            uchar ucKeyValue = GetKey();
            if(ucKeyValue) 
            {
                if(ucKeyValue == DATA_KEY_DEC)
                {
                    g_flagBeepTimer = isNo;
                }
                execute_key_task(ucKeyValue);    
            }                
        }    
        TR0 = 0;    
        TL0 = 0;    
        TH0 = 0;    
        g_flag = isNo;    
        if(g_flagBeepTimer == isYes)
        {
            buzzerCall();        
        }        
    }
}



                


import RPi.GPIO as GPIO
import time

# 设置舵机引脚
servo_pin = 18

# 设置传感器引脚
sensor_pin = 17

# 设置最低液位值
lowest_level = 10  # 这里的值需要根据实际情况进行设置

# 初始化GPIO设置
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
GPIO.setup(sensor_pin, GPIO.IN)

# 定义舵机控制函数
def control_servo(angle):
    pwm = GPIO.PWM(servo_pin, 50)
    pwm.start(0)
    duty_cycle = angle / 18.0 + 2.5
    pwm.ChangeDutyCycle(duty_cycle)
    time.sleep(1)
    pwm.stop()

# 主程序
try:
    while True:
        # 读取传感器状态
        sensor_status = GPIO.input(sensor_pin)

        if sensor_status == GPIO.LOW:
            print("实际液位低于最低液位,启动舵机工作")
            control_servo(90)  # 设置舵机角度,这里是90度,根据实际情况进行设置
            time.sleep(1)  # 控制舵机工作的持续时间
            control_servo(0)  # 舵机回到初始位置
        else:
            print("实际液位正常")

        time.sleep(1)  # 每隔1秒检测一次传感器状态

except KeyboardInterrupt:
    GPIO.cleanup()

使用了RPi.GPIO库来控制树莓派上的GPIO引脚。程序会不断检测传感器引脚的状态,当检测到实际液位低于最低液位时,舵机会开始工作,持续一定时间后回到初始位置。可以根据实际情况修改舵机引脚、传感器引脚、最低液位值和舵机角度等参数。

你好,代码有什么问题么,我看函数都蛮好的


/*****************************************************************************
 ** 文件            : main.c
 ** 作者            : Zheng23
 ** 日期            :             
 ** 功能            : 
/*****************************************************************************/
//#include <STC15.h>
//#include"STC89C5xRC.H"
 
 
//一定要用12M的晶振
//一定要用12M的晶振
//一定要用12M的晶振
//一定要用12M的晶振
//一定要用12M的晶振
//一定要用12M的晶振
 
#include "reg51.h"
 
#define uint8    unsigned char    
#define uint16    unsigned short int
#define uint32    unsigned long 
 
sbit SERVO0=P1^4;            //控制舵机的PWM输出口
 
uint16 Servo0PwmDuty=1500;    //PWM脉冲宽度
 
/***********************************************************
* 名    称: DelayMs(uint16 ms) 
* 功    能: 延时ms毫秒
* 入口参数: ms    毫秒
* 出口参数: 无
* 说    明:                      
/**********************************************************/
void DelayMs(uint16 ms)
{
    uint16 i,j;
    for(i=0;i<85;i++)        //89单片机用85,12系列单片机用800
        for(j=0;j<ms;j++);
}
/***********************************************************
* 名    称:InitTimer0()
* 功    能:时钟0初始化
* 入口参数:无
* 出口参数:无
* 说    明:12M晶振,12分频,所以计数器每递增一个数就是1微秒,完全满足舵机控制的精度要求
            因为定时器是TH0,TL0都要全部计数到0xFF后在计1个数就会产生中断,所以要想产生
            x毫秒的中断,那么TH0,TL0就应该赋值(0xFFFF-x)    从这个值开始计数产生定时中断                     
/**********************************************************/ 
void InitTimer0(void)
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0x00;            //设置定时初值
    TH0 = 0x00;            //设置定时初值
    TF0 = 0;            //清除TF0标志
    TR0 = 1;            //定时器0开始计时
    ET0 = 1;            //开定时器0中断
}
/***********************************************************
* 名    称:Timer0Value(uint16 pwm)  
* 功    能:给定时器0计数器赋值产生定时中断 
* 入口参数:pwm        控制舵机的PWM脉冲宽度值(范围:500~2500)
* 出口参数:无
* 说    明:12M晶振,12分频,所以计数器每递增一个数就是1微秒,完全满足舵机控制的精度要求
            因为定时器是TH0,TL0都要全部计数到0xFF后在计1个数就会产生中断,所以要想产生
            pwm毫秒的中断,那么TH0,TL0就应该赋值(0xFFFF-pwm)    从这个值开始计数产生定时中断                      
/**********************************************************/ 
void Timer0Value(uint16 pwm)
{
    uint16 value;
    value=0xffff-pwm;    
    TR0 = 0;
    TL0=value;            //16位数据给8位数据赋值默认将16位数据的低八位直接赋给八位数据
    TH0=value>>8;        //将16位数据右移8位,也就是将高8位移到低八位,再赋值给8位数据    
    TR0 = 1;
}
/***********************************************************
* 名    称: main()
* 功    能: 入口函数
* 入口参数: 无
* 出口参数: 无
* 说    明:                      
/**********************************************************/ 
void main(void)
{
 
    InitTimer0();    //定时器0初始化
    EA = 1;            //开总中断
    while(1)        //大循环
    {    
        Servo0PwmDuty = 500;        //脉冲宽度在500微秒,对应-90°
        DelayMs(1000);        //延时1秒
        Servo0PwmDuty = 1000;    //脉冲宽度在1000微秒,对应-45°
        DelayMs(1000);
        Servo0PwmDuty = 1500;
        DelayMs(1000);
        Servo0PwmDuty = 2000;
        DelayMs(1000);
        Servo0PwmDuty = 2500;
        DelayMs(1000);
        Servo0PwmDuty = 2000;
        DelayMs(1000);
        Servo0PwmDuty = 1500;
        DelayMs(1000);
        Servo0PwmDuty = 1000;
        DelayMs(1000);
    }
}
 
/***********************************************************
* 名    称: Timer0_isr() interrupt 1 using 1
* 功    能: 时钟0中断处理
* 入口参数: 无
* 出口参数: 无
* 说    明:                      
/**********************************************************/ 
void Timer0_isr(void) interrupt 1 using 1
{
    static uint16 i = 1;    //静态变量:每次调用函数时保持上一次所赋的值,
                            //跟全局变量类似,不同是它只能用于此函数内部
    switch(i)
    {
        case 1:
            SERVO0 = 1;    //PWM控制脚高电平
            //给定时器0赋值,计数Pwm0Duty个脉冲后产生中断,下次中断会进入下一个case语句
            Timer0Value(Servo0PwmDuty);    
            break;
        case 2:
            SERVO0 = 0;    //PWM控制脚低电平
            //高脉冲结束后剩下的时间(20000-Pwm0Duty)全是低电平了,Pwm0Duty + (20000-Pwm0Duty) = 20000个脉冲正好为一个周期20毫秒 
            Timer0Value(20000-Servo0PwmDuty);
            i = 0;    
            break;     
    }
    i++;
}

以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:

你好,以下是一个简单的单个舵机控制程序的C语言代码示例,使用了51单片机和proteus仿真环境:

#include <reg51.h>
#define Servo P1  // 定义舵机控制引脚P1
#define Sensor P2  // 定义液位传感器引脚P2

void delay(unsigned int n)  // 延时函数
{
    unsigned int i, j;
    for(i=0; i<n; i++)
        for(j=0; j<125; j++);
}

void main()
{
    while(1)
    {
        if(Sensor < 100)  // 当实际液位低于最低液位时
        {
            Servo = 0x00;  // 舵机转到最低位置
            delay(50000);  // 延时等待舵机到位
            Servo = 0xFF;  // 舵机转到最高位置
            delay(50000);  // 延时等待舵机到位
        }
        else
        {
            Servo = 0x00;  // 舵机转到最低位置
            delay(50000);  // 延时等待舵机到位
        }
    }
}

该程序中使用P1口控制舵机的转动,P2口接液位传感器检测实际液位高低,当实际液位低于最低液位时,舵机会先转到最低位置,然后再转到最高位置,等待一段时间后再转回最低位置;当实际液位高于最低液位时,舵机只会转到最低位置。程序中的delay函数用于延时等待舵机到位。这只是一个简单的示例程序,具体实现还需根据具体的硬件和需求进行调整。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
以下是单个舵机控制程序的 Python 代码:

import RPi.GPIO as GPIO
import time

# 设置GPIO模式为BCM编码方式
GPIO.setmode(GPIO.BCM)

# 设置GPIO21为输出信号口
GPIO.setup(21, GPIO.OUT)

# 设置脉宽为50Hz
servo = GPIO.PWM(21, 50)

# 启动脉冲,设置角度为0,初始化位置
servo.start(0)

# 指定位置函数
def setPosition(degrees):
    duty = degrees / 18 + 2.5
    servo.ChangeDutyCycle(duty)
    time.sleep(1)
    servo.ChangeDutyCycle(0)

# 角度从0到180依次打印
for i in range(0, 180, 10):
    print(i)
    setPosition(i)

# 角度从180到0依次打印
for i in range(180, 0, -10):
    print(i)
    setPosition(i)

# 停止脉冲
servo.stop()

# 清除GPIO口
GPIO.cleanup()

需要注意的是,这里使用的是树莓派GPIO控制舵机的方式,如果使用其他硬件,请使用相应的代码进行控制。同时,代码只是一个简单的示例,具体实现需要根据具体的舵机和控制方式进行调整。
如果我的回答解决了您的问题,请采纳!

以下答案由GPT-4.5Plus大模型(语音)与博主A努力中.......共同编写:
一个简单的单个舵机控制程序可以设计如下:

  1. 包含舵机对象,用于存储舵机参数及状态:
python
class Servo: 
    def __init__(self, min_width, max_width, center_width):
        self.min_width = min_width    # 舵机最小脉冲宽度
        self.max_width = max_width    # 舵机最大脉冲宽度
        self.center_width = center_width # 舵机中心脉冲宽度
        self.curr_width = center_width # 当前脉冲宽度

  1. 设置舵机转动函数,用于根据给定脉冲宽度转动舵机:
python
def rotate(self, width):
    self.curr_width = width
    # 发送舵机转动信号,可调用外部库

  1. 定义舵机旋转度数转化函数,用于根据旋转角度计算舵机脉冲宽度:
python 
def angle_to_width(self, angle):
    range = self.max_width - self.min_width
    ratio = (angle + 90) / 180   # 角度范围转化到0-1之间
    return self.min_width + range * ratio 

  1. 编写舵机控制代码:
python
servo = Servo(1000, 2000, 1500)   # 初始化舵机对象

# 转动舵机到90度
servo.rotate(servo.angle_to_width(90))  

# 中心位置 
servo.rotate(servo.center_width)

# 转动舵机到-45度
servo.rotate(servo.angle_to_width(-45)) 

以上是一个简单的单舵机控制程序,通过定义舵机对象存储参数,设置转动函数和角度转换函数,可以方便地根据给定角度控制舵机转动。