写在前面

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

在之前的文章里,我已经讲过了光电传感器回传的数据格式以及基本的购物机器人的姿态调整方案,那么在这篇文章里我将分享购物机器人是如何在模式A和模式B的情况下停车的

效果展示

代码讲解

这个函数是一直跑在默认线程里面的,首先来看一下函数调用吧,这个线程是FreeRTOS里面的默认线程,也就是说停车判断是一直在执行的,get_data是数据接收标志位,当嵌入式芯片接收到树莓派发送的命令之后该标志位会置1,底盘子系统完成相应的动作之后就会将该标志位置0,只有当get_data为1的时候,底盘子系统才会执行相应的动作,否则就只会停车在原地

void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */

  /* Infinite loop */
  for(;;){
            SENSOR_Handler();
            SERDEB_Handler();      //get cmd of pi and deal with it
            osDelay(10);

            if(get_data == 1){//每次停车就会等待命令,没有pi的命令不会动

                    if(MOV_MODE == MODE_A)
                        mov_task_A();        
                    else if(MOV_MODE == MODE_B)
                        mov_task_B();        

                    if_finish_work();                             //1 work  0 stop
                    ChangeWheelSpeed();

            }else{
                    stop_task();
                    ChangeWheelSpeed();    
            }
    }
  /* USER CODE END StartDefaultTask */
}

当底盘子系统接收到树莓派发送的指令之后就会执行相应的动作,在每次循环当中,默认线程都会执行if_finish_work()函数,这个函数里面就是我们的停车判断,在停车判断里,程序首先会确认接收到的运动模式MODE_A还是MODE_B,购物车只会在模式A的时候转圈,我只在格点上转圈,因此模式A都是在格点上停车,因为这样转圈结果能稳定很多

模式A时前进后退都是走够树莓派要求的格数就可以停车了,左转和右转都需要前面的光电传感器都感知到黑色背景之后,再由前端光电传感器的特定感知灯去感知白色循迹线停车

模式B时,只有前进后退的状态,后退只需要走相应的格数就可以了,而前进的话就需要进行一个预减速的操作,因此在感知到走了N-1个格子之后购物车就会开始减速,直到前面的光电传感器中间部分全部感知到白色循迹线后就会停车了

void if_finish_work(void)
{        
    if(MOV_MODE == MODE_A){
        switch (MOV_STA){
            case BACK :  //go back
                    if(mid_cnt-cross_sta==STEP){
                        stop_task();
                    }
                    break;
            case RIGHT : //turn right
                    if(((uart7Rx[1]!=0x00)||(uart7Rx[0]!=0x00))&&(all_black!=0x00)){
                        all_black=0x20;
                    }
                    if((uart7Rx[1]==0x00)&&(uart7Rx[0]==0x00)&&(all_black==0x20)){
                        all_black=0x00;
                    }
                    if(((all_black==0x00)&&(((uart7Rx[1])&0x20)==0x20))){
                        stop_task();
                    }
                    break;
            case LEFT : //turn left
                    if(((uart7Rx[1]!=0x00)||(uart7Rx[0]!=0x00))&&(all_black!=0x00)){
                        all_black=0x20;
                    }
                    if((uart7Rx[1]==0x00)&&(uart7Rx[0]==0x00)&&(all_black==0x20)){
                        all_black=0x00;
                    }
                    if(((all_black==0x00)&&((uart7Rx[1])&0x20)==0x20)){
                        stop_task();
                    }
                    break;
            case RUN : //run
                    if(mid_cnt-cross_sta==STEP){       //总共格子数-开始格子数 = 需要走的步数                    
                        stop_task();
                    }
                    break;
            case GET_WALL:
                    break;
        }
    }else if(MOV_MODE == MODE_B){
        switch (MOV_STA){
            case BACK :  //go back
                if(mid_cnt-cross_sta==STEP){
                    stop_task();
                }
                break;
            case RUN : //run
                if(((uart7Rx[0]&0xff)==0xff)&&(mid_cnt-cross_sta==STEP)){       //    
                    stop_task();
                }
                break;
        }
    }

    if(stop_flag == 1){
        printf("HI,finished work!\n");
        printf("%d+%d",cross_sta,mid_cnt);
        stop_flag = 0;
    }
}

在停车的时候,我们需要做的是将速度数组都置0,并且将转圈标志位all_black置为原始值0x01,get_data标志位置0,stop_flag停车标志位置1,以及速度变化时候阶段标志位cut_spd清零

void stop_task(void)
{
        set_spd[0] = set_spd[1] = set_spd[2] = set_spd[3] = 0;
        turn_speed=0;  
        speed=0;  
        all_black=0x01;    
        get_data = 0;    
        stop_flag = 1;
        cut_spd = 0;
        osDelay(5);
}

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