嵌入式实验智能小车避障+上位机手柄控制

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

嵌入式实验报告小车避障+上位机
李晨,颜文杰
2012/6/7
一、小车的功能及部件
小车能够实现的主要功能有自动避障和上位机两个方面。

避障主要是依靠传感器检测小车与前方的距离,然后根据算法的程序,自动选择最近的方式避障。

上位机则是依靠电脑与小车通过无线串口相连,利用游戏手柄控制上位机的指令对小车进行前进、后退、左转、右转、加速等控制,从而实现用手柄对小车的无线遥控。

传感器的分布直接的影响到了小车的自动避障功能,因此,为达到最优的效果,将传感器如下图的分布:
前面两个用来判断小车与障碍物所成的角度,左右两边用来使小车与边界有一定的距离。

为实现上位机的无线遥控功能,将小车加上无线模块与游戏手柄。

二、小车功能的实现
小车的功能已经在上部分说明了,但是为实现两者功能的转化,我们采用了使用上位机发送指令从而改变小车工作模式的方法。

下图为上位机工作界面:
由上图可知,小车与电脑通过无线模块相连时,通过点选按钮“控制”和“自动避障”,可以使小车实现两种功能的切换。

具体实现如下:
通过串口中断,在计算机发送指令时改变flag_mode_choice的值,改变主程序中运行的不同模块,从而改变功能。

while (1) {
while (flag_mode_choice==0)
{
ADC_Ch0_Res = ADC_RegularConvertedValueTab[0] - ADC_Calibration_DR;
ADC_Ch1_Res = ADC_RegularConvertedValueTab[1] - ADC_Calibration_DR;
ADC_Ch2_Res = ADC_RegularConvertedValueTab[2] - ADC_Calibration_DR;
ADC_Ch3_Res = ADC_RegularConvertedValueTab[3] - ADC_Calibration_DR;
if (RxBuffer[1]==0xCC) now_speed=100;
Forward_Cmd();
if(ADC_Ch3_Res<0x520)Turn_Right();
else if(ADC_Ch0_Res<0x520)Turn_Left();
if(ADC_Ch2_Res<0x520||ADC_Ch1_Res<0x520)
{
if(ADC_Ch2_Res<ADC_Ch1_Res)
Turn_Right();
else if(ADC_Ch2_Res>ADC_Ch1_Res)
Turn_Left();
if(ADC_Ch2_Res<0xAA&&ADC_Ch1_Res<0xAA)
Backward_Cmd();
}
Delay(0XAFFFF);
}
while (flag_mode_choice==1) {
if(RxBuffer[1]==0x11)
Forward_Cmd();
else if (RxBuffer[1]==0xCC)
{ now_speed=100;Forward_Cmd();}
else if (RxBuffer[1]==0x22)
Backward_Cmd();
else if (RxBuffer[1]==0x1A)
Forward_Accelerate_Cmd();
else if (RxBuffer[1]==0x1B)
Forwar_non_Accelerate_Cmd();
else if (RxBuffer[1]==0x33)
Turn_Right();
else if (RxBuffer[1]==0x44)
Turn_Left();
else Break_Cmd();
}
}
利用以下的串口中断实现功能转换:
extern u8 RxBuffer[6];
extern int flag_mode_choice;
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);
/* Read one byte from the receive data register */
while(!USART_GetFlagStatus(USART1,USART_FLAG_RXNE)) ;
RxBuffer[0] = USART_ReceiveData(USART1);
while(!USART_GetFlagStatus(USART1,USART_FLAG_RXNE)) ;
RxBuffer[1] = USART_ReceiveData(USART1);
if (RxBuffer[0] == 0xEA)
flag_mode_choice=0;
if( RxBuffer[0] == 0xEB)
flag_mode_choice=1;
/* Clear the USART1 Receive interrupt */
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
}
}
1.避障功能的实现
为实现小车的避障功能,使小车前面两个传感器的值相比较,若其中一个大于另一个,则向偏大的方向转弯,反之亦然。

程序实现如下:
ADC_Ch0_Res = ADC_RegularConvertedValueTab[0] - ADC_Calibration_DR;
ADC_Ch1_Res = ADC_RegularConvertedValueTab[1] - ADC_Calibration_DR;
ADC_Ch2_Res = ADC_RegularConvertedValueTab[2] - ADC_Calibration_DR;
ADC_Ch3_Res = ADC_RegularConvertedValueTab[3] - ADC_Calibration_DR;
if (RxBuffer[1]==0xCC) now_speed=100;
Forward_Cmd();
if(ADC_Ch3_Res<0x520)Turn_Right();
else if(ADC_Ch0_Res<0x520)Turn_Left();
if(ADC_Ch2_Res<0x520||ADC_Ch1_Res<0x520)
{
if(ADC_Ch2_Res<ADC_Ch1_Res)
Turn_Right();
else if(ADC_Ch2_Res>ADC_Ch1_Res)
Turn_Left();
if(ADC_Ch2_Res<0xAA&&ADC_Ch1_Res<0xAA)
Backward_Cmd();
2.上位机功能实现
上位机的界面是由Visual C++ 6.0中的MFC编写的。

其中有打开串口,发送显示,接受显示等功能,也可实现小车的功能切换,可以直接支持游戏手柄的控制。

使用无线的控制时,波特率为9600,按钮的代码段如下所示:
//避障模式
void CSerialPortTestDlg::OnButtonSend()
{
Buf[0]=0xEA;
Buf[1]=0xAA;
//Buf[2]=0xAA;
// TODO: Add your control notification handler code here
if(!m_bSerialPortOpened) r eturn;//检查串口是否打开
//UpdateData(TRUE); //读入编辑框中的数据
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg); //发送数据
}
void CSerialPortTestDlg::OnChangeEditSendmsg()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog() // function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
}
//上位机控制模式
void CSerialPortTestDlg::OnButtonSend2()
{
Buf[0]=0xEB;
Buf[1]=0xAA;
//Buf[2]=0xAA;
//Buf[3]=0xAA;
// TODO: Add your control notification handler code here
if(!m_bSerialPortOpened) r eturn;//检查串口是否打开
//UpdateData(TRUE); //读入编辑框中的数据
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
}
//前进//
void CSerialPortTestDlg::OnButtonSend6()
{
Buf[0]=0xEB;
Buf[1]=0x11;
//Buf[2]=0xAA;Buf[3]=0xAA;
// TODO: Add your control notification handler code here
if(!m_bSerialPortOpened) r eturn;//检查串口是否打开
//UpdateData(TRUE); //读入编辑框中的数据
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
}
//后退
void CSerialPortTestDlg::OnButtonSend4()
{
Buf[0]=0xEB;
Buf[1]=0x22;
//Buf[2]=0xAA;Buf[3]=0xAA;
// TODO: Add your control notification handler code here
if(!m_bSerialPortOpened) r eturn;//检查串口是否打开
//UpdateData(TRUE); //读入编辑框中的数据
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
}
//左转
void CSerialPortTestDlg::OnButtonSend3()
{
Buf[0]=0xEB;
Buf[1]=0x33;
//Buf[2]=0xAA;Buf[3]=0xAA;
// TODO: Add your control notification handler code here
if(!m_bSerialPortOpened) r eturn;//检查串口是否打开
//UpdateData(TRUE); //读入编辑框中的数据
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
}
//右转
void CSerialPortTestDlg::OnButtonSend5()
{
Buf[0]=0xEB;
Buf[1]=0x44;
//Buf[2]=0xAA;Buf[3]=0xAA;
// TODO: Add your control notification handler code here
if(!m_bSerialPortOpened) r eturn;//检查串口是否打开
//UpdateData(TRUE); //读入编辑框中的数据
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
}
//手柄控制
LRESULT CSerialPortTestDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
joyx = LOWORD(lParam)/2048;
joyy = HIWORD(lParam)/2048;
//WORD joyx,joyy;
if ((Buf[0]==0xEB)&&(Buf[1]==0x44)&&(joyx<=20&&joyx>=12)) {
Buf[0]=0xEB;Buf[1]=0x11;
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
//Sleep(TIMEDELAY);
}else if((Buf[0]==0xEB)&&(Buf[1]==0x33)&&(joyx<=20&&joyx>=12)) { Buf[0]=0xEB;Buf[1]=0x11;
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
} else if((Buf[0]==0xEB)&&(Buf[1]==0x22)&&(joyy<=25&&joyy>=12)) { Buf[0]=0xEB;Buf[1]=0x11;
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
}
if (message==MM_JOY1MOVE)
{
joyx = LOWORD(lParam)/2048;
joyy = HIWORD(lParam)/2048;//如果游戏杆在中心位置的左边,移动光标到左边。

反之亦然
if(joyx <= 12)
{
//SetDlgItemText(IDC_STATIC1,"左转");
Buf[0]=0xEB;Buf[1]=0x44;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}else if(joyx >= 20)
{
Sleep(5);
//SetDlgItemText(IDC_STATIC1,"右转");
Buf[0]=0xEB;Buf[1]=0x33;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}else if(joyy <= 12)//如果游戏杆在中心位置的下边,移动光标到下边。

反之亦然
{
//SetDlgItemText(IDC_STATIC1,"快速前进");
Buf[0]=0xEB;Buf[1]=0x11;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}
else if(joyy >= 25)
{
//SetDlgItemText(IDC_STATIC1,"后退");
Buf[0]=0xEB;Buf[1]=0x22;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
} if(wParam & JOY_BUTTON1)
{
Sleep(5);
//SetDlgItemText(IDC_STATIC1,"1");//前进
Buf[0]=0xEA;Buf[1]=0xAA;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}else if (wParam & JOY_BUTTON2)
{
Sleep(5);
//SetDlgItemText(IDC_STATIC1,"2");//后退
}else if(wParam & JOY_BUTTON3)
{
Sleep(5);
//SetDlgItemText(IDC_STATIC1,"3");
Buf[0]=0xEB;
Buf[1]=0xAA;
// TODO: Add your control notification handler code here
//if(!m_bSerialPortOpened) return;//检查串口是否打开
//UpdateData(TRUE); //读入编辑框中的数据
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}
else if(wParam & JOY_BUTTON4)
{
Sleep(5);
//SetDlgItemText(IDC_STATIC1,"4");
}
else if (wParam&JOY_BUTTON1CHG)
{
//SetDlgItemText(IDC_STATIC1,"select");//标准避障模式
Buf[0]=0xEA;Buf[1]=0xCC;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}else if(wParam&JOY_BUTTON2CHG)
{
//SetDlgItemText(IDC_STATIC1,"start");//标准上位机控制模式Buf[0]=0xEB;Buf[1]=0xCC;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}else if(wParam&JOY_BUTTON5)
{
//SetDlgItemText(IDC_STATIC1,"5");
}
else if(wParam&JOY_BUTTON6)
{
//SetDlgItemText(IDC_STATIC1,"6");
}else if(wParam&JOY_BUTTON7)//select
{
//SetDlgItemText(IDC_STATIC1,"7");
Buf[0]=0xEB;Buf[1]=0x1A;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}else if(wParam&JOY_BUTTON8)//select
{
//SetDlgItemText(IDC_STATIC1,"8");
Buf[0]=0xEB;Buf[1]=0x1B;
//if(!m_bSerialPortOpened) return;//检查串口是否打开
m_strEditSendMsg = (CString)Buf ;
m_SerialPort.WriteToPort((LPCTSTR)m_strEditSendMsg);
Sleep(TIMEDELAY);
}
}
return CDialog::WindowProc(message, wParam, lParam);
}
BOOL CSerialPortTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
UINT result;
result=::joySetCapture(CDialog::m_hWnd, JOYSTICKID1, 0, FALSE);
if(result==JOYERR_NOCANDO)
{
MessageBeep(MB_ICONEXCLAMATION);
MessageBox("不能捕获游戏杆", NULL, MB_OK | MB_ICONEXCLAMATION);
return -1;
}
if(result==JOYERR_UNPLUGGED)
{
MessageBeep(MB_ICONEXCLAMATION);
MessageBox("游戏杆未与系统连接", NULL, MB_OK | MB_ICONEXCLAMATION);
return -1;
}
//ENDS
return TRUE; // return TRUE unless you set the focus to a control }
这样就实现了小车的两种模式的控制以及通过手柄来控制界面。

三、实验总结
本次试验中出现的主要问题是调试过程。

由于本次试验中的代码众多,功能调试就造成了部分问题,还有由于手柄控制界面的加入,使得难度又增加了。

不过参考网上的程序,加上自己的研究,终于克服了难题,最终实现了控制。

不过有的地方其实可以增加一些新的东西,界面也可以做的更好,不过由于时间的限制,这次的并不是最完美的。

总之,在本次小车的功能实现中,我们学会了不少知识,以及对嵌入式系统有了更深一步的认识,让我们受益匪浅。

相关文档
最新文档