久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
51單片機的6自由度機械臂 16路舵機控制 源碼
[打印本頁]
作者:
秦書力
時間:
2017-3-24 16:58
標題:
51單片機的6自由度機械臂 16路舵機控制 源碼
這是我畢設的源碼 16路舵機控制實現6自由度機械臂控制,采用的是51單片機。
0.png
(49.74 KB, 下載次數: 174)
下載附件
2017-3-24 20:45 上傳
完整源碼下載:
6自由度手臂源代碼.rar
(589.48 KB, 下載次數: 344)
2017-3-24 16:57 上傳
點擊文件名下載附件
6自由度機械臂源碼
下載積分: 黑幣 -5
單片機主程序:
/***************************************************************************************************************
文 件 名:main.c
功能描述:
備 注: 16路舵機控制
****************************************************************************************************************/
#include "STC15Fxxxx.H" //STC15系列單片機
#include <intrins.h>
#include "UART.H"
#include "timer.h"
#include "util.h"
#include "ps2/ps2.h"
#include "flash/flash.h"//頭文件
#include <string.h>
#include <stdio.h>
#include "LED/led.h"
#include <string.h>
#include <stdlib.h>
#include "adc/adc.h"
extern uint8 flag_p;
extern bit flag_RecFul;
//extern uchar KEY[9];
uint16 pos[7][MOTOR_NUM]={ {1000,1500,1500,1500,1500,1500,1500,1500,1500},
{1000,1500,1500,1500,1500,1500,1500,1500,1500},
{1000,1500,1500,1500,1500,1500,1500,1500,1500},
{1000,500,500,500,500,500,500,500,500},
{1000,1500,1500,1500,1500,1500,1500,1500,1500},
{1000,500,500,500,500,500,500,500,500},
{1000,1500,1500,1500,1500,1500,1500,1500,1500}
}; //位置
uint16 pwm[MOTOR_NUM]= {1500,1500,1500,1500,1500,1500,1500,1500,1500};
uint16 UartRec[MOTOR_NUM]={1500,1500,1500,1500,1500,1500,1500,1500,1500};
uint8 redata[257] = {0}; // 定義接收數據變量數組
uint8 line=0; //緩存存入口與出口之間的距離,即當前緩存中有多少個沒有執行的數據
uint8 point_now=0; //與point_aim一起標記緩存出口位置,即取數位置
uint8 point_aim=1;
uint8 point_in=2; //標記緩存入口位置,即上一行數據存放位置
bit flag_connect = 0;
bit flag_stop=1; //表示一行執行結束
uint8 flag_vpwm=0; //表示到達了該更新pwm[]的時間
bit flag_in=1; //表示緩存中有空閑空間
bit flag_out=0; //表示緩存中有可執行數據的標志位
bit flag_run_ready=0; //表示有要要放入緩存的EErom數據
uint16 n=1000; //用來計算需要建立多少個中間數據
uint16 m=1; //用來累計已經執行了多少中間數據
double dp;
double dp0[MOTOR_NUM] = {0}; //插補增量
bit flag_download = 0;//判斷是否下載
bit flag_read = 0;// 讀取flash內容,發送上位機
bit flag_connect_run = 0;//連接上位機的執行flash保存的命令
bit flag_stop_download = 0;//停止下載
bit flag_online_run = 0;
bit flag_uart2_rev = 0;
bit flag_uart2_rev_time_out = 0;
bit flag_ps2_rev = 0;
bit flag_read_adc = 0;
unsigned long send_mode = 0;//當前串口接收到命令狀態存儲
MotorData motor_data;//舵機總信息
MotorOneCmd motor_one_cmd;//單個命令
CurrentItem cur_item;
uint16 tuoji_count = 0;//脫機執行次數
bit flag_scan_ps2 = 0;
uint8 error = 0;
uchar file_list[MAX_SUPPORT_FILE_SAVE] = {0};
int file_list_count = 0;
int file_last_num = 0;
char ps2_buf[120] = {0};
char uart2_buf[50] = {0};
uint cur_count = 0;
uchar ad_value = 0;
uchar beep_mode = 1;
uchar key_bak;
uchar ps2_key;
uchar ps2_mode=0;
void updata_file_list()
{
uchar i = 0;
uchar j = 0;
file_last_num = -1;
ReadMoterInfor();
for (i = 0; i < motor_data.filecount; i++)
{
if (motor_data.file_flag[i] == 1)
{
file_list[j] = i;
j++;
file_last_num = i;
}
}
file_list_count = j;
}
void InitMotor()
{
ReadMoterInfor();//讀取舵機控制信息
updata_file_list();
memset(&cur_item,0,sizeof(cur_item));
beep_mode = motor_data.beep_mode;
}
/***************************************************************************************************************
函 數 名:主函數
功能描述:入口函數 ,進行各種初始化配置
輸入參數:無
返 回 值:無
備 注:
****************************************************************************************************************/
void main(void)
{
uint temp = 0;
P0M1=0x00; //設置P0口為強推挽輸出模式
P0M0=0xFF;
P1M1|=0x80;
P1M0|=0xc8;
P5M1|=0x00;
P5M0|=0x2d;
P4M0|=0x20;
P4M1|=0x00;
Timer_init(); //定時器初始化
Timer0(31); //定時任意值,啟動定時器,進入定時器循環
#if MOTOR_NUM > 9
Timer1(30);
#endif
SpiFlashInit();//初始化flash
while((temp = SpiFlashReadID())!=W25Q64)LED_ALL_ON();//判斷flash有沒有接錯
LED_ALL_OFF();
InitMotor();
UART1_Init(); //串口1初始化
UART2_Init(); //串口2初始化
#if PS_SUPPORT
Timer3_init();
#endif
InitADC(7);
BEEP_On_Or_OFF();
while(1)
{
if(flag_vpwm==1)
{
vpwm(); //更新pwm[]數組
flag_vpwm=0;
}
if( flag_RecFul==1) //串口接受完一條指令
{
DealRec(); //處理串口緩存中的數據
flag_RecFul=0;
}
GetOneMotorCMD();//獲取一個命令
SendUartState();//發送狀態信息
#if PS_SUPPORT
scan_ps2();
#endif
LED_State();
Check_Power();
cur_count++;
}
}
void Check_Power()
{
if ((cur_count % 800) == 0)
{
StartADC(7);
//cur_count=0;
}
if (flag_read_adc)
{
flag_read_adc = 0;
//UART_Put_Inf("adc:",ad_value);
if (ad_value > 46)//根據電壓粗略估計
{
//UART_Put_Inf("adc:",ad_value);
BEEP_OFF();
// LED2_OFF();
}
else
{
//UART_Put_Inf("adc1111:",ad_value);
BEEP=~BEEP;
LED1=0;
LED2=0;
LED3=0;
}
}
}
void LED_State()
{
uint error_count = 0;
if (error != 0)
{
if (error & ERROR_FLASH_FULL)
{
error_count = 100;
}
if (error & ERROR_FLASH_FILE_FULL)
{
error_count += 100;
}
if (error & ERROR_FLASH_WRITE)
{
error_count += 100;
}
if (error & ERROR_FLASH_WRITE1)
{
error_count += 100;
}
if ((cur_count % error_count) == 0)//判斷flash是否正確
{
LED1_ON_OR_OFF();
}
}
if (flag_ps2_rev)
{
LED1_ON();
if ((cur_count % 100) == 0)
{
flag_ps2_rev = 0;
LED1_OFF();
}
}
if (flag_connect)
{
LED3_ON();
}
else
{
LED3_OFF();
}
}
void scan_ps2()
{
int kind = 0;
char *p = NULL;
char buf[15] = {0};
char i = 0;
if (flag_scan_ps2)//
{
flag_scan_ps2 = 0;
ps2_key=PS2_DataKey();
ps2_mode=PS2_RedLight();
//UART_Put_Inf("mode",ps2_mode);
if(ps2_mode==0)
{
if(key_bak == ps2_key)return;
key_bak=ps2_key;
BEEP=~BEEP;
switch(ps2_key)
{
case PSB_PAD_UP:kind = 1;break;
case PSB_PAD_DOWN:kind = 2;break;
case PSB_PAD_LEFT:kind = 3;break;
case PSB_PAD_RIGHT:kind = 4;break;
case PSB_TRIANGLE:kind = 7;break;
case PSB_CROSS:kind = 8;break;
case PSB_PINK:kind = 9;break;
case PSB_CIRCLE:kind = 10;break;
case PSB_L1:kind = 6;break;
case PSB_L2:kind = 5;break;
case PSB_R1:kind = 12;break;
case PSB_R2:kind = 11;break;
default:break;
}
if (kind != 0)
{
flag_ps2_rev = 1;
flag_connect = 1;
SpiFlashRead(ps2_buf,(PS2_FLASH_ADDR)<<WRITE_BIT_DEPTH,sizeof(ps2_buf));
sprintf(buf,"%dK",kind);
//UART1_SendStr(buf);
p = strstr(ps2_buf,buf);
if (p != NULL)
{
p = p + strlen(buf);
while(i < 14 && *p != 0)
{
buf[i] = *p++;
i++;
if (*p == '#')
break;
}
if (i < 12)
{
buf[i] = '\r';
buf[i+1] = '\n';
memcpy(redata,buf,sizeof(buf));
flag_RecFul = 1;
}
UART1_SendStr(redata);
}
}
}
else if(ps2_mode==1)//綠燈模式
{
switch(ps2_key)
{
case PSB_PAD_UP:pwm[1]+=10;if(pwm[1]>=2300) pwm[1]=2300;break;
case PSB_PAD_DOWN:pwm[1]-=10;if(pwm[1]<=700) pwm[1]=700;break;
case PSB_PAD_LEFT:pwm[2]+=10;if(pwm[2]>=2300) pwm[2]=2300;break;
case PSB_PAD_RIGHT:pwm[2]-=10;if(pwm[2]<=700) pwm[2]=700;break;
case PSB_TRIANGLE:pwm[3]+=10;if(pwm[3]>=2300) pwm[3]=2300;break;
case PSB_CROSS:pwm[3]-=10;if(pwm[3]<=700) pwm[3]=700;break;
case PSB_PINK:pwm[4]+=10;if(pwm[4]>=2300) pwm[4]=2300;break;
case PSB_CIRCLE:pwm[4]-=10;if(pwm[4]<=700) pwm[4]=700;break;
case PSB_L1:pwm[5]+=10;if(pwm[5]>=2300) pwm[5]=2300;break;
case PSB_L2:pwm[5]-=10;if(pwm[5]<=700) pwm[5]=700;break;
case PSB_R1:pwm[6]+=10;if(pwm[6]>=2300) pwm[6]=2300;break;
case PSB_R2:pwm[6]-=10;if(pwm[6]<=700) pwm[6]=700;break;
default:break;
}
}
}
}
/***************************************************************************************************************
函 數 名:從flash讀取舵機總的信息
功能描述:初始化舵機控制信息
輸入參數:無
返 回 值:無
備 注:
****************************************************************************************************************/
void ReadMoterInfor()
{
memset(&motor_data,0,sizeof(motor_data));//清 0
SpiFlashRead((char *)&motor_data,(CMD_FLASH_ADDR)<<WRITE_BIT_DEPTH,sizeof(motor_data));//讀取信息
if (motor_data.CRC1 != 0x12345678 || motor_data.sum < 0 || motor_data.duoji_count > MOTOR_NUM)//判斷信息存儲是否有錯
{
memset(&motor_data,0,sizeof(motor_data));
//memset(&cur_item,0,sizeof(cur_item));
}
else//正常信息
{
//UART1_SendOneChar(motor_data.sum + 0x30);
//cur_item.tuoji_count = motor_one_cmd.tuoji_count;//脫機運行次數
//cur_item.cur_num = 0;//清 0
}
}
void ReadOneCmdInfor(unsigned int addr)
{
memset(&motor_one_cmd,0,sizeof(motor_one_cmd));//清 0
SpiFlashRead((char *)&motor_one_cmd,((((unsigned long)addr)<<4) + FILE_FLASH_ADDR)<<WRITE_BIT_DEPTH,sizeof(motor_one_cmd));//讀取信息
if (motor_one_cmd.start >= motor_one_cmd.end || motor_one_cmd.cur_file_num != (addr) || motor_data.file_flag[motor_one_cmd.cur_file_num] == 0)//判斷信息存儲是否有錯
{
memset(&motor_one_cmd,0,sizeof(motor_one_cmd));
}
else//正常信息,以后留著驗證用的
{
cur_item.tuoji_count = motor_one_cmd.tuoji_count;//脫機運行次數
cur_item.cur_num = motor_one_cmd.start;
//UART1_SendOneChar(motor_one_cmd.tuoji_count + 0x30);
//cur_item.cur_num = 0;//清 0
}
}
/***************************************************************************************************************
函 數 名:把舵機信息寫到flash中
功能描述:把舵機信息寫到flahs中
輸入參數:無
返 回 值:無
備 注:
****************************************************************************************************************/
void WriteMoterInfor()
{
uchar temp = 0;
motor_data.CRC1 = 0x12345678;//校驗碼
motor_data.duoji_count = MOTOR_NUM-1;
temp = motor_data.filecount;
SpiFlashEraseSector(CMD_FLASH_ADDR >> 4);//擦除以前存儲的信息
SpiFlashWrite((char *)&motor_data,CMD_FLASH_ADDR<<WRITE_BIT_DEPTH,sizeof(motor_data)); //寫入flash
ReadMoterInfor();
if (temp != motor_data.filecount)
{
error |= ERROR_FLASH_WRITE;
}
else
{
error &= ~ERROR_FLASH_WRITE;
}
}
void WriteOneCmdInfor(unsigned int addr)
{
uchar temp = 0;
temp = motor_one_cmd.end;
if (((((unsigned long)addr)<<4) + FILE_FLASH_ADDR) % 16 == 0)
SpiFlashEraseSector(((((unsigned long)addr)<<4) + FILE_FLASH_ADDR) >> 4);//擦除以前存儲的信息
SpiFlashWrite((char *)&motor_one_cmd,((((unsigned long)addr)<<4) + FILE_FLASH_ADDR)<<WRITE_BIT_DEPTH,sizeof(motor_one_cmd)); //寫入flash
ReadOneCmdInfor(addr);
if (temp != motor_one_cmd.end)
{
error |= ERROR_FLASH_WRITE1;
}
else
{
error &= ~ERROR_FLASH_WRITE1;
}
}
/***************************************************************************************************************
函 數 名:獲取一串舵機的控制字符串
功能描述:處理從flash讀取的舵機控制字符串處理
輸入參數:無
返 回 值:無
備 注:
****************************************************************************************************************/
void GetOneMotorCMD()
{
#if DEBUG
uchar buf[20] = {0};
#endif
if (flag_stop_download)//接收到了上位機的停止下載的命令
{
flag_download = 0;//清楚下載狀態標志位
flag_stop_download = 0;
flag_read = 0;
if (motor_data.filecount < MAX_SUPPORT_FILE_SAVE)
{
updata_file_list();
motor_data.sum = motor_one_cmd.end;
motor_data.file_flag[motor_data.filecount] = 1;
motor_one_cmd.cur_file_num = file_last_num + 1;
motor_data.filecount = motor_one_cmd.cur_file_num + 1;
error &= ~MAX_SUPPORT_FILE_SAVE;
#if DEBUG
sprintf(buf,"%d %d\r\n",(uint)motor_data.filecount,(uint)motor_data.file_flag[motor_data.filecount-1]);
UART1_SendStr(buf);
#endif
WriteMoterInfor();
WriteOneCmdInfor(motor_one_cmd.cur_file_num);
updata_file_list();
#if DEBUG
sprintf(buf,"%d %d\r\n",(uint)motor_data.filecount,(uint)motor_data.file_flag[motor_data.filecount-1]);
UART1_SendStr(buf);
#endif
}
else
{
error |= MAX_SUPPORT_FILE_SAVE;
}
if (!(error &(MAX_SUPPORT_FILE_SAVE | ERROR_FLASH_FULL)))
send_mode |= SEND_DOWN_OK;//狀態位置為
}
if (flag_connect)//如果當前跟上位機聯機狀態
{
if (flag_read)//如果上位機讀取flash內存儲的信息
{
if (cur_item.cur_num < motor_one_cmd.end)//判斷是否超過之前存儲的數
{
if ((send_mode & SEND_SEND_FILE))//開始接收到讀取命令需要先發送個start
{
UART1_SendStr("#Start\r\n");
send_mode &= ~SEND_READ_FILE;
}
memset(redata,0,WRITE_SIZE);//清 0
SpiFlashRead(redata,(((long)cur_item.cur_num)<<WRITE_BIT_DEPTH),WRITE_SIZE);//讀取信息
#if DEBUG
sprintf(buf,"%d\r\n",cur_item.cur_num);
UART1_SendStr(buf);
#endif
UART1_SendStr(redata);//發送
cur_item.cur_num++;
}
else//否則
{
if (cur_item.cur_num > 0)
UART1_SendStr("#End\r\n");//發送結束字符串
flag_read = 0;
}
send_mode = 0;//請 0
}
if (flag_online_run)
{
if ((send_mode & SEND_CC) != 0 || cur_item.cur_num == motor_one_cmd.start)//如果當前需要更新舵機命令
{
if (cur_item.tuoji_count > 0)//脫機次數沒結束
{
if (cur_item.cur_num < motor_one_cmd.end)//判斷是否讀取結束
{
SpiFlashRead(redata,((long)cur_item.cur_num)<<WRITE_BIT_DEPTH,WRITE_SIZE);//讀取命令
flag_RecFul = 1;//標志位為1,
cur_item.cur_num++;//
}
else//執行玩一遍
{
cur_item.cur_num = motor_one_cmd.start;
cur_item.tuoji_count--;//減一
}
}
else//執行完成
{
flag_online_run = 0;
if (flag_connect_run)//如果上位機選擇執行的功能,需要發送 AGF作為結束
{
UART1_SendStr("#AGF\r\n");
flag_connect_run = 0;
}
}
//讀取數據
}
}
}
else//脫機
{
if (file_list_count < 0)
{
return;
}
if (cur_item.tuoji_count > 0)
{
if ((send_mode & SEND_CC) != 0 || cur_item.cur_num == motor_one_cmd.start)//如果當前需要更新舵機命令
{
if (cur_item.cur_num < motor_one_cmd.end)//判斷是否讀取結束
{
SpiFlashRead(redata,((long)cur_item.cur_num)<<WRITE_BIT_DEPTH,WRITE_SIZE);//讀取命令
flag_RecFul = 1;//標志位為1,
cur_item.cur_num++;//
}
else//執行玩一遍
{
cur_item.cur_num = motor_one_cmd.start;
cur_item.tuoji_count--;//減一
}
//讀取數據
}
}
else
{
ReadOneCmdInfor(file_list[cur_item.file_num]);
file_list_count--;
cur_item.file_num++;
}
}
}
/***************************************************************************************************************
函 數 名:發送串口狀態信息
功能描述:根據狀態標志位發送相應的信息
輸入參數:無
返 回 值:無
備 注:
****************************************************************************************************************/
void SendUartState()
{
uchar buf[40] = {0};
uchar read_motor_num = 0;
uint i = 0;
static int count = 0;
if (send_mode)//如果有狀態需要發送
{
if (send_mode & SEND_A) //發送A
{
UART1_SendOneChar('A');
send_mode &= ~SEND_A;//清狀態
}
if (send_mode & SEND_CC) //發送CC
{
UART1_SendStr("#CC\r\n");
send_mode &= ~SEND_CC;
}
if (send_mode & SEND_DOWN_OK)//發送下載ok的狀態字符串
{
sprintf(buf,"#Down+OK+%d\r\n",(int)motor_data.filecount-1);
UART1_SendStr(buf);
send_mode &= ~SEND_DOWN_OK;
#if DEBUG
sprintf(buf,"%d\r\n",(uint)motor_data.filecount);
UART1_SendStr(buf);
#endif
}
if (send_mode & SEND_START_OK)//發送連接時候的字符串
{
UART1_SendStr("#Veri+UART+OK+20160906+176\r\n");
send_mode &= ~SEND_START_OK;
}
if (send_mode & SEND_READ_FILE)//發送讀取文件的時候字符串
{
if (motor_data.filecount > 0)//如果保存的有舵機命令
{
//#Name:1.txt--Size:48--Name:2.txt--Size:190--Name:desktop.ini--Size:531--
UART1_SendStr("#");//發送
for (i = 0; i < motor_data.filecount;i++)
{
if (motor_data.file_flag[i] == 1)
{
ReadOneCmdInfor(i);
if (motor_one_cmd.end - motor_one_cmd.start <= 0)
{
motor_data.file_flag[i] = 0;
WriteMoterInfor();
#if DEBUG
sprintf(buf,"E=%d S=%d",motor_one_cmd.end, motor_one_cmd.start);
#endif
}
else
{
sprintf(buf,"Name:%d.txt--Size:%d--",i,motor_one_cmd.end - motor_one_cmd.start);//獲取命令個數
UART1_SendStr(buf);//發送
}
}
}
UART1_SendStr("\r\n");
}
else
{
sprintf(buf,"#\r\n",motor_data.sum);
UART1_SendStr(buf);
}
send_mode &= ~SEND_READ_FILE;
}
if (send_mode & SEND_SET_OFFLINE_OK)//設置脫機運行次數
{
WriteOneCmdInfor(motor_one_cmd.cur_file_num);//保存
UART1_SendStr("#Enable+OK...\r\n");
send_mode &= ~SEND_SET_OFFLINE_OK;
}
if (send_mode & SEND_SET_DISABLEOFFLINE_OK)//禁止脫機運行
{
for (i = 0; i < motor_data.filecount;i++)
{
if (motor_data.file_flag[i] == 1)
{
ReadOneCmdInfor(i);
motor_one_cmd.tuoji_count = 0;
WriteOneCmdInfor(i);
}
}
WriteMoterInfor();
UART1_SendStr("#Disable+OK...\r\n");
send_mode &= ~SEND_SET_DISABLEOFFLINE_OK;
}
if (send_mode & SEND_SET_ONLINE_OK)//發送聯機運行狀態
{
UART1_SendStr("#OK\r\n");
sprintf(buf,"#%dGC%d\r\n",cur_item.file_num,tuoji_count);
UART1_SendStr(buf);
UART1_SendStr("#LP=0\r\n");
send_mode &= ~SEND_SET_ONLINE_OK;
flag_connect_run = 1;
}
if (send_mode & SEND_SET_DELETE_ONE_FILE_OK)//發送刪除文件命令
{
//cur_item.tuoji_count = 0;
if (cur_item.delete_num < motor_data.filecount)
{
motor_data.file_flag[cur_item.delete_num] = 0;
WriteMoterInfor();
updata_file_list();
if (cur_item.delete_num == motor_data.filecount-1)
{
motor_data.filecount = file_last_num + 1;
if (file_last_num == -1)
{
motor_data.sum = 0;
}
else
{
ReadOneCmdInfor(file_last_num);
motor_data.sum = motor_one_cmd.end;
motor_data.sum = (((long int)(motor_data.sum) >>4)<<4) + (1<<4);
}
WriteMoterInfor();
}
updata_file_list();
UART1_SendStr("#FDel+OK\r\n");
}
send_mode &= ~SEND_SET_DELETE_ONE_FILE_OK;
}
if (send_mode & SEND_SET_DELETE_ALL_FILE_OK)//發送擦除所有文件的命令
{
UART1_SendStr("#Format+Start\r\n");
SpiFlashEraseChip();
cur_item.tuoji_count = 0;
motor_data.sum = 0;
motor_data.filecount = 0;
memset(motor_data.file_flag,0,sizeof(motor_data.file_flag));
WriteMoterInfor();
UART1_SendStr("#Format+OK\r\n");
send_mode &= ~SEND_SET_DELETE_ALL_FILE_OK;
updata_file_list();
}
if (send_mode & SEND_SET_PS2_OK)
{
UART1_SendStr("#PS2+OK...\r\n");
send_mode &= ~SEND_SET_PS2_OK;
}
#define MATHION_HAND_NUM 20
if (send_mode & SEND_SET_READ_UART_MOTOR_ANGLE)
{
if (cur_item.read_num < MATHION_HAND_NUM)
{
if (flag_uart2_rev)
{
read_motor_num = atoi(uart2_buf + 1);
if (read_motor_num == cur_item.read_num)
{
i = atoi(uart2_buf+5);
sprintf(uart2_buf,"#%dP%d",(int)read_motor_num,i);
UART1_SendStr(uart2_buf);
cur_item.read_num++;
buf[0] = '#';
buf[1] = cur_item.read_num / 100 % 10 + 0x30;
buf[2] = cur_item.read_num / 10 % 10 + 0x30;
buf[3] = cur_item.read_num % 10 + 0x30;
buf[4] = 'P';buf[5] = 'R';buf[6] = 'A';buf[7] = 'D';buf[8] = '\r';buf[9] = '\n';
UART2_SendStr(buf);
}
flag_uart2_rev = 0;
count = 0;
}
else
{
count++;
if (count >= 10)
{
cur_item.read_num++;
buf[0] = '#';
buf[1] = cur_item.read_num / 100 % 10 + 0x30;
buf[2] = cur_item.read_num / 10 % 10 + 0x30;
buf[3] = cur_item.read_num % 10 + 0x30;
buf[4] = 'P';buf[5] = 'R';buf[6] = 'A';buf[7] = 'D';buf[8] = '\r';buf[9] = '\n';
UART2_SendStr(buf);
flag_uart2_rev = 0;
flag_uart2_rev_time_out = 0;
count = 0;
}
}
}
else
{
send_mode &= ~SEND_SET_READ_UART_MOTOR_ANGLE;
cur_item.read_num= 0;
UART1_SendStr("\r\n");
}
}
}
if (send_mode & SEND_SET_SET_UART_MOTOR_PULK)
{
if (cur_item.pulk_num < MATHION_HAND_NUM)
{
count++;
if (count >= 20)
{
sprintf(uart2_buf,"#%dPULK\r\n",(int)cur_item.pulk_num);
UART2_SendStr(uart2_buf);
#if DEBUG
UART1_SendStr(uart2_buf);
#endif
cur_item.pulk_num++;
count = 0;
}
}
else
{
send_mode &= ~SEND_SET_SET_UART_MOTOR_PULK;
}
}
if (send_mode & SEND_SET_SET_UART_MOTOR_ANGLE)
{
if (cur_item.pulk_num < MATHION_HAND_NUM)
{
count++;
if (count >= 5)
{
sprintf(uart2_buf,"#%dPMOD%d\r\n",(int)cur_item.pulk_num,(int)cur_item.angle_mode);
UART2_SendStr(uart2_buf);
#if DEBUG
UART1_SendStr(uart2_buf);
#endif
cur_item.pulk_num++;
count = 0;
}
}
else
{
sprintf(buf,"#255PMOD%d+0K...\r\n",(int)cur_item.angle_mode);
UART1_SendStr(buf);
send_mode &= ~SEND_SET_SET_UART_MOTOR_ANGLE;
flag_uart2_rev = 0;
}
}
if (send_mode & SEND_SET_BEEP_ON)
{
ReadMoterInfor();
motor_data.beep_mode = 1;
beep_mode = 1;
WriteMoterInfor();
UART1_SendStr("#FMQENABLE+OK...\r\n");
send_mode &= ~SEND_SET_BEEP_ON;
}
if (send_mode & SEND_SET_BEEP_OFF)
{
ReadMoterInfor();
motor_data.beep_mode = 0;
beep_mode = 0;
WriteMoterInfor();
UART1_SendStr("#FMQDISABLE+OK...\r\n");
send_mode &= ~SEND_SET_BEEP_OFF;
}
}
/***************************************************************************************************************
函 數 名:作業初位置,末尾置更新函數
功能描述:從緩存中取一個新的目標位置替換原來的目標位置,原來的目標位置變為新的初位置,一次更替
:有效的數據是插補增量,和插補次數,知道這兩個量,和當前初位置即可
備 注: 先進先出,循環訪問
****************************************************************************************************************/
void change(void)
{
uchar s;
if(line>0) //緩存中有數據
{
line--; //執行一行
if(line<5) //緩存允許放入新的數據
flag_in=1;
point_now++; //取數位置更新
point_aim++;
if(point_aim==7)
point_aim=0;
if(point_now==7)
point_now=0;
n=pos[point_aim][0]*4/5; //計算新的插補次數
for(s=1;s<MOTOR_NUM;s++) //計算新的插補增量
{
if(pos[point_aim][s]>pos[point_now][s])
{
dp=pos[point_aim][s]-pos[point_now][s];
dp0[s]=dp/n;
}
if(pos[point_aim][s]<=pos[point_now][s])
{
dp=pos[point_now][s]-pos[point_aim][s];
dp0[s]=dp/n;
dp0[s]=-dp0[s];
}
}
m=0; //m清0
flag_stop=0; //產生了新的目標位置,停止標志清零
}
else //沒有緩存數據,即line==0
{
flag_out=0; //緩存中沒有數據
}
}
/***************************************************************************************************************
函 數 名:vpwm()
功能描述:數據插補,插補時間間隔為20/12ms,由timer0控制,使舵機平滑實現速度控制
:另一個功能是執行完一行后去更新下一行數據,即調用change()
備 注:
****************************************************************************************************************/
void vpwm(void)
{
uchar j=0;
uchar how=0;
static uchar flag_how;
static uchar flag_Tover;
if(flag_stop==1) //一行作業全部完成
{
if(flag_out==1) //緩沖數組中有數據
{
change(); //更新行
}
}
else //不是一行數據全部完成,處于中間插補階段
{
m++; //用來累加插補過的次數
if(m==n) //n是本行作業要插補的總次數
{
flag_Tover=1; //一行數據的執行時間已經完成
send_mode |= SEND_CC;
}
for(j=1;j<MOTOR_NUM;j++)
{
if(abs(pwm[j]-pos[point_aim][j])<5)
{ //檢測靠近終點位置
how++; //是,則累加一個
pwm[j]=pos[point_aim][j];//并且直接過度到終點位置
}
else //不靠近終點,繼續插補
pwm[j]=pos[point_now][j]+m*dp0[j];
}
//UART_Put_Inf("pwm",pwm[1]);
if(how==MOTOR_NUM-1)
flag_how=1; //16個舵機都到達終點
how=0;
if((flag_Tover==1)&&(flag_how==1))
{ //從插補次數,和脈寬寬度兩方面都到達終點,本作業行完成
flag_Tover=0;
flag_how=0;
flag_stop=1;
}
}
return;
}
復制代碼
作者:
噻籮籮籮哩噻
時間:
2017-5-5 20:20
點個贊!
作者:
cd556688crg
時間:
2017-8-15 14:03
kankan 看看看 學習學習!!謝謝!!
作者:
981737652
時間:
2017-10-25 13:01
請問樓主用的是單片機控制舵機控制板嗎
作者:
小身體大智慧
時間:
2018-3-9 22:09
學習學習
作者:
小身體大智慧
時間:
2018-3-9 23:04
單用單片機可以嗎不用其他的東西?
作者:
cuiyb
時間:
2018-8-8 15:12
新來初到,能下載嗎
作者:
Dong東
時間:
2018-8-27 10:37
你好,
只有程序嗎?
作者:
蒙面可達鴨
時間:
2018-9-15 20:35
你好,請問這是用中斷輸出pwm控制的嗎,怎么實現同時控制幾個舵機啊。聽說程序模擬pwm波誤差大
作者:
fsadsa
時間:
2018-11-11 14:45
學習下 看看看 學習學習!!謝謝!!
作者:
18986405238
時間:
2019-9-24 23:32
只用單片機么?
作者:
mdx111
時間:
2019-11-20 16:51
請問 16路舵機是什么意思?是16個舵機嗎
作者:
不負時光@
時間:
2020-1-7 20:45
感謝分享
作者:
lulgs
時間:
2020-1-17 12:25
舵機用單片機直接驅動?
作者:
老婆當家
時間:
2020-5-14 12:53
不錯 果斷收藏學習
作者:
aktuan007
時間:
2021-1-21 22:07
作者好像都沒有回帖啊
作者:
zxqy
時間:
2021-9-7 10:58
你好,有沒有電路圖
作者:
Secret丶
時間:
2022-1-9 17:29
這是實現什么功能呢?
作者:
睜眼看世界1
時間:
2022-3-29 22:54
您好樓主 您的機械臂抓取物體是靠什么識別的
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
欧美a v在线
|
嫩草影院网址
|
国产精品久久久久久久毛片
|
国产精选一区
|
欧美男人天堂
|
色婷婷久久久久swag精品
|
天天干天天干
|
欧美激情久久久
|
国产91在线 | 亚洲
|
久久手机在线视频
|
欧美成人h版在线观看
|
欧美一区二区三区在线观看视频
|
亚洲97
|
一区二区三区视频在线
|
在线观看中文字幕亚洲
|
免费国产一区二区视频
|
日韩一级一区
|
国产日韩欧美91
|
午夜免费电影院
|
精品欧美乱码久久久久久1区2区
|
永久免费视频
|
中文在线视频
|
久久久久中文字幕
|
成人午夜网站
|
成人欧美一区二区三区黑人孕妇
|
免费成人高清在线视频
|
久久国产精品无码网站
|
成人精品一区二区三区中文字幕
|
国产精品久久久久久久岛一牛影视
|
精品久久久一区二区
|
亚洲国产精品久久久久
|
在线观看国产三级
|
中文字幕人成人
|
婷婷在线免费
|
午夜国产一级
|
欧美激情视频网站
|
日本国产精品视频
|
成人精品一区二区
|
羞羞网站在线观看
|
九九热精品在线视频
|
www.天天干.com
|