【脑洞大赛】Sparrow 开发板化身电脑音量调节器 [已更新]

2019-07-026584
精华项目
AI 快速预览详细 收起
本文介绍了如何使用Sparrow开发板实现电脑音量调节功能。首先,通过NicoHood/HID库模拟HID设备,实现静音切换。然后,利用电位器模拟音量调节旋钮,通过map函数将电位器的模拟值映射到系统音量范围。最终效果是通过拨动电位器来调整电脑音量。

Sparrow

前言

原创文章,转载引用务必注明链接,水平有限,如有疏漏,欢迎指正。
之前的新浪不能用啦,这次部分图片用的sm.ms的图床,加载慢,请耐心,准备换图床。  

1、开箱简介

来填坑了!这次是 Sparrow 可穿戴微控制器(以下称S板), 产品页面wiki页面
S板主控芯片使用的是与Arduino Leonardo相同的ATmega32u4主芯片,那么它和经典爆款Arduino UNO使用的ATmega328主芯片的有何不同呢?我们来瞅一瞅:

这只是官方提供的介绍,真正应用上的区别,可以参考这篇文章《Arduino各开发板的比较》,综合可知Leonardo的优劣势:

  • 优点: Leonardo与所有先前的板子不同之处在于ATmega32u4具有内置的USB通讯,无需使用类似UNO上的16u2辅助处理器。这允许Leonardo作为鼠标和键盘出现在连接的计算机上,以及虚拟(CDC)串口或 COM端口。
  • 缺点: 编译原理和其他arrduino的avr主控不太一样,深层开发有些麻烦。

    UNO 是使用额外的16u2芯片来实现USB 串口功能的,就是板子上那块小芯片,注意它也是可编程的,相信有很多玩家改造过了。

1.1 硬件规格

![800px-DFR0589_Overview_Front]
如图所示,一眼望去,供电途径很多样,板子很小,有硬件输出(四枚LED+BUILTIN LED),硬件输入(Potentiometer),感觉怪怪的,好像都不是传统的输入输出手段,可能镊子也挺好用的吧。

1.2 引脚定义与注意点

pinout.png

  1. 官方wiki介绍
  2. 参考官方电位器读取例程,发现不对,找到原理图,最后确定如下:
    • 电位器接在A2
    • BulitIn LED接在D13引脚,板上丝印是D8,D代表二极管,可以看出这整体是有点混乱的,希望后续可以改进。
    • LED灯带接在D10引脚
    • 自锁开关单纯用于控制供电(microUSB除外),没有接到MCU上,所以无法作为输入;红绿led用于显示锂电池充电情况。
    • microusb有串口调试功能

1.3 出厂程序

下载地址
led.jpg
需要安装Adafruit NeoPixel库,效果就是拨动电位器,四颗灯珠颜色逐渐变化。默认亮度着实瞎眼,另外大家能告诉我为啥子是菱形发散的光,摄像头(iphone6)问题?通过第1个示例可知电位器输出0-1023。

题外话:为啥胃酸是盐酸,而不是硫酸、醋酸啊什么的。

1.4 尚能饭否?

Arduino Leonardo,发布去今有好多年了,彼时物联网概念并不热门,但是随着ESP8266的出现,无线能力几乎成了标配,现在出这么一款产品,无疑限制了它的应用范围。
此外,对于S板有以下建议:

  • 电池接口:我感觉用的多的是PH2.0接口,比如DF商城的锂电池、micro:bit等,默认焊接2.54的有点难受
  • 板载一个按钮作为输入手段是否更好
  • 丝印有待改进

power
另外看到注意事项关于电源的内容有很多,这个能否傻瓜一点,我这种小白记不住boom了咋办。
那么,Sparrow究竟如何呢?我们接着往下看。

2、开展便民服务

2.1 项目设想

最近配了一台台式机(见前文),没有之前Thinkpad笔记本电脑的物理音量调节按钮,就想自己搞一个,于是看着手头的Sparrow,计上心头。
S板主要有两点优势:

  1. 32u4内置USB通讯,适合模拟HID (Human Interface Device)设备
  2. S板上有个电位器角度传感器,是不是很像音量调节旋钮?

原理是这么回事:现在常用的键盘属于HID设备的一种,而很多键盘上都有多媒体键,可以方便地调节音量、打开执行程序甚至自定义功能,我们利用S板模拟出键盘上的多媒体按键即可。看起来比较简单,下面动手看看如何实现。大致拆分了一下,流程拢共分两步:一是模拟成键盘;二是使用电位器调节音量。

2.2 环境需求

  • 软件:Arduino IDE
  • 硬件:MicroUSB Cable,Builtin Potentiometer

哇,引脚都不用焊接!

2.3 项目实施——轮子的救赎

既往没做过,先找块石头摸着过河,看看有没有人做过类似的,放狗(Google)一搜,看到这个USB Volume Control,顺蔓摸瓜找到这个Trinket USB Volume Knob,研究一下。

  • 主控板使用Adafruit开发的 Trinket,采用ATtiny85主控芯片,额,没事,程序代码可以参考思路
  • 使用Arduino编程语言,借助Adafruit-Trinket-USB库,可能需要移植或者更换

2.3.1 第一部分:模拟HID

理论基础有了,我们说干就干,但是AdaFruit 的Trinket还是存在一些不同,我们直接在Arduino IDE里面搜索看看有木有现成的轮子可用,关键词HID,然后发现了这位大佬NicoHood,此外还看到了大佬的IR库:IRLremote
, This library is way more efficient than the "standard" IR library from Ken Shirriff.
我们这里用到NicoHood/HID库,直接在IDE里面的包管理工具安装即可,话说新版的IDE好像下载东西不用挂代理了。
lib.png
下面实现一个简单的Demo:按下按钮,使电脑切换静音。代码如下:

/*
  Copyright (c) 2014-2015 NicoHood
  See the readme for credit to other people.

  Consumer example
  Press a button to play/pause music player

  You may also use SingleConsumer to use a single report.

  See HID Project documentation for more Consumer keys.
  https://github.com/NicoHood/HID/wiki/Consumer-API
*/

#include "HID-Project.h"

const int pinLed = LED_BUILTIN;
const int pinButton = 9;

void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);

  // Sends a clean report to the host. This is important on any Arduino type.
  Consumer.begin();
}

void loop() {
  if (!digitalRead(pinButton)) {
    digitalWrite(pinLed, HIGH);

    // See HID Project documentation for more Consumer keys
    Consumer.write(MEDIA_VOLUME_MUTE);

    // Simple debounce
    delay(300);
    digitalWrite(pinLed, LOW);
  }
}

这里修改自官方例程Consumer,我这里没有按钮,就直接用镊子了,最终效果就是将Sparrow通过MicroUSB线插到电脑上,短接D9和GND(相当于按下了按钮),然后在板上D8上的Builtin灯会闪一下(发白光),电脑就静音啦,再短接一次就会取消静音,如此反复。
btn.jpg
由此第一步就完事了。再来看看第二步,参考下Adafruit的教程,虽然不一样但是思路总能参考吧!但是!结果!发现越发看不懂了,我们的电位器没有ABC脚!大费周章,茅塞顿开,恍然大悟,Encoder编码器和Potentiometer电位器不一样!

电位器和编码器的区别

上文的Adafruit教程原本以为可以参考一下思路,然后发现我这里是电位器(Potentiometer,模拟信号),原文是旋转编码器(Rotary Encoder,数字信号),虽然外观上相似,但本质不同:
电位器:

编码器:

两者的辨别:

电位器与编码器,有着本质的区别,最直接的分辨方法就是:旋转一下,要是旋转角度不足一圈的是电位器,要是可以360度无限旋转的是编码器。

有兴趣可以看这篇电位器和编码器的区别文章,具体还可以移步杜洋的免费公开课《工欲善其事——电子技术探索与教学》,里面有讲解有拆解。

2.3.2 第二部分:旋钮调节音量

首先摸摸情况,夯实基础。我们手头有这些线索:

  1. 电位器输出模拟值,范围0-1024,windows系统的音量控制范围是0-100(应该是百分比)。
  2. 每次按下音量UP/DOWN按钮系统音量变动步进为2。我们参考Consumer API,只有简单的步进。而且我手动测试发现步进为2,即每次按下按钮增加2,这和电脑上的多媒体键一样的,这是在哪定义的呢?我们看看API Documentation,大佬就是大佬,这里找到usb协会的定义。原页面的链接地址失效了,新的是:

下面思考的内容:

  • 需要用到map函数,角度0~270° -> 0-1023 -> 0-100。
    • PLAN A:电位器最大范围和音量范围对应满程,避免出现电位器到底了音量没到底。这就需要接上的时候根据电位器位置初始化音量,模拟按下指定次数。
    • PLAN B:电位器不精确对应音量,仅仅是有调整音量大小的作用。需要电位器范围尽量大于音量范围,2倍?但是此方案无论如何都会出现问题。
  • 能不能实现鼠标即点即改到目标音量?试了一下笔记本上的音量控制键,一次仅增加一点,长按快速按步进增加。也就是UP/DOWN按键没这功能。
  • 另外按键模拟有usb、ps/2接口,后者无论何时都有用,前者是usb hid模拟?bios有用,与系统无关。16进制代码。
  • 看了hut1_12v2.pdf的130页,发现音量控制有两种方案,一是+/-按钮,二是Knob,也就是旋钮式控制。参考Ada的我们再瞅瞅。旋钮仅仅能转270°?不过我们看到的是df有300°,360°和3600°的。大致看了下,S板上的电位器角度传感器大概就是270度。

那么用电位器就不行了吗,当然不是,只是逻辑上有区别,我们参考这个项目的代码进行修改。

#include <HID-Project.h>                    //include HID_Project library
#include <HID-Settings.h>

#define REVERSED false                      //if your controller is reversed change it to true

int val = 0;
int previousval = 0;
int val2 = 0;

void setup() {
  Consumer.begin();                         //initialize computer connection
  delay(1000);                              //wait for computer to connect
  for(int a = 0; a < 52; a++) {
    Consumer.write(MEDIA_VOLUME_DOWN);      //set the volume to 0
    delay(2);
  }
}

void loop() {
  val = analogRead(2);                      //read potentiometer value
  val = map(val, 0, 1023, 0, 101);          //map it to 102 steps
  if(REVERSED) {
    val = 101 - val;
  }
  if(abs(val - previousval) > 1) {          //check if potentiometer value has changed
    previousval = val;
    val /= 2;                               //divide it by 2 to get 51 steps
    while(val2 < val) {
      Consumer.write(MEDIA_VOLUME_UP);      //turn volume up to appropiate level
      val2++;
      delay(2);
    }
    while(val2 > val) {
      Consumer.write(MEDIA_VOLUME_DOWN);    //turn volume down to appropiate level
      val2--;
      delay(2);
    }
  }
  delay(301);                               //wait at least 300ms between changing volume levels
}                                           //if it will change faster Windows can sometimes 
                                            //increase or decrease volume by 10 steps at once

简单的代码要点介绍:

  • 判断电位器正接反接(reversed),这里S板的电位器是固定的,我们不用管
  • 初始化,将音量调到0,再增大到电位器目前所在位置音量,这样才可以完整用到电位器全程。前面介绍过,每次up/down的音量步进为2,所以最多51次降到0,实测降到0后继续down无影响。
  • 检测电位器值变化,每次间隔300ms+,否则可能一次变动步进为10。

效果演示及注意:
demo.gif

  • 可以看到接上S板之后系统响了一下识别音(current 45)->系统音量降到0->增大到电位器目前位置对应音量(46)->开始拨动电位器调整音量,最小步进2。
  • 由于板载电位器最大角度270°,加上阻尼小,所以拨动有点快,对于我这种强迫症不到整数不舒服的实在不友好,以后可以使用角度比较大的电位器,或者干脆使用旋转编码器。

这里使用以下软件

更进一步

  • 更多功能键
    我们从这里可以看到其他功能按键的定义,对源码稍加改动就可以做一个自定义的专属键盘了。
  • 其他用法
    BadUSB之类的,有兴趣的自己搜搜。
  • USB协议分析软件
    Bus Hound/USBlyzer/USBTrace等,不过都收费,而且有段时间没更新了。

后记

这里实现了一个小功能,后续再把其他做的东西整理分享出来,此外micro:bit的东西也拖了好久了。

Reference

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(13)
jzzgb
jzzgb
这创意很棒。
EmSECpn6
EmSECpn6
汤半泛
汤半泛
膜拜大神的动手能力
汤半泛
汤半泛
为什么我现在才来呢
汤半泛
汤半泛
发现了一个精彩的世界
URvj0KkE
URvj0KkE
加油。
汤果
汤果
果然 Geek 的世界就是不一样!
韩俊
韩俊
鼓励一下
江宇瀚
江宇瀚

#嘉诚欧巴#
#嘉诚欧巴#
也有想法用Leonardo做个电脑输入设备,你这个调音量物理按键角度不错!!支持一波~~
pATAq
pATAq
作者
顺便 @KIKIYA
gada888
gada888
鼓励一下
pATAq
pATAq
作者
回复gada888
感谢支持
Ash1
Ash1
啥时候fill-----前排发广告----



pATAq
pATAq
作者
回复Ash1
已经更新啦!
@ASH腻
- 没有更多了 -