无人水质监测船 - 源码与架构介绍

目录

一、自动巡航展示

二、项目技术点

三、项目架构

四、下位机架构

一、自动巡航展示

无人水质监测船_哔哩哔哩_bilibili

二、项目技术点

        RTOS:采用freertos作为多线程运行架构,在项目中使用临界区和互斥量对其初始化过程和外设部分进行保护。使用信号量实现通知任务目的,这里展示部分,有的函数被传入做回调函数。

/**
 * @brief 用于Give到<定位任务>信号量
 * 
 */
void give_locating_binary(void)
{
	xSemaphoreGive(locating_Binary_Handle);
}

/**
 * @brief 用于Tack到<定位任务>信号量
 * 
 */
void take_locating_binary(void)
{
	xSemaphoreTake(locating_Binary_Handle, portMAX_DELAY);
}

/**
 * @brief 用于Give到<获取数据任务>信号量
 * 
 */
void give_getd_binary(void)
{
	xSemaphoreGive(getd_Binary_Handle);
}

/**
 * @brief 用于Tack到<获取数据任务>信号量
 * 
 */
void take_getd_binary(void)
{
	xSemaphoreTake(getd_Binary_Handle, portMAX_DELAY);
}


void give_Pidturn_binary(void)
{
	xSemaphoreGive(Pidturn_Binary_Handle);
}

/**
 * @brief 用于Give到<通信任务>信号量
 * 
 */
void give_m780eg_uart_binary(void)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	
 	xSemaphoreGiveFromISR( m780_uart_Binary_Handle, &xHigherPriorityTaskWoken);    
	
 	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

/**
 * @brief 用于Tack到<通信任务>信号量
 * 
 */
void take_m780eg_uart_binary(void)
{
	xSemaphoreTake(m780_uart_Binary_Handle, portMAX_DELAY);
}

        面向对象:初始化阶段使用大量面向对象写法,将其定义为只读数据区,进行内存优化,并将其通过抽象封装好的函数进行初始化,减少代码复用。

//通讯指令数组
const rx_datacom_t rx_datacom[RXD_CODE_LENGTH] = {
	/*app-->manual*/
	{APP_UP			,"UP"		,2	,rxd_app_manual_fun},   
	{APP_BOTTOM		,"BOTTOM"	,6	,rxd_app_manual_fun},
	{APP_LEFT		,"LEFT"		,4	,rxd_app_manual_fun},
	{APP_RIGHT		,"RIGHT"	,6	,rxd_app_manual_fun},
	{APP_STOP		,"STOP"		,4	,rxd_app_manual_fun},
	/*app-->command*/
	{APP_ACQUIRE	,"ACQUIRE"	,7	,rxd_app_command_fun},
	/*CHECK --> 检查  进行校准 检查传感器初始化状态*/
	{APP_CHECK		,"CHECK"	,5	,rxd_boat_check_fun}, 
	/*紧急停止*/
	{APP_EMER_STOP	,"EMERSTOP"	,8	,rxd_boat_emer_stop_fun},
	/*恢复停止*/
	{APP_RESUME_STOP	,"RESSTOP"	,7	,rxd_boat_Resume_fun},

	{APP_GET_GPS	,"GETGPS"	,6	,rxd_app_command_fun},
	/*app-->gps locating*/
	{APP_GPS_AXIS	,"F1"		,2	,rxd_app_locating_fun},
	/*dtu-->command  Rec*/
	/*DTU_REC_CSQ --> 信号质量data  DTU_REC_GPS --> GPS定位数据*/
	{DTU_REC_CSQ 	,"\r\nconfig,csq,ok,"	,16	,rxd_dtu_rec_command_fun},		
	{DTU_REC_REBOOT ,"\r\nconfig,reboot,ok\r\n"	,20	,rxd_dtu_rec_command_fun},
	// {DTU_REC_GPSEXT ,"\r\nconfig,gps,ok,"	,16	,rxd_dtu_rec_command_fun},
	{DTU_REC_GPS 	,"\r\nconfig,gps,ok,"	,16	,rxd_dtu_rec_gps_fun},
};

//调试指令数组
const rx_command_t rx_command_buff[10] = {
	{"help"		,	rx_command_help_fun}, 	 //帮助
	{"showhc"	,	rx_command_showhc_fun},	 //查看电子罗盘校准值
	{"showgps"	,	rx_command_show_gps_fun}, //查看当前定位信息
	{"con:"		,	rx_command_control_fun},  //控制电机
	{"check"	,	rx_command_boat_check_fun}, //校准
	{"set:"		,	rx_command_set_angle_fun}, //设置角度
	{"pidt"		,	rx_command_take_Pidturn_Binary}, //执行PID
	{"reset"	,	rx_command_SystemReset_fun}, //通过软件复位
	{"sus"		,	rx_command_emer_stop_fun}, //挂起 - 紧急停止
	{"res"		,	rx_command_resume_stop_fun}, //恢复
};

//通讯任务 遍历相关指令并执行对应函数指针
void dispose_Task(void *p)
{
	uint8_t rxd_ret = 0;
	register_m780eg_Binary_Handler(give_m780eg_uart_binary);

	m780_uart_Binary_Handle = xSemaphoreCreateBinary();
	locating_Binary_Handle = xSemaphoreCreateBinary();
	while (1)
	{
		xSemaphoreTake(m780_uart_Binary_Handle, portMAX_DELAY);
		{
			rbklen = readFromFIFO(&m780eg_rec_t,rbkbuff,148);

			printf("buff = %s \r\nlen  = %d \r\n", rbkbuff,rbklen);
			
			for(uint8_t rxd_len = 0 ; rxd_len < RXD_CODE_LENGTH ; rxd_len++)
			{
				rxd_ret = rxd_find_code_fun(&rx_datacom[rxd_len]);
				VOID_CHECK_FLAGS(rxd_ret);
			}

			memset(rbkbuff,0x00,sizeof(rbkbuff));
		}
	}
}

const dri_I2C2_t dri_I2C2 = {
	{	.pin   = "PB10,PB11",
		.mode  = GPIO_Mode_AF,
		.pupd  = GPIO_PuPd_NOPULL,
		.otype = GPIO_OType_OD,
		.speed  = GPIO_Speed_50MHz,
		.AFpin = GPIO_AF_I2C2, },
	{	.i2c_ClkSpeed = 400000,
		.i2C_DuCycle = I2C_DutyCycle_2,
		.i2c_AckAddress = I2C_AcknowledgedAddress_7bit,
		.i2c_OwnAddress = 0x30,
		.i2c = I2C2,
	},
};

bool dev_io_config(dev_gpio_t *drv_gpio)
{
	dev_gpio_pt gpio_pint={0};
	GPIO_InitTypeDef GPIO_InitStructure;	

	gain_gpio_pin(drv_gpio->pin,&gpio_pint);  //解析字符串 如"PA8,PA9"

	GPIO_InitStructure.GPIO_Pin    = gpio_pint.gpioPin[0] | gpio_pint.gpioPin[1]; 
	GPIO_InitStructure.GPIO_Mode   = drv_gpio->mode;             
	GPIO_InitStructure.GPIO_Speed  = drv_gpio->speed;         
	GPIO_InitStructure.GPIO_OType  = drv_gpio->otype;            
	GPIO_InitStructure.GPIO_PuPd   = drv_gpio->pupd;             
	GPIO_Init(gpio_pint.gpiot, &GPIO_InitStructure);                     
	
	if(drv_gpio->AFpin != AF_DISABLE_FLG)
	{
		switch (gpio_pint.pincnt)
		{
			case 1:GPIO_PinAFConfig(gpio_pint.gpiot, (uint8_t)gpio_pint.gpioPinSour[1] , drv_gpio->AFpin);
			case 0:GPIO_PinAFConfig(gpio_pint.gpiot, (uint8_t)gpio_pint.gpioPinSour[0] , drv_gpio->AFpin);
			break;
		} 
	}

	return true;
}

bool dev_i2c_config(dev_i2c_t  *drv_i2ct)
{
	I2C_InitTypeDef I2C_InitStructure;
	I2C_DeInit(drv_i2ct->i2c);
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;                              
	I2C_InitStructure.I2C_AcknowledgedAddress =drv_i2ct->i2c_AckAddress; 
	I2C_InitStructure.I2C_ClockSpeed = drv_i2ct->i2c_ClkSpeed;                              
	I2C_InitStructure.I2C_DutyCycle =drv_i2ct->i2C_DuCycle;                       
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;                              
	I2C_InitStructure.I2C_OwnAddress1 = drv_i2ct->i2c_OwnAddress;                               
	I2C_Init(drv_i2ct->i2c,&I2C_InitStructure);     
	
	I2C_Cmd(drv_i2ct->i2c,ENABLE);

	return true;
}

三、项目架构

用户端:能够实现自动巡航、手动控制、查看水质数据、实时定位信息

云平台:将用户端和设备端进行数据交互,做数据流转。

设备端

指令Task:开发调试任务,遍历相关指令执行相关操作。

通讯Task:负责执行相关任务以及同步相关线程(信号量),包括校准、手动控制等。

上传数据Task:这里负责采集水质数据,以状态机的架构进行采集,包括采集数据、均值滤波、打包数据、上传数据、清空缓存状态机制。

自动巡航Task:处理坐标、实现直行PID、通知转向PID、通知采集数据。

转向Task:负责转向处理。

船体状态Task:负责避障工作和船体姿态检测工作。

四、下位机架构

该项目采用分层架构设计,实现应用层和驱动层分离,驱动层的修改只会影响少量的应用层。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值