Ariduino入门笔记——11. Arduino 默认函数(USB设备控制)
文章目录
- Keyboard
- 开启键盘模拟 Keyboard.begin()
- 关闭键盘模拟 Keyboard.end()
- 长摁键盘 Keyboard.press()
- 敲击键盘 Keyboard.print()
- 带回车的敲击事件 Keyboard.println()
- 释放按键 Keyboard.release()
- 释放全部按键 Keyboard.releaseAll()
- 发送单个敲击指令 Keyboard.write()
- Mouse
- 开启鼠标模拟 Mouse.begin()
- 鼠标点击事件 Mouse.click()
- 函数原型
- 参数说明
- 关闭鼠标模拟 Mouse.end()
- 鼠标移动事件 Mouse.move()
- 函数原型
- 参数说明
- 长按鼠标 Mouse.press()
- 函数原型
- 参数说明
- 鼠标按键释放 Mouse.release()
- 函数原型
- 参数说明
- 鼠标状态检测 Mouse.isPressed()
- 函数原型
- 参数说明
作为本系列的最后一篇了,这里介绍一下Arduino用来模拟USB设备,比如键盘和鼠标的方法。比如做硬件外挂等,就可以使用到Arduino这里提供的功能。
Keyboard
首先来看一看在Arduino中文社区提供的一段栗子1
VCC 5V串联一只1K欧姆的电阻,然后电阻一端连接Arduino针脚,另一端和开关连接。开关的另一只引脚接地。开关没有接通时,输入引脚4的电位因为VCC接地所以是低电平。当开关摁下后,VCC和接地被阻断,引脚4收到高电平信号,于是在每次摁下开关后,计数器就加1。
于是我们得到一个简单的USB控制代码,它大概如下面这样:
#include "Keyboard.h"const int buttonPin = 4; // 按键连接引脚
int previousButtonState = HIGH; // 之前按键状态
int counter = 0; // 按键计数器void setup() {// 初始化按键引脚,如果没有上拉电阻,需要使用INPUT_PULLUPpinMode(buttonPin, INPUT);// 初始化模拟键盘功能Keyboard.begin();
}void loop() {// 读按键状态int buttonState = digitalRead(buttonPin);// 如果按键状态改变,且当前按键状态为高电平if ((buttonState != previousButtonState) && (buttonState == HIGH)) {// 按键计数器加1counter++;// 模拟键盘输出信息Keyboard.print("You pressed the button ");Keyboard.print(counter);Keyboard.println(" times.");}// 保存当前按键状态,用于下一次比较previousButtonState = buttonState;
}
回到官方的文档,分别提供了关于键盘的以及鼠标的USB连接方案。那么对于键盘呢,首先需要注意的是:
无法处理ASC II表中的非打印字符,也就是EOF、蜂鸣器等控制字符是无法处理的。
另外,Arduino 支持基于32u4和SAMD系列的主控板,比如SAMD21和电脑相连。至于重要不重要,我觉得反正对于我们这种主打软件的人来说,只要能验证方案就行了,并不需要花费过多心思在嵌入式芯片和主控板的选型上。如果有条件的话,最好一个主做软件,一个主做硬件的朋友搭伙一起搞设备是比较合适的。
哦,对了,再多说一句。如果你已经使用USB模块并已经让程序运行起来,那么此时试图修改代码会非常困难。因为Arduino会接管你的鼠标和键盘,由于程序处理效率比手工高出不知道多少倍。所以你会发现鼠标会到处游走,或者键盘不停的输出字符。
解决方案是,比如在设计电路的时候,多增加一个按钮,当摁下的时候启动USB托管程序,当再次摁下这个摁钮的时候,就关闭USB托管功能,这样方便你进行调试。此外,在正式运行程序之前,官方建议你先用 Serial.print 把运行结果打印出来,以验证程序是否正确,再接入到USB库里。
当然,你也可以无视这些warning。
开启键盘模拟 Keyboard.begin()
对于Leonardo和Due板来说,这个函数的意义在于启动一个虚拟的键盘,并连接到电脑上,如果需要终止这个连结,使用 Keyboard.end()。
#include <Keyboard.h>void setup() {// make pin 2 an input and turn on the// pullup resistor so it goes high unless// connected to ground:pinMode(2, INPUT_PULLUP);Keyboard.begin();
}void loop() {//if the button is pressedif (digitalRead(2) == LOW) {//Send the messageKeyboard.print("Hello!");}
}
关闭键盘模拟 Keyboard.end()
没啥好说的,就是关闭键盘模拟
长摁键盘 Keyboard.press()
这是十分有用的指令,用于向电脑输入某个被摁下的按键,就像你为了在FPS游戏中,控制角色前后左右移动,需要长摁WSAD一样。那么释放某个按键,就使用Keyboard.release() 或者Keyboard.releaseAll()。
#include <Keyboard.h>// use this option for OSX:
char ctrlKey = KEY_LEFT_GUI;
// use this option for Windows and Linux:
// char ctrlKey = KEY_LEFT_CTRL;void setup() {// make pin 2 an input and turn on the// pullup resistor so it goes high unless// connected to ground:pinMode(2, INPUT_PULLUP);// initialize control over the keyboard:Keyboard.begin();
}void loop() {while (digitalRead(2) == HIGH) {// do nothing until pin 2 goes lowdelay(500);}delay(1000);// new document:Keyboard.press(ctrlKey);Keyboard.press('n');delay(100);Keyboard.releaseAll();// wait for new window to open:delay(1000);
}
敲击键盘 Keyboard.print()
模拟敲击事件,比如模拟文本输入。可以使用这个指令。不过都需要注意,所有跟键盘有关的指令,都需要在Keyboard.begin() 被设置后才会有效。
#include <Keyboard.h>void setup() {// make pin 2 an input and turn on the// pullup resistor so it goes high unless// connected to ground:pinMode(2, INPUT_PULLUP);Keyboard.begin();
}void loop() {//if the button is pressedif (digitalRead(2) == LOW) {//Send the messageKeyboard.print("Hello!");}
}
带回车的敲击事件 Keyboard.println()
和上面的功能相似,区别只是多了一个回车功能。
#include <Keyboard.h>void setup() {// make pin 2 an input and turn on the// pullup resistor so it goes high unless// connected to ground:pinMode(2, INPUT_PULLUP);Keyboard.begin();
}void loop() {//if the button is pressedif (digitalRead(2) == LOW) {//Send the messageKeyboard.println("Hello!");}
}
释放按键 Keyboard.release()
跟Press功能对应,不过release是释放具体的按键
#include <Keyboard.h>// use this option for OSX:
char ctrlKey = KEY_LEFT_GUI;
// use this option for Windows and Linux:
// char ctrlKey = KEY_LEFT_CTRL;void setup() {// make pin 2 an input and turn on the// pullup resistor so it goes high unless// connected to ground:pinMode(2, INPUT_PULLUP);// initialize control over the keyboard:Keyboard.begin();
}void loop() {while (digitalRead(2) == HIGH) {// do nothing until pin 2 goes lowdelay(500);}delay(1000);// new document:Keyboard.press(ctrlKey);Keyboard.press('n');delay(100);Keyboard.release(ctrlKey);Keyboard.release('n');// wait for new window to open:delay(1000);
}
释放全部按键 Keyboard.releaseAll()
跟上面的功能相似,不过这是释放全部按键的。
发送单个敲击指令 Keyboard.write()
跟print和println的作用相似,只不过这是只发送一个键位的敲击指令。
Keyboard.write(65); // sends ASCII value 65, or A
Keyboard.write('A'); // same thing as a quoted character
Keyboard.write(0x41); // same thing in hexadecimal
Keyboard.write(0b01000001); // same thing in binary (weird choice, but it works)
需要注意的是,无论println还是print或者write指令,都只能发送ASC II可打印字符,换句话说,就是你键盘上可以敲击的按键,比如字符的ABCD,数字的1234,或者空格、回车、Ctrl这一类的,对于字符串中止字符\0 ,文章EOF字符,蜂鸣器等控制指令字符都无法使用。
Mouse
讲完键盘,就需要介绍鼠标的控制。不过注意事项和支持都和键盘一样,所以这里不做过多赘述。
开启鼠标模拟 Mouse.begin()
启动鼠标模拟,如果需要关闭鼠标模拟,那么可以通过Mouse.end() 关闭。
#include <Mouse.h>void setup() {pinMode(2, INPUT);
}void loop() {//initiate the Mouse library when button is pressedif (digitalRead(2) == HIGH) {Mouse.begin();}
}
鼠标点击事件 Mouse.click()
发送瞬间的鼠标点击事件,比如你平时的左击选中,或者右击菜单这样。
函数原型
- Mouse.click()
- Mouse.click(button)
参数说明
通常有三个按键可供选择,左键,右键,和中建。
- MOUSE_LEFT (default)
- MOUSE_RIGHT
- MOUSE_MIDDLE
关闭鼠标模拟 Mouse.end()
没什么好说的,就是关闭鼠标模拟的。
鼠标移动事件 Mouse.move()
把光标移动到指定的位置,这里是相对位置。
函数原型
Mouse.move(xVal, yVal, wheel)
参数说明
- xVal: amount to move along the x-axis. Allowed data types: signed char.
- yVal: amount to move along the y-axis. Allowed data types: signed char.
- wheel: amount to move scroll wheel. Allowed data types: signed char.
需要注意的一点就是,官方并未给出值范围,而只提到这个值接受signed char,所以范围自然就只能 (-127, 127) 之间,所以这里移动距离其实是个相对位置。
#include <Mouse.h>const int xAxis = A1; //analog sensor for X axis
const int yAxis = A2; // analog sensor for Y axisint range = 12; // output range of X or Y movement
int responseDelay = 2; // response delay of the mouse, in ms
int threshold = range / 4; // resting threshold
int center = range / 2; // resting position value
int minima[] = {1023, 1023}; // actual analogRead minima for {x, y}
int maxima[] = {0, 0}; // actual analogRead maxima for {x, y}
int axis[] = {xAxis, yAxis}; // pin numbers for {x, y}
int mouseReading[2]; // final mouse readings for {x, y}void setup() {Mouse.begin();
}void loop() {// read and scale the two axes:int xReading = readAxis(0);int yReading = readAxis(1);// move the mouse:Mouse.move(xReading, yReading, 0);delay(responseDelay);
}/*reads an axis (0 or 1 for x or y) and scales theanalog input range to a range from 0 to <range>
*/int readAxis(int axisNumber) {int distance = 0; // distance from center of the output range// read the analog input:int reading = analogRead(axis[axisNumber]);// of the current reading exceeds the max or min for this axis,// reset the max or min:if (reading < minima[axisNumber]) {minima[axisNumber] = reading;}if (reading > maxima[axisNumber]) {maxima[axisNumber] = reading;}// map the reading from the analog input range to the output range:reading = map(reading, minima[axisNumber], maxima[axisNumber], 0, range);// if the output reading is outside from the// rest position threshold, use it:if (abs(reading - center) > threshold) {distance = (reading - center);}// the Y axis needs to be inverted in order to// map the movemment correctly:if (axisNumber == 1) {distance = -distance;}// return the distance for this axis:return distance;
}
长按鼠标 Mouse.press()
比如拉取选框、拖拽的时候,通常配合move函数一起可以实现这种功能。需要释放的时候,可以使用Mouse.release()。
函数原型
- Mouse.press()
- Mouse.press(button)
参数说明
- MOUSE_LEFT (default)
- MOUSE_RIGHT
- MOUSE_MIDDLE
#include <Mouse.h>void setup() {//The switch that will initiate the Mouse presspinMode(2, INPUT);//The switch that will terminate the Mouse presspinMode(3, INPUT);//initiate the Mouse libraryMouse.begin();
}void loop() {//if the switch attached to pin 2 is closed, press and hold the left mouse buttonif (digitalRead(2) == HIGH) {Mouse.press();}//if the switch attached to pin 3 is closed, release the left mouse buttonif (digitalRead(3) == HIGH) {Mouse.release();}
}
鼠标按键释放 Mouse.release()
如果鼠标中有某个按键被摁下后,使用这个函数可以释放该按键。
函数原型
- Mouse.release()
- Mouse.release(button)
参数说明
- MOUSE_LEFT (default)
- MOUSE_RIGHT
- MOUSE_MIDDLE
鼠标状态检测 Mouse.isPressed()
如果某个鼠标按键被摁下了,或者Mouse.press 发送了长摁命令,则返回true
函数原型
- Mouse.isPressed();
- Mouse.isPressed(button);
参数说明
- MOUSE_LEFT (default)
- MOUSE_RIGHT
- MOUSE_MIDDLE
#include <Mouse.h>void setup() {//The switch that will initiate the Mouse presspinMode(2, INPUT);//The switch that will terminate the Mouse presspinMode(3, INPUT);//Start serial communication with the computerSerial.begin(9600);//initiate the Mouse libraryMouse.begin();
}void loop() {//a variable for checking the button's stateint mouseState = 0;//if the switch attached to pin 2 is closed, press and hold the left mouse button and save the state ina variableif (digitalRead(2) == HIGH) {Mouse.press();mouseState = Mouse.isPressed();}//if the switch attached to pin 3 is closed, release the left mouse button and save the state in a variableif (digitalRead(3) == HIGH) {Mouse.release();mouseState = Mouse.isPressed();}//print out the current mouse button stateSerial.println(mouseState);delay(10);
}
《Arduino模拟USB键盘》 https://www.arduino.cn/thread-81605-1-1.html ↩︎
Ariduino入门笔记——11. Arduino 默认函数(USB设备控制)相关推荐
- Ariduino入门笔记——1. Arduino 默认函数(数字接口/模拟接口)
说实话,对于我这种朝三暮四,动不动就要开新坑的人来说,肯定很多人都烦死了.没办法,因为脑袋里的猴子有点多,一直做一件事的话,我反而很容易就弃坑.也就是所谓新鲜感,隔一段时间回过头来看看草稿箱里有哪些稿 ...
- Ariduino入门笔记——9. Arduino 默认函数(串口通信)
文章目录 什么是串口 Serial 串口函数 串口准备--if(Serial) 获取可读取的字节数--available() 获取可写入的最大字节数--availableForWrite() 串口连接 ...
- 【机器学习入门笔记11:numpy模块实现矩阵的增删改查】20190217
2019-02-17 by 崔斐然 除了TensorFlow设置的矩阵之外,我们还可以通过numpy模块使用矩阵. 我们先在anaconda中参考笔记1中的配置方法安装numpy. 下面我们通过nu ...
- 【太极创客】零基础入门学用Arduino 第一部分 合辑笔记
[太极创客]零基础入门学用Arduino 第一部分 合辑 笔记大多整理于B站评论区 https://www.bilibili.com/video/BV164411J7GE/?spm_id_from=3 ...
- 11岁过python1级_11岁表弟写的Python零基础入门笔记!
一.Python输入与输出输出:使用print()函数. print()函数的基本语法格式如下:print(输出内容). 输出内容可以是数字和字符串(字符串需要用引号括起来),也可以是包含运算符的表达 ...
- python入门笔记——内置函数作业
python入门笔记--内置函数作业 # 求三组连续自然数的和:求出1到10,20到30,35到45的三个和 sum1 = sum(range(1,11)) sum2 = sum(range(20,3 ...
- ESP32 入门笔记03:PWM (ESP32 for Arduino IDE)
先导知识 ESP32 入门笔记01:开发板信息.开发环境搭建以及学资料准备 ESP32 入门笔记02: GPIO参考指南 ESP32 有一个 LED PWM 控制器,具有 16 个独立通道,可配置为生 ...
- C++11构造与禁用默认函数
C++11(五)继承构造 在继承体系中,假设派生类想要使用基类的构造函数,必须要在构造函数中显式声明. 举个小例子: class Base { public:int value1;int value2 ...
- 凸优化学习笔记 11:对偶原理 拉格朗日函数
前面讲了凸优化问题的定义,以及一些常见的凸优化问题类型,这一章就要引入著名的拉格朗日函数和对偶问题了.通过对偶问题,我们可以将一些非凸问题转化为凸优化问题,还可以求出原问题的非平凡下界,这对复杂优化问 ...
最新文章
- 物料变式的订货型生产(3.0C:可库存的类型)(26)
- Maximum sum(poj 2479)
- java后端获取客户端(用户)真实ip,原理
- jquery slideDown slideUp 对于table无效
- FTP连接报530错误(FTP Error: 530 User cannot log in, home directory inaccessible)
- Linux下C编程入门
- 写出质量好软件的75条体会-转载篇
- java 反射 框架_Java——利用反射实现框架类
- 用JSP实现简单的留言板
- 用python证明采样定理_这一切都从指数函数开始(4)——采样定理
- 怎么使用播放麦克风输入的音频呢
- 如何将拉勾网(智联招聘)的预览简历导出来
- 微信豆有什么作用?微信豆怎么用?附攻略
- rust 入门笔记: rustlings(推荐一些学习rust语法的一些非常好的小练习)
- Visual Studio界面颜色更换 及 Visual Assist X助手使用
- python 创建和使用字典
- 5G,V2X强强联手,无人驾驶还会远吗
- go Jenkins流水线极速打包镜像上传
- 中文文件如何翻译为英文
- 7大创业误区:听听过来人的故事
热门文章
- python创建_python 创建txt并写入Python基础1 Hello World!
- 在线调试后台管理系统HTTP的POST请求
- 陆奇:除了好代码,工程师怎样才算优秀?
- P1823 [COI2007] Patrik 音乐会的等待(单调栈)
- mysql 的delete from 子查询限制
- 游戏编程之十 图像引擎DirectXDraw
- Unraid下虚拟DSM7.1,并开启相册人脸识别
- 判断Android Textview是否换行
- Altium Designer 生成 BOM(Bill of Material)
- Python中的getter、setter、deleter