找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7686|回复: 1
打印 上一主题 下一主题
收起左侧

利用舵机制作简单机械臂

[复制链接]
跳转到指定楼层
楼主
ID:162561 发表于 2017-12-13 17:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

**项目名称:利用舵机制作简单机械臂
**编写时间:2017.07.11
**使用芯片:stc12c2052ad
**时钟频率:使用外部晶振频率12MHz
**简要说明:本次制作的机械臂共用了3个舵机,可以控制机械臂上下、左右移动和抓放动作。
#include <stc12c2052ad.h>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned short int u16;

sbit CTRL_u_d = P3^3;                                                //控制上、下方向的舵机控制端口
sbit CTRL_l_r = P3^4;                                                //控制左、右方向的舵机控制端口
sbit CTRL_g = P3^5;                                                        //控制抓起的舵机控制端口

void delay_20ms(u16 x);
u8 KeyScan();

u16 TIME = 20000;                                                                //PWM周期时间(单位us)
u16 Min = 700;                                                                        //高电平最小持续时间
u16 Max = 2300;                                                                        //高电平最大持续时间
u8 Degree = 50;                                                                        //单位时间宽度(最小是舵机死区设定大约10us)

u16 Times = 0;                                                                        //TIME/Degree(PWM周期除于单位时间宽度)

//高电平持续时间除于单位时间宽度
u16 cTimes_u_d = 0;       
u8 cTimes_l_r = 0;
u8 cTimes_g = 0;
u8 Min_cTimes = 0;
u8 Max_cTimes = 0;

u8 R_TH0 = 0, R_TL0 = 0;                                //定时器0计数重载值

u8 KeyValue = 0;                                                                //1-上、2-左、3-抓、4-右、5-下

void main()
{
        Times = TIME/Degree;       

        cTimes_u_d = 1500/Degree;
        cTimes_l_r = 1500/Degree;
        cTimes_g = Min_cTimes;
        Min_cTimes = Min/Degree;
        Max_cTimes = Max/Degree;       
       
        P1 = 0xff;
        CTRL_u_d = 0;
        CTRL_l_r = 0;
        CTRL_g = 0;                                                       

        R_TL0 = 65536 - Degree;
        R_TH0 = (65536 - Degree) >> 8;
       
        //设置定时器0
        TMOD = 0x01;                                                                        //16位计数
        TL0 = R_TL0;
        TH0 = R_TH0;
        ET0 = 1;                                                                                        //定时器0中断开关打开
        TR0 = 1;                                                                                        //定时器0计数开始
       
        EA = 1;                                                                                                //中断总开关打开
       
        while(1)
        {
                u8 temp = 0;
                KeyValue = KeyScan();
               
                switch(KeyValue)
                {
                        case 1:                                                                                //向上移动
                                cTimes_u_d = --cTimes_u_d < Min_cTimes ? Min_cTimes : cTimes_u_d;
                                break;
                        case 2:                                                                                //向左移动
                                cTimes_l_r = --cTimes_l_r < Min_cTimes ? Min_cTimes : cTimes_l_r;
                                break;
                        case 3:                                                                                //抓、放动作
                                if(cTimes_g == Min_cTimes)
                                        cTimes_g = Max_cTimes;
                                else
                                        cTimes_g = Min_cTimes;
                               
                                delay_20ms(15);
                                break;
                        case 4:                                                                                //向右移动
                                cTimes_l_r = ++cTimes_l_r > Max_cTimes ? Max_cTimes : cTimes_l_r;
                                break;
                        case 5:                                                                                //向下移动
                                cTimes_u_d = ++cTimes_u_d > Max_cTimes ? Max_cTimes : cTimes_u_d;
                                break;
                }
        }
}


u8 KeyScan()
{
        u8 key = 0;
        if(P1 != 0xff)
        {
                delay_20ms(2);
                if(P1 != 0xff)
                {
                        u8 temp  = P1;
                        key = 1;
                        while(temp & 0x01)
                        {
                                temp = temp >> 1;
                                key++;
                        }                       
                }
        }       
       
        return key;
}


void Delay20ms()                //@12.000MHz
{
        unsigned char i, j, k;

        _nop_();
        _nop_();
        i = 1;
        j = 234;
        k = 113;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}

void delay_20ms(u16 x)
{
        while(x--)  Delay20ms();
}


//定时器0中断函数   每次进入中断间隔时间为Degree(单位时间宽度)
void timer0() interrupt 1 using 1
{
        static u16 times = 0;
        TL0 = R_TL0;
        TH0 = R_TH0;
       
        //每次只控制一个舵机移动
        if(times == 0)
        {
                switch(KeyValue)
                {
                        case 1:
                        case 5:
                                CTRL_u_d = 1;
                                CTRL_l_r = 0;
                                CTRL_g = 0;
                                break;
                        case 2:
                        case 4:
                                CTRL_u_d = 0;
                                CTRL_l_r = 1;
                                CTRL_g = 0;
                                break;
                        case 3:
                                CTRL_u_d = 0;
                                CTRL_l_r = 0;
                                CTRL_g = 1;
                                break;
                }
        }
        else
        {
                switch(KeyValue)
                {
                        case 1:
                        case 5:
                                if(times >= cTimes_u_d)
                                {
                                        CTRL_u_d = 0;
                                }
                                break;
                        case 2:
                        case 4:
                                if(times >= cTimes_l_r)
                                {
                                        CTRL_l_r = 0;
                                }
                                break;
                        case 3:
                                if(times >= cTimes_g)
                                {
                                        CTRL_g = 0;
                                }       
                                break;
                }
        }
       
        times = ++times >= Times ? 0 : times;
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:253033 发表于 2018-3-9 23:24 | 只看该作者
这个单用51单片机就可以实现吗?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表