保姆级教学 基于HAL库的蓝牙四组机器人

自己在刷B站的时候,看见很多大佬自己手工做的四组机器人,要知道,没有一个男人可以拒绝这些可以动的机器的时候,都是没有抵抗力的,我自己也不例外,如何自己也在犹豫,要不要自己也做一个,说实话自己做的时候也没有底气,因为自己也觉得很困难,有点不相信自己,但是还是鼓起勇气做了一个,慢慢的自己也学到了一些东西,而且对电路也有了认识,我自己也觉得是一个还不错的项目,而且还没有想象的那么难,比较简单,但是做起来还是蜿蜒曲折,做的时候走了不少的弯路,所以在这分享给各位,如果对各位有帮助,那也挺不错的,如果有大佬看出有什么不足,还请大佬指出来,比较自己也是一个小白,学习的过程在于交流。

需要的材料

需要的耗材其实也不是很多,在淘宝上也比较便宜,

首先就是机器人的灵魂,主控板:stm32f103c8t6

这个随便那个店铺都可以,现在stm32也是白菜价,买几个也无所谓,我推荐还是买没有焊的,比较比较便宜嘛,自己拿回来焊一下,可以给自己省几块钱

然后就是蓝牙模块,主要是用于控制机器人的运动,这个买一个CH-05或者CH-06啊什么的都可以,毕竟蓝牙不需要自己写代码,插上就能用。

然后就是舵机的控制板,因为涉及到的舵机比较多,所以舵机不能直接连接到stm32上,不然浪费stm32的资源不说,供电也容易把板子烧了。

可以看见这样一个板子可以驱动16路舵机哈,而且只需要连接四根线,还是比较强大的这个板子。

然后就是机器人的身体了,这个身体是3D打印出来的,在网上买的也比较贵,就光买一个支架差不多都要四五十米,我也会把3D打印的图纸放在最下面,如果有条件的可以自己打印,实在不行也可以自己去买一个。

最后就是舵机了,因为需要的舵机有点多,需要八个,这个看各位自己了,但是我建议用SG90,虽然这个只能转180度,但是别的舵机塞不进去这个身体里面,反正我是没有塞进去,所以我才建议SG90。

串口通信

然后我们开始着手串口通信,其实用蓝牙连接串口很简单,都不需要自己些代码,用HAL库直接生成,然后直接调用就行了。

先来看HAL库把。

然后可以看见,就这三步串口就可以说已经生成好了,然后我波特率用的是9600,要和自己设置蓝牙的波特率一致不然单片机接收不到数据。然后进入工程直接调用就好了,但要记住,把外部时钟打开,还要开到72兆话不多说上个图。

然后就可以开始写代码了,代码也很简单,直接调用就好了,但是要把蓝牙设置为从机模式,我之前也遇到了,明明直接用就可以了,但是单片机就是没有反应,最后绕了很久才知道,要把蓝牙设置为从机模式,这个软件等一会我也放到云盘里面。

先给大家看看怎么设置从机模式。

可以看见啊,只需要打开串口,然后点两下,就设置完成了,还是比较简单的。

然后就是代码,可以看见啊,就自己定义了一个变量,然后接一下线就可以了,就直接可以用了。

int main(void)
{
  /* USER CODE BEGIN 1 */
    uint8_t RX;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
    
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  printf("AT+ROLE=S");
//    HAL_UART_Transmit(&huart1,"11111\r\n",7,HAL_MAX_DELAY);
  while ( 1 )
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      HAL_UART_Receive(&huart1,&RX,1,HAL_MAX_DELAY);//接收函数    
        if(RX == '1')
        {
            HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
        }
        else if(RX == '2')
        {
            HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
        }
}

PAC9685

然后串口写完了,就是轮到了PAC9685,这个模块需要一个驱动代码,这个也是我找的一个大佬的代码,写的非常好,也很详细,如果有兴趣可以去看看:(54条消息) 使用CodeMX配置stm32单片机实现对PCA9685的控制_田小呱的博客-CSDN博客,然后这个PAC9685需要用I2C驱动,这里把步骤给大家看一下。

其实根本不用设置,这个些都是默认设置,把I2C打开就好了。然后就是PAC9685:

这个是.C文件

#include "stm32_pca9685.h"
#include "math.h"
#include "i2c.h"

uint8_t pca_read(uint8_t startAddress) {
    //Send address to start reading from.
    uint8_t tx[1];
    uint8_t buffer[1];
    tx[0]=startAddress;

    HAL_I2C_Master_Transmit(&hi2c1,pca_adrr, tx,1,10000);
    HAL_I2C_Master_Receive(&hi2c1,pca_adrr,buffer,1,10000);
    return buffer[0];
}

void pca_write(uint8_t startAddress, uint8_t buffer) {
    //Send address to start reading from.
    uint8_t tx[2];
    tx[0]=startAddress;
    tx[1]=buffer;
    HAL_I2C_Master_Transmit(&hi2c1,pca_adrr, tx,2,10000);

}

void pca_setfreq(float freq)//设置PWM频率
{
        uint8_t prescale,oldmode,newmode;
        double prescaleval;
        freq *= 0.92; 
        prescaleval = 25000000;
        prescaleval /= 4096;
        prescaleval /= freq;
        prescaleval -= 1;
        prescale =floor(prescaleval + 0.5f);

        oldmode = pca_read(pca_mode1);
    
        newmode = (oldmode&0x7F) | 0x10; // sleep
    
        pca_write(pca_mode1, newmode); // go to sleep
    
        pca_write(pca_pre, prescale); // set the prescaler
    
        pca_write(pca_mode1, oldmode);
        HAL_Delay(2);
    
        pca_write(pca_mode1, oldmode | 0xa1); 
}

void pca_setpwm(uint8_t num, uint32_t on, uint32_t off)
{
        pca_write(LED0_ON_L+4*num,on);
        pca_write(LED0_ON_H+4*num,on>>8);
        pca_write(LED0_OFF_L+4*num,off);
        pca_write(LED0_OFF_H+4*num,off>>8);
}
/*num:舵机PWM输出引脚0~15,on:PWM上升计数值0~4096,off:PWM下降计数值0~4096
一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时
跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,
off/4096的值就是PWM的占空比。*/

/*
    函数作用:初始化舵机驱动板
    参数:1.PWM频率
          2.初始化舵机角度
*/
void PCA_MG9XX_Init(float hz,uint8_t angle)
{
    uint32_t off=0;
//    IIC_Init();
    pca_write(pca_mode1,0x0);
    pca_setfreq(hz);//设置PWM频率
    off=(uint32_t)(145+angle*2.4);
    pca_setpwm(0,0,off);pca_setpwm(1,0,off);pca_setpwm(2,0,off);pca_setpwm(3,0,off);
    pca_setpwm(4,0,off);pca_setpwm(5,0,off);pca_setpwm(6,0,off);pca_setpwm(7,0,off);
    pca_setpwm(8,0,off);pca_setpwm(9,0,off);pca_setpwm(10,0,off);pca_setpwm(11,0,off);
    pca_setpwm(12,0,off);pca_setpwm(13,0,off);pca_setpwm(14,0,off);pca_setpwm(15,0,off);
    HAL_Delay(500);
}

/*
    函数作用:控制舵机转动;
    参数:1.输出端口,可选0~15;
          2.起始角度,可选0~180;
          3.结束角度,可选0~180;
          4.模式选择,0 表示函数内无延时,调用时需要在函数后另外加延时函数,且不可调速,第五个参数可填任意值;
                      1 表示函数内有延时,调用时不需要在函数后另外加延时函数,且不可调速,第五个参数可填任意值;
                      2 表示速度可调,第五个参数表示速度值;
          5.速度,可填大于 0 的任意值,填 1 时速度最快,数值越大,速度越小;
    注意事项:模式 0和1 的速度比模式 2 的最大速度大;
*/
void PCA_MG9XX(uint8_t num,uint8_t end_angle)
{
    uint32_t off=0;
    
    off=(uint32_t)(158+end_angle*2.2);
    pca_setpwm(num,0,off);
}

这个是.h文件

#ifndef __STM32PCA9685_H
#define __STM32PCA9685_H    

//#include "stm32f10x.h"
#include "stm32f1xx_hal.h"

#define pca_adrr 0x80

#define pca_mode1 0x0
#define pca_pre 0xFE

#define LED0_ON_L 0x6
#define LED0_ON_H 0x7
#define LED0_OFF_L 0x8
#define LED0_OFF_H 0x9

#define jdMIN  115 // minimum
#define jdMAX  590 // maximum
#define jd000  130 //0度对应4096的脉宽计数值
#define jd180  520 //180度对应4096的脉宽计算值


void pca_write(uint8_t adrr,uint8_t data);
uint8_t pca_read(uint8_t adrr);
void PCA_MG9XX_Init(float hz,uint8_t angle);
void pca_setfreq(float freq);
void pca_setpwm(uint8_t num, uint32_t on, uint32_t off);
void PCA_MG9XX(uint8_t num,uint8_t end_angle);

#endif

这个把I2C打开了直接用就好了然后看一下调用把

int main(void)
{
  /* USER CODE BEGIN 1 */
    uint8_t RX;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
    
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
    PCA_MG9XX_Init(65,90);//初始化舵机驱动
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  printf("AT+ROLE=S");
//    HAL_UART_Transmit(&huart1,"11111\r\n",7,HAL_MAX_DELAY);
  while ( 1 )
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      HAL_UART_Receive(&huart1,&RX,1,HAL_MAX_DELAY);//接收函数    
        if(RX == '1')
        {
            PCA_MG9XX(2,50); //通道0 从0度转到180度
            PCA_MG9XX(1,100); //通道2 从0度转到180度
            HAL_Delay(200);
            PCA_MG9XX(9,70); //通道0 从0度转到180度
            PCA_MG9XX(0,40); //通道0 从180度转到0度
            PCA_MG9XX(2,120); //通道0 从0度转到180度
            PCA_MG9XX(1,30); //通道2 从0度转到180度
            PCA_MG9XX(3,170); //通道0 从0度转到180度
            HAL_Delay(200);
            PCA_MG9XX(0,100); //通道0 从180度转到0度
            PCA_MG9XX(2,120); //通道0 从0度转到180度
            PCA_MG9XX(1,30); //通道2 从0度转到180度
            PCA_MG9XX(3,110); //通道0 从0度转到180度
            
            HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
        }
        else if(RX == '2')
        {
            PCA_MG9XX(0,140); //通道0 从180度转到0度
            PCA_MG9XX(1,10); //通道0 从180度转到0度
            PCA_MG9XX(2,50); //通道2 从180度转到0度
            PCA_MG9XX(3,160); //通道0 从0度转到180度
            
            HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
//            HAL_UART_Transmit(&huart1,"led two\r\n",6,HAL_MAX_DELAY);
        }
}
  1. 然后就好了,然后把接线图和程序都放到一起,程序写的很散,如果有大佬发现问题,希望直接指出来,如果有不懂的,也可以直接问我,我们互相学习,互相进步,创作不易,如果有人看到这里,希望点给赞,我会很开心的

链接:https://pan.baidu.com/s/12EmAttUPv-b8qysu2D9wiQ?pwd=1234

提取码:1234

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值