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

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

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


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

效果如演示视频所示。

目录
相关文章
|
Shell 开发工具 git
Git获取本地仓库及基础操作指令
Git获取本地仓库及基础操作指令
316 0
|
7月前
|
人工智能 数据可视化 算法
FISSPACE 技术白皮书节选|因果自导机制(Causal Self-Guidance Mechanism)
FISSPACE提出因果自导机制(CSG),让智能体从被动训练迈向自主演化。通过内部能量流、压痕反馈与因果梯度闭环,构建具备自我修正与成长能力的智能系统,实现无外部奖励下的内驱进化,推动AI走向具有方向与意志的自演化时代。(238字)
389 1
|
Web App开发 安全 应用服务中间件
Burpsuite工具的代理抓包功能实验
Burpsuite工具的代理抓包功能实验
|
10月前
|
SQL 人工智能 分布式计算
在数据浪潮中前行:我与ODPS的实践、思考与展望
在数据驱动决策的时代,企业如何高效处理海量数据成为数字化转型关键。本文结合作者实践,深入解析阿里云自研大数据平台 ODPS 的技术优势与应用场景,涵盖 MaxCompute、DataWorks、Hologres 等核心产品,分享从数据治理到实时分析的落地经验,并展望其在 AI 与向量数据时代的发展前景。
368 70
|
监控 前端开发 JavaScript
|
11月前
|
Java
银行转账p图软件,对公转账截图生成器,java版开发银行模拟器【仅供学习参考】
这是一套简单的银行账户管理系统代码,包含`BankAccount`和`BankSystem`两个核心类。`BankAccount`负责单个账户的管理
|
机器学习/深度学习 算法 安全
提高人脸识别识别率技术
智能工厂趋势中,人脸识别技术在提升生产效率和安全管理方面展现应用价值。技术挑战包括环境光线控制、背景干扰、数据多样性和算法优化。解决方案涉及模型选择、实时性与准确性平衡,以及使用标签平滑技术减轻模型过拟合,提高泛化能力。通过训练优化的CNN模型,结合数据增强和标签平滑,实现更精准的人脸识别系统。
|
数据采集 人工智能 分布式计算
探索 MaxCompute MaxFrame:AI 数据预处理的高效之选
探索 MaxCompute MaxFrame:AI 数据预处理的高效之选

热门文章

最新文章