开源:智能宠物弹射喂食器连载贴之步进电机控制(二)

简介: 开源:智能宠物弹射喂食器连载贴之步进电机控制(二)

想要从云端控制宠物自动喂食器,最重要的部分就是电机啦,电机的作用就是用于将装在食物储物槽里的食物倒出来供宠物食用,如下图所示,这是某宝常见的一款宠物喂食器产品,其实下图所示动力舱其实就是一个电机,用于控制出料。


640.png

640.png

涂鸦官方推荐此时需要用一个减速电机来完成这个产品的设计,然而我手上没有这个电机,所以我就用步进电机来代替了,一样也可以完成这个功能,那么如何来实现呢?先来看看实验效果:


我手上的这个是一个步进模块:

640.png

步进电机选用的型号是:28BYJ48-H12

640.png

这里在软件编程上有一个比较重要参数需要了解一下,就是步距角。那么什么是步距角呢?度娘给你答案,可以详细看看。

https://baike.baidu.com/item/%E6%AD%A5%E8%B7%9D%E8%A7%92/5946465?fr=aladdin

来看看下面这个换算公式,或许你就明白了。如上图所示,步距角=5.625°/64,意思就是每64个脉冲步进电机就会转5.625度,因此我们很容易得出以下计算公式:电机转一圈有360°,那么转一圈的脉冲数 = 360 / 5.625 * 64 = 4096 个脉冲。进而很容易得到以下角度与脉冲的简单算法:

/*
 Rotation_Angle:旋转角度
 返回:Motor_Pulse 根据公式计算得出的脉冲个数
*/
int Motor_Angle_Cal(int Rotation_Angle)
{
 if(Rotation_Angle < 0 || Rotation_Angle > 360)
      return -1 ;
    Motor_Pulse = (int)((double)(Rotation_Angle / 5.625) * 64) ;
    return Motor_Pulse ;
}

下面开始在CubeMX上配置管脚,然后编写程序:

640.png

编写步进电机驱动程序:


motor.h

#ifndef __MOTOR_H
#define __MOTOR_H
#include "main.h"
//4相控制定义
#define MOTOR_A_ON  HAL_GPIO_WritePin(MOTOR_A_GPIO_Port, MOTOR_A_Pin, GPIO_PIN_SET);
#define MOTOR_A_OFF HAL_GPIO_WritePin(MOTOR_A_GPIO_Port, MOTOR_A_Pin, GPIO_PIN_RESET);
#define MOTOR_B_ON  HAL_GPIO_WritePin(MOTOR_B_GPIO_Port, MOTOR_B_Pin, GPIO_PIN_SET);
#define MOTOR_B_OFF HAL_GPIO_WritePin(MOTOR_B_GPIO_Port, MOTOR_B_Pin, GPIO_PIN_RESET);
#define MOTOR_C_ON  HAL_GPIO_WritePin(MOTOR_C_GPIO_Port, MOTOR_C_Pin, GPIO_PIN_SET);
#define MOTOR_C_OFF HAL_GPIO_WritePin(MOTOR_C_GPIO_Port, MOTOR_C_Pin, GPIO_PIN_RESET);
#define MOTOR_D_ON  HAL_GPIO_WritePin(MOTOR_D_GPIO_Port, MOTOR_D_Pin, GPIO_PIN_SET);
#define MOTOR_D_OFF HAL_GPIO_WritePin(MOTOR_D_GPIO_Port, MOTOR_D_Pin, GPIO_PIN_RESET);
extern int direction  ;
extern uint16_t Motor_Pulse ;
//电机脉冲计算
int Motor_Angle_Cal(int Rotation_Angle);
//电机8节拍控制
void MOTOR_CONTROLD(uint8_t step, uint8_t direction);
//关闭电机
void CLOSE_MOTOR(void);
#endif //__MOTOR_H

motor.c

#include "Motor.h"
//电机旋转的方向
int direction = 0 ;
//电机旋转的脉冲个数
uint16_t Motor_Pulse = 0 ;
//电机控制,采用8节拍来做
//A->AB->B->BC->C->CD->D->DA
void MOTOR_CONTROLD(uint8_t step, uint8_t direction)
{
    uint8_t __step = step ;
    //判断电机的旋转方向,如果为1,则逆向旋转
    if(1 == direction)
        __step = 8 - step ;
    switch(__step)
    {
        //A
        case 0:
            MOTOR_A_ON;
            MOTOR_B_OFF;
            MOTOR_C_OFF;
            MOTOR_D_OFF;
            break ;
        //AB
        case 1:
            MOTOR_A_ON;
            MOTOR_B_ON;
            MOTOR_C_OFF;
            MOTOR_D_OFF;
            break ;
        //B
        case 2:
            MOTOR_A_OFF;
            MOTOR_B_ON;
            MOTOR_C_OFF;
            MOTOR_D_OFF;
            break ;
        //BC
        case 3:
            MOTOR_A_OFF;
            MOTOR_B_ON;
            MOTOR_C_ON;
            MOTOR_D_OFF;
            break ;
        //C
        case 4:
            MOTOR_A_OFF;
            MOTOR_B_OFF;
            MOTOR_C_ON;
            MOTOR_D_OFF;
            break ;
        //CD
        case 5:
            MOTOR_A_OFF;
            MOTOR_B_OFF;
            MOTOR_C_ON;
            MOTOR_D_ON;
            break ;
        //D
        case 6:
            MOTOR_A_OFF;
            MOTOR_B_OFF;
            MOTOR_C_OFF;
            MOTOR_D_ON;
        //DA
        case 7:
            MOTOR_A_ON;
            MOTOR_B_OFF;
            MOTOR_C_OFF;
            MOTOR_D_ON;
            break ;
    }
}
//关闭电机
void CLOSE_MOTOR(void)
{
  MOTOR_A_OFF;
  MOTOR_B_OFF;
  MOTOR_C_OFF;
  MOTOR_D_OFF;
}
/*
 Rotation_Angle:旋转角度
 返回:Motor_Pulse 根据公式计算得出的脉冲个数
*/
int Motor_Angle_Cal(int Rotation_Angle)
{
 if(Rotation_Angle < 0 || Rotation_Angle > 360)
      return -1 ;
    Motor_Pulse = (int)((double)(Rotation_Angle / 5.625) * 64) ;
    return Motor_Pulse ;
}

编写主程序控制逻辑,在这里我们采用嘀嗒定时器来驱动步进电机:

640.png

我们在中断服务函数这个文件这里讲嘀嗒定期器产生的中断处理添加到这里,跳转进去发现这是个弱函数,也就是带__weak关键字修饰的,这并不是标准C的语法,而是拓展的,并没有实现。加上了__weak修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak声明的函数,并且编译器不会报错。所以我们可以在别的地方定义一个相同名字的函数,而不必也尽量不要修改之前的函数。

640.png

接下来我们定义个跟这个弱函数一模一样的处理函数,实现它。


main.c

/* USER CODE BEGIN 4 */
void HAL_SYSTICK_Callback(void)
{
    static uint8_t step = 0 ;
    //如果当前设置的脉冲数不为0
    if(Motor_Pulse)
    {
        //控制步进电机旋转
        MOTOR_CONTROLD(step, direction);
        step++ ;
        if(8 == step)
          step = 0 ;
        //脉冲计数不断减,当减到0时,说明控制到位,即需要执行else的关闭电机步骤。
        Motor_Pulse-- ;
    }
    else
    {
        //关闭电机
        CLOSE_MOTOR();
    }
}

然后在下行指令区调用电机转动函数即可:

640.png

效果如演示视频所示。

目录
相关文章
|
前端开发 芯片
【芯片前端】保持代码手感——交通灯
【芯片前端】保持代码手感——交通灯
|
3月前
|
人工智能 自然语言处理 搜索推荐
博物馆地图导览系统:GIS与蓝牙定位技术实现地图导览与语音解说功能
维小帮博物馆地图导览系统结合GIS地图、蓝牙定位及智能语音解说,为访客提供沉浸式导览。系统采用自研地图引擎,精准构建三维模型,支持路径规划与个性化定制。蓝牙技术实现高精度室内定位及自动触发语音解说功能,无需手动操作。系统还支持多语言解说与AI语音生成,提升参观体验。目前已在多个博物馆应用并获好评。期待与您共同推进文化科技的融合发展!
117 3
|
6月前
|
传感器 算法 机器人
LabVIEW开发聋哑人智能辅助手套
LabVIEW开发聋哑人智能辅助手套
38 0
LabVIEW开发聋哑人智能辅助手套
|
6月前
|
人工智能 前端开发 JavaScript
家居智能灯光窗帘控制器的设计与制作
家居智能灯光窗帘控制器的设计与制作
HMI-29-【运动模式】转速表实现及中心油耗仪表实现
今天我要搞得就是中心的这个表,指针的是转速表 中心显示的油耗表。
HMI-29-【运动模式】转速表实现及中心油耗仪表实现
|
传感器 芯片
聊聊身边的嵌入式,方便好用的人体感应灯
聊聊身边的嵌入式,方便好用的人体感应灯
|
存储 物联网 开发工具
开源:纯手工基于小熊派&涂鸦三明治模组快速打造一款智能宠物喂食器连载贴(一)
开源:纯手工基于小熊派&涂鸦三明治模组快速打造一款智能宠物喂食器连载贴(一)
463 0
|
算法 Linux Android开发
动手智能小车记(5)-坦克底盘硬件模块大杂烩
动手智能小车记(5)-坦克底盘硬件模块大杂烩
245 0
五款炫酷精美动态登录页面,彩虹气泡动态云层深海灯光水母炫酷星空蛛网HTMLCSS源码
五款炫酷精美动态登录页面,彩虹气泡动态云层深海灯光水母炫酷星空蛛网HTMLCSS源码
142 0
|
数据挖掘
STM32入门开发: 制作红外线遥控器(智能居家-万能遥控器)
STM32入门开发: 制作红外线遥控器(智能居家-万能遥控器)
915 0
STM32入门开发: 制作红外线遥控器(智能居家-万能遥控器)