跳到主要内容

Wio Terminal USB 从设备

本文主要介绍如何将 Wio-Terminal 用作一个 USB 从设备(USB-Client),例如将其用作键盘、鼠标等人机接口设备(HID),以及用作乐器数字接口设备(MIDI)。

安装依赖库

首先需要为 Wio Terminal 安装 TinyUSB 库 Adafruit_TinyUSB_Arduino

1、在 Adafruit_TinyUSB_ArduinoGitHub 仓库 下载 zip 包。

2、然后将 Adafruit_TinyUSB_Arduino 库安装到 Arduino IDE 中。具体操作:点击 项目 > 加载库 > 添加 .ZIP 库…,然后选择刚刚下载的 Adafruit_TinyUSB_Arduino.zip 文件。

将 Wio Terminal 用作键盘

Wio Terminal 上有三个按键,本示例将这三个按键映射成 iot 三个字母键,当你按下它们时,就相当于按下你的实际键盘一样。这个功能可以轻松实现到你的设计中,帮助你未来完成更具挑战的任务。

安装依赖库

为了完成任务,我们还需要为 Wio Terminal 安装 Keyboard 库。

1、在 Arduino Keyboard LibraryGitHub 仓库 下载 zip 包。

2、然后将 Arduino Keyboard Library 库安装到 Arduino IDE 中。具体操作:点击 项目 > 加载库 > 添加 .ZIP 库…,然后选择刚刚下载的 Keyboard.zip 文件。

完整代码

关于 USB Keyboard 的更多功能和玩法,请参考 Arduino 官方文档 keyboard functions

#include "Keyboard.h" //keyboard library 

void setup() {
//set button pins as inputs
pinMode(WIO_KEY_A, INPUT);
pinMode(WIO_KEY_B, INPUT);
pinMode(WIO_KEY_C, INPUT);

Keyboard.begin(); //start keyboard communication
}

void loop() {
if (digitalRead(WIO_KEY_A) == LOW) { //detect button press
Keyboard.write('t'); //single key is pressed (character)
}
if (digitalRead(WIO_KEY_B) == LOW) {
Keyboard.write('o');
}
if (digitalRead(WIO_KEY_C) == LOW) {
Keyboard.write('i');
}

delay(200); //delay between keypresses
}

将 Wio Terminal 用作鼠标

Wio Terminal 上有一个五向开关,本示例将这个五向开关模拟成鼠标移动,例如向上、向下、向左和向右。 此外,鼠标左键/右键单击、上/下滚动也可以实现。

安装依赖库

为了完成任务,我们还需要为 Wio Terminal 安装 Mouse 库。

1、在 Arduino Mouse LibraryGitHub 仓库 下载 zip 包。

2、然后将 Arduino Mouse Library 库安装到 Arduino IDE 中。具体操作:点击 项目 > 加载库 > 添加 .ZIP 库…,然后选择刚刚下载的 Mouse.zip 文件。

完整代码

关于 USB Mouse 的更多功能和玩法,请参考 Arduino 官方文档 mouse functions

/*    
* A demo for Wio Terminal to simulate mouse by buttons.
* Such as Mouse Up, Mouse Down, Mouse Left, Mouse Right,
* Click the left mouse button, Click the right mouse button,
* Up roll, Down roll and etc.
*
* Copyright (c) 2020 seeed technology co., ltd.
* Author : weihong.cai (weihong.cai@seeed.cc)
* Create Time : July 2020
* Change Log :
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software istm
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INcommInterface
* THE SOFTWARE.
*
* Usage(in Wio Terminal):
* Press the WIO_5S_UP --------------------> Mouse Up
* Press the WIO_5S_DOWN --------------------> Mouse Down
* Press the WIO_5S_LEFT --------------------> Mouse Left
* Press the WIO_5S_RIGHT --------------------> Mouse Right
* Press the BUTTON_3 ------------------------> Click the left mouse button
* Press the BUTTON_2 ------------------------> Click the right mouse button
* Press the WIO_5S_PRESS and WIO_5S_UP ----> Up roll
* Press the WIO_5S_PRESS and WIO_5S_DOWN ----> Down roll
*
* Some tips:
* 1. If your PC unables to recognize USB device leading the Wio Terminal can’t work.
* You can solve this problem through updating your ArduinoCore.
* Please follow this: https://forum.seeedstudio.com/t/seeeduino-xiao-cant-simulate-keys-pressed/252819/6?u=weihong.cai
*
* You can know more about the Wio Terminal from: https://wiki.seeedstudio.com/Wio-Terminal-Getting-Started/
* If you have any questions, you can leave a message on the forum: https://forum.seeedstudio.com
*/

#include "Mouse.h"

/*----------------define the button pins---------------------------*/
const int upButton = WIO_5S_UP;
const int downButton = WIO_5S_DOWN;
const int leftButton = WIO_5S_LEFT;
const int rightButton = WIO_5S_RIGHT;
const int mouseWheel = WIO_5S_PRESS;
const int mouseBttonLeft = BUTTON_3;
const int mouseBttonRight = BUTTON_2;

// output range of X or Y movement; affects movement speed
int range = 2;

// response delay of the mouse, in ms
int responseDelay = 5;

// the time record paramas
unsigned long _currentMillis;
unsigned long _previousMillis;

void setup() {
// initialize the buttons' inputs:
pinMode(upButton, INPUT);
pinMode(downButton, INPUT);
pinMode(leftButton, INPUT);
pinMode(rightButton, INPUT);
pinMode(mouseWheel, INPUT);
pinMode(mouseBttonLeft, INPUT);
pinMode(mouseBttonRight, INPUT);

// initialize mouse control:
Mouse.begin();
}

void loop() {
// read the button state:
int upState = digitalRead(upButton);
int downState = digitalRead(downButton);
int rightState = digitalRead(rightButton);
int leftState = digitalRead(leftButton);
int clickState_mouseWheel = digitalRead(mouseWheel);
int clickState_mouseButtonLeft = digitalRead(mouseBttonLeft);
int clickState_mouseButtonRight = digitalRead(mouseBttonRight);

// calculate the movement distance based on the button states:
int xDistance = (leftState - rightState) * range;
int yDistance = (upState - downState) * range;

/*------------------Mouse Move--------------------------------------*/
// if X or Y is non-zero, move:
if ((xDistance != 0) || (yDistance != 0)) {
Mouse.move(xDistance, yDistance, 0);
}

/*-------------Mouse Button Left Click------------------------------*/
// if the mouse button left is pressed:
if (clickState_mouseButtonLeft == LOW) {
// if the mouse is not pressed, press it:
if (!Mouse.isPressed(MOUSE_LEFT)) {
Mouse.press(MOUSE_LEFT);
//Mouse.click(MOUSE_LEFT);
}
}
// else the mouse button left is not pressed:
else {
// if the mouse is pressed, release it:
if (Mouse.isPressed(MOUSE_LEFT)) {
Mouse.release(MOUSE_LEFT);
}
}

/*-------------Mouse Button Right Click-----------------------------*/
// if the mouse button right is pressed:
if (clickState_mouseButtonRight == LOW) {
// if the mouse is not pressed, press it:
if (!Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.press(MOUSE_RIGHT);
//Mouse.click(MOUSE_RIGHT);
}
}
// else the mouse button right is not pressed:
else {
// if the mouse is pressed, release it:
if (Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.release(MOUSE_RIGHT);
}
}

/*------------------Up roll----------------------------------------*/
if ((upState == LOW) && (clickState_mouseWheel == LOW)) {
Mouse.move(0, 0, 1);
My_delay(200);
}

/*------------------Down roll--------------------------------------*/
if ((downState == LOW) && (clickState_mouseWheel == LOW)) {
Mouse.move(0, 0, -1);
My_delay(200);
}

/*-----------------------------------------------------------------*/
// a delay so the mouse doesn't move too fast:
My_delay(responseDelay);
}

// a delay function uses millis()
void My_delay(int Time)
{
while((_currentMillis - _previousMillis) <= Time)
{
_currentMillis = millis();
}
_previousMillis = _currentMillis;
}

将 Wio Terminal 用作 MIDI 设备

接下来这个示例,将介绍如何将 Wio Terminal 用作 USB MIDI(乐器数字接口)设备,它可以用来控制乐器!

本示例,我们将 Wio Terminal 连接到 Macbook 并使用 macOS 附带的“音频 MIDI 设置”(Audio MIDI Setup)应用程序进行测试。同时还可以在 Arduino IDE 中查看串行监视器中打印的数据。如果你有可用的 MIDI 设备,可以修改示例代码以获得更逼真的场景!

将 Wio Terminal 用作 MIDI 设备

安装依赖库

为了完成任务,我们还需要为 Wio Terminal 安装 MIDI 库 arduino_midi_library

1、在 Arduino MIDI LibraryGitHub 仓库 下载 zip 包。

2、然后将 Arduino MIDI Library 库安装到 Arduino IDE 中。具体操作:点击 项目 > 加载库 > 添加 .ZIP 库…,然后选择刚刚下载的 arduino_midi_library.zip 文件。

完整代码

#include <Arduino.h>
#include <Adafruit_TinyUSB.h>
#include <MIDI.h>

// USB MIDI object
Adafruit_USBD_MIDI usb_midi;

// Create a new instance of the Arduino MIDI Library,
// and attach usb_midi as the transport.
MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, MIDI);

// Variable that holds the current position in the sequence.
uint32_t position = 0;

// Store example melody as an array of note values
byte note_sequence[] = {
74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78,
74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61,
56,61,64,68,74,78,81,86,90,93,98,102
};

void setup()
{
pinMode(LED_BUILTIN, OUTPUT);

// Initialize MIDI, and listen to all MIDI channels
// This will also call usb_midi's begin()
MIDI.begin(MIDI_CHANNEL_OMNI);

// Attach the handleNoteOn function to the MIDI Library. It will
// be called whenever the Bluefruit receives MIDI Note On messages.
MIDI.setHandleNoteOn(handleNoteOn);

// Do the same for MIDI Note Off messages.
MIDI.setHandleNoteOff(handleNoteOff);

Serial.begin(115200);

// wait until device mounted
while( !USBDevice.mounted() ) delay(1);
}

void loop()
{
static uint32_t start_ms = 0;
if ( millis() - start_ms > 266 )
{
start_ms += 266;

// Setup variables for the current and previous
// positions in the note sequence.
int previous = position - 1;

// If we currently are at position 0, set the
// previous position to the last note in the sequence.
if (previous < 0) {
previous = sizeof(note_sequence) - 1;
}

// Send Note On for current position at full velocity (127) on channel 1.
MIDI.sendNoteOn(note_sequence[position], 127, 1);

// Send Note Off for previous note.
MIDI.sendNoteOff(note_sequence[previous], 0, 1);

// Increment position
position++;

// If we are at the end of the sequence, start over.
if (position >= sizeof(note_sequence)) {
position = 0;
}
}

// read any new MIDI messages
MIDI.read();
}

void handleNoteOn(byte channel, byte pitch, byte velocity)
{
// Log when a note is pressed.
Serial.printf("Note on: channel = %d, pitch = %d, velocity - %d", channel, pitch, velocity);
Serial.println();
}

void handleNoteOff(byte channel, byte pitch, byte velocity)
{
// Log when a note is released.
Serial.printf("Note off: channel = %d, pitch = %d, velocity - %d", channel, pitch, velocity);
Serial.println();
}