发帖
8 0 0

用Ai-Thinker-WB2做一个简易的编码器

WildboarG
金牌会员

12

主题

132

回帖

2943

积分

金牌会员

积分
2943
Ai-WB2系列 90 8 前天 16:44
[i=s] 本帖最后由 WildboarG 于 2025-2-20 17:30 编辑 [/i]

用Ai-Thinker-WB2做一个简易的编码器

Static Badge Static Badge

引言

最近在搬运美化官方提供的API, 搬运的API已经完成,还有汉化中文版!方便我这种没过46级的小白快速参考!顺带又把我收藏吃灰的AI-WB2-12F拿出来,试着用它做一些简单可玩的项目,加深一下理解。

ps 一直在入门啊!

关于

最近刚好在自制简易的编码器,顺道分享一下我的思路,有更好的方案,欢迎评论区讨论分享。

既然是再一次入门,那就再搬一次园长和各位大佬的帖子,带大家再捋一下WB2的API,如有不足,还请各位指正。

GPIO

概念


通用型之输入输出(General-purpose input/output,通常称为GPIO),GPIO管理功能提供GPIO控制寄存器,实现软件对 GPIO 属性的配置,使用户能够方便地操作 GPIO。每个GPIO可以配置为输入、输出和可选功能三种模式。在每个模式下(除模拟可选功能),提供设置上拉,下拉,浮空三种端口状态,此外GPIO还提供中断功能,可以配置为上升沿触发,下降沿触发或者高电平/低电平触发。

Ai-WB2的 GPI0主要特点:

  • 配置为普通输入输出功能,该模式下可以设定上拉,下拉或者浮空输入输出
  • 配置为可选功能,搭配外设功能使用,可以设定上拉,下拉,在使用模拟功能时,必须设置为浮空
  • 设置驱动能力,以提供更大的输出电流
  • 设置施密特触发器功能,提供简单硬件防抖功能

每个GPIO可以通过软件配置为:

  1. 高阻输入
  2. 上拉输入
  3. 下拉输入
  4. 上拉中断输入
  5. 下拉中断输入
  6. 高阻中断输入
  7. 上拉输出
  8. 下拉输出
  9. 高阻输出
  10. 模拟输入可选功能
  11. 模拟输出可选功能
  12. 数字可选功能

GPIO的功能框图如下:

每个GPIO基本上都可以选择一些可选功能:

不同于STM32将复用功能放在指定引脚上,WB2的可选功能有些可以定义在任意引脚上

比如:stm32串口uart1 的发送接收功能一般就固定在GPIO PA9 PA10的复用功能上,但是WB2 是可以任意指定;假如GPIO0 复用功能选择UART,默认与之对应串口的RTS功能,加入我想强制他是UART发送的功能,只需要UART_SIGO_SEL 设置为6

功能

  • 通用输入输出
  • 可选与外设(uart,adc,dac,spi)搭配使用
  • 中断

举个栗子:

如何将WB2的各个针脚设置为普通gpio功能:

  1. 通过设定func_sel 选定GPIO 为 SWGPIO
  2. 设置输入输出方向
  3. IE:INPUT enbale 输入使能 ,1有效 0无效 | OE:OUTPUT enable输出时能
  4. IE和OE只能选一个有效,不然就冲突了!!!
  5. 还可以通过SMT控制位来决定是否启用施密特触发器(这个玩意很有用,硬件过滤抖动)
  6. 通过PD PU决定是否开启上拉
  7. 最后如果是输入,那个就通过读取GPIO_I寄存器对应的位获取电平。如果是输出,引脚就会通过GPIO_O寄存器设置对应的电平
  8. 可选功能亦是如此

相关API

不知道函数怎么用就去看对应的GPIO API 有相应的注解

硬件准备


  • AI-WB2-12F (多一些针脚的也行)
  • RGB 板载自带
  • 数据线
  • 杜邦线
  • 红外对射模块AEDS-9300
  • 光栅板
  • 比较器LM393

需求分析


编码器本质就是一个速度很快的计数器,所以我打算采用GPIO的外部中断实现计数,再配合光栅旋转不停的遮盖红外灯,实现一个简易的编码器。

可能会存在的问题: gpio中断抖动误触发导致计数值大的离谱

但是! WB2可是内置了施密特触发器,施密特触发器硬件防抖。搞!

原理分析

原理图.png

  1. 当光栅遮住红外对射模块,接收信号不导通,导致2IN+ 为高电平,假设电源VCC 是5V 那么2IN+此时就是5V
  2. 2IN-一直保持为2.5V (比例分压)
  3. LM393是比较器,工作原理就是正极大于负极时out端输出高电平,同理,负极大于正极out输出低电平。
  4. 那么,当遮挡光电开关2OUT输出高电平,led熄灭
  5. 相反,拿开2OUT输出低电平,LED点亮
    用上图连接我的WB2 OUT1连接到我的中断触发引脚IO4 ,就可以通过中断触发来计数。

代码

#include <blog.h>
#include <hosal_gpio.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>


#define LED_PIN 3  //用板子LED亮灭来观测是否触发了中断
#define TIGGER_PIN 4

// #define TAG "gpio_exti"

static bool led_state = false;
static hosal_gpio_dev_t led;
static hosal_gpio_dev_t tigger;

static int32_t counter = 0; // 计数值
static uint8_t value;


// 初始化灯
static void init_led(void) {
  led.port = LED_PIN;
  led.config = OUTPUT_PUSH_PULL;
  hosal_gpio_init(&led);
  printf("led inited\r\n");
}

// 中断回调
static void tigger_irq_callback(void *arg) {
  uint16_t i = 1000;
  while (i--)
    ; 
  hosal_gpio_input_get(&tigger, &value);// 软件延时防抖
  if (value == 1) {
    printf("tigger pressed:%d\r\n", counter++);
    led_state = !led_state;
    hosal_gpio_output_set(&led, led_state);
    if (counter > 1024) { // 重新计数
      counter = 0;
    }
  }
}

// 初始化触发引脚
static void init_pin() {
  tigger.port = TIGGER_PIN;
  tigger.config = INPUT_HIGH_IMPEDANCE;
  hosal_gpio_init(&tigger);  //初始化GPIO

  hosal_gpio_irq_set(&tigger, HOSAL_IRQ_TRIG_POS_PULSE, tigger_irq_callback,
                     NULL); //开启GPIO中断以上升沿的方式触发中断
  printf("tigger inited\r\n");
}

void main(void) {
  init_led();
  init_pin();
  while (1) {
  }
}

实物连接

遮挡效果.png

  • VCC接 3.3V
  • GND接GND
  • OUT1接IO4

不要问为什么这么简陋还飞线,问就是画反封装了

串口监控计数值

串口输出.png

不停的遮挡光电模块就会通过中断触发计数

下一步制作光栅,把这玩意做成圆形的

后续思路


这个只是简单的计数编码器,不能分辨方向正反向,所以用两个错相位的光电模块,接入到D触发器来实现正反向的读取,在用一个光电模块对接光栅的定位孔来实现z脉冲。

图片.png

──── 0人觉得很赞 ────

使用道具 举报

棒~
格式很好看呢
前天 18:13

你应该夸内容!这个编辑器真难用 用typora写的好好的,复制过来全加粗了,又删又改
👍
加两个传感器就能检测正反了
前天 22:11
HaydenHu 发表于 2025-2-20 20:27
加两个传感器就能检测正反了

对,看我的后续思路,实现了检测正反转,还有Z脉冲,
前天 23:07
赞一个
WildboarG 发表于 2025-2-20 18:13
你应该夸内容!这个编辑器真难用 用typora写的好好的,复制过来全加粗了,又删又改 ...

做的这么棒,用言语已经没法表达了。所以另辟蹊径夸一夸样式👍都非常棒。
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 27900 个
  • 话题数: 39283 篇