第十七篇?rico board双模式小车项目演示(结项帖)
项目所需的硬件也都分别的调试通了,主要用到了Rico Board 的GPIO、外部中断、高精度定时器、定时器,还有额外的一个PWM转DA输出的硬件电路。
整个系统结构如下所示:
上图,也列出来了,是用到的GPIO管脚编号。
对应的驱动,都在我之前的帖子里都能找到。我也上传到了我的github上:iysheng's github。
编写的用户空间的程序如下所示:
- #include
- #include
- #include
- #include
- #include
- #include
- typedef enum
- {
- false,true
- }bool;
- #define PT2262_PATH "/dev/input/event1"
- #define RADAR_PATH "/dev/radar0"
- #define MOTOR_PATH "/dev/motor0"
- #define MOTOR_F 1500
- #define MOTOR_L 1000
- #define MOTOR_R 2000
- #define DIRECTION_NUM 1
- int fd_mada[4],fd_pt2262,fd_radar,fd_motor;
- int motor_f = MOTOR_F;
- int motor_l = MOTOR_L;
- int motor_r = MOTOR_R;
- int direction_num = DIRECTION_NUM+1;
- bool robot_mode = false;
- int wt_mada(int *fd, int *value)
- {
- int i,ret;
- char value_buf[8];
- for(i=0; i value_l) ? motor_r : motor_l;
-
- fail:
- printf("\n**********************************return is %d.\n", ret);
- return ret;
- }
- void paulse(void)
- {
- int mada_value_tmp[4];
- mada_value_tmp[0]=1;mada_value_tmp[1]=1;mada_value_tmp[2]=1;mada_value_tmp[3]=1;
- wt_mada(fd_mada, mada_value_tmp);
-
- }
- int main(int argc,char * * argv)
- {
- char path_tmp[16];
- char length_buf[16];
-
- int ret,i,j,mada_value[4],length;
- struct input_event event;
- ret = open(PT2262_PATH, O_RDWR|O_NONBLOCK);
- if(ret < 0)
- goto fail1;
- else
- fd_pt2262 = ret;
- ret = open(MOTOR_PATH, O_RDWR);
- if(ret < 0)
- goto fail2;
- else
- fd_motor = ret;
- ret = open(RADAR_PATH, O_RDWR);
- if(ret < 0)
- goto fail3;
- else
- fd_radar= ret;
-
- for(i=0;i<4;i++)
- {
- sprintf(path_tmp, "/dev/mada%d", i);
- ret = open(path_tmp, O_RDWR);
- if(ret < 0)
- goto fail4;
- fd_mada[i] = ret;
- }
- while(1)
- {
- read(fd_pt2262, &event, sizeof(struct input_event));
- if((event.value == 1)&&(event.type == EV_KEY)&&(event.code == 0x0f))
- {
- robot_mode = !robot_mode;//切换工作模式
- }
- if((event.value == 1)&&(event.type == EV_KEY)&&(robot_mode == true))
- {
- wt_motor(fd_motor,MOTOR_F);
- switch(event.code)
- {
- case 0x10:
- mada_value[0]=1;mada_value[1]=999;mada_value[2]=1;mada_value[3]=999;break;
- case 0x12:
- mada_value[0]=1;mada_value[1]=999;mada_value[2]=999;mada_value[3]=1;break;
- case 0x13:
- mada_value[0]=999;mada_value[1]=1;mada_value[2]=1;mada_value[3]=999;break;
- case 0x11:
- mada_value[0]=1;mada_value[1]=1;mada_value[2]=1;mada_value[3]=1;break;
- default:
- break;
- }
- wt_mada(fd_mada, mada_value);
- }
- else if(robot_mode == false)
- {
- memset(length_buf,0,sizeof(length_buf));
- ret = read(fd_radar,length_buf,sizeof(length_buf));
- if(ret < 0)
- {
- printf("read radar failed.\n");
- goto fail4;
- }
- //printf("read length is %s.\n",length_buf);
- length = atoi(length_buf);
- if(length < 50)
- {
- ret = get_direction();
- if(ret == motor_r)
- {
- mada_value[0]=999;mada_value[1]=1;mada_value[2]=1;mada_value[3]=999;wt_mada(fd_mada, mada_value);
- }
- else if(ret == motor_l)
- {
- mada_value[0]=1;mada_value[1]=999;mada_value[2]=999;mada_value[3]=1;wt_mada(fd_mada, mada_value);
- }
- else
- {
- printf("valid get_direction return.\n");
- }
- sleep(1);
- }
- else
- {
- wt_motor(fd_motor,MOTOR_F);
- mada_value[0]=1;mada_value[1]=999;mada_value[2]=1;mada_value[3]=999;wt_mada(fd_mada, mada_value);
- }
- }
- printf("robot_mode is %d.\n", robot_mode);
- }
-
- fail4:
- printf("fd_radar err.\n");
- close(fd_radar);
- for(j=0; j<i; j++)
- {
- close(fd_mada[j]);
- }
- fail3:
- printf("fd_motor err.\n");
- close(fd_motor);
- fail2:
- printf("fd_pt2262 err.\n");
- close(fd_pt2262);
- fail1:
- return ret;
- }
对应的按键的功能呢个如下:
其中,前进、停止、左转、右转都是在遥控模式下使用的,电视键起到遥控模式和自主避障两种模式之间的切换。自主避障模式下,前方的舵机会自动旋转带动雷达,探测两侧到障碍物的距离信息,完成避障。
对应的,我录制了模拟的演示的视频(包含两种模式,极其切换过程):
http://v.youku.com/v_show/id_XMTgzNjY5OTU3Ng==.html
以及两种模式下的运动视频(还是接的5v电源,所以只是在我的桌子上运动了下,权当作演示了):
自主导航避障模式:
http://v.youku.com/v_show/id_XMTgzNzM4OTIyNA==.html
遥控模式:
http://v.youku.com/v_show/id_XMTg0MTE3NjM2NA==.html
总结一下这次试用,在linux驱动方面,对于一个架构有了进一步的了解,知道了总线、设备和驱动的三部分;对于uboot我学习到了如何添加自定义命令的层次;对于kernel,我学到了如何固化自己的驱动到内核中。
干货 get
谢谢支持。
必须支持, 原创高手来袭~
lemon,uboot,我修改了对应的start.S,让LED熄灭,但是led却还在亮着,可能是什么问题啊?
start.S 修改了, 建议你看一下反汇编代码,确认一下对应的代码是否已经改变了; 另外就是查看一下LED对应的寄存器,是不是看错了。 一般来说, start.S编译之后的start.o 在链接中,应该是最先开始的。
应该是改变了,因为,修改后,uboot从SD卡启动,串口都没有输出了,取消我修改的部分,串口就能正常输出。uboot编译后生成了MLO uboot.img这种形式有什么特殊要注意的地方吗?
这个具体生成的文件,你要看看 rico的芯片是什么, S5PV210生成的是uboot.bin
AM437X,官方的生成的就是MLO和uboot.img
那就应该没有错的; 加入你的代码,串口就没有输出, 这个着实奇怪了,你加一个打印字符的语句看看。
我准备换一个别的gpio试一下,不用板载的led。
恩, 这个主意也是极好的。
再uboot的的start.S文件直接修改,使用用别的gpio配置,还是没有成功。
你重新解压一下uboot的压缩包,重新修改试试看。
不太懂啊!