经典CV键盘——树莓派版本复刻

这篇具有很好参考价值的文章主要介绍了经典CV键盘——树莓派版本复刻。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关键词: DIY    CV键盘     树莓派    PICO    微控制器    TinyUSB

0 写在前面

1) CV键盘简介

顾名思义,只提供 “复制粘贴” 功能的小键盘。

他们说:高端的程序员,往往采用最朴素的编程方式。

他们说:顶尖程序员都把自己叫做CV工程师。

他们说:CV大法是一门正派武功,没几年沉淀学不来。

他们说:程序员的事不叫抄,这叫代码复用。

在他们之间,有一款键盘十分受追捧。这款神秘键盘,抛弃了那些冗余花哨的键位,只保留了最纯粹的功能,专为追求效率的CV工程师量身打造。

搬砖,只要这一个键盘就够了。

经典CV键盘——树莓派版本复刻

2) 主控芯片简介:

经典CV键盘——树莓派版本复刻

RP2040,一款树莓派mcu

https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdfhttps://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf

经典CV键盘——树莓派版本复刻

Pico开发板,灵活、易用的树莓派微控制器开发板,基于rp2040芯片       https://pico.org.cnhttps://pico.org.cn

3) 硬件准备

a)开发环境:树莓派4B

经典CV键盘——树莓派版本复刻

b)目标设备:树莓派PICO

经典CV键盘——树莓派版本复刻

c)PCB:CV键盘

d)电子元件:机械按键  0805 1K电阻  100nF电容

4) 术语:

HID:人机交互设备

Host/Device:主机/从机(设备)

TinyUSB:一种USB协议栈

PHY:外设

1  使用树莓派开发树莓派:

https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdfhttps://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

1)构建开发环境

a) 下载构建脚本

$ wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh

b)获取权限

$ chmod +x pico_setup.sh

c)执行脚本

$ ./pico_setup.sh

d)重新启动

$ sudo reboot

2)获取示例代码和SDK

$ cd ~/
$ mkdir pico
$ cd pico

获取sdk

$ git clone -b master https://github.com/raspberrypi/pico-sdk.git
$ cd pico-sdk
$ git submodule update --init
$ cd ..
$ git clone -b master https://github.com/raspberrypi/pico-examples.git

3)获取编译工具

$ sudo apt update
$ sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential

更新SDK

$ cd pico-sdk
$ git pull
$ git submodule update

4)编译示例代码

$ cd pico-examples
$ mkdir build
$ cd build

导入sdk路径

$ export PICO_SDK_PATH=../../pico-sdk
$ cmake ..

编译代码

$ cd usb/device/dev_hid_composite
$ make -j4

5)下载和运行

按住booltest按键同时将pcio连接到4B上,弹出大容量设备挂在点击ok,拷贝到.uf2目标盘

$ sudo cp dev_hid_composite.uf2 /media/pi/RPI_RP2 

此时按下bootest按键可以观察到键盘输入字符A,鼠标移动x和y分别移动5

2 TinyUsb协议栈

键盘的按键触发基于USB进行传输,因此引入开源的USB协议栈TinyUSB。

TinyUSB是一种用于嵌入式系统的开放源代码跨平台USB主机/设备堆栈,设计为内存安全,无动态分配和线程安全,所有中断事件都被延迟,然后在非ISR任务功能中处理。

https://docs.tinyusb.org/en/latesthttps://docs.tinyusb.org/en/latest

USB 设备通过报告形式向主机传递数据,这种报告称为USB HID报告描述符。HID是人机交互设备的缩写。

USB HID报告描述符是USB主机请求于USB设备的一种描述符。HID设备用报告的形式发送数据到主机,描述符告诉主机如何解释数据。在像键盘、鼠标等低速设备中,每10ms进行一次数据上报。通过数据上报告诉主机哪个按键被按下或者鼠标移动的位置。

3 Demo代码分析

在路径pico/pico-example/build/usb/device/dev_hid_composite/main.c中。        

main调用了5个函数:

int main(void)
{
  board_init(); //外设初始化
  tusb_init(); //tinyUsb协议栈初始化
  while (1)
  {
    tud_task(); // tinyusb device task
    led_blinking_task();// LED运行指示灯
    hid_task(); //人机交互设备任务
  }
  return 0;
}

关键:hid_task()其实现为:

void hid_task(void)
{
  // Poll every 10ms
  const uint32_t interval_ms = 10;
  static uint32_t start_ms = 0;
  //判断时间是否到10ms
  if ( board_millis() - start_ms < interval_ms) return;
  start_ms += interval_ms;
  //按键是否被按下
  uint32_t const btn = board_button_read();
​​​​​​​  //当挂起时远端唤醒
  if ( tud_suspended() && btn )
  {
    // Wake up host if we are in suspend mode
    // and REMOTE_WAKEUP feature is enabled by host
    tud_remote_wakeup();
  }
  else
  {
    // 发送报告上第一条信息
    send_hid_report(REPORT_ID_KEYBOARD, btn);
  }
}

其中关键函数:send_hid_report()函数实现:

static void send_hid_report(uint8_t report_id, uint32_t btn)

{
  // skip if hid is not ready yet
  if ( !tud_hid_ready() ) return;
  //HID 设备类型
  switch(report_id)
  {
    case REPORT_ID_KEYBOARD:
    {
      // use to avoid send multiple consecutive zero report for keyboard
      static bool has_keyboard_key = false;
      if ( btn )
      {
        uint8_t keycode[6] = { 0 };
        keycode[0] = HID_KEY_A; //按键A触发
        tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
        has_keyboard_key = true;
      }else
      {

        // send empty key report if previously has key pressed
        if (has_keyboard_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL);
        has_keyboard_key = false;
      }
    }
    break;
    case REPORT_ID_MOUSE:
    {
      int8_t const delta = 5;
      // no button, right + down, no scroll, no pan
      tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0);
    }
    break;
    case REPORT_ID_CONSUMER_CONTROL:
    {
      // use to avoid send multiple consecutive zero report
      static bool has_consumer_key = false;
      if ( btn )
      {
        // volume down
        uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT;
        tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2);
        has_consumer_key = true;
      }else
      {

        // send empty key report (release key) if previously has key pressed
        uint16_t empty_key = 0;
        if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2);
        has_consumer_key = false;
      }
    }
    break;
    case REPORT_ID_GAMEPAD:
    {
      // use to avoid send multiple consecutive zero report for keyboard
      static bool has_gamepad_key = false;
      hid_gamepad_report_t report =
      {
        .x   = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0,        
        .hat = 0, .buttons = 0
      };
      if ( btn )
      {
        report.hat = GAMEPAD_HAT_UP;
        report.buttons = GAMEPAD_BUTTON_A;
        tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
        has_gamepad_key = true;
      }else
      {

        report.hat = GAMEPAD_HAT_CENTERED;
        report.buttons = 0;
        if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
        has_gamepad_key = false;
      }   
   }
   break;
   default: break;
  }
}

伪代码逻辑:

函数入口
{
    初始化外设
    初始化协议栈
    进入循环
    {
        协议栈任务
        按键触发协议传输
        LED运行灯任务
    }
}

代码过程分析:

        进入循环后,每10ms判断一次按键是否触发,触发则触发链式消息中的第一条,发送键盘消息,随后的消息会在协议栈任务中以链式消息顺序发送。

4 修改代码

1)修改按键触发的gpio6.7.8初始化

        文件目录 pico/pico-sdk/lib/tinyusb/hw/rp2040/family.c

#define CV_BOARD
#ifdef CV_BOARD
#define KEY_CTRL 6
#define KEY_C 7
#define KEY_V 8
#endif

#ifdef CV_BOARD
  gpio_init(KEY_CTRL);
  gpio_init(KEY_C);
  gpio_init(KEY_V);
  gpio_set_dir(KEY_CTRL,GPIO_IN);
  gpio_set_dir(KEY_C,GPIO_IN);
  gpio_set_dir(KEY_V,GPIO_IN);
#endif

2)删除链式消息中其他HID设备行为

原枚举

enum
{
  REPORT_ID_KEYBOARD = 1,
  REPORT_ID_MOUSE,
  REPORT_ID_CONSUMER_CONTROL,
  REPORT_ID_GAMEPAD,
  REPORT_ID_COUNT
};

现枚举:

enum
{
  REPORT_ID_KEYBOARD = 1,
  REPORT_ID_COUNT,
  REPORT_ID_MOUSE,
  REPORT_ID_CONSUMER_CONTROL,
  REPORT_ID_GAMEPAD
};

3)修改原来的按键触发

void hid_task(void){
    uint32_t const btn = board_button_read();    
}

void hid_task(void){
    uint32_t const btn = (!gpio_get(KEY_CTRL)) | (!gpio_get(KEY_C)) |(!gpio_get(KEY_V));
}

4)原来的传递的按键码

static void send_hid_report(uint8_t report_id, uint32_t btn)
{
  // skip if hid is not ready yet
  if ( !tud_hid_ready() ) return;
  switch(report_id)
  {
    case REPORT_ID_KEYBOARD:
    {
      // use to avoid send multiple consecutive zero report for keyboard
      static bool has_keyboard_key = false;
      if ( btn )
      {
        uint8_t keycode[6] = { 0 };
        keycode[0] = HID_KEY_A;
        tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
        has_keyboard_key = true;
      }
      else
……
……
……
}

修改为

static void send_hid_report(uint8_t report_id, uint32_t btn)
{
  // skip if hid is not ready yet
  if ( !tud_hid_ready() ) return;
  switch(report_id)
  {
    case REPORT_ID_KEYBOARD:
    {
      // use to avoid send multiple consecutive zero report for keyboard
      static bool has_keyboard_key = false;
      if ( btn )
      {
        uint8_t keycode[6] = { 0 };
        if(!gpio_get(KEY_CTRL)) keycode[0] = HID_KEY_CNOTROL_LEFT;
        if(!gpio_get(KEY_C)) keycode[1] = HID_KEY_C;
        if(!gpio_get(KEY_V)) keycode[2] = HID_KEY_V;
        for(int i = 6; i < 6 ; i++)
        {
           if(keycode[i] == 0)
           {    
                memcpy(&keycode[i],&kecode[i+1],6 - i + 1);
           }
        }
        tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
        has_keyboard_key = true;
      }
      else
……
……
……
}

5)编译与烧录

$ make -j4
$ sudo cp dev_hid_composite.uf2 /media/pi/RPI_RP2

5 硬件电路设计

使用GPIO6-8作为键盘三个按键的输入脚。电路原理图如下:

经典CV键盘——树莓派版本复刻

PCB设计

经典CV键盘——树莓派版本复刻

经典CV键盘——树莓派版本复刻

经典CV键盘——树莓派版本复刻

6 成品测试

(补充视频)

2022/10/3文章来源地址https://www.toymoban.com/news/detail-495314.html

到了这里,关于经典CV键盘——树莓派版本复刻的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 实现同时查找多个关键词——KeywordCrafter - 关键词匠心

    具体功能:同时查找多个,高亮加粗显示,并显示出现次数。 🧐碎碎念:最近在写文案的时候,总是要避免出现一个敏感词汇,利用 (command+F) or (Ctr+F) 查找,只能一个一个单词去查,很麻烦。🤷‍♂️ 所以我写了一个简单的网页,在文本框输入一整篇文章,在

    2024年02月13日
    浏览(74)
  • 关键词生成器在线-在线免费关键词生成器

    生成,什么是生成,生成就是根据你输入的一个生成成千上百的核心,围绕着你输入的核心词来生成的,优先生成大量用户搜索的,今天就给大家分享一款免费生成工具,生成的来源主要是用户都在搜索的词,相关搜索的

    2024年02月04日
    浏览(241)
  • 长尾关键词挖掘软件-免费的百度搜索关键词挖掘

    嗨,大家好!今天,我想和大家聊一聊长尾挖掘工具。作为一个在网络世界里摸爬滚打多年的人,我对这个话题有着一些个人的感悟和见解,希望能与大家分享。 首先,让我坦白一点,长尾挖掘工具对于我来说真是救命稻草。在我刚开始做网站优化和内容创作的

    2024年02月09日
    浏览(96)
  • 网站SEO关键词规划时如何筛选出合适的关键词?

    在网站SEO优化过程中,布局是一个至关重要的环节。首先,我们需要确定核心,然后通过各种策略和方法对进行扩展。完成扩展后,接下来的任务就是对这些扩展后的进行筛选。那么,如何进行有效的筛选呢?我们通常建议选择那些具有

    2024年04月17日
    浏览(84)
  • 关键词提取 | 基于Textrank算法的两种关键词提取

    目录 一、PageRank算法 二、TextRank算法 1. 抽取(keyword extraction) 2. 关键短语抽取(keyphrase extration) 3. 关键句抽取(sentence extraction) 三、TextRank算法实现 1. 基于Textrank4zh的TextRank算法实现 2. 基于jieba的TextRank算法实现 3. 基于SnowNLP的TextRank算法实现 四、PageRank算法与Text

    2024年04月14日
    浏览(81)
  • Stable Diffusion 告别猜关键词,LoRA适配关键词自动生成

    有没有想想过在SD绘图的时候下载好的LoRA模型选择之后不生效是为什么?或者说不知道怎么填写? 这里介绍基于 Civitai 的LoRA 使用方法。 如果没有安装的小伙伴可以参考前面的文章先对 Civitai 的模型管理进行安装和使用,确保你的SD主页已经出现了 Civitai 助手 选项卡。

    2024年02月09日
    浏览(65)
  • 一个AI关键词能卖500块?AI绘画引发研究关键词的商机

    一个AI能卖500块?AI绘画引发研究的商机! 绘画一直被人们看作是视觉艺术的呈现方式。通常情况下,学习绘画需要理解调色、构图和线条等要素。然而,自从AI介入绘画领域后,绘画的\\\"画风\\\"迅速发生了变化。网络上涌现出许多教程,教人如何学习AI绘画的关键

    2024年02月10日
    浏览(56)
  • 长尾词和关键词的区别,长尾关键词最简单最常用的2个​获取方法

        要知道长尾词与的区别就要先了解什么是,什么是长尾词。      什么是呢?     是定义您的内容的想法和主题。     什么是长尾词呢?     长尾词是与相关的,可以带来搜索流量的组合型。     获取长尾的最简单的2个方

    2024年02月11日
    浏览(49)
  • 网站万词霸屏推广系统源码:实现关键词推广,轻松提高关键词排名,带完整的安装部署教程

    现如今,互联网的快速发展,网站推广成为企业网络营销的重要手段。而排名作为网站推广的关键因素,一直备受关注。罗峰给大家分享一款网站万词霸屏推广系统源码,该系统可实现推广,有效提高排名,为企业带来更多流量和潜在客户。 以下是部分代

    2024年01月19日
    浏览(90)
  • 中文关键词提取算法

    如何提取query或者文档的? 一般有两种解决思路: 有监督方法,把提取问题当做分类问题,文本分词后标记各词的重要性打分,然后挑出重要的topK个词; 无监督方法,使用TextRank、TFIDF等统计算法区分各词的term weight,然后按weight排序后挑出重要的topK个词。 有

    2024年02月08日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包