经典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日
    浏览(52)
  • 长尾关键词挖掘软件-免费的百度搜索关键词挖掘

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

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

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

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

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

    2024年04月17日
    浏览(64)
  • 关键词提取 | 基于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日
    浏览(66)
  • Stable Diffusion 告别猜关键词,LoRA适配关键词自动生成

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

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

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

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

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

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

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

    2024年01月19日
    浏览(70)
  • 关键词的提取方法

    为了方便用户快速了解文章的中心主题,会抽取文章的一些中心词来表达文章的中心思想。抽取就是通过一定的方法抽取出能表达文章的中心主题的一系列方法。 的提取方法主要分为以下四类 (1)基于语义的方法 在词典的帮助下,通过词法与句法分析进行自动分

    2024年02月06日
    浏览(66)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包