本帖最后由 zhjb1 于 2016-5-26 10:18 编辑
6、小车的控制逻辑 为了简单起见,前进只有一种策略两步:前进,无障碍加速;有障碍,减速产生随机数判断向左[向右],如果连续转弯没有路,转向右转,都没有路就回头前进。 大致流程图如下图:小车的实际I/O口分配:
LCD4个I/O口:D4,D5,D6,D7 电机控制3个口:C5,C6,C7 PWM输出1个口:C4 板载LED闪烁指示1个:C3 ADC采样1个口:B0 测速脉冲测试1个口:E0[100mS中断1次] 1个时钟中断口:A4[完成E0口计脉冲数] UART0占用2个口:A1,A2 由于时间关系,测速已经没有问题;ADC采样也已通过,但这两个功能还没有开发应用,由于中间出差两次,开会1次,累计超过15天,加上设计总不如愿,方案改了好几次,才最后定型,因此先完成蔽障运行。
编程 编程分成以下几个部分: LCD显示控制、IO口功能设置、中断控制、IR测试障碍获取和处理、小车控制运行。 原来预计设计的自动跟踪I/O口已经没有了,只能从取消LCD显示得到的4个I/O口完成运动物体采样和跟踪——看来近期已无时间完成此项了。 6.1、I/O设置 //LCD控制信号 GPIO_QuickInit(res,4,kGPIO_Mode_OPP); GPIO_QuickInit(rs, 5,kGPIO_Mode_OPP); GPIO_QuickInit(sck,6,kGPIO_Mode_OPP); GPIO_QuickInit(sda,7,kGPIO_Mode_OPP); //电机控制信号 GPIO_QuickInit(HW_GPIOC,5,kGPIO_Mode_OPP);//DIR1 GPIO_QuickInit(HW_GPIOC,6,kGPIO_Mode_OPP);//DIR2 GPIO_QuickInit(HW_GPIOC,7,kGPIO_Mode_OPP);//CTRL //3'IR采样I/O口 GPIO_QuickInit(HW_GPIOB,1,kGPIO_Mode_IPU);//ford GPIO_QuickInit(HW_GPIOC,1,kGPIO_Mode_IPU);//left GPIO_QuickInit(HW_GPIOC,2,kGPIO_Mode_IPU);//right //GPIOPORTA4_Interupt_for speed counter||In GPIO Set it GPIO_QuickInit(HW_GPIOA,4,kGPIO_Mode_IPU); GPIO_CallbackInstall(HW_GPIOC,kPinAlt0); GPIO_ITDMAConfig(HW_GPIOA,4,kGPIO_IT_RisingFallingEdge,true);//PTA4Interupt enable //LED0=KEY_K0 GPIO_QuickInit(HW_GPIOC,3,kGPIO_Mode_OPP);//C3=LED0-K0 //UART LPUART_QuickInit(LPUART0_RX_A01_TX_A02,115200); //ADC ADC_QuickInit(ADC0_SE8A_PB00,kADC_SingleDIff16);//ADC-B0 //PWM TPM_PWM_QuickInit(TPM0_CH3_PC04,kPWM_EdgeAligned,10000);//PWM-C4 //Speedtest plus GPIO_QuickInit(HW_GPIOE,0,kGPIO_Mode_IPU);//Extplus 6.2、中断初始化 //PIT0Initial voidpit0Init(void){ PIT_QuickInit(HW_PIT_CH0,10);//1000=1mS|10=10uS PIT_CallbackInstall(HW_PIT_CH0,PIT_ISR0); PIT_ITDMAConfig(HW_PIT_CH0,kPIT_IT_TOF,true); } 6.3、中断进程 voidPIT_ISR0(void){ static int i=0; i++; if(i%10){; if(GPIO_ReadBit(HW_GPIOE,0)) dp=1;//设置dp参数 }else if(i%20){ if(!GPIO_ReadBit(HW_GPIOE,0) &&dp==1) plus++;dp=0;//10uS后E0有仍效.plus计数 } if(i>1000){i=0;pp++;dspd++;}//1mS后续控制参数pp累加,dspd累加 } 6.4、红外探测控制 正前方1个,左边个,右边一个:信号集合为111,负电平有效。控制逻辑判别为: 前进,左,右=000~111有8种情况,111代表前左右都无碍,前进[加速方法为10us为单位,一次增加1/200];011、001、010代表前方有碍,后两位01和10分别代表左或右有碍,必须向相反方向转弯;000代表前左右都有碍,加速后退; 探测判断完成后直接给出WPM负脉冲的宽度[可能是电路设计上开始没有控制好,结果是负脉冲有效——PWM值越小电机转动越快],单节锂电测试的结果是PWM在3/10时开始运动,到1/10000达到最大速度。实际控制逻辑为: 前进初值为2000,最后加速到200——1/5~1/500的脉宽。 转弯固定设置为8/100的脉冲宽度,速度很慢——地打滑,电机功率不够,看视频小车像停止了一样,只能以后该电路了。 程序如下: //IRTest voidirTest(void){ ford=GPIO_ReadBit(HW_GPIOB,1); left=GPIO_ReadBit(HW_GPIOC,1); right=GPIO_ReadBit(HW_GPIOC,2); if(!ford &&(left&&right)){//011=go left Or Right //if(pp>50){ // GPIO_WriteBit(HW_GPIOC,6,0); // GPIO_WriteBit(HW_GPIOC,5,1); //}else{ GPIO_WriteBit(HW_GPIOC,6,1); GPIO_WriteBit(HW_GPIOC,5,0); //} duty=dut0; //dspd=0; }else if(!ford && !left &&right==1){//001=go right GPIO_WriteBit(HW_GPIOC,6,0); GPIO_WriteBit(HW_GPIOC,5,1); duty=dut0; //dspd=0; }else if(!ford && left==1 &&!right){//010=go left GPIO_WriteBit(HW_GPIOC,6,1); GPIO_WriteBit(HW_GPIOC,5,0); duty=dut0; //dspd=0; }else if(!(ford||left||right)){//000=turn back GPIO_WriteBit(HW_GPIOC,6,0); GPIO_WriteBit(HW_GPIOC,5,0); duty=dut0; //dspd=0; }else{//111,100,110,101=go forword GPIO_WriteBit(HW_GPIOC,6,1); GPIO_WriteBit(HW_GPIOC,5,1); if(ford && dspd>50){ if(duty>200){duty -=50;} if(duty>dut0){duty=dut0;} dspd=0; } } TPM_PWM_ChangeDuty(HW_TPM0,kTPM_IT_CH3,duty);//PWM=C4 } 运行程序: //MoveCortral voiddir12(void){ if(!(left||right||ford)){//000=STOP停止没有做,原考虑用Key //GPIO_WriteBit(HW_GPIOC,7,0); //}else{//Other move GPIO_WriteBit(HW_GPIOC,7,1); } } 6.5、主函数 //MainPrograms intmain(void){ int adcs; //SystemCoreClockUpdate(); SystemInit(); //SystemClockSetup(); DelayInit(); ioInit(); //cmd_spi(0, NULL); lptmrInit(); pit0Init(); printf("TEST ADC value to LCD\r\n"); lcdInit(); lcdClear(); dispBase(); dir12(); while(1){ value=ADC_QuickReadValue(ADC0_SE8A_PB00);//ADC0 Test-B00 leds(); js++; irTest(); dir12(); dir1=GPIO_ReadBit(HW_GPIOC,6); dir2=GPIO_ReadBit(HW_GPIOC,5); ctrl=GPIO_ReadBit(HW_GPIOC,7); ford=GPIO_ReadBit(HW_GPIOB,1); left=GPIO_ReadBit(HW_GPIOC,1); right=GPIO_ReadBit(HW_GPIOC,2); dispMes(); if(pp>=100){ speed=plus;//测速输出显示 plus=0; pp=0; } } } LCD.h和LCD.c省略了,屏幕输出照片为显示ADC、PWM的数值、程序计数器——中程序运行一个周期计数累加1、显示3个IR红外状态和控制电机的4个信号,以0,1表示。照片如下:
SPD——测速、DIR——控制左右两路电机方向、PWM显示实际PWM输出的数值[周期为10000]、CTR——电机控制信号、ADC——模拟采样,没有用、IR:——3路红外测试信号,前,左,右、JSQ——程序运行计数。 LCD程序省略,太长和无用,也就是以前扔到网站的LCD驱显代码。 7、小结 经过断续的小车设计和测试,感慨颇多,写出来一起讨论和提高。 7.1、动力问题 测试电机时,单节锂电电机就发出很浓的电弧味,因此设计为单节锂电,实际跑起来单节锂电动力稍差,在家里的木质地板上直线运动还好,转弯由于,轮胎抓地无力打滑电机几乎不转了——可以再加大WPM电压解决,但感觉可能采用两节锂电会更好,但电机可能会很快烧掉的。解决方法只能是换电机。 7.2、电机控制芯片的选择 测试后感觉L91101Ade应该够了,实测也是如此,快速运动几乎无温升、但慢速转弯时芯片有发烫的感觉,说明在PWM控制下芯片功耗增加造成发热,L298可能也只是凑合,因为最大电流也在2A左右,更高的芯片会好些的。此次测试就是仅采用了L9110H双列DIP芯片。能用。 7.3、电源选择 由于手头超声模块多为5V的,后来买了3.3V也能工作的、但占用I/O口较多,放弃了。采用红外遇到难点:在3.3V下的距离超不过20CM自己设计的PCB回来后机关可以达到超过50CM或更远,但本省籍以超声自震荡——无反射信号也会闪动。最后只好采用1片升压模块,将1节锂电升压到5V,而后再降压到3.3V共给MCU。电源更复杂了。但最后算是解决了——凑合解决的。 红外模块和超声模块是买来的,就不抄板放原理和PCB了。 7.4、原计划自动跟踪 这个任务在整个都处于考虑没有实施的过程——机关热释电模块买来了2块,只是测试了其功能,测试距离相当远——大约超过2M——可以实现跟踪和蔽障同时完成。此次实验没有做这个功能。 7.5、MCU的选择 原来设想KL27应该够了——实际上也是够了——如果将A0、A3都用上应该够了——因为LCD占用的4个IO可以共享使用——需要显示,这4个IO给LCD用,需要测试其他传感器信号则将这4个IO口用来测试。这个方案也考虑过了,应该没有问题。但从设计有冗余考虑还是选择I/O口更多的KL26好点,实际上可能XS128可能更适合。因为这款小车较为笨重、电机功率也不太足并不需要低功耗MCU,当然这是后话。 最后将我的工程打包。将制作过程写的word文档也发上。此工程包含所有有用和无用[注释了]的设置,可以看出设计过程不断的更改和调整。算作抛砖引玉,互相学习吧。
裁剪的短视频链接:
|