最新消息:码丁实验室,一站式儿童编程学习产品,寻地方代理合作共赢,微信联系:leon121393608。

Arduino 获得 WS1361 音量计数值

Arduino 少儿编程 1640浏览 0评论

码丁实验室,一站式儿童编程学习产品,寻地方代理合作共赢,微信联系:leon121393608。

去年买了一个带有 USB 输出噪音计型号是
WS1361,我特地去查了一下,2017年2月6日买的,然后一直拖到了最近才动手编写 Arduino 的代码。也多亏找到其他人的研究资料【参考1】,所以才比较顺利的完成解码。这部分的工作就像在解密一样,在不知道答案的情况下是一头雾水,当完成之后如释重负。

同样的,USB逻辑分析在这次编写中也发挥了重要。此外,最近接触到的Windows USB分析软件对于反向工程也是很多有效果【参考2】。

第一步还是抓取描述符

Arduino 获得 WS1361 音量计数值

 

之前的键盘鼠标的描述符对于分析非常有用,但是这次描述符在分析过程中几乎可以称作毫无用处。当然,如果非要说有什么作用的话,只是让我得知他使用了自定义的协议。

第二步,使用逻辑分析仪查看抓包。这款逻辑分析仪带有USB接口,插入系统后,安装对应的驱动和应用程序可以在电脑上实时看到获得的当前音量(美中不足的是他们的软件没有数字签名,使用Windows 8/8.1/10 64位的朋友,必须禁用签名才能安装和运行起来)。

抓到的关键数据如下: Get Device Descriptor(Transfer 12) -> 获取自定义数据(Transfer 13) –> Get Device Descriptor(Transfer 14) 这样循环下去。这样的循环是他的应用程序驱动完成的。在我看来Get Device Descriptor 是毫无用处的。可能是应用程序用来确定设备是否被 remove才做的。

 

Arduino 获得 WS1361 音量计数值

详细分析获取数据的过程 Transfer 13, 由 Transaction 283/286/287 三笔来组成。Transaction 283用户自定义的 Setup 过程,我们代码只需要做出和他内容相同的发出去即可。然后Transaction 286 是噪音计回复的数据包,其中有我们需要的当前音量数据。具体格式从【参考1】可以看到。

硬件方面使用的是 Arduino USB Host板+ Arduino Uno,因为是 Shield板,直接插上即可使用。为了更清楚的展示接收数据的过程,我使用了巨大的LED数码管(1.8寸),关于这个数码管的介绍可以在之前的文章中找到。

 

Arduino 获得 WS1361 音量计数值

根据上述内容,编写程序如下:

#include
“Usb.h”

 

USB Usb;

 

uint16_t LastDB=0;

 

void digitalshow(int
value)

{

//这是数码管要求的数据头信息

Serial.write(0xff);

Serial.write(0×00);

Serial.write(0×04); //显示四位数值

 

//下面是四位当前值

 

Serial.write(0×10); //第一位黑

Serial.write((value – value /1000 * 1000) /
100);

//第三位后面有小数点,最高位为 1 表示显示小数点

Serial.write((value – value /100 * 100) /
10+ 0×80);

Serial.write(value % 10);

 

//最后一位是亮度

Serial.write(1);

}

void
DataParser(UsbDevice *pdev)

{

int nbytes=4;

uint8_t value[2];

 

Usb.ctrlReq(

pdev->address.devAddress,

0, //EndPoint

0xC0, //bmRequestType

0×04, //bRequest

0×01, //wValeLow

0×00, //wValueHigh

0×0000, //wIndex

nbytes,

nbytes,

&value[0],

NULL);

if ((value[0]+(value[1]<<8))==LastDB) {

return;

}

else

LastDB=(value[0]+(value[1]<<8));

//Serial.print(“RAW:”);

//Serial.print(value[0],HEX);

//Serial.print(” “);

//Serial.println(value[1],HEX);

 

//Serial.print(” DB:”);

//Serial.println((value[0] + ((value[1] &
3) * 256)) * 0.1 + 30);

digitalshow(((value[0] + ((value[1] & 3)
* 256)) * 0.1 + 30)*10);

}

 

 

void setup()

{

Serial.begin( 115200 );

 

Serial.println(“Start”);

 

if (Usb.Init() == -1)

Serial.println(“OSC did not
start.”);

 

delay( 200 );

 

}

 

void loop()

{

Usb.Task();

 

if ( Usb.getUsbTaskState() ==
USB_STATE_RUNNING )

{

Usb.ForEachUsbDevice(&DataParser);

delay(200);

}

}

工作的视频:

 

 

Arduino 获得 WS1361 音量计数值

https://www.zhihu.com/video/948948344039550976

参考:

1. ebswift.com/reverse-eng
Reverse Engineering the USB Protocol on the WENSN WS1361 Sound Pressure Level
Meter

2. lab-z.com/usblyzer/介绍一个 USB
分析软件
Usblyzer

始发于知乎专栏:王朝

您必须 登录 才能发表评论!