打印

立创梁山派-21年电赛F题-智能送药小车-按键检测的消抖和实现

[复制链接]
1620|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
立创开发板|  楼主 | 2023-8-4 10:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#申请原创# #每日话题# #技术资源#
送药小车代码仓库:https://gitee.com/lcsc/medical_car

更好的观看体验请去:https://lceda001.feishu.cn/wiki/ZDYbwqDfCiwVlckUEcScF0KSnRh

送药小车立创开源平台资料:https://oshwhub.com/li-chuang-kai-fa-ban/21-dian-sai-f-ti-zhi-neng-song-yao-xiao-che

购买链接:https://item.szlcsc.com/5810323.html


按键检测的消抖和实现

在送药小车中,预留了三个按键,药品装载检测是通过一个轻触开关来实现的,也可以把他理解成一个按键。
按键的实际电路如下:

我们通常用的按键内部都是机械弹性开关,当它按下弹起的时候,机械触点会因为弹性作用而在闭合和断开的瞬间伴随着一连串的抖动。这种抖动会导致输入信号在高低电位之间弹跳,产生不正确的输入。这里面电阻的作用是限流(害怕初学者不小心给设置成推挽输出了),在这里要注意的是要在芯片内部设置一个下拉(电路图上是没有加下拉电阻得到)。电容作用是硬件去抖,不过软件上还是需要软件消抖,硬件去抖只能改善不能消除,所以在有一些批量电路中,这个电容都是可以省去的,毕竟还是省不了软件消抖的。
轻触开关的实际电路如下:

在这里,我又要安利一波RT-Thread的软件包的,可以在RT-Thread软件包里面,搜索button,可以看到是有很多按键的软件包,这里就选择MultiButton了。用ENV工具把他添加到工程里面就可以了。参考他自带的example建立线程就可以轻松实现按键检测的,按下,弹起,单击,双击,长按等事件了:
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "multi_button.h"
#include "bsp_beep.h"

static struct button btn1;
static struct button btn2;
static struct button btn3;

#define KEY1_PIN GET_PIN(G, 11)
#define KEY2_PIN GET_PIN(G, 13)
#define KEY3_PIN GET_PIN(B, 3)

static uint8_t button1_read_pin(void) { return rt_pin_read(KEY1_PIN); }
static uint8_t button2_read_pin(void) { return rt_pin_read(KEY2_PIN); }
static uint8_t button3_read_pin(void) { return rt_pin_read(KEY3_PIN); }

void button1_callback(void *btn)
{
    uint32_t btn_event_val;

    btn_event_val = get_button_event((struct button *)btn);

    switch (btn_event_val)
    {
    case PRESS_DOWN:
        rt_kprintf("button1 press down\n");
        break;

    case PRESS_UP:
        rt_kprintf("button1 press up\n");
        break;

    case PRESS_REPEAT:
        rt_kprintf("button1 press repeat\n");
        break;

    case SINGLE_CLICK:
        beep(20);
        rt_kprintf("button1 single click\n");
        break;

    case DOUBLE_CLICK:
        rt_kprintf("button1 double click\n");
        break;

    case LONG_PRESS_START:
        rt_kprintf("button1 long press start\n");
        break;

    case LONG_PRESS_HOLD:
        rt_kprintf("button1 long press hold\n");
        break;
    }
}
void button2_callback(void *btn)
{
    uint32_t btn_event_val;

    btn_event_val = get_button_event((struct button *)btn);

    switch (btn_event_val)
    {
    case PRESS_DOWN:
        rt_kprintf("button2 press down\n");
        break;

    case PRESS_UP:
        rt_kprintf("button2 press up\n");
        break;

    case PRESS_REPEAT:
        rt_kprintf("button2 press repeat\n");
        break;

    case SINGLE_CLICK:
        beep(20);
        rt_kprintf("button2 single click\n");
        break;

    case DOUBLE_CLICK:
        rt_kprintf("button2 double click\n");
        break;

    case LONG_PRESS_START:
        rt_kprintf("button2 long press start\n");
        break;

    case LONG_PRESS_HOLD:
        rt_kprintf("button2 long press hold\n");
        break;
    }
}
void button3_callback(void *btn)
{
    uint32_t btn_event_val;

    btn_event_val = get_button_event((struct button *)btn);

    switch (btn_event_val)
    {
    case PRESS_DOWN:
        rt_kprintf("button3 press down\n");
        break;

    case PRESS_UP:
        rt_kprintf("button3 press up\n");
        break;

    case PRESS_REPEAT:
        rt_kprintf("button3 press repeat\n");
        break;

    case SINGLE_CLICK:
        beep(20);
        rt_kprintf("button3 single click\n");
        break;

    case DOUBLE_CLICK:
        rt_kprintf("button3 double click\n");
        break;

    case LONG_PRESS_START:
        rt_kprintf("button3 long press start\n");
        break;

    case LONG_PRESS_HOLD:
        rt_kprintf("button3 long press hold\n");
        break;
    }
}

void btn_thread_entry(void *p)
{
    while (1)
    {
        /* 5ms */
        rt_thread_delay(RT_TICK_PER_SECOND / 200);
        button_ticks();
    }
}

int multi_button_test(void)
{
    rt_thread_t thread = RT_NULL;

    /* Create background ticks thread */
    thread = rt_thread_create("btn", btn_thread_entry, RT_NULL, 2048, 20, 10);
    if (thread == RT_NULL)
    {
        return RT_ERROR;
    }
    rt_thread_startup(thread);

    /* low level drive */
    rt_pin_mode(KEY1_PIN,
                PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */
    button_init(&btn1, button1_read_pin, PIN_HIGH);
    button_attach(&btn1, PRESS_DOWN, button1_callback);
    button_attach(&btn1, PRESS_UP, button1_callback);
    button_attach(&btn1, PRESS_REPEAT, button1_callback);
    button_attach(&btn1, SINGLE_CLICK, button1_callback);
    button_attach(&btn1, DOUBLE_CLICK, button1_callback);
    button_attach(&btn1, LONG_PRESS_START, button1_callback);
    button_attach(&btn1, LONG_PRESS_HOLD, button1_callback);
    button_start(&btn1);

    rt_pin_mode(KEY2_PIN,
                PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */
    button_init(&btn2, button2_read_pin, PIN_HIGH);
    button_attach(&btn2, PRESS_DOWN, button2_callback);
    button_attach(&btn2, PRESS_UP, button2_callback);
    button_attach(&btn2, PRESS_REPEAT, button2_callback);
    button_attach(&btn2, SINGLE_CLICK, button2_callback);
    button_attach(&btn2, DOUBLE_CLICK, button2_callback);
    button_attach(&btn2, LONG_PRESS_START, button2_callback);
    button_attach(&btn2, LONG_PRESS_HOLD, button2_callback);
    button_start(&btn2);

    rt_pin_mode(KEY3_PIN,
                PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */
    button_init(&btn3, button3_read_pin, PIN_HIGH);
    button_attach(&btn3, PRESS_DOWN, button3_callback);
    button_attach(&btn3, PRESS_UP, button3_callback);
    button_attach(&btn3, PRESS_REPEAT, button3_callback);
    button_attach(&btn3, SINGLE_CLICK, button3_callback);
    button_attach(&btn3, DOUBLE_CLICK, button3_callback);
    button_attach(&btn3, LONG_PRESS_START, button3_callback);
    button_attach(&btn3, LONG_PRESS_HOLD, button3_callback);
    button_start(&btn3);

    return RT_EOK;
}
INIT_APP_EXPORT(multi_button_test);

不想搞这么复杂,就只是单独想检测一下药物有没有放好的话也可以用最简单的延时来消除这个按键按下的抖动。像下面这个一样:
<pre class="ace-line ace-line old-record-id-PlC2d4o2MoGgXPxYv9Lc88BdnRh"><code class="language-C" data-wrap="false"><div>static void button_scan(void *arg)
{
    while (1)
    {
        rt_thread_mdelay(50);
        if (button_key0_read() == 1)
        {
            rt_thread_mdelay(50);
            if (button_key0_read() == 1)
            {
                medicine_state = 1;
            }
        }
        else
        {
            medicine_state = 0;
        }
    }
}</div></code></pre><div class="ace-line ace-line old-record-id-Hb4CdY0S0oZkodx9UP2crvtQn7b"></div>




使用特权

评论回复
沙发
tpgf| | 2024-2-5 13:15 | 只看该作者
这个小车是不是有点类似于agv智能小车的样子

使用特权

评论回复
板凳
wowu| | 2024-2-5 14:07 | 只看该作者
这个小车所能使用的外部环境是不是有比较严格的要求啊

使用特权

评论回复
地板
木木guainv| | 2024-2-5 22:23 | 只看该作者
智能小车如何识别路障以及道路呢

使用特权

评论回复
5
晓伍| | 2024-2-5 22:59 | 只看该作者
按键的消抖完全可以通过软件来实现

使用特权

评论回复
6
xiaoqizi| | 2024-2-5 23:31 | 只看该作者
我们的智能小车的难点就在路途的识别以及归位上

使用特权

评论回复
7
申小林一号| | 2024-4-30 16:37 | 只看该作者
非常不错的帖子,值得推广扩散!!!

使用特权

评论回复
8
为你转身| | 2024-6-30 15:25 | 只看该作者
在送药小车中,预留了三个按键,药品装载检测是通过一个轻触开关来实现的,也可以把他理解成一个按键。

使用特权

评论回复
9
wanduzi| | 2024-6-30 16:47 | 只看该作者
一个过时的主题,不过值的思考学习。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

26

帖子

0

粉丝