简易暴力推图机械臂制作

    最近在玩一款手游,玩到最后发现整个人就像个机器一样就是不停地点手机屏幕,有时候推图不过还要不停地点同一个位置,非常地sb。于是就想有没有个什么办法可以让它自动推图。在研究了一下游戏的网络传输协议发现是加密的之后,软件层面破解估计是没什么戏,于是另辟蹊径,从硬件入手,做个简易的机械臂模拟人的动作,去点手机屏幕。

    要完成这个目标需要解决的难题有两个:一是目前普遍使用的电容屏要手指点在上面才会有反应,带手套或者用手拿笔之类的绝缘体去点是不行的;二就是机械臂的制作了。

    首先分析第一个问题。现在市场上有电容屏手套卖,但是原理却是使用导电橡胶把外面跟手指连接起来,最终还是类似于手直接拿个导体去点屏幕,这样子我试过是行的,但是我总不能一直就握着机械臂吧。。。。经过对电容屏的原理分析知道其实只要点在屏幕上的导体连接了大地,导体跟屏幕里面的电极形成一个电容,这个电容就会改变屏幕里面的高频电流,从而被里面的电路检测到。所以要让屏幕能被点到,有两个关键点:一是靠近屏幕部分要是个导体,二是这个导体要接地。但是问题又来了,如何才能接地呢?其实地这个概念呢,也是个相对的东西。只要是足够大的导体,都可以当成地,比如说人体就可以当成一个地了,所以,把机械臂连接到水龙头、金属栏杆、金属窗这些大导体上就可以了,亲测有效!!!

    然后是第二个问题了,由于没打算做太复杂的,一个自由度就好,于是一个舵机加一个控制器再外加若干固定支架、电线之类的东西就可以了,下面就开工。

1.原材料与工具

 原材料:51单片机开发板(带串口线或者usb转串口线)一套,中性笔盒一个(或者其他可以用来做支架的东西),用完墨水的中性笔芯一支,塑料夹子一个,耳机线一条,9g舵机一个,电线若干。

工具:电脑(安装有开发51单片机所需的软件和驱动),电烙铁(包括焊锡、松香等)、剪力、小刀、透明胶等。

原材料除了舵机其他都在下面这图里了:

左上角是我以前做的一个单片机最小系统板,加上个usb转ttl就可以拿来当开发板用了,右上是一个刚用完的一盒笔的盒子,就拿来当底座,笔芯跟夹子是用来做手臂的,耳机线嘛,就用来连接手臂跟地,因为它够柔软够长,但是缺点是就是有点难焊接。

原材料

2.机械臂制作

    把夹子拆开,取一半作为机械臂的手指,用小刀把笔芯有墨水的部分切掉,并用钳子把一头压扁,把夹子的一边套在笔芯上,并用透明胶绑好,这个手就差不多做好了;然后再把笔芯另一头绑在舵机的转子上,整个手臂的机械结构就完成了;最后把舵机固定在笔盒上,结果如下图所示:



3.手指尖制作

    虽然这东西是机械臂中一个不起眼的部分,但是去是整个系统的精华所在,我花在上面的时间不比编程少多少。理论上可以拿一个金属片贴在夹子尖上的,我一开始就是这么干的,但是它会把手机屏幕戳得啪啪响,虽然短时间看不出屏幕不什么操作,但是心里还是有点不太踏实,于是把旧键盘上抠了个软胶垫下来,贴在夹子尖上,再把耳机线的细线全部拆开,均匀分布在软垫下方,如下图所示(当然如果有导电橡胶就更好办了):


4.电路连接

    其实这个手臂电路应该是非常简单的,舵机一共有三跟线,黑色的接到开发板的GND,红色接到VCC,白色的是信号线,用来控制舵机转的角度,输入的是20ms周期、高电平从5ms到15ms之间的方波,这里我把它接到了单片机的P3.3上。另外说一句,由于把机械臂的动作写死在程序里会比较麻烦,所以我直接通过串口上输出参数来控制舵机的转动,从而通过电脑来控制手臂的动作。

5.编程

    单片机工程文件里共有两个c文件:duoji.c和series.c,其中duoji.c是控制T0产生20ms方波,由于以前写了个舵机的demo用到了T1来做定时,这里只是简单注释掉,而没有删除(串口要用到T1,所以这里肯定不能用),代码如下:

#include<reg52.h>
#include<string.h>

extern void serial_to_pc(unsigned char data_send[]);
extern void init_serial();
extern unsigned char serial_buf[33]; //接收缓存
extern bit flag_rec;   //中断接收完成标志

sbit duoji=P3^3;
//sbit test=P1^1;
//方波高电平和低电平的持续时间计数
unsigned int count_h=0;
unsigned int count_l=0;
//长计时计数变量
unsigned int count=0;
//方波高电平时间,范围是5-25,分别对应-90度到90度(对于180度的舵机来说)
unsigned int space=15;
unsigned int tmp=0;
//存储舵机位置的数组
//#define MAX_LEN 10
//unsigned int pos[]={10,12,14,14,14,14,14,14,14,14};
//unsigned int index=0;
//串口发送数据缓存
unsigned char send_buf[20];
void main()
{
	duoji=0;
	EA=1;
	ET0=1;
//	ET1=1;

	//TMOD[3:0]=0x02,timer 0 in mod 2: 8 bits auto reload
	TMOD &=	0xF0;
	TMOD |= 0x02;
	TH0=0x9c;
	TL0=0x9c;//0.1ms(12MHz),mod2
/*
	//TMOD[7:4]=0x01,timer 1 in mod 1: 16 bits
	TMOD &=	0x0F;
	TMOD |= 0x10;
	TH1=0x3c;
	TL1=0xb0;//50ms(12MHz),mod1
*/
	TR0=1;
//	TR1=1;
	init_serial();
	for(;;){
	 	if(flag_rec){
			flag_rec=0;
			serial_to_pc(serial_buf);
			if(!memcmp(serial_buf,"T=",2) && serial_buf[4]=='m' && serial_buf[5]=='s'){
					tmp = (serial_buf[2]-'0')*10+(serial_buf[3]-'0');
					if(tmp>=6 && tmp <= 26)
						space = tmp;
					strcpy(send_buf," space:");
					serial_to_pc(send_buf);
					send_buf[0]='0'+ (space)/10;
					send_buf[1]='0'+ (space)%10;
					send_buf[2]= ' ';
					send_buf[3]= 0;
					serial_to_pc(send_buf);
			}
		}
	}		
}
void t0() interrupt 1
{
	//TH0=0xf0;
	//TL0=0x0c;
	//**************
	//test
	//TH0=0xed;
	//TL0=0x08;
	//**************
	if(duoji==0)
	{
		count_l++;
		if(count_l>=200-space)
		{
			count_l=0;
			duoji=1;
		}
	}
	else
	{
		count_h++;
		if(count_h>=space)
		{
			count_h=0;
			duoji=0;
		}			
	}	
}
/*
void t1() interrupt 3
{
	TH1=0x3c;
	TL1=0xb0;
	count++;	
	if(count>=20)
	{
		count=1;
		test=~test;

		index++;
		if(index >= 5)
			index = 0;
		space=pos[index];
	}
}
 */

文件series.c也是从以前写的一个STC单片机免断电下载程序里改过来的,代码如下:

/*****************************************************************************
extern void serial_to_pc(unsigned char data_send[]);
extern void init_serial();
extern unsigned char serial_buf[33]; //接收缓存
extern bit flag_rec;   //中断接收完成标志
*****************************************************************************/
#include<reg52.h>

//串口方式1时,SMOD=0,定时器1模式2时的重装值
#define T1_RESTORE_V 0xF3//11.059M : 9.6k(0xFD),4.8k(0xFA),2.4k(0xF4),1.2k(0xE8)
						 //12.000M : 2.4k(0xF3),1.2k(0xE6),600(0xCC),300(0x98)

#define Self_Define_ISP_Download_Command 0x22 //自定义下载命令
sfr IAP_CONTR=0xe7;		//ISP控制寄存器
unsigned char serial_buf[10]={'-'};    //接收缓存
unsigned char ptr_t;  //接收计数器
bit flag_rec;  //中断接收完成标志

void init_serial()
{
	SM0=0;
	SM1=1;	//方式1
	REN=1;	//允许接收
	//TMOD=0x20; //定时器1在方式2
	TMOD &=	0x0F;
	TMOD |= 0x20;
	TH1=T1_RESTORE_V;
	TL1=T1_RESTORE_V; //2400bit/s
	ES=1;
	EA=1;
	TR1=1;
}

void serial_to_pc(unsigned char data_send[])
{
	unsigned char i;
	ES=0;
	TI=0;
	for(i=0;data_send[i]!=0;i++)
	{
		SBUF=data_send[i];
		while(!TI);
		TI=0; 	
	}
	ES=1;
}

void soft_reset_to_ISP_Monitor(void)
{
	unsigned char j=0;
	unsigned int g=0;
	for(j=0;j<250;j++)
	{
		for(g=0; g<480;g++);
	}
	IAP_CONTR=0x60;
}

void serial_int() interrupt 4
{
	if(RI)
	{
		RI=0;
		if(SBUF==Self_Define_ISP_Download_Command)
		{
			soft_reset_to_ISP_Monitor();
		}
 		else if(SBUF=='#'||ptr_t>9)
		{
			flag_rec=1;
			serial_buf[ptr_t]=0;
			ptr_t=0;
		}
		else
		{
			serial_buf[ptr_t]=SBUF;
			ptr_t++;
		}
	}
}

在STC下载器右边的“文件缓冲区”下面的“自定义下载”选项卡里设置好串口参数并且输入下载命令“22”点击下载就可以不用断电直接下载程序,在调试的时候非常方便,如下图所示:


当程序下载好之后可以用串口助手设置好串口参数,发送类似于“T=16ms#”的命令去控制手臂的位置,其中16是参数,一定要是两位数,这个参数的范围是05-25。当然也可以用串口助手自动按一定的时间间隔发送一组参数,这样子就可以完成特定动作了,如下图所示就是我刷图的指令(右上就是指令,下面是串口配置):




猜你喜欢

转载自blog.csdn.net/zebra2011/article/details/44204827