본문 바로가기
DSP, MCU/STM32 (ARM Cortex-M)

STM32 ] 델타로봇, UART로 Command Line Interface 구현 + 기판에 다시 납땜 (5)

by eteo 2022. 9. 4.

 

2022.08.25 - [프로그래밍/C] - C ] 명령 프롬프트 구현 (함수포인터 사용)

 

C ] 명령 프롬프트 구현 (함수포인터 사용)

#include #include /* for strcmp() strlen*/ //#include /* for usleep() */ #include #include #define MAX_CMD_NUM 10 #define BUF_LEN 128 int cmd_continue = 0; typedef int cmd_func(int argc, char* argv[..

eteo.tistory.com

 

 

 

이전에 콘솔에서 구현했었던 명령 프롬프트를 가져와 STM32에서 UART로 Command Line Interface를 구현하고 간단하게 델타로봇을 제어해봤다.

 

 

 

 

cli.h

/*
 * cli.h
 *
 *  Created on: Sep 4, 2022
 *      Author: J
 */

#ifndef INC_CLI_H_
#define INC_CLI_H_

#define MAX_CMD_NUM 10


typedef int cmd_func(int argc, char* argv[]);

struct Command_List
{
	char* cmd;
	cmd_func* func;
	char* help_str;
};

int cmd_torque(int argc, char* argv[]);
int cdm_pump(int argc, char* argv[]);
int cmd_conveyorBelt(int argc, char* argv[]);
int cmd_pick(int argc, char* argv[]);
int cmd_throw(int argc, char* argv[]);
void parse_input_string(char* input_string, int* argc, char* argv[]);
void cmd_handler(char* cmd);

#endif /* INC_CLI_H_ */

 

 

cli.c

/*
 * cli.c
 *
 *  Created on: Sep 4, 2022
 *      Author: Jo soo hyun
 *
 *
 */

#include "cli.h"
#include "main.h"

#include <stdio.h>
#include <string.h>

#include "stm32f4xx_hal.h"
extern UART_HandleTypeDef huart3;

#include "cmsis_os.h"

extern osSemaphoreId UPSemHandle;
extern osSemaphoreId DOWMSemHandle;
extern osSemaphoreId ReadPosSemHandle;
extern osSemaphoreId TorqueOnSemHandle;
extern osSemaphoreId TorqueOffSemHandle;
extern osSemaphoreId ThrowSemHandle;
extern osSemaphoreId PumpOnSemHandle;
extern osSemaphoreId PumpOffSemHandle;
extern osSemaphoreId ConveyorRightOnSemHandle;
extern osSemaphoreId ConveyorLeftOnSemHandle;
extern osSemaphoreId ConveyorOffSemHandle;


int _write(int file, char* p, int len){
	HAL_UART_Transmit(&huart3, (uint8_t*)p, len, 10);
	return len;
}

struct Command_List  CmdList[] =
{
	{"torque",	cmd_torque,	"on/off Torque"},
	{"pump",	cdm_pump,	"on/off Pump"},
	{"cvbelt",	cmd_conveyorBelt,	"on/off Conveyor Belt. right/left"},
	{"pick",	cmd_pick,	"no option. End effector Down + Pump On + default position"},
	{"throw",	cmd_throw,	"no option. Throw + default position"},
	{0,0,0}
};



int cmd_torque(int argc, char* argv[])
{
	if (argv[1] == NULL) {
		printf("wrong command pattern. \n");
	}
	else {
		if (!strcmp(argv[1], "on")) {
			osSemaphoreRelease(TorqueOnSemHandle);
		}
		else if (!strcmp(argv[1], "off")) {
			osSemaphoreRelease(TorqueOffSemHandle);
		}
	}

	return 0;
}

int cdm_pump(int argc, char* argv[])
{
	if (argv[1] == NULL) {
		printf("wrong command pattern. \n");
	}
	else {
		if (!strcmp(argv[1], "on")) {
			osSemaphoreRelease(PumpOnSemHandle);
		}
		else if (!strcmp(argv[1], "off")) {
			osSemaphoreRelease(PumpOffSemHandle);
		}
	}

	return 0;
}

int cmd_conveyorBelt(int argc, char* argv[])
{
	if (argv[1] == NULL) {
		printf("wrong command pattern. \n");
	}
	else {
		if (!strcmp(argv[1], "on")) {
			if (argv[2] == NULL) {
				printf("wrong command pattern. \n");
			}
			else {
				if (!strcmp(argv[2], "right")) {
					osSemaphoreRelease(ConveyorRightOnSemHandle);
				}
				else if (!strcmp(argv[2], "left")) {
					osSemaphoreRelease(ConveyorLeftOnSemHandle);
				}else {
					printf("wrong command pattern. \n");
				}
			}
		}
		else if (!strcmp(argv[1], "off")) {
			osSemaphoreRelease(ConveyorOffSemHandle);
		}
	}

	return 0;
}

int cmd_pick(int argc, char* argv[])
{
	printf("pick up item on the conveyor belt. \n");
	return 0;
}

int cmd_throw(int argc, char* argv[])
{
	printf("throw item away \n");
	return 0;
}


void parse_input_string(char* input_string, int* argc, char* argv[])
{
	int found_arg = 1;
	int argn = 0;

	while (*input_string)
	{
		if (*input_string == '\n') {
			*input_string = '\0';
			break;
		}

		if (*input_string == ' ') {
			found_arg = 1;
			*input_string = '\0';
		}
		else if (found_arg) {
			argv[argn++] = input_string;
			found_arg = 0;
		}
		input_string++;
	}

	*argc = argn;
}


void cmd_handler(char* cmd)
{
	struct Command_List* pCmdList = CmdList;

	uint32_t command_found = 0;

	int	  argc;
	char* argv[MAX_CMD_NUM] = { 0, };

	parse_input_string(cmd, &argc, argv);

	if (argc)
	{
		while (pCmdList->cmd)
		{
			if (!strcmp((const char*)pCmdList->cmd, (const char*)cmd))
			{
				command_found = 1;
				pCmdList->func(argc, argv);
				break;
			}
			++pCmdList;
		}
	}
	if (command_found == 0) printf("command not found!\n");
}

 

 

 

UART 수신부분

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

	if(huart->Instance == USART3){
		if(rx3_data != '\n' && bufindex < BUFSIZE)
			rx3buf[bufindex++] = rx3_data;
		else {
			cmd_handler((char*)rx3buf);
			char temp[4]={0,};
			sprintf(temp, ">> ");
			HAL_UART_Transmit_IT(&huart3, (uint8_t*)temp, sizeof(temp));
			memset(rx3buf,0,sizeof(rx3buf));
			bufindex=0;

		}

		HAL_UART_Receive_IT(&huart3, &rx3_data, 1);
	}

}

 

 

 

CLI는 나중에 매우 유용하게 쓸 수 있을거 같아서 나중에 시간이 있을 때 조금 손보고 재활용이 가능하도록 헤더와 소스파일을 만들어두려고 한다.

 

일단은 콜백함수 내에서 처리하게 해놨는데 나중에 처리하는 태스크를 따로 둘 것이다.

 

 

CLI만 테스트해본 프로젝트 파일

https://github.com/joeteo/uart_cli_test

 

GitHub - joeteo/uart_cli_test

Contribute to joeteo/uart_cli_test development by creating an account on GitHub.

github.com

 

 

 

 

 

 

그리고 이전에 했던 납땜이 너무 조악한것 같아서 공책에 회로를 그리고 보면서 다시 납땜을 했다.

 

전면과 후면