我们开发踏板固件来学习演奏巴拉莱卡

我真的很喜欢视频教程。 由于某种原因,我个人非常非常糟糕地感觉到了来自文本的信息。 但是在某些情况下,纸上的信息并不多。 举例来说,您可以播放演奏平衡性音乐的课程:在YouTube上,关于如何播放这种旋律或该旋律(谁有兴趣,我们正在寻找“ Sergey Vorontsov”)进行了精彩的讨论,但是很难重复并记住流式视频中的音序。 有必要在纸上写下(根据课程中的评论判断,有的这样做),或购买其他材料(但我不是贪婪的,而是自制的)。



总的来说,在我的巴拉莱卡(balalaika)案件中,我和其他许多人一样,我必须这样做:我查看了片段,将其暂停,在作者后面重复了几次,然后继续观看。 如果不清楚-倒退,请仔细观察。 但是,如果您的手很忙,该如何解决呢? 而且,就我而言,他们很忙,即使不是用一个巨大的按钮手风琴,也有些忙,但有一个莱莱卡琴。 因此,您需要双腿锻炼。

许多很多年前,当所有进步的人类都使用PS / 2键盘时,他们为我们带来了数十个USB键盘用于该项目。 当然,我们将它们连接到一台计算机上,在其中一台计算机上按Ctrl,在第二台计算机上按Alt,在第三台计算机上按Del。 效果已经达到。 从那时起,我就知道USB键盘可以完全并行工作,因此您可以连接另一个键盘来帮助主键盘,它会发送一些代码。

因此,这个想法诞生了,使踏板可以伪装成键盘并发送玩家控制代码。 作为播放器,我最初选择了VLC Player,因为它具有详细记录的控制按钮,但后来证明我选择的代码在全屏模式下在YouTube上观看视频时具有完全相同的目的。 这很好,因为对于多个广告而言,在线观看次数众多,似乎就落在了作者的脑海中。 观看下载内容并不道德。

因此,我们开始设计设备。

工作逻辑


起初,我想制作几个踏板,每个踏板都有自己的功能。 最初,我数了其中的3-4个功能:打开,关闭,在那儿绕风,向后回风。 但是后来我弄清楚需要多少塑料,再加上-我如何通过触摸来理解踏板,并且很难过。 因此,决定从根本上修改整个逻辑。 根本需要什么功能? 启停,但它通常挂在同一键上,通常挂在一个空格上。 并倒带。 VLC Player具有“ Shift +向左”。 事实证明,YouTube也是如此。 而且,如果您这样认为,那就没有更多的功能了。

太好了! 让我们短暂地使用“开始-停止”功能,并通过“快退”功能使踏板变长。

将来,您可以扩展功能。 您可以训练踏板以识别莫尔斯电码。 我的妻子了解了这个想法后,建议使用爱尔兰舞蹈的元素编码控制脉冲。一般来说,您可以根据需要扩展功能。 但是有一点很清楚:一个踏板就足够了。 好吧,现在我们将对长按和短按进行识别。

机械师


对于那些在家中穿拖鞋走路的人,有一个非常简单的解决方案(我在Thingiverse网站上找到了它)。 我们拿一个直径大于一厘米的按钮,将其拧入任何盒形物体中,然后得到一个踏板。 麻烦在于我不喜欢拖鞋,因此此选项不适合我个人。 我需要更大的表面以便脚不会受伤。

踏板在Ali Express上有大量销售,您应该搜索“脚踏开关”一词。 那里的价格从30卢布开始,但按这个价格,交货成本大约为400卢布。 搜索后,我发现很有可能找到一个踏板,“价格加交货”总和为150卢布。 但是您将平均需要等待几个月(最近我一直在这里等待所有三个月的SD卡)。

因此,我走了更快的路:在3D打印机上踩了踏板。 个人经验(以及Thingiverse的所有选项)表明,该轴必须是金属的,否则一切都会很快破裂。 我拿起了现有的M6x60家具螺栓,上面装有螺母,以及邻近的Radio Parts中的按钮(PSW-13),并尽可能用塑料勾勒出它们的轮廓。 这是原始资料的外观:



在这里,将它们插入下半部分。 如您所见,主要设计特征是墙壁,至少四毫米厚。 使用这些参数,即使是温和的原型打字机也变得非常耐用。 安装按钮时没有螺母,因为按钮下面的任何空洞都会导致塑料脱落,并且保持良好。



这是一个几乎已编译的版本:



这是踏板组件:



原则上,我将附加STL文件,但是解决方案并不完美。 但是,任何人都可以重复此操作(如果他找到带有相应螺母和PSW-13按钮的M6x60螺栓)。 第一次就足够了,然后-您可以在ALI上加盖模具和订购。

USB设备


尽管最近我一直在积极地推广PSoC,但在踏板上使用它却是闻所未闻的。 我认为最好的解决方案是基于STM32F103C8T6的面包板,现在可以在ALI Express上以大约120卢布的价格订购(包括运费)。



当然,我们可以推测出有基于AVR的较便宜的电路板,但是那里的价格差异并不明显,并且由于通过JTAG进行调试,STM32的开发时间大大缩短。 一个小时的时间(甚至在家)-也要花费一些时间。 因此,根据“设备价格+人工成本”的总标准,STM32F103是此任务的最佳选择。 而且,在这种情况下,我在商店中有六个这样的实体模型,因此对于我来说,交货等待时间现在等于零。

我上网冲浪了基于该芯片的现成USB键盘。 我找到了有关Habr如何制作USB鼠标的文章。 但是我需要一个键盘。 在键盘主题上,我在论坛上找到了很多聪明的提示(但我想准备一些东西),在GitHub上找到了一些现成的但复杂的项目(但我想弄清楚)。 但是,寻求者将永远找到。 这是一篇很棒的文章 ,其中包含了所有需要的内容(尽管代码中有一个,但我不怕这个非俄语的单词,一个潜在的DeadLock,但我会编写自己的代码)。 最主要的是,其中清楚地描述了所有步骤,以及如何从Cube MX制成的成品“鱼”中获得USB键盘。 作者唯一没有做的就是不发布关键代码。 在此处添加它们:



美中不足的是,在现代版本的Cube MX中,文件,函数甚至常量的名称与该文章中指定的名称稍有不同,但以此类推,很快就可以找到所有内容。 我可以写一个新版本的文本,但是哪里可以保证开发人员不会再次更改所有内容呢? 他们喜欢这样做。 通常,您可以在示例中看到类似物。

这样啊 我在Cube MX中创建了一个基本项目,进行了上述文章建议的所有更改。 接下来是什么? 接下来,添加按钮端口的描述。 我选择了PB12(完全是因为相应的触点位于面包板的一角)。 由于我总是通过Konstantin Chizhov的mcucpp库使用iron,因此我们在项目属性中删除了“ -C99”宏定义,将main.c重命名为main.cpp ,然后添加声明:

typedef Mcucpp::IO::Pb12 pedal1; 

我们将端口初始化添加到main()函数中(启用端口时钟,设置分支方向,打开吊架):

 pedal1::ConfigPort::Enable(); pedal1::SetDirRead(); pedal1::SetPullUp (pedal1::Port::PullUp); 

实际上,一切都已初始化。 我决定根据Verilog流程构建主体。 我不知道为什么,我只是想。 该过程通常称为时钟脉冲。 我决定将系统刻度完全视为刻度。 因此,在stm32f1xx_it.c文件添加了系统刻度处理程序的常规功能,如下所示:



相同的文字:
 void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); HAL_SYSTICK_IRQHandler(); /* USER CODE BEGIN SysTick_IRQn 1 */ TickProcess(); /* USER CODE END SysTick_IRQn 1 */ } 


我将TickProcess()函数本身放在了main中。 cpp 。 首先,请完整地考虑它,然后是部分考虑。

这是全部功能:
 uint8_t report [8] = {0,0,0,0,0,0,0,0}; uint32_t* pReport = (uint32_t*)report; extern "C" void TickProcess() { //      20!!! static const int shortTime = 700; //      static const int longTime = 2000; //    static int localTick = 0; static int tickDuringButton = 0; static bool bButtonStatePrev; bool bButtonState = pedal1::IsSet(); //     if ((!bButtonState) && bButtonStatePrev) { tickDuringButton = 0; } //     if (bButtonState && (!bButtonStatePrev)) { //       //  ,  50  () if ((tickDuringButton >100)&&(tickDuringButton < shortTime)) { //    report [2] = 0x2C; } } //    if ((!bButtonState) && (!bButtonStatePrev)) { if ((tickDuringButton == shortTime)||(tickDuringButton > longTime)) { //  Shift+ report [0] = 2; // Shift report [2] = 0x50; //  } } //    bButtonStatePrev = bButtonState; tickDuringButton += 1; if (localTick++ % 20 == 0) { USBD_HID_SendReport (&hUsbDeviceFS,report,sizeof(report)); pReport [0] = 0; pReport [1] = 0; } } 


在此处理程序中实现的第一个任务很简单。 每隔20毫秒,我们会发送一份报告,其中包含有关按下的按钮的信息(如果没有按钮,无论如何我们都会发送带有零的信息)。 由于该函数每毫秒调用一次,因此应将报告发送到其二十个调用之一。 为此,该函数的开头有一个变量:

  static int localTick = 0; 

和末尾的代码(我们发送数据,然后擦除缓冲区,以便从下一个会话开始发送零):

  if (localTick++ % 20 == 0) { USBD_HID_SendReport (&hUsbDeviceFS,report,sizeof(report)); pReport [0] = 0; pReport [1] = 0; } 

第二项任务比较复杂。 它跟踪踩踏板的性质,并填写报告以供后续提交。 为什么我说意识形态就像Verilog? 因为我总是会遇到这种语言的差异:我有一个变量,用于放置按钮的当前状态:

  bool bButtonState = pedal1::IsSet(); 

并且有一个变量存储了它的先前状态(我们记得,先前状态是在1 ms计时器进行的先前中断处理期间按钮的状态):

  static bool bButtonStatePrev; 

按下的按钮的值为false ,按下的按钮为true 。 因此,我们总是可以得出关于按钮的动态状态的结论:

bButtonStatebButtonStatePrev条件
是真的是真的长时间发布
是真的错误的根据先前的措施发布
错误的是真的按上一小节
错误的错误的长按

我们介绍两个常数。 一个设置短按时间。 如果按压持续的时间少于700毫秒,那么它是短暂的。 第二个设置打开自动重复的时间。 如果仅在七百毫秒后您开始发送键码,则播放器将开始突然晃动。 这是凭经验确定的。 因此,工作逻辑如下:700毫秒后,发送单个代码“ Shift + Left”,此后,用户将有机会松开踏板。 如果继续保持踏板,则从第二秒开始就一直持续发送此代码,直到释放踏板为止。

  const int shortTime = 700; //      const int longTime = 2000; //    

按下按钮的时间存储在变量中:

  static int tickDuringButton = 0; 

如果刚刚按下了按钮,我们将该变量清零,开始测量新的时间段:

  //     if ((!bButtonState) && bButtonStatePrev) { tickDuringButton = 0; } 

如果按钮刚刚被释放,那么我们将检查按钮被按下的时间。 如果只是一点点(现在它说“少于100毫秒”),这就是一个a不休。 这不算在内。 忽略此点击。 如果我们只做短按的持续时间,下面将对长按进行处理。 如果在短时间内按一下,我们在缓冲区中创建一个带有空格的报告(当时间到时将发送该报告):

  //     if (bButtonState && (!bButtonStatePrev)) { //       //  ,  100  () if ((tickDuringButton >100)&&(tickDuringButton < shortTime)) { //    report [2] = 0x2C; } } 

如果按钮已长时间按住,则在两种情况下,我们会发送“ Shift + Left”:

  • 该按钮正好保持700毫秒(单个包装);
  • 该按钮将保持2秒钟以上(在随后的每个报告中发送,直到释放该按钮)。

  //    if ((!bButtonState) && (!bButtonStatePrev)) { if ((tickDuringButton == shortTime)||(tickDuringButton > longTime)) { //  Shift+ report [0] = 2; // Shift report [2] = 0x50; //  } } 

实际上,仅此而已。 这段代码与Cube MX给我们的“鱼”没什么不同。 我们进行组装,闪存...不,没有错误是不可能的(这里都被捕获了,但是最初我不能没有它们),我们通过JTAG调试在10分钟内识别了它们(您好到AVR),我们正在缝制,我们很高兴...

替代设计


通常,在没有自动莱卡(或其他视频教程观看)的情况下,此类操作很有用。 我尤其喜欢躺在床上,肚子上有一台笔记本电脑,看新闻。 要滚动文本,必须始终保持右手弯曲,这会导致肘部疼痛。 因此,我一直梦想着有一个红色的大按钮,它可以滚动页面而不会弯曲我的手臂。 实际上,它可以由与踏板相同的组件制成,用少量热胶代替家具螺栓。 总计:PSW13按钮,STM32F103C8T6面包板,用于3D打印机的塑料,热熔胶。 好吧,在“固件”中,我短按了“ PgDn”,长按了“ Up”。





结论


当您的双手忙时,您可以用腿来控制视频教程的显示。 为此,只需一个踏板即可模拟USB键盘的操作。 一个踏板可以发送多个按键代码,并根据不同类型的按键选择它们。 本文考虑的踏板可解析两种类型(短按和长按)。

这些机制可以在Ali Express的“脚踏开关”一词下找到,也可以在3D打印机上打印。 作为电子产品,可以使用面包板STM32F103C8T6。 根据由STM32控制器制造商Cube MX创建的“鱼”,在不到一个小时的时间内完成了“固件”。 附加代码占用多个屏幕文本(分辨率为2K-一个屏幕)。

通常,整个设备(力学+“固件”)在一个晚上就完成了设计,此外,在3D打印机上打印力学要花费大约四个小时。

可以在此处下载准备用于踏板打印的STL文件(最好将顶部元素降低0.4毫米,以避免产生大量支撑:表面被稍微弄圆,降低了模型的高度,我们将使打印的部分变得平坦)。

可以在此处下载 “红色大按钮”的STL文件。

可在此处下载该项目的现成源文件和该固件的HEX文件。

本文的发布日期并非偶然。 理事会决定最好在当天在严肃的网站上发布有关此类事情的文章。 但是实际上,如果您查看“ Alexey Arkhipovsky”,“ Dmitry Kalinin”,“ Cranberry Show”,“ Alexey Kodenko”短语中的视频,很明显,学术上的莱莱卡舞就像是一个组装工。 那里和那里都结合了绝对的简单性和疯狂的表达能力。 通过短语“ Sergey Vorontsov”,您可以了解如何学习如何使用此工具。

加法


操作8个月后,PSW-13按钮开始工作一次,但压力很大。 当尝试替换时,结果显示出一个非常有趣的细节。 与上一个按钮同时购买的新按钮具有完全不同的动力储备,并且在完全不同的位置工作。 结果,她总是踩我的踏板。 我不得不用德雷梅尔磨碎它。 谁来重复我的技巧-请记住。 您可能需要用文件修改按钮,反之亦然-在其上雕刻电工胶带以增加它。 该按钮的塑料部分的重复性不是很好。 但总的来说-经过这样的修订,一切都会恢复。

Source: https://habr.com/ru/post/zh-CN445160/


All Articles