【DIY】远程手机遥控车 androidbot

  androidbot机器人

              


一、设计初衷:

当过爸爸妈妈的都有类似感受:小孩慢慢长大,学说话,学走路,而自己平时上班太忙,陪小孩的时间自然就少了!为了弥补心中遗憾,很多我认识的朋友中会在自己家里安装WIFI IP camera方便自己随时查看小孩在家是否有哭闹或者做一些不安全的事,而也有很少一部分喜欢DIY的朋友选择了自己动手,我也是其中之一。

二、项目发展历程

尤其是当我女儿在2岁左右的时候,此时才刚好学会说话,走路,我是特别希望自己能多点时间陪伴她,于是这个项目在当时2015.8启动了。

这款安卓手机远程陪伴机器人项目经过了2年的反复改进,目前有三个版本,分别是2015/2016/2017三个版本, 虽然从外观,硬件和软件app上都有很大变动,但都是围绕主要功能来改进的:远程视频陪伴。


三、优势:

    设计之初不完全是为了DIY,我是希望能够做出一款实用便宜易用的产品,所以没有采用常用的DIY开源硬件方案例如arduino,而是选择了价格便宜,功耗极低的蓝牙BT4.0和MCU控制一体TI最新芯片CC2541来做控制方案。当然也相信大家能理解我为什么会选择android手机来做机器人大脑。

 

    项目过程中遇到最大难题是android手机兼容性问题,在APP的开发过程中,这个问题花最多时间和精力才做到今天这种程度,我个人感觉是非常有成就感的。

因为类似项目不止我一个人想做,但最后都因为这个问题而放弃,包括国外2012很火的romo机器人,国内也有不少这样的公司,他们最终都不得不选择苹果的手机或者平板来做。这里面主要是解决了app在没有root权限的情况下待机以后还会长时间不掉线,还可以随时被唤醒。

与WIFI IP camera对比:

1)可以到处跑,因为不需要插着电源线;2)省电,待机长,所以不用担心充电问题。3)监控温湿度声音情况。


四、功能:

 

1)远程视频(android手机+webrtc)

2)蓝牙遥控车(20天待机 BT4.0  CC2541)

3)百度语音识别和聊天(android手机编程)

4)温湿度传感器 (DHT11传感器模块)

5)声音传感器



五、硬件列表

下图是完整的实物零件图,基本上是从淘宝上面淘的(除了控制底板),

2)小车底盘(淘宝上面有非常多的小车底盘卖,自己任选),

3)马达:TT马达3元/个

4)轮子:2元/个

5)锂电池:2200mAH  7.4V   + 充电器  一起30元

1)控制板包括:

 蓝牙模块CC2541:11元

 电机模块:5元

 稳压模块:5元

温湿度传感器:5元

底板:自己设计的,自己也可以用面包板或者飞线来代替,只是可能会比较乱不好看。


自己算算很便宜吧!



六、应用介绍   
   

        CrabRobot是一款小孩陪伴机器人APP, 已经通过小米审核,可以在小米应用商店搜索CrabRobot 

1、两大功能:


1)、移动看家
2)、智能语音聊天

2、其他特点:

1)用手机替代网络摄像头,更智能,更省电;
2)自动应答;
3)查询环境温湿度信息;
4)支持蓝牙玩具遥控车; (移动功能和温湿度查询功能,需要配一款蓝牙玩具遥控车,可待机20天)。

3、使用方法:
1、注册账号,分别在两部手机上各自注册一个账号;
2、添加对方为好友;
3、把其中一部手机放到蓝牙遥控玩具车上;




组装后效果图,个人挺满意的 ^_^:


七、开放资源

https://github.com/luojin012/Android-phone-telepresence-robot

1、开源:控制电路板,结构,控制板软件;app免费使用

2、app接口免费使用,接口开放

这里列举下蓝牙命令接口,

例如通过蓝牙发送命令:


1)  b2;\n

小车以2的速度前行,如果是负数就倒车

2)  t3;\n

小车以3的速度转弯,负数的话就是反方向转弯


温湿度传感器命令:

如果小车控制板上有温湿度传感器,也可以按照下面格式发送数据到APP

DHT:60.2;28.5

60.2是湿度,28.5是温度。


控制板的代码是开源的基于CC251蓝牙模块C51核写的


读取温湿度代码,这里要感谢“甜甜的大香瓜”,在他的基础上修改来的,少走了弯路。

 //******************************************************************************                
    //name:             DHT11_Read_Humiture                
    //introduce:        DHT11的读温湿度函数              
    //parameter:        none          
    //return:           TRUE:读取正确,FALSE:读取错误              
    //author:           甜甜的大香瓜         
    //email:            897503845@qq.com       
    //changetime:       2016.04.11             
    //******************************************************************************   
     void DHT11_Read_Humiture(uint8 *pDHT11_data)     
    {  
        uint8 nHumidity_integer;  
        uint8 nHumidity_decimal;  
        uint8 nTemperature_integer;  
        uint8 nTemperature_decimal;   
        uint8 nChecksum;    
        uint8 nChecksum_count;  
        uint8 nFLAG;  
   //   EA = 0;
        //主机开始信号   
        SET_PIN_OUT;                                //IO口配置为输出  
          
        SET_DATA_PIN;                               //输出高电平  
           
     //  Delay_Us(100000);  
        CLR_DATA_PIN;                               //输出低电平  
            
        Delay_Us(4000);                            //延时至少18MS  
               
        SET_DATA_PIN;                               //输出高电平  
      
        Delay_Us(4);  
           
        //切换到DHT11端发数据  
        SET_PIN_IN;                                 //IO口配置为输入  
         
        Delay_Us(4);    
             
       if(DATA_PIN == 0) 
        {  
            //DHT11响应                         
           nFLAG = 2;   
            EA = 0;
            while((DATA_PIN == 0) && (nFLAG++));  
              
            nFLAG = 2;  
              
            while((DATA_PIN == 1) && (nFLAG++));   
              
              
            //DHT11读值  
            nHumidity_integer = DHT11_Read_Char();          //湿度高位,整数  
              
            nHumidity_decimal = DHT11_Read_Char();          //湿度低位,小数  
              
            nTemperature_integer = DHT11_Read_Char();       //温度高位,整数  
              
            nTemperature_decimal = DHT11_Read_Char();       //温度低位,小数   
              
            nChecksum = DHT11_Read_Char();                  //校验和   
      
             EA = 1; 
            //结束  
            SET_DATA_PIN;  
              
                  
            //计算校验和  
            nChecksum_count = nHumidity_integer + nHumidity_decimal + nTemperature_integer + nTemperature_decimal;  
              
            //验证数据正确性  
            if(nChecksum == nChecksum_count)  
            {            
                //正确,则将读出的值保存到全局变量  
                pDHT11_data[0] = nHumidity_integer;  
                  
                pDHT11_data[1] = nHumidity_decimal;  
                  
                pDHT11_data[2] = nTemperature_integer;  
                  
                pDHT11_data[3] = nTemperature_decimal;                
            }  
            else  
            {            
                 //错误,则值全为0  
                pDHT11_data[0] = 0;  
                  
                pDHT11_data[1] = 0;  
                  
                pDHT11_data[2] = 0;  
                  
                pDHT11_data[3] = 0;   
                 EA = 1;       
                return  ;  
            }   
        }  
        else                          
        {                                 
            //错误,则值全为0  
            pDHT11_data[0] = 0;  
                  
            pDHT11_data[1] = 0;  
                  
            pDHT11_data[2] = 0;  
                  
            pDHT11_data[3] = 0;   
             EA = 1;       
            return  ;        
        }  
          EA = 1; 
        return  ;  
    }  
命令接受解析控制,可以看到和上面命令例子 是对应的。
void  car_stop()
{
	motor_Set(motor_A0, 0);
	motor_Set(motor_A1, 0);
	motor_Set(motor_B0, 0);
	motor_Set(motor_B1, 0);
	car.left=car.right=0;
	car.carn=0;
}


/*void motor_Set( uint8 pin_d, uint8 mode )
{
 // 

   // cmd_st.key_timer=0;

  //  PIN_setOutputValue(hKeyPins, pin_d, mode);
	 pin_d=mode;
}
*/
void cmd_pase(char *data_c,int len)
{
 	int i;
	 
	//char *data_c=Receive_CMD[0].receive_buf;

	//memset(RX2_Buffer,0,BUF_LENTH);

			

	for(i=0;i<len;i++)
	{
		if(data_c[i]=='t')		   // turn right or left  
		{
			
			car.right=atoi(data_c+i+1);
                        if(car.right>0)
                          car.right+=2;
                        else
                          car.right-=2;
                        car.left=-car.right;
			//motor_Set(duoji_A, 1);
			douji.x=0; 
			car.carn=0;
			break;
		}
		
		else if(data_c[i]=='b')	   // both motor speed
		{
		 	car.right=car.left=  atoi(data_c+i+1);
			//motor_Set(duoji_A, 1);
			douji.x=0; 
			car.carn=0;
			//if(car.right==2)
			//	car_led = ~car_led;  

			break;
		}
		

			
	}
}

void receing_data(char datar)
{

	if(datar==';')
	{
		Receive_CMD[0].receive_buf[Receive_CMD[0].receive_len++] = 0;	
		Receive_CMD[0].receive_status=2;
		idle_buf++;
		/
		
		cmd_pase(Receive_CMD[0].receive_buf,Receive_CMD[0].receive_len);
		Receive_CMD[0].receive_status=0;
		Receive_CMD[0].receive_len=0;
		
		
	}
	else
	//else  if(Receive_CMD[0].receive_status<2)
	
	{
		Receive_CMD[0].receive_buf[Receive_CMD[0].receive_len++] = datar;	
		Receive_CMD[0].receive_status=1;
		if(Receive_CMD[0].receive_len>max_rebuf) 
			Receive_CMD[0].receive_len=0;

	}

        
}

#if 1


void car_control()
{

 // car_led = (car.left||car.right);  
	car.left_count++;
	if((car.left_count>=8))
	{
		car.left_count=1;
        if(car.left!=1)
        {
          motor_Set(motor_A0, 0);
          motor_Set(motor_A1, 0);
        }
	}

	if(car.left==0)
	{ // stop
		motor_Set(motor_A0, 0);
		motor_Set(motor_A1, 0);
	}	 

	  if(car.left==car.left_count)
		motor_Set(motor_A0, 1);
 		//motor_A0=1;	

	  if(car.left==-car.left_count)
		motor_Set(motor_A1, 1);
 		//motor_A1=1;		



*/

    car.right_count++;	
    if((car.right_count>=8))
	{
		car.right_count=1;
                if(car.right!=1)
                {
                 // car.right=0;
                  motor_Set( motor_B0, 0 );
                  motor_Set( motor_B1, 0 );
                      
		}

	}


        if(car.right==car.right_count)
        {
		motor_Set(motor_B0, 1);
        //car_led = 1;         
        }
 	//	motor_B0=1;		

	  if(car.right==(-car.right_count))
        {
		motor_Set(motor_B1, 1);
              // car_led = 1;   
        }

	  if(car.right==0)
	{ // stop
		motor_Set(motor_B0, 0);
		motor_Set(motor_B1, 0);
	            
	}	 

	
	

	 



}

让我开心的是,隔壁家的男孩比我们家的女儿更喜欢玩;另外有次我把样品拿出去玩时,有个妈妈问有没有开始卖,她也需要一个来照看她家的老人和小孩。

https://item.taobao.com/item.htm?id=552635703115  想自己DIY的伙伴可以联系我,提供3D打印相关外壳及其它硬件!QQ:1074814960







评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值