어플 화면
SCAN 버튼을 눌러 블루투스 페어링 합니다.
Control을 누르면 아래 버튼을 사용해 수동제어를 할 수 있고, Waypoint 버튼을 누른 뒤 어플 지도상의 파란색 마커(Waypoint)를 찍으면 해당 위치로 자율주행을 시작합니다.
bluetooth.c 중 일부
void BT_Init()
{
HAL_UART_Receive_IT(&huart7, &rx7_data, sizeof(rx7_data));
}
void transmit_To_Phone(){
char buf[GPSBUFSIZE] = {0,};
sprintf(buf, "A,%.13f\n\r", GPS.dec_latitude);
//HAL_UART_Transmit(&huart3, (unsigned char *)buf, strlen(buf), 10);
HAL_UART_Transmit(&huart7, (unsigned char *)buf, strlen(buf), 10);
sprintf(buf, "O,%.13f\n\r", GPS.dec_longitude);
//HAL_UART_Transmit(&huart3, (unsigned char *)buf, strlen(buf), 10);
HAL_UART_Transmit(&huart7, (unsigned char *)buf, strlen(buf), 10);
sprintf(buf, "C,%.13f\n\r", headingDegrees);
//HAL_UART_Transmit(&huart3, (unsigned char *)buf, strlen(buf), 10);
HAL_UART_Transmit(&huart7, (unsigned char *)buf, strlen(buf), 10);
}
STM32에서 스마트폰으로 송신하는 부분. GPS 모듈로 수신된 위도, 경도와 지자기센서로 알아낸 방위각을 송신하다. 어플에서 파싱할 수 있게 A, O, C, 로 시작하는 구분자와 함께 데이터를 보내고 라인피드와 캐리지리턴으로 끝난다.
void Phone_UART_CallBack(){
// AUTO_MODE_SIGNAL == 'A'
if((Mode_Flag == CONTROL_MODE || Mode_Flag == WAYPOINT_MODE) && rx7_data==AUTO_MODE_SIGNAL){
memset(rx7_buffer, 0, sizeof(rx7_buffer));
Mode_Flag=AUTO_MODE;
// WAYPOINT_MODE_SIGNAL == 'W'
}else if((Mode_Flag == AUTO_MODE || Mode_Flag == CONTROL_MODE) && rx7_data==WAYPOINT_MODE_SIGNAL){
memset(rx7_buffer, 0, sizeof(rx7_buffer));
Mode_Flag=WAYPOINT_MODE;
// CONTROL_MODE_SIGNAL == 'C'
}else if((Mode_Flag == AUTO_MODE || Mode_Flag == WAYPOINT_MODE) && rx7_data==CONTROL_MODE_SIGNAL){
memset(rx7_buffer, 0, sizeof(rx7_buffer));
Mode_Flag=CONTROL_MODE;
}
if(Mode_Flag==CONTROL_MODE){
if (rx7_data != '\n' && rx7_index < sizeof(rx7_buffer)) {
rx7_buffer[rx7_index++] = rx7_data;
} else {
rx7_buffer[rx7_index]=0;
rx7_index = 0;
sscanf((const char*)(rx7_buffer+2), "%d", &controlCMD);
}
}else if(Mode_Flag==WAYPOINT_MODE){
if (rx7_data != '\n' && rx7_index < sizeof(rx7_buffer)) {
rx7_buffer[rx7_index++] = rx7_data;
} else {
rx7_buffer[rx7_index]=0;
rx7_index = 0;
sscanf((const char*)(rx7_buffer+1), "%f,%f", &phoneGPS.latitude, &phoneGPS.longitude);
if(phoneGPS.latitude > 34 && phoneGPS.latitude< 38 && phoneGPS.longitude > 126 && phoneGPS.longitude < 130){
waypointGPS.latitude=phoneGPS.latitude;
waypointGPS.longitude=phoneGPS.longitude;
}
}
}else if(Mode_Flag==AUTO_MODE){
if (rx7_data != '\n' && rx7_index < sizeof(rx7_buffer)) {
rx7_buffer[rx7_index++] = rx7_data;
} else {
rx7_buffer[rx7_index]=0;
rx7_index = 0;
sscanf((const char*)(rx7_buffer+1), "%f,%f", &phoneGPS.latitude, &phoneGPS.longitude);
}
}
HAL_UART_Transmit(&huart3, &rx7_data, sizeof(rx7_data), 10);
HAL_UART_Receive_IT(&huart7, &rx7_data, sizeof(rx7_data));
}
스마트폰으로부터 들어온 데이터를 파싱하는 부분. main.c의 HAL_UART_RxCpltCallback() 을 거쳐 들어온다.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart2) GPS_UART_CallBack();
if(huart->Instance == UART7) Phone_UART_CallBack();
}
Mode_Flag는 다음 3개의 값을 가질 수 있는데 AUTO_MODE는 아직 구현된 부분이 아니다.
enum{
CONTROL_MODE,
WAYPOINT_MODE,
AUTO_MODE
};
CONTROL_MODE 는 시작비트인 C와 제어신호를 뜻하는 ASCII 코드 한바이트가 들어오는데 짧아서 그런지 오류가 없다.
WAYPOINT_MODE 는 시작비트인 W와 이어서 위도, 경도가 콤마로 구분되어 들어오는데 아무래도 길어서인지 가끔 이상한 값이 들어올 때가 있다. 일단은 어플에서 WaPpoint 마커가 새로운 곳에 찍혔을 때 한번이 아니라 계속 위도, 경도를 보내게끔해서 정상범위의 값만 받게끔 했는데 이 부분은 추후 수정될 수도 있다.
그리고 현재의 main.c 의 while 문은 이렇게 작성했다.
/* USER CODE BEGIN WHILE */
while (1)
{
current_tick = HAL_GetTick();
if(current_tick - start_tick >= 70){
calculateHeading();
start_tick = current_tick;
}
if(Mode_Flag==CONTROL_MODE){
Move(controlCMD);
}else if(Mode_Flag==WAYPOINT_MODE){
if(waypointGPS.latitude!=0 && waypointGPS.latitude!=0){
SelfDriving();
}
}else if(Mode_Flag==AUTO_MODE){
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
아래는 동료의 자료 입니다.
'임베디드 개발 > STM32 (ARM Cortex-M)' 카테고리의 다른 글
STM32 ] TIMER OC (Output Compare 단자 출력) 사용 예제 (2) | 2022.07.21 |
---|---|
STM32 ] TIMER OC (Output Compare No Output) 사용 예제 (0) | 2022.07.21 |
STM32 ] BLDC 모터 제어 - 프로젝트 준비과정 (4) (5) | 2022.07.19 |
STM32 ] 초음파 센서로 거리재기 Timer Input Capture 사용 + 노이즈 (튀는 값) 제거 (5) | 2022.07.18 |
STM32 ] DAC 제어 (오실로스코프로 파형 확인) (2) | 2022.07.18 |