目录:

1.前言

1.所需硬件模块

2.引脚图设计及模块原理介绍

1.引脚图设计

2.驱动模块L298N介绍

3.机械臂舵机模块介绍

4.蓝牙模块介绍

(1)主从模式介绍

(2)AT命令

5.OLED模块介绍(简单了解原理)

(1) 行地址

(2) 列地址

3.驱动部分代码介绍

4.机械臂控制部分代码介绍

5.蓝牙遥控部分代码介绍

6.结束语


1.前言

        这个是自己在刚接触stm32单片机和openmv时做的第一个小车,网上关于蓝牙遥控的小车资料有很多,但也希望这篇文章能提供给别人不同的代码和硬件设计思路。

1.所需硬件模块

        主控板可以根据自己项目的实际需要进行更改,开发方式这里选择的是stm32标准库函数,相应数量的杜邦线,面包板,12V电池组,大家可以根据自己的需要进行准备。

2.引脚图设计及模块原理介绍

1.引脚图设计

1.L298N驱动

前A:PA6---------AENA (TIM3_CH1)

          PA7---------AENB  (TIM3_CH2)

          PB3 PB4 PB5 PB6 控制IN1 IN2 IN3 IN4

后B:PB0--------BENA  (TIM3_CH3)

          PB1--------BENB   (TIM3_CH4)

          PC0 PC1 PC2 PC3 控制IN1 IN2 IN3 IN4

2.蜂鸣器

           PA12------I/O

3.OLED模块 ---- SPI

           PB13 ------------- D0 (时钟线)

           PB15 ------------- D1 (数据线)

           PB12 ------------- RES(复位线)

           PB10 ------------- DC (数据/命令控制线)

           PB11 ------------- CS (片选线 低电平有效 如果不想用必须接地)

4.机械臂四个舵机

           PA0(TIM2_CH1)------------正面左舵机

           PA1(TIM2_CH2)------------正面右舵机

           PA2(TIM2_CH3)------------机械夹舵机

           PA3(TIM2_CH4)------------底部转身舵机

5.蓝牙模块

USART1

           PA9(TX) -------- 蓝牙RX

           PA10(RX)-------- 蓝牙TX

2.驱动模块L298N介绍

      

        电源输入7~12V电压时,5v的位置不用接电源,该位置可输出一个5v,用于给单片机供电,L298N的GND接单片机的GND,一定要共地,( 否则没有参考电压,不能进行正常控制 )。给对应的ENA和ENB引脚使能后,通过给IN1和IN2引脚赋不同的高低电平,实现对应直流减速电机的转动。

举例:(IN1 IN2指的是对应引脚的高低电平)

IN1    IN2       电机状态

0         0            停止

1         1            停止 (同电平时,电机不转动)

1         0            正转

0         1            反转

3.机械臂舵机模块介绍

        脉冲宽度调制(PWM):用于测量,通信功率控制与变换的许多领域,是一种数字信号,最常用于控制电路。该信号在预定义的时间和速度中设置为高(5v或3.3v)和低(0v)。通常,我们将PWM的高电平称为1,低电平为0。PWM 信号是通过比较定时器计数器CK_CNT的当前值与 CCR 中的参考值来生成的。

        PWM占空比在一串理想的脉冲序列(如方波)中,正脉冲的持续时间与脉冲总周期的比值,PWM信号保持高电平的时间百分比称为占空比。如果信号始终为高电平,则它处于100%占空比,如果它始终处于低电平,则占空比为0%。如图1所示,T1为占空比,T为一个PWM周期。

        而SG90舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分。以180度角度伺服为例,那么对应的控制关系是这样的:

   0.5ms--------------0度;

   1.0ms------------45度;

   1.5ms------------90度;

   2.0ms-----------135度;

   2.5ms-----------180度;

注意:平时学校中很多用于比赛的机械臂对舵机要求较高,SG90便宜但是扭矩很小,在比赛夹取物块时很容易烧坏,大家可以选用扭矩更大,性能更稳定的金属舵机平替。

4.蓝牙模块介绍

(1)主从模式介绍

          蓝牙通信的工作频段为2.54GHz的ISM频段。采用高速跳频扩展技术(Frequency Hopping Spread Spectrum,FHSS),提高其抗干扰能力,跳频速度为每秒1600跳。

        蓝牙地址为符合IEEE 802标准的48位地址,每个蓝牙设备都有一个全球唯一的地址码。蓝牙以无线局域网标准IEEE802.11为基础,实现了“即连即用”。

        HC-05蓝牙模块具有两种工作模式:自动连接工作模式和命令响应工作模式。

        在自动连接工作模式下,HC-05模块的工作模式可分为主(Master)、从(Slave)和回环(Loopback)3种。在主模式下,HC-05蓝牙模块会主动搜索周边的蓝牙设备,并发起连接。在从模式下,HC-05模块被动响应配对请求。在回环模式下,HC-05模块被动响应配对请求,建立连接后,会将接收到的数据发回发送方。

        在命令响应工作模式下,模块能响应AT命令。此时用户可以通过串口向HC-05模块发送AT命令,设定模块的工作方式,改变模块的设定参数等,控制HC-05模块的工作。

        HC-05蓝牙模块上的输入引脚EN控制蓝牙模块的工作模式,引脚为高电平时进入命令响应工作模式,为低电平时进入自动连接工作模式。

        模块上的按键控制EN引脚的电平,按下按键时EN引脚上拉为高电平,松开时为低电平,可以通过按键切换蓝牙模块的工作模式。

(2)AT命令

        HC-05蓝牙模块出厂时默认设置为从模式,配对码为1234,波特率为38400bps,1个停止位,没有校验位。

        模块进入命令响应工作模式(即AT模式)后,可以发送AT命令对模块进行配置,如查询模块状态、修改模块参数等。

        AT命令是以字符“AT”开始,以回车换行结束的字符串,AT指令不区分字母大小写。发送AT命令时需要将EN引脚拉高一次,而部分AT命令需要将EN引脚一直设置为高电平才有效。

5.OLED模块介绍(简单了解原理)

        OLED本身是没有显存的,它的显存是依赖于SSD1306提供的。而SSD1306提供一块显存,芯片具体的讲解见下文。SSD1306的显存总共为128*64bit大小,SSD1306将这些显存分为了8页。每页包含了128个字节,总共8页,这样刚好是128*64的点阵大小。

(1) 行地址

        OLED 显示屏通常将其垂直方向(纵向)分为多个页,每页包含一组连续的行。在一个典型的 128x64 像素的 OLED 显示屏中,它通常被分成 8 页,每页 8 行,总共 64 行。每个页对应于显示器中的一个 8 行区域。页地址:页地址用来选择显示区域中的特定页。页地址的选择影响的是显示屏中哪一组 8 行被写入或读取数据。

        如何设置:设置页地址的命令通常以 0xb0 为基地址,加上页的索引值 y。比如,页地址为 0xb0 + y,其中 y 是从 0 到 7 的整数,表示第 y 页。

(2) 列地址

        列地址用于选择显示屏的水平位置,即在选定的页中显示的具体列。列地址:列地址由两个部分组成:高四位和低四位。在 OLED 控制器中,这些高低四位被分别设置,以便选择具体的列位置。

        如何设置:列地址高四位:通常需要设置列地址的高四位,范围从 0 到 15(对应于 16 个可能的列地址高位值)。通常的命令是 0x10 加上列地址的高四位部分。列地址低四位:设置列地址的低四位,范围从 0 到 15(对应于 16 个可能的列地址低位值)。通常的命令是 0x01 加上列地址的低四位部分。

3.驱动部分代码

//1.驱动模块头文件部分的代码 MOTOR.h
#ifndef __MOTOR_H
#define __MOTOR_H


#include "SYS.h"
#include "LED.h"
#include "TIM.h"
#include "PWM.h"

#define		PWM_SetRatio(x)		(TIM3->CCR1=(x),TIM3->CCR2=(x),TIM3->CCR3=(x),TIM3->CCR4=(x))
#define		Motor_Start()			PWM_Start()			//start motor without changing moving direction														
#define		Motor_Stop()			PWM_Stop()
#define		Motor_SetSpeed(x)		PWM_SetRatio(x)  //x in the range of  [300, 900]

void MOTOR_Init(void);
void MOTOR_Forward(void);
void MOTOR_Backward(void);
void MOTOR_leftward(void);
void MOTOR_rightward(void);

#endif


//2.实现驱动部分的实现代码  MOTOR.c
#include "MOTOR.h"

/**
  *@brief  L298N模块的初始化
  *@param  NONE
  *@retval NONE
  **/
void MOTOR_Init(void)
{
	LED_Init();
	TIM_Init(72,1000);
	PWM_Init(201);
}
/*
  前A:PA6---------AENA
       PA7---------AENB
       PB3 PB4 PB5 PB6 控制IN1 IN2 IN3 IN4
  后B:PB0--------BENA
       PB1--------BENB
			 PC0 PC1 PC3 PC2 控制IN1 IN2 IN3 IN4
 */

void MOTOR_Forward(void)	
{
	//前轮部分
	GPIO_WriteBit(GPIOB,GPIO_Pin_4|GPIO_Pin_5,Bit_SET);
	GPIO_WriteBit(GPIOB,GPIO_Pin_3|GPIO_Pin_6,Bit_RESET);
	//后轮部分
	GPIO_WriteBit(GPIOC,GPIO_Pin_0|GPIO_Pin_2,Bit_SET);
	GPIO_WriteBit(GPIOC,GPIO_Pin_1|GPIO_Pin_3,Bit_RESET);
}

void MOTOR_Backward(void)
{
	//前轮部分
	GPIO_WriteBit(GPIOB,GPIO_Pin_3|GPIO_Pin_6,Bit_SET);
	GPIO_WriteBit(GPIOB,GPIO_Pin_4|GPIO_Pin_5,Bit_RESET);
	//后轮部分
	GPIO_WriteBit(GPIOC,GPIO_Pin_1|GPIO_Pin_3,Bit_SET);
	GPIO_WriteBit(GPIOC,GPIO_Pin_0|GPIO_Pin_2,Bit_RESET);
}

void MOTOR_leftward(void)
{
	//后轮部分
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);
	GPIO_WriteBit(GPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_6,Bit_RESET);
	//前轮部分
	GPIO_WriteBit(GPIOC,GPIO_Pin_2,Bit_SET);
	GPIO_WriteBit(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3,Bit_RESET);
}

void MOTOR_rightward(void)
{
  //后轮部分
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);
	GPIO_WriteBit(GPIOB,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_6,Bit_RESET);
	//前轮部分
	GPIO_WriteBit(GPIOC,GPIO_Pin_0,Bit_SET);
	GPIO_WriteBit(GPIOC,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3,Bit_RESET);
}
//1.定时器时基初始化实现代码 TIM.c
#include "TIM.h"
extern uint16_t time;

/**
  *@brief  TIM3的时基初始化
  *@param  psc 精度 arr 量程
  *@retval NONE
  **/
void TIM_Init(uint16_t psc,uint16_t arr)
{
	TIM_TimeBaseInitTypeDef timebaseinit;
	TIM_TimeBaseStructInit(&timebaseinit);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	TIM_Cmd(TIM3,ENABLE);
	timebaseinit.TIM_Prescaler = psc-1;
	timebaseinit.TIM_CounterMode = TIM_CounterMode_Up;
	timebaseinit.TIM_Period = arr-1;
	timebaseinit.TIM_ClockDivision = TIM_CKD_DIV1; //不进行时钟分割
	TIM_TimeBaseInit(TIM3,&timebaseinit);
	TIM_ARRPreloadConfig(TIM3,ENABLE);
}



void TIM2_IRQHandler()
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
	{
		if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1) == 1)
		{
			time++;
		}
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}



//2.驱动模块PWM实现代码 PWM.c
#include "PWM.h"

/**
  *@brief  PWM的初始化
  *@param  pulse  占空比
  *@retval NONE
  **/
void PWM_Init(uint16_t pulse)
{
	#if MY_DRIVER
	//寄存器开发
	#else
	//库函数开发
	TIM_OCInitTypeDef pwminit;
	TIM_OCStructInit(&pwminit);
	pwminit.TIM_OCMode = TIM_OCMode_PWM1;  //设置为PWM1模式
	pwminit.TIM_Pulse = pulse-1;           //设置脉冲宽度 占空比
	pwminit.TIM_OutputState = TIM_OutputState_Disable;
	pwminit.TIM_OCNPolarity = TIM_OCNPolarity_High;   //设置高电平为有效电平
	
	TIM_OC1Init(TIM3,&pwminit);
	TIM_OC2Init(TIM3,&pwminit);
	TIM_OC3Init(TIM3,&pwminit);
	TIM_OC4Init(TIM3,&pwminit);
	
	//预装载功能
	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
	TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
	TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
	TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
	#endif
	
}



void PWM_Start(void)
{
	TIM_CCxCmd(TIM3, TIM_Channel_1, TIM_CCx_Enable);
	TIM_CCxCmd(TIM3, TIM_Channel_2, TIM_CCx_Enable);
	TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Enable);
	TIM_CCxCmd(TIM3, TIM_Channel_4, TIM_CCx_Enable);
}

void PWM_Stop(void)
{
	TIM_CCxCmd(TIM3, TIM_Channel_1, TIM_CCx_Disable);
	TIM_CCxCmd(TIM3, TIM_Channel_2, TIM_CCx_Disable);
	TIM_CCxCmd(TIM3, TIM_Channel_3, TIM_CCx_Disable);
	TIM_CCxCmd(TIM3, TIM_Channel_4, TIM_CCx_Disable);
}

void PWM_ARM_Start(void)
{
	TIM_CCxCmd(TIM2, TIM_Channel_1, TIM_CCx_Enable);
	TIM_CCxCmd(TIM2, TIM_Channel_2, TIM_CCx_Enable);
	TIM_CCxCmd(TIM2, TIM_Channel_3, TIM_CCx_Enable);
	TIM_CCxCmd(TIM2, TIM_Channel_4, TIM_CCx_Enable);
}

void PWM_ARM_Stop(void)
{
	TIM_CCxCmd(TIM2, TIM_Channel_1, TIM_CCx_Disable);
	TIM_CCxCmd(TIM2, TIM_Channel_2, TIM_CCx_Disable);
	TIM_CCxCmd(TIM2, TIM_Channel_3, TIM_CCx_Disable);
	TIM_CCxCmd(TIM2, TIM_Channel_4, TIM_CCx_Disable);
}



4.机械臂控制部分代码

//1.机械臂舵机部分头文件代码 MEROBOTICARM.h
#ifndef __MEROBOTICARM__H
#define __MEROBOTICARM__H

#include "SYS.h"

#define		ARM_Start()			PWM_ARM_Start()			//start motor without changing moving direction														
#define		ARM_Stop()			PWM_ARM_Stop()

void MEARM_Init(void);
void PWM_SetCompare1(uint16_t compare);
void PWM_SetCompare2(uint16_t compare);
void PWM_SetCompare3(uint16_t compare);
void PWM_SetCompare4(uint16_t compare);



#endif


//2.机械臂舵机部分实现代码 MEROBOTICARM.c
#include "MEROBOTICARM.h"

//对机械臂的控制就是对四个舵机的控制 PS2手柄遥控改变的是舵机的转动角度

//机械臂四个舵机
//PA0(TIM2_CH1)------------正面左舵机
//PA1(TIM2_CH2)------------正面右舵机
//PA2(TIM2_CH3)------------机械夹舵机
//PA3(TIM2_CH4)------------底部转身舵机

/**
  *@brief  对四个舵机及引脚的初始化
  *@param  NONE  舵机的时基配置为 72 20000 <=> 20ms
  *@retval NONE
  **/
void MEARM_Init(void)
{
	//库函数开发
	GPIO_InitTypeDef gpioinit;
	TIM_TimeBaseInitTypeDef timeinit;
	TIM_OCInitTypeDef pwminit;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	GPIO_StructInit(&gpioinit);
	gpioinit.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	gpioinit.GPIO_Mode =GPIO_Mode_AF_PP;
	gpioinit.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpioinit);
	
	TIM_TimeBaseStructInit(&timeinit);
	timeinit.TIM_CounterMode = TIM_CounterMode_Up;
	timeinit.TIM_Prescaler = 72-1;
	timeinit.TIM_Period = 20000-1;
	timeinit.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInit(TIM2,&timeinit);
	TIM_ARRPreloadConfig(TIM2,ENABLE);
	
	TIM_OCStructInit(&pwminit);
	pwminit.TIM_OCMode = TIM_OCMode_PWM1;     //对于舵机采用PWM1模式
	pwminit.TIM_Pulse = 0;
	pwminit.TIM_OCPolarity = TIM_OCPolarity_High;
	pwminit.TIM_OutputState = TIM_OutputState_Enable;
	
	TIM_OC1Init(TIM2,&pwminit);
	TIM_OC2Init(TIM2,&pwminit);
	TIM_OC3Init(TIM2,&pwminit);
	TIM_OC4Init(TIM2,&pwminit);
	
	TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);
	TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);
	TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable);
	TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);
	
	TIM_Cmd(TIM2,ENABLE);
}

/**
  *@brief    设置TIM2_CH1,2,3,4的PWM输出占空比 
  *@param    compare
  *@retval   NONE
  */
void PWM_SetCompare1(uint16_t compare)  //PA0 正面左舵机
{
	TIM_SetCompare1(TIM2,compare);
}

void PWM_SetCompare2(uint16_t compare)  //PA1 正面右舵机
{
	TIM_SetCompare2(TIM2,compare);
}

void PWM_SetCompare3(uint16_t compare)  //PA2 机械夹舵机
{
	TIM_SetCompare3(TIM2,compare);
}

void PWM_SetCompare4(uint16_t compare)  //PA3 机械臂底部舵机
{
	TIM_SetCompare4(TIM2,compare);
}

        重复的舵机初始化代码,大家掌握熟悉舵机的控制后,可根据自己对应定时器的通道更改自己的代码配置。

5.蓝牙遥控部分代码

//1.蓝牙遥控部分代码的头文件 Bluetooth.h
#ifndef __BLUETOOTH__H
#define __BLUETOOTH__H

#include "SYS.h"
#include "EXTI.h"
#include "MOTOR.h"
#include "MEROBOTICARM.h"


void Bluetooth_USART1_Init(void);
void Bluetooth_MOTOR(void);
#endif


//2.蓝牙遥控部分代码的实现 Bluetooth.c
#include "Bluetooth.h"

extern uint8_t rx_end;
extern uint16_t rx_data;

//USART1
//PA9(TX) -------- 蓝牙RX
//PA10(RX)-------- 蓝牙TX

/**
  *@brief  蓝牙模块的NVIC初始化
  *@param  NONE
  *@retval NONE
  **/
void Bluetooth_NVIC_Init(void)
{
	
	NVIC_InitTypeDef nvicinit;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	nvicinit.NVIC_IRQChannel = USART1_IRQn;
	nvicinit.NVIC_IRQChannelPreemptionPriority = 0;
	nvicinit.NVIC_IRQChannelSubPriority = 1;
	nvicinit.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&nvicinit);
	
}

//USART1
//PA9(TX) -------- 蓝牙RX
//PA10(RX)-------- 蓝牙TX

/**
  *@brief  蓝牙模块串口1的初始化
  *@param  NONE
  *@retval NONE
  **/
void Bluetooth_USART1_Init(void)
{
	GPIO_InitTypeDef gpioinit;
	USART_InitTypeDef usartinit;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//配置TX引脚 PA10  PA10(RX)
	gpioinit.GPIO_Pin = GPIO_Pin_10;
	gpioinit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioinit.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpioinit);

   //配置RX引脚 PA9
    gpioinit.GPIO_Pin = GPIO_Pin_9;
	gpioinit.GPIO_Mode = GPIO_Mode_Out_PP;
	gpioinit.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpioinit);
	
	//串口通信USART1
	usartinit.USART_BaudRate = 115200;
	usartinit.USART_WordLength =USART_WordLength_8b;
	usartinit.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	usartinit.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
	usartinit.USART_Parity = USART_Parity_No;
	usartinit.USART_StopBits = USART_StopBits_1;
	
	USART_Init(USART1,&usartinit);
	Bluetooth_NVIC_Init();
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);    //使能接收中断
	USART_Cmd(USART1,ENABLE);
}

void Bluetooth_MOTOR(void)
{
	if(rx_end)
	{
		rx_end = 0;
		GPIO_WriteBit(GPIOD,GPIO_Pin_2,Bit_RESET);
		if(rx_data == 'F')  //前进
		{
			Motor_Start();
			MOTOR_Forward();
			Motor_SetSpeed(1500);
			GPIO_WriteBit(GPIOD,GPIO_Pin_2,Bit_SET);
		}
		else if(rx_data == 'B')  //后退
		{
			Motor_Start();
			MOTOR_Backward();
			Motor_SetSpeed(1800);
			GPIO_WriteBit(GPIOD,GPIO_Pin_2,Bit_RESET);
		}
		else if(rx_data == 'L')  //左转
		{
			Motor_Start();
			MOTOR_leftward();
			Motor_SetSpeed(1800);   
		}
		else if(rx_data == 'R')  //右转
		{
			Motor_Start();
			MOTOR_rightward();
			Motor_SetSpeed(1800);
		}
		else if(rx_data == 'S')   //刹车
		{
			Motor_Stop();
		}
		else if(rx_data == '4')   //机械臂底部向左转
		{
			ARM_Start();
			MEARM_Init();
			PWM_SetCompare4(500);
		}
		else if(rx_data ==  '6')   //机械臂底部向右转
		{
			ARM_Start();
			MEARM_Init();
			PWM_SetCompare4(1800);
		}
		else if(rx_data == '8')   //夹子打开  //1800->1000   开-合
		{
			ARM_Start();
			MEARM_Init();
			PWM_SetCompare3(1200);
		}
		else if(rx_data == '2')   //夹子闭合
		{
			ARM_Start();
			PWM_SetCompare3(700);
		}
		else if(rx_data == '7')   //左舵机下降(前伸)   //600->1500   降-升
		{
			ARM_Start();
			PWM_SetCompare1(600);
		}
		else if(rx_data == '1')   //左舵机上升(后退)
		{
			ARM_Start();
			PWM_SetCompare1(1500);
		}
		else if(rx_data == '9')   //右舵机下降(前伸)  //2500->1800  降-升
		{
			ARM_Start();
			PWM_SetCompare2(2500);
		}
		else if(rx_data == '3')   //右舵机上升(后退)
		{
			ARM_Start();
			PWM_SetCompare2(1800);
		}
	}
}

        1.初始化蓝牙串口:通过Bluetooth_USART1_Init初始化串口和GPIO,配置USART通信。
        2.接收命令:通过蓝牙接收数据并存储在rx_data中,判断命令并根据命令执行不同的动作。Bluetooth_MOTOR()函数实现了对机器人运动和机械臂的控制,具体操作基于从蓝牙模块接收到的数据(rx_data),根据接收到的命令控制电机和机械臂动作。通过判断rx_end是否为1:如果接收到完整数据,则rx_end会被设置为1,表示可以处理接收到的数据并执行相应动作。
        3.控制运动和机械臂:根据接收到的命令,控制电机、机械臂的运动,改变电机的速度和位置。

6.结束语

        这里的蓝牙调试器选取网络上常见的安卓手机蓝牙调试器即可。有问题欢迎评论留言交流,希望大家都可以顺利做出自己的蓝牙遥控小车。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐