写在前面

下面是购物机器人的底盘子系统调试方案

那么这篇博客呢就来为大家分享一下机器人是如何稳定计算自己所经过的白色交叉点的数量的。

基本方案

在我的机器人底下的正中间有2个光电传感器,示意图如下

首先来介绍一下为什么购物机器人要数白色交叉点吧,因为购物机器人在接收树莓派指令的时候会接收运动方向和运动格数,在前进或者后退的直走类过程中,购物机器人接收到要走的格数是怎么确定的呢?就是通过数白色交叉点的个数。
举例子来说,假设树莓派让购物机器人前进3格,那么购物机器人就会一直按照前进的速度控制和方向控制来运动,当购物机器人数到了3个白色交叉点的时候,购物机器人就会停车。因此数白色交叉点非常的重要,他保证了购物机器人的底盘子系统能稳定准确的完成上层树莓派指派给他的运动任务。

基本思路分析

在购物机器人底盘下面有2颗光电传感器,当光电传感器感知到白线的时候引脚电平会拉低,也就是低电位(也就是0),反之,当光电传感器感知到黑色背景的时候引脚电平会拉高,也就是高电位(也就是1),因此我写了这么一个逻辑来判断购物机器人是否感知到了白色交叉点,我底下的光电传感器连续判断到2次白线才算是感知白线了,而且2个光电传感器全都感知到黑色背景之后才算是离开了一个白色交叉点

//M_R_Pin是底下右边的光电传感器,M_L_Pin是底下左边的光电传感器
#define mid_getwhite  ((0 == HAL_GPIO_ReadPin(M_R_GPIO_Port,M_R_Pin)) || (0 == HAL_GPIO_ReadPin(M_L_GPIO_Port,M_L_Pin)))
switch(mid_sta){
    case 0:
        if(mid_getwhite){//
            mid_sta = 1;
        }
        break;
    case 1:
        if(mid_getwhite){
            mid_sta = 2;
            xSemaphoreTake(crossMutexSemaphore,portMAX_DELAY);                    
            mid_cnt++;
            xSemaphoreGive(crossMutexSemaphore);
        }else{
            mid_sta = 0;
        }
        break;

    case 2:
        if((0 != HAL_GPIO_ReadPin(M_R_GPIO_Port,M_R_Pin)) && (0 != HAL_GPIO_ReadPin(M_L_GPIO_Port,M_L_Pin))){
            mid_sta = 0;
        }
        break;        
}

请大家注意,我这里将底下2个光电传感器的灯的状态进行了或运算,但是找分析来看,不是应该2个灯都感知到了白线(均呈现低电平)才算是经过了一个白色交叉点吗?不是应该进行与运算吗?这是因为购物机器人也是需要在白色交叉点上转圈的,但是转圈结束之后,底下的2颗光电传感器不一定,或者说很大概率上不能同时踩到白线,我们理想的转圈停车应该是这个效果:

但是因为购物机器人转圈时候的停车条件是前端特定的感应灯感知到了白线,所以不能保证底下的2颗光电传感器同时踩线,因此其转圈结束之后的位置可能是这样的:

也可能是这样的:

购物机器人转圈的时候是处于一个盲转的状态,配好整辆车子的重心,让4个轮子的对角承重差不太多,再给购物机器人4个轮子一样的速度,购物机器人就能实现原地转圈了。但是这样难免出现上述这种转圈结束之后底下的2个光电传感器不全在白线上的情况,那么这样会导致什么问题呢?
如上面左转圈结束之后所示,假如说这次转圈结束之后需要购物机器人前进1格,那么购物机器人往前走一点点之后,购物车底下的光电传感器就会感知到白线了,那么他就会认为自己走过了一格完成任务了,但是实际上他并没有走过一格,这样就直接影响到了全图的运动规划

问题解决

仔细分析一下上面的问题,我们就可以发现主要是转圈之后走直线会有误判的问题,因此我想了一个办法来解决这个问题,其实可以发现,在购物机器人前进一格的过程中,在底下光电传感器感知到白线之前,前端的光电传感器必先会感知到白线,因此我就把前端的光电传感器接触到白线当成数白色交叉点的必要条件,因为当购物机器人前端的光电传感器接触到了白线之后,底下的光电传感器肯定已经离开了上一个白色交叉点的附近,这样就不存在误判的问题了

因此前面的数白色交叉点的程序修改为

    switch(mid_sta){
        case 0:
                if(mid_getwhite && pre_calcu_cross == 2){//
                    mid_sta = 1;
                }
                break;
            case 1:
                if(mid_getwhite){
                    mid_sta = 2;
                    xSemaphoreTake(crossMutexSemaphore,portMAX_DELAY);                    
                    mid_cnt++;
                    pre_calcu_cross = 0;
                    xSemaphoreGive(crossMutexSemaphore);
                }else{
                    mid_sta = 0;
                }
                break;

            case 2:
                if((0 != HAL_GPIO_ReadPin(M_R_GPIO_Port,M_R_Pin)) && (0 != HAL_GPIO_ReadPin(M_L_GPIO_Port,M_L_Pin))){
                    mid_sta = 0;
                }
                break;        
        }

其中,pre_calcu_cross的状态是在默认线程进行修改的,当前端光电传感器感知到白线之后,该变量置1,当前端光电传感器离开白线之后,该变量置2那么在pre_calcu_cross =2的情况下,购物机器人才会去数白色的格子,这样就能完全避免转圈对于购物机器人数白色交叉点的影响了

if((uart7Rx[0]&0xff)==0xff){
                        pre_calcu_cross = 1;
                    }

                    if((uart7Rx[0]&0xff)==0x00 && pre_calcu_cross == 1){
                        pre_calcu_cross = 2;
                    }

(づ ̄3 ̄)づ╭❤~一键三连,这次一定(๑•̀ㅂ•́)و✧