Arduino 简明教程
Arduino - Overview
Arduino 是一个基于易于使用的硬件和软件的原型平台(开源)。它包括一个电路板,可以进行编程(称为微控制器),以及一个用于编写和将计算机代码上传到物理板的现成软件,称为 Arduino IDE(集成开发环境)。
主要功能 −
-
Arduino 电路板能够从不同的传感器读取模拟或数字输入信号,并将其转换为输出,例如启动电机、打开/关闭 LED,连接云以及许多其他动作。
-
您可以通过 Arduino IDE(称为上载软件)向电路板上的微控制器发送一组指令来控制电路板功能。
-
与大多数以前的可编程电路板不同,Arduino 无需额外的硬件(称为编程器)即可将新代码加载到电路板上。您可以简单地使用 USB 数据线。
-
此外,Arduino IDE 使用 C++ 的简化版本,让编程更容易学习。
-
最后,Arduino 提供了标准的外形尺寸,将微控制器的功能分成更易于获取的封装。
Board Types
根据所用的不同微控制器,有各种类型的 Arduino 电路板。然而,所有的 Arduino 电路板有一个共同点:可以通过 Arduino IDE 进行编程。
差异基于输入和输出的数量(您可以在一块电路板上使用的传感器、LED 和按钮的数量)、速度、工作电压、外形尺寸等。一些电路板被设计成嵌入式,没有编程接口(硬件),您需要单独购买。一些可以直接通过 3.7V 电池供电,其他则至少需要 5V。
以下是不同 Arduino 电路板的列表。
Arduino boards based on ATMEGA328 microcontroller
Board Name |
Operating Volt |
Clock Speed |
Digital i/o |
Analog Inputs |
PWM |
UART |
Programming Interface |
Arduino Uno R3 |
5V |
16MHz |
14 |
6 |
6 |
1 |
USB via ATMega16U2 |
Arduino Uno R3 SMD |
5V |
16MHz |
14 |
6 |
6 |
1 |
USB via ATMega16U2 |
Red Board |
5V |
16MHz |
14 |
6 |
6 |
1 |
USB via FTDI |
Arduino Pro 3.3v/8 MHz |
3.3V |
8MHz |
14 |
6 |
6 |
1 |
FTDI-Compatible Header |
Arduino Pro 5V/16MHz |
5V |
16MHz |
14 |
6 |
6 |
1 |
FTDI-Compatible Header |
Arduino mini 05 |
5V |
16MHz |
14 |
8 |
6 |
1 |
FTDI-Compatible Header |
Arduino Pro mini 3.3v/8mhz |
3.3V |
8MHz |
14 |
8 |
6 |
1 |
FTDI-Compatible Header |
Arduino Pro mini 5v/16mhz |
5V |
16MHz |
14 |
8 |
6 |
1 |
FTDI-Compatible Header |
Arduino Ethernet |
5V |
16MHz |
14 |
6 |
6 |
1 |
FTDI-Compatible Header |
Arduino Fio |
3.3V |
8MHz |
14 |
8 |
6 |
1 |
FTDI-Compatible Header |
LilyPad Arduino 328 主电路板 |
3.3V |
8MHz |
14 |
6 |
6 |
1 |
FTDI-Compatible Header |
LilyPad Arduino simple board |
3.3V |
8MHz |
9 |
4 |
5 |
0 |
FTDI-Compatible Header |
Arduino boards based on ATMEGA32u4 microcontroller
Board Name |
Operating Volt |
Clock Speed |
Digital i/o |
Analog Inputs |
PWM |
UART |
Programming Interface |
Arduino Leonardo |
5V |
16MHz |
20 |
12 |
7 |
1 |
Native USB |
Pro micro 5V/16MHz |
5V |
16MHz |
14 |
6 |
6 |
1 |
Native USB |
Pro micro 3.3V/8MHz |
5V |
16MHz |
14 |
6 |
6 |
1 |
Native USB |
LilyPad Arduino USB |
3.3V |
8MHz |
14 |
6 |
6 |
1 |
Native USB |
Arduino boards based on ATMEGA2560 microcontroller
Board Name |
Operating Volt |
Clock Speed |
Digital i/o |
Analog Inputs |
PWM |
UART |
Programming Interface |
Arduino Mega 2560 R3 |
5V |
16MHz |
54 |
16 |
14 |
4 |
USB via ATMega16U2B |
Mega Pro 3.3V |
3.3V |
8MHz |
54 |
16 |
14 |
4 |
FTDI-Compatible Header |
Mega Pro 5V |
5V |
16MHz |
54 |
16 |
14 |
4 |
FTDI-Compatible Header |
Mega Pro Mini 3.3V |
3.3V |
8MHz |
54 |
16 |
14 |
4 |
FTDI-Compatible Header |
Arduino boards based on AT91SAM3X8E microcontroller
Board Name |
Operating Volt |
Clock Speed |
Digital i/o |
Analog Inputs |
PWM |
UART |
Programming Interface |
Arduino Mega 2560 R3 |
3.3V |
84MHz |
54 |
12 |
12 |
4 |
USB native |
Arduino - Board Description
在本章中,我们将了解 Arduino 板上的不同组件。我们研究 Arduino UNO 板,因为它在 Arduino 板系列中是最流行的板。此外,它是开始学习电子和编码的最佳选择。一些板看起来与下面给出的有些不同,但大多数 Arduino 都具有这些组件的大部分共同点。
Power USB Arduino 板可以使用来自计算机的 USB 电缆供电。您需要做的就是将 USB 数据线连接到 USB 连接器(1)。 |
|
Power (Barrel Jack) Arduino 板可以通过将其连接到 Barrel Jack(2)从交流主电源直接供电。 |
|
Voltage Regulator 电压调节器的作用是控制给 Arduino 板的电压并稳定处理器和其他元件使用的直流电压。 |
|
Crystal Oscillator 晶体振荡器帮助 Arduino 处理时间问题。Arduino 如何计算时间?答案是,通过使用晶体振荡器。印刷在 Arduino 晶体顶部的数字是 16.000H9H。它告诉我们频率是 16,000,000 赫兹或 16 兆赫。 |
|
Arduino Reset 您可以重置 Arduino 板,即从头开始运行程序。有两种方式可以重置 UNO 板。首先,使用板上的复位按钮(17)。其次,您可以将外部复位按钮连接到标记为 RESET(5)的 Arduino 引脚。 |
|
Pins (3.3, 5, GND, Vin) 3.3V(6)− 提供 3.3 输出伏5V(7)− 提供 5 输出伏与 Arduino 板一起使用的大多数组件都适用于 3.3 伏和 5 伏。GND(8)(接地)− Arduino 上有几个 GND 引脚,任何一个引脚都可以用来接地电路。Vin(9)− 此引脚也可用于从外部电源(如交流主电源)为 Arduino 板供电。 |
|
Analog pins Arduino UNO 板有六个模拟输入引脚 A0 至 A5。这些引脚可以读取模拟传感器(如湿度传感器或温度传感器)发来的信号,然后将其转换为微处理器可以读取的数字值。 |
|
Main microcontroller 每个 Arduino 板都有自己的微控制器 (11)。你可以把它当作板上的“大脑”。Arduino 上的主要 IC(集成电路)从一块板到另一块板略有不同。这些微控制器通常来自 ATMEL 公司。在从 Arduino IDE 加载新程序之前,你必须知道板上有什么 IC。此信息显示在 IC 的顶部。有关 IC 构造和功能的更多详细信息,请参阅数据表。 |
|
ICSP pin 通常,ICSP (12) 是一个 AVR,一个带有 MOSI、MISO、SCK、复位、VCC 和 GND 的微型编程头。它通常被称为 SPI(串行外围接口),可被认为是输出的“扩展”。实际上,你将输出设备用作 SPI 总线的从设备。 |
|
Power LED indicator 将 Arduino 插入电源后,此 LED 应亮起,表明你的板已正确通电。如果此指示灯未亮起,则连接有问题。 |
|
TX and RX LEDs 在你的板上,你会发现两个标签:TX(发送)和 RX(接收)。它们出现在 Arduino UNO 板上的两个位置。首先,在数字引脚 0 和 1 上,表示负责串行通信的引脚。其次,TX 和 RX LED (13)。发送串行数据时,TX LED 以不同的速度闪烁。闪烁速度取决于板使用的波特率。接收过程中,RX 会闪烁。 |
|
Digital I/O Arduino UNO 板有 14 个数字 I/O 引脚 (15)(其中 6 个提供 PWM(脉冲宽度调制)输出)。可以配置这些引脚,使其作为输入数字引脚工作,以读取逻辑值(0 或 1),或作为数字输出引脚,以驱动不同的模块,如 LED、继电器等。标记为“~”的引脚可用于产生 PWM。 |
|
AREF AREF 表示模拟参考。有时,它用于设置外部参考电压(0 到 5 伏特之间)作为模拟输入引脚的上限。 |
Arduino - Installation
在了解了 Arduino UNO 电路的各个主要部分后,我们便可以学习如何设置 Arduino IDE。一旦学会,我们便可以将程序上传至 Arduino 电路板。
在本部分中,我们将分步学习如何将 Arduino IDE 设置到我们的计算机上,并使用 USB 电缆准备电路板接收程序。
Step 1 − 首先,你必须准备 Arduino 电路板(你可以选择你偏好的电路板)和一条 USB 电缆。如果你使用 Arduino UNO、Arduino Duemilanove、Nano、Arduino Mega 2560 或 Diecimila,则需要一条标准 USB 电缆(A 型插头至 B 型插头),即你用于连接 USB 打印机的电缆,如以下图片所示。
如果你使用 Arduino Nano,则你需要一条 A 型至 Mini-B 型电缆,如以下图片所示。
Step 2 − Download Arduino IDE Software.
你可以在 Arduino 官方网站上的 Download page 获得不同版本的 Arduino IDE。你必须选择适合你的操作系统(Windows、IOS 或 Linux)的软件。下载文件完成后,解压该文件。
Step 3 − Power up your board.
Arduino Uno、Mega、Duemilanove 和 Arduino Nano 自动从计算机的 USB 连接或外部电源获取电能。如果你使用的是 Arduino Diecimila,则必须确保电路板配置为从 USB 连接获取电能。电源通过跳线(小块塑料,可装在 USB 和电源插孔之间的三个插针中的两个插针上)选择。请检查跳线是否位于最靠近 USB 端口的两个插针上。
使用 USB 电缆将 Arduino 电路板连接至你的计算机。绿色的电源 LED(标记为 PWR)应亮起。
Step 4 − Launch Arduino IDE.
下载 Arduino IDE 软件后,你需要解压文件夹。在文件夹中,你可以找到带有无穷大符号(application.exe)的应用程序图标。双击该图标启动 IDE。
@[s0]
软件启动后,你有两个选择 -
-
Create a new project.
-
打开现有项目示例。
要创建新项目,请选择文件 → @[s1]。
要打开现有项目示例,请选择文件 → 示例 → 基础 → 闪烁。
此处,我们仅选择一个名为 Blink 的示例。它会延迟一段时间打开和关闭 LED 灯。你可以从列表中选择任何其他示例。
@[s3]
为了避免在将程序上传到电路上时出现错误,你必须选择正确的 Arduino 电路板名称,该名称与连接到计算机的电 路板相匹配。
转到工具 → 电路板,并选择你的电 路板。
此处,我们根据教程选择了 Arduino Uno 电路板,但你必须选择与你使用的电 路板相匹配的名称。
@[s4]
选择 Arduino 电路板的串口设备。转到 @[s5] 菜单。此设备可能是 COM3 或更高版本(COM1 和 COM2 通常保留给硬件串行端口)。要查找,你可 以断开 Arduino 电路板并重新打开菜单,消失的条目应属于 Arduino 电路板。重新连接电 路板并选择该串行端口。
@[s6]
在解释如何将程序上传到电 路板之前,我们必须说明 Arduino IDE 工具栏中出现的每个符号的功能。
@[s7] - 用于检查是否存在任何编译错误。
@[s8] - 用于将程序上传到 Arduino 电路板。
@[s9] - 用于创建新草稿的快捷方式。
@[s10] - 用于直接打开一个示例草稿。
E − 用于保存你的草图。
F − 串行监视器用于从电路板接收串行数据并向电路板发送串行数据。
现在,只须点击环境中的“上传”按钮。等待几秒钟,你将看到电路板上的 RX 和 TX LED 闪烁。如果上传成功,状态栏中将出现“上传完成”信息。
Note − 如果你有 Arduino Mini、NG 或其他电路板,在点击 Arduino 软件上的上传按钮前,你需要在电路板上按复位按钮。
Arduino - Program Structure
在本章中,我们将深入学习 Arduino 程序结构,并将学习在 Arduino 世界中使用更多新术语。Arduino 软件是开源的。Java 环境的源代码在 GPL 下发布,C/C++ 微控制器库在 LGPL 下发布。
Sketch − 第一个新术语是名为“ sketch ”的 Arduino 程序。
Structure
Arduino 程序可以分为三个主要部分: Structure, Values (变量和常量)以及 Functions 。在本教程中,我们将逐步了解 Arduino 软件程序以及如何在不出现任何语法或编译错误的情况下编写程序。
让我们从 Structure 开始。软件结构包含两个主要函数 ——
-
Setup( ) function
-
Loop( ) function
Void setup ( ) {
}
-
PURPOSE − 当草图开始时,将调用 setup() 函数。使用它来初始化变量、引脚模式、开始使用库等。在 Arduino 电路板每次上电或复位后,设置函数只会运行一次。
-
INPUT − -
-
OUTPUT − -
-
RETURN − -
Void Loop ( ) {
}
-
PURPOSE − 在创建初始化并设置初始值的 setup() 函数后, loop() 函数准确地执行其名称所暗示的内容,并连续循环,使您的程序能够更改和作出响应。使用它来主动控制 Arduino 电路板。
-
INPUT − -
-
OUTPUT − -
-
RETURN − -
Arduino - Data Types
C 中的数据类型是指用于声明不同类型的变量或函数的广泛系统。一个变量的类型决定了它在存储中占据多少空间以及存储的位模式如何解释。
下表提供了您在 Arduino 编程中将使用所有数据类型。
void |
Boolean |
char |
Unsigned char |
byte |
int |
Unsigned int |
word |
long |
Unsigned long |
short |
float |
double |
array |
String-char array |
String-object |
Char
占用一个字节的内存来存储字符值的数据类型。字符字面值用单引号编写,如下所示:'A',对于多个字符,字符串使用双引号:“ABC”。
然而,字符存储为数字。您可以在 ASCII chart 中看到特定编码。这意味着可以对字符执行算术运算,其中使用字符的 ASCII 值。例如,'A' + 1 的值为 66,因为大写字母 A 的 ASCII 值为 65。
int
整数是用于存储数字的主要数据类型。int 存储一个 16 位(2 字节)的值。这产生了 -32,768 到 32,767 的范围(最小值 -2^15,最大值 (2^15) - 1)。
int 的大小因板而异。例如,在 Arduino Due 上,一个 int 存储一个 32 位(4 字节)的值。这产生了-2,147,483,648 到 2,147,483,647 的范围(最小值为 -2^31,最大值为 (2^31) - 1)。
Unsigned int
无符号 int(无符号整数)在存储 2 字节的值方式上与 int 相同。但它们不存储负数,只存储正值,产生了 0 到 65,535 (2^16) - 1)的有用范围。Due 存储一个 4 字节(32 位)的值,其范围是从 0 到 4,294,967,295 (2^32 - 1)。
unsigned long
无符号长变量是用于存储数字的扩展大小变量,存储 32 位(4 字节)。与标准长不同,无符号长不会存储负数,其范围为 0 到 4,294,967,295 (2^32 - 1)。
short
一个短的是一个 16 位的数据类型。在所有 Arduino(基于 ATMega 和 ARM)上,一个短的存储一个 16 位(2 字节)的值。这产生了 -32,768 到 32,767 的范围(最小值 -2^15,最大值 (2^15) - 1)。
Arduino - Variables & Constants
在我们开始解释变量类型之前,我们需要确保你充分理解的一个非常重要的主题被称为 variable scope 。
What is Variable Scope?
Arduino 使用的 C 编程语言中的变量有一个称为作用域的属性。作用域是程序的一个区域,可以在三个地方声明变量。它们是 −
-
在函数或块内,称为 local variables 。
-
在函数参数的定义中,称为 formal parameters 。
-
在所有函数外部,称为 global variables 。
Arduino - Operators
运算符是一个符号,它告诉编译器执行特定的数学或逻辑函数。C 语言拥有丰富的内置运算符,并提供了以下类型的运算符 −
-
Arithmetic Operators
-
Comparison Operators
-
Boolean Operators
-
Bitwise Operators
-
Compound Operators
Arithmetic Operators
假设变量 A 保存 10,变量 B 保存 20,则 −
Operator name |
Operator simple |
Description |
Example |
assignment operator |
= |
将等号右侧的值保存到等号左侧变量中。 |
A = B |
addition |
+ |
Adds two operands |
A + B 会给出 30 |
subtraction |
- |
从第一个操作数中减去第二个操作数 |
A - B 会给出 -10 |
multiplication |
* |
Multiply both operands |
A * B 会给出 200 |
division |
/ |
Divide numerator by denominator |
B / A 会给出 2 |
modulo |
% |
模运算符,整数除法后的余数 |
B % A 会给出 0 |
Comparison Operators
假设变量 A 保存 10,变量 B 保存 20,则 −
Operator name |
Operator simple |
Description |
Example |
equal to |
== |
检查两个操作数的值是否相等,如果相等,则条件变为真。 |
(A == B) 为假 |
not equal to |
!= |
检查两个操作数的值是否相等,如果不相等,则条件变为真。 |
(A != B) 为真 |
less than |
< |
检查左操作数的值是否小于右操作数的值,如果小于,则条件变为真。 |
(A < B) 为真 |
greater than |
> |
检查左操作数的值是否大于右操作数的值,如果大于,则条件变为真。 |
(A > B) 不为真 |
小于或等于 |
⇐ |
检查左操作数的值是否小于或等于右操作数的值,如果小于或等于,则条件变为真。 |
(A ⇐ B) 为真 |
大于或等于 |
>= |
检查左操作数的值是否大于或等于右操作数的值,如果大于或等于,则条件变为真。 |
(A >= B) 不为真 |
Boolean Operators
假设变量 A 保存 10,变量 B 保存 20,则 −
Operator name |
Operator simple |
Description |
Example |
and |
&& |
称为逻辑 AND 运算符。如果两个操作数都是非零,则条件变为真。 |
(A && B) 为真 |
or |
|||
称为逻辑 OR 运算符。如果两个操作数中的任何一个是非零,则条件变为真。 |
(A |
B) is true |
|
not |
! |
称为逻辑 NOT 运算符。用于反转操作数的逻辑状态。如果条件为 true,则逻辑 NOT 运算符会将其变为 false。 |
!(A && B) 为假 |
Bitwise Operators
假设变量 A 保存 60,变量 B 保存 13,则 −
Operator name |
Operator simple |
Description |
Example |
and |
& |
二进制与运算符将位复制到结果中(如果它存在于两个操作数中)。 |
(A 和 B) 结果是 12,即 0000 1100 |
or |
如果二进制 OR 运算符在任一操作数中存在位,则复制该位 |
||
(A |
B) 结果是 61,即 0011 1101 |
xor |
^ |
二进制 XOR 运算符会在其中一个操作数中但不在两个操作数中都设置的情况下复制比特。 |
(A ^ B) 结果为 49,即 0011 0001 |
not |
~ |
二进制逻辑补运算符是单操作数运算符,它会“翻转”比特。 |
(~A ) 将得到 -60,即 1100 0011 |
shift left |
<< |
二进制左移运算符。左操作数的值会向左移动由右操作数指定的比特数。 |
A << 2 的结果是 240,即 1111 0000 |
shift right |
>> |
Compound Operators
假设变量 A 保存 10,变量 B 保存 20,则 −
Operator name |
Operator simple |
Description |
Example |
increment |
++ |
自增运算符,将整数加一 |
A++ will give 11 |
decrement |
— |
自减运算符,将整数减一 |
A-- will give 9 |
compound addition |
+= |
增加且赋值运算符。 它将右操作数添加到左操作数,并将其结果赋予左操作数 |
B = A 等同于 B = B A |
compound subtraction |
-= |
减去且赋值运算符。 它从左操作数中减去右操作数,并将其结果赋予左操作数 |
B -= A 等同于 B = B - A |
compound multiplication |
*= |
乘以且赋值运算符。 它将右操作数乘以左操作数,并将其结果赋予左操作数 |
B*= A 等同于 B = B* A |
compound division |
/= |
除以且赋值运算符。 它用右操作数除以左操作数,并将其结果赋予左操作数 |
B /= A 等同于 B = B / A |
compound modulo |
%= |
取余且赋值运算符。 它用两个操作数取模,并将其结果赋予左操作数 |
B %= A 等同于 B = B % A |
compound bitwise or |
= |
按位或且赋值运算符 |
|
A |
= 2 等同于 A = A |
2 |
compound bitwise and |
Arduino - Control Statements
决策制定结构要求程序员指定一个或多个条件,供程序进行评估或测试。它应与确定条件为真的情况下要执行的语句或语句一起制定,并且可以选择性地制定在确定条件为假情况下要执行的其他语句。
以下是大多数编程语言中常见的典型决策结构的一般形式 −
控制语句是源代码中的元素,用于控制程序执行的流程。它们是 −
S.NO. |
Control Statement & Description |
1 |
If statement 它采用括号中的表达式和语句或语句块。如果表达式为真,那么语句或语句块将被执行,否则这些语句将被跳过。 |
2 |
If …else statement if 语句后面可以跟一个可选的 else 语句,当表达式为假时执行该语句。 |
3 |
If…else if …else statement if 语句后面可以跟一个可选的 else if…​else 语句,这对于使用单一的 if… else if 语句测试各种条件非常有用。 |
4 |
switch case statement 与 if 语句类似, switch…​case 通过允许程序员指定应在各种条件下执行的不同代码来控制程序流程。 |
5 |
Conditional Operator ? : 条件运算符 ? : 是 C 中唯一的三个运算符。 |
Arduino - Loops
编程语言提供了各种控制结构,允许执行更复杂的路径。
循环语句允许我们多次执行一个语句或一组语句,以下是大多数编程语言中循环语句的一般形式 −
C 编程语言提供以下类型的循环来处理循环要求。
S.NO. |
Loop & Description |
1 |
while loop while 循环将连续无限循环,直到圆括号 () 内的表达式变为假。某种东西必须改变被测的变量,否则 while 循环将永远不会退出。 |
2 |
do…while loop do…while 循环类似于 while 循环。在 while 循环中,循环持续条件在执行循环体之前在循环开始时接受测试。 |
3 |
for loop 一个 for loop 执行语句一个预先确定的次数。 循环的控制表达式完全在 for 循环括号内进行初始化、测试和操纵。 |
4 |
Nested Loop C 语言允许你在一个循环内使用另一个循环。下面的示例说明了这个概念。 |
5 |
Infinite loop 它是没有终止条件的循环,因此循环变成无限循环。 |
Arduino - Functions
函数允许对代码段进行结构化,针对各个任务。创建函数的典型情况是,当程序中需要多次执行相同操作时。
将代码片段标准化成函数具有多个优势 −
-
函数帮助程序员保持井井有条。这常常有助于概念化程序。
-
函数将一个操作编码在一个地方,这样就只需要考虑和调试一次函数。
-
如果需要更改代码,还可以减少修改错误的机会。
-
函数可以多次复用部分代码,使整个草图更小、更紧凑。
-
通过模块化更容易在其他程序中复用代码,并且使用函数可以常常提高代码可读性。
Arduino 草图或程序中的两个必需函数是:setup() 和 loop()。其他函数必须在两个函数的括号之外创建。
定义函数最常见的语法是 −
Function Declaration
可以在任何其他函数外部声明函数,高于或低于循环函数。
我们可以通过两种不同的方式声明函数 −
第一种方法是在循环函数的上方写出名为 a function prototype 的函数部分,其包括 −
-
Function return type
-
Function name
-
函数参数类型,无需写出参数名称
函数原型后必须跟分号 ( ; )。
下面的示例演示如何使用第一种方法进行函数声明。
Example
int sum_func (int x, int y) // function declaration {
int z = 0;
z = x+y ;
return z; // return the value
}
void setup () {
Statements // group of statements
}
Void loop () {
int result = 0 ;
result = Sum_func (5,6) ; // function call
}
第二部分称为函数定义或声明,必须在循环函数的下方声明,其包括 −
-
Function return type
-
Function name
-
函数参数类型,这里必须添加参数名称
-
函数体(当函数被调用时执行的函数内的语句)
下面的示例演示如何使用第二种方法声明函数。
Example
int sum_func (int , int ) ; // function prototype
void setup () {
Statements // group of statements
}
Void loop () {
int result = 0 ;
result = Sum_func (5,6) ; // function call
}
int sum_func (int x, int y) // function declaration {
int z = 0;
z = x+y ;
return z; // return the value
}
第二种方法只是在循环函数的上方声明函数。
Arduino - Strings
字符串用于存储文本。它们可用于在 LCD 上或 Arduino IDE 串行监视器窗口中显示文本。字符串对于存储用户输入也很有用。例如,用户在连接到 Arduino 的键盘上键入的字符。
在 Arduino 编程中有两种类型的字符串 -
-
字符数组,这与 C 编程中使用的字符串相同。
-
Arduino String,它允许我们在草图中使用字符串对象。
在本章中,我们将学习字符串、对象以及字符串在 Arduino 草图中的用法。在本节末尾,你将学习在草图中使用哪种类型的字符串。
String Character Arrays
我们将学习的第一种类型的字符串是一系列 char 类型的字符。在上一章中,我们学习了数组是什么;一系列连续的同类型变量,存储在内存中。字符串是 char 变量的数组。
字符串是一个特殊的数组,其在字符串末尾有一个额外的元素,该元素的值始终为 0(零)。这被称为“空终止字符串”。
String Character Array Example
此示例将展示如何制作字符串并将其打印到串行监视器窗口。
Example
void setup() {
char my_str[6]; // an array big enough for a 5 character string
Serial.begin(9600);
my_str[0] = 'H'; // the string consists of 5 characters
my_str[1] = 'e';
my_str[2] = 'l';
my_str[3] = 'l';
my_str[4] = 'o';
my_str[5] = 0; // 6th array element is a null terminator
Serial.println(my_str);
}
void loop() {
}
以下示例显示了字符串的构成;一个字符数组,其中包含可打印字符,并且 0 为数组的最后一个元素,以表明这是字符串的结束位置。可以使用 Serial.println() 并传递字符串的名称将字符串打印到 Arduino IDE 串行监视器窗口。
可以使用以下更简洁的方式编写此示例 -
Example
void setup() {
char my_str[] = "Hello";
Serial.begin(9600);
Serial.println(my_str);
}
void loop() {
}
在此草图中,编译器计算字符串数组的大小,并使用零自动空终止字符串。与上一草图完全相同的方式创建了一个由六个元素组成且包含五个字符后跟一个零的数组。
Manipulating String Arrays
我们可以在草图中更改字符串数组,如下面的草图所示。
Example
void setup() {
char like[] = "I like coffee and cake"; // create a string
Serial.begin(9600);
// (1) print the string
Serial.println(like);
// (2) delete part of the string
like[13] = 0;
Serial.println(like);
// (3) substitute a word into the string
like[13] = ' '; // replace the null terminator with a space
like[18] = 't'; // insert the new word
like[19] = 'e';
like[20] = 'a';
like[21] = 0; // terminate the string
Serial.println(like);
}
void loop() {
}
Functions to Manipulate String Arrays
前一节草图通过访问字符串中的单个字符来以一种手动的方式操纵字符串。要使其更容易操纵字符串数组,你可以编写你自己的函数来操作它们,或使用来自 C 语言库的部分字符串函数。
下一节草图使用了部分 C 字符串函数。
Example
void setup() {
char str[] = "This is my string"; // create a string
char out_str[40]; // output from string functions placed here
int num; // general purpose integer
Serial.begin(9600);
// (1) print the string
Serial.println(str);
// (2) get the length of the string (excludes null terminator)
num = strlen(str);
Serial.print("String length is: ");
Serial.println(num);
// (3) get the length of the array (includes null terminator)
num = sizeof(str); // sizeof() is not a C string function
Serial.print("Size of the array: ");
Serial.println(num);
// (4) copy a string
strcpy(out_str, str);
Serial.println(out_str);
// (5) add a string to the end of a string (append)
strcat(out_str, " sketch.");
Serial.println(out_str);
num = strlen(out_str);
Serial.print("String length is: ");
Serial.println(num);
num = sizeof(out_str);
Serial.print("Size of the array out_str[]: ");
Serial.println(num);
}
void loop() {
}
Result
This is my string
String length is: 17
Size of the array: 18
This is my string
This is my string sketch.
String length is: 25
Size of the array out_str[]: 40
草图按以下方式工作。
Get the Length of the String
strlen() 函数用于获取字符串的长度。字符串的长度仅限于可打印字符,且不包含空终止符。
该字符串包含 17 个字符,所以我们将在 Serial Monitor 窗口中看到打印的 17。
Get the Length of the Array
sizeof() 运算符用于获取包含字符串的数组的长度。该长度包含空终止符,所以该长度比字符串长度多 1。
sizeof() 看起来像一个函数,但实际上它是一个运算符。它不是 C 字符串库的一部分,但在草图中使用了它来展示数组的大小和字符串的大小(或字符串长度)之间的差异。
Arduino - String Object
Arduino 编程中使用的第二种类型的字符串是字符串对象。
What is an Object?
对象是一种同时包含数据和函数的结构。可以创建字符串对象,就像创建变量并为其分配一个值或字符串一样。字符串对象包含函数(在面向对象编程 (OOP) 中称为“方法”),这些函数对字符串对象中包含的字符串数据进行操作。
以下草图和说明将明确说明什么是对象以及如何使用字符串对象。
Example
void setup() {
String my_str = "This is my string.";
Serial.begin(9600);
// (1) print the string
Serial.println(my_str);
// (2) change the string to upper-case
my_str.toUpperCase();
Serial.println(my_str);
// (3) overwrite the string
my_str = "My new string.";
Serial.println(my_str);
// (4) replace a word in the string
my_str.replace("string", "Arduino sketch");
Serial.println(my_str);
// (5) get the length of the string
Serial.print("String length is: ");
Serial.println(my_str.length());
}
void loop() {
}
Result
This is my string.
THIS IS MY STRING.
My new string.
My new Arduino sketch.
String length is: 22
在草图顶部创建字符串对象并为其分配值(或字符串)。
String my_str = "This is my string." ;
这会创建一个名为 my_str 的字符串对象,并为其赋予“This is my string.” 的值。
这可以与创建变量并为其分配值(例如整数)进行比较
int my_var = 102;
草图按以下方式工作。
Convert the String to Upper-case
创建的字符串对象 my_str 具有一些可以对其进行操作的函数或方法。通过使用对象名称后跟点运算符(.),然后使用要使用的函数的名称来调用这些方法。
my_str.toUpperCase();
toUpperCase() 函数对 my_str 对象中包含的字符串进行操作,该对象类型为 String,并将对象包含的字符串数据(或文本)转换为大写字符。可以在 Arduino String 参考中找到 String 类中包含的函数的列表。从技术上讲,String 被称为一个类,用于创建 String 对象。
Overwrite a String
赋值运算符用于为替换旧字符串的 my_str 对象分配新字符串。
my_str = "My new string." ;
赋值运算符不能用于字符数组字符串,但仅适用于 String 对象。
When to Use a String Object
字符串对象比字符串字符数组更容易使用。对象具有内置函数,可以对字符串执行许多操作。
使用字符串对象的主要缺点是它使用大量内存,并且可能会快速耗尽 Arduino 的 RAM 内存,这可能导致 Arduino 悬空、崩溃或行为异常。如果 Arduino 上的一个草图很小并限制对对象的使用的,那么应该没有问题。
字符数组字符串更难使用,您可能需要编写自己的函数来操作这些类型的字符串。优点是您可以控制所制作的字符串数组的大小,因此您可以将数组保持较小以节省内存。
使用字符串数组时,你需要注意不要超出数组范围的末尾。String 对象没有这个问题,它会处理字符串范围,只要有足够的内存供它操作即可。String 对象在内存不足时可能会尝试写入不存在的内存,但它永远不会覆盖它正在操作的字符串的末尾。
Arduino - Time
Arduino 提供四个不同的时间处理函数。它们是 −
S.No. |
Function & Description |
1 |
delay () function delay() 函数的工作方式非常简单。它接受单个整数(或数字)参数。此数字表示时间(以毫秒为单位)。 |
2 |
delayMicroseconds () function delayMicroseconds() 函数接受单个整数(或数字)参数。毫秒中有 1000 微秒,而秒中有 100 万微秒。 |
3 |
millis () function 此函数用于返回毫秒数,此时 Arduino 板开始运行当前程序。 |
4 |
micros () function micros() 函数返回从 Arduino 板开始运行当前程序以来的微秒数。此数字会溢出,即在大约 70 分钟后返回 0。 |
Arduino - Arrays
数组是同类型的连续内存位置组。要提及数组中的特定位置或元素,我们指定数组的名称和数组中特定元素的位置编号。
下面给出的插图显示了一个名为 C 的整数数组,其中包含 11 个元素。您可以通过给出数组名后跟方括号([])中的特定元素的位置编号来引用这些元素中的任何一个。位置编号更正式的名称是下标或索引(此编号指定了从数组开始的元素数量)。第一个元素的下标为 0(零),有时称为零元素。
因此,数组 C 的元素为 C[0](读作“C 零下标”)、C[1]、C[2],依此类推。数组 C 中最高的下标是 10,比数组中的元素数量(11)少 1。数组名遵循与其他变量名相同的约定。
下标必须是一个整数或整数表达式(使用任何整数类型)。如果程序使用表达式作为下标,则程序会计算该表达式的值以确定下标。例如,如果我们假设变量 a 等于 5 且变量 b 等于 6,那么该语句会将 2 添加到数组元素 C[11] 中。
带下标的数组名是一个左值,它可以像非数组变量名一样用在赋值的左侧。
我们更详细地研究给定图片中的数组 C。整个数组的名称是 C。其 11 个元素被称为 C[0] 到 C[10]。C[0] 的值为 -45,C[1] 的值为 6,C[2] 的值为 0,C[7] 的值为 62,C[10] 的值为 78。
要打印数组 C 的前三个元素中包含的值的总和,我们会写:
Serial.print (C[ 0 ] + C[ 1 ] + C[ 2 ] );
要将 C[6] 的值除以 2 并将结果分配给变量 x,我们会写:
x = C[ 6 ] / 2;
Declaring Arrays
数组占用内存中的空间。要指定数组中元素的类型和数组所需元素的数量,请使用以下形式的声明:
type arrayName [ arraySize ] ;
编译器会保留适当数量的内存。(回想一下,保留内存的声明更确切地称为定义)。arraySize 必须大于零的整数常量。例如,要告诉编译器为整数数组 C 保留 11 个元素,请使用声明:
int C[ 12 ]; // C is an array of 12 integers
可以声明数组以包含任何非引用数据类型的值。例如,可以将字符串类型的数组用于存储字符串。
Examples Using Arrays
本部分提供了许多示例,用以演示如何声明、初始化和操作数组。
Example 1: Declaring an Array and using a Loop to Initialize the Array’s Elements
该程序声明了一个 10 个元素的整数数组 n 。第 a-b 行使用 For 语句将数组元素初始化为零。与其他自动变量一样,不会隐式将自动数组初始化为零。第一个输出语句(第 c 行)显示了 subsequent for 语句(第 d-e 行)中打印的列的列标题,这些语句以表格格式打印数组。
Example
int n[ 10 ] ; // n is an array of 10 integers
void setup () {
}
void loop () {
for ( int i = 0; i < 10; ++i ) // initialize elements of array n to 0 {
n[ i ] = 0; // set element at location i to 0
Serial.print (i) ;
Serial.print (‘\r’) ;
}
for ( int j = 0; j < 10; ++j ) // output each array element's value {
Serial.print (n[j]) ;
Serial.print (‘\r’) ;
}
}
Result − 将产生以下结果:
Element
Value
0
1
2
3
4
5
6
7
8
9
0
0
0
0
0
0
0
0
0
0
Example 2: Initializing an Array in a Declaration with an Initializer List
数组的元素也可以在数组声明中初始化,方法是在数组名称后跟一个等号和一个用花括号分隔的逗号分隔的初始化程序列表。该程序使用初始化程序列表使用 10 个值初始化一个整数数组(第 a 行),并将数组以表格格式打印(第 b-c 行)。
Example
// n is an array of 10 integers
int n[ 10 ] = { 32, 27, 64, 18, 95, 14, 90, 70, 60, 37 } ;
void setup () {
}
void loop () {
for ( int i = 0; i < 10; ++i ) {
Serial.print (i) ;
Serial.print (‘\r’) ;
}
for ( int j = 0; j < 10; ++j ) // output each array element's value {
Serial.print (n[j]) ;
Serial.print (‘\r’) ;
}
}
Result − 将产生以下结果:
Element
Value
0
1
2
3
4
5
6
7
8
9
32
27
64
18
95
14
90
70
60
37
Example 3: Summing the Elements of an Array
数组的元素通常表示要用于计算的一系列值。例如,如果数组的元素表示考试成绩,教授可能希望计算数组元素的总和,并使用该总和计算考试的班级平均成绩。该程序对 10 个元素的整型数组 a 中包含的值求和。
Example
const int arraySize = 10; // constant variable indicating size of array
int a[ arraySize ] = { 87, 68, 94, 100, 83, 78, 85, 91, 76, 87 };
int total = 0;
void setup () {
}
void loop () {
// sum contents of array a
for ( int i = 0; i < arraySize; ++i )
total += a[ i ];
Serial.print (“Total of array elements : ”) ;
Serial.print(total) ;
}
Result − 将产生以下结果:
Total of array elements: 849
对于 Arduino 来说,阵列很重要,应该受到更多关注。以下与阵列相关的重要的概念应该对 Arduino 很清楚−
S.NO. |
Concept & Description |
1 |
Passing Arrays to Functions 要将数组参数传递给函数,请指定数组的名称,不要使用任何括号。 |
2 |
Multi-Dimensional Arrays 具有两个维度(即下标)的数组通常表示由按行和列排列的信息组成的数据表。 |
Arduino - I/O Functions
Arduino 板上的引脚可以配置为输入或输出。我们将在这些模式中解释引脚的功能。重要的是要注意,大多数 Arduino 模拟引脚可以按照与数字引脚完全相同的方式配置和使用。
Pins Configured as INPUT
Arduino 引脚默认配置为输入,因此当你将它们用作输入时,不需要用 pinMode() 显式声明为输入。这样配置的引脚称为处于高阻抗状态。输入引脚对它们采样的电路的要求极低,相当于引脚前的 100 兆欧姆串联电阻。
这意味着从一个状态转换到另一个状态的输入引脚只需很小的电流。这使得引脚可用于诸如实现电容式触摸传感器或将 LED 作为光电二极管读取的任务。
配置为 pinMode(pin, INPUT) 的引脚与未连接任何东西或连接到未连接到其他电路的电线,报告在引脚状态中的看似随机更改,从环境中拾取电噪声或电容耦合附近引脚的状态。
Pull-up Resistors
如果不存在输入,上拉电阻通常可用于将输入引脚引导到已知状态。可以通过在输入端添加上拉电阻(至 +5V)或下拉电阻(电阻至地)来实现这一点。10K 电阻是上拉或下拉电阻的良好值。
Using Built-in Pull-up Resistor with Pins Configured as Input
Atmega 芯片内置有 20000 个上拉电阻,可以通过软件访问。通过将 pinMode() 设置为 INPUT_PULLUP 来访问这些内置的上拉电阻。这实际上是反转了 INPUT 模式的行为,其中 HIGH 表示传感器已关,而 LOW 表示传感器已开。此上拉电阻的值取决于使用的微控制器。在大多数基于 AVR 的板上,该值保证在 20kΩ 到 50kΩ 之间。在 Arduino Due 上,它介于 50kΩ 和 150kΩ 之间。对于确切值,请参考板上微控制器的规格书。
在将传感器连接到使用 INPUT_PULLUP 配置的引脚时,另一端应连接到地。如果是简单的开关,当开关打开时,它会导致引脚读取 HIGH,当开关按下时,它会读取 LOW。上拉电阻提供足够的电流来点亮连接到配置为输入的引脚的微弱 LED。如果项目中的 LED 似乎工作正常,但非常微弱,这很可能正在发生的事情。
控制引脚是 HIGH 还是 LOW 的相同寄存器(内部芯片存储器位置)控制上拉电阻。因此,当引脚处于 INPUT 模式时配置为打开上拉电阻的引脚,如果然后使用 pinMode() 将引脚切换到 OUTPUT 模式,则引脚将配置为 HIGH。这种方法也适用于其他方向,而留在 HIGH 状态的输出引脚在使用 pinMode() 切换到输入时将设置上拉电阻。
Example
pinMode(3,INPUT) ; // set pin to input without using built in pull up resistor
pinMode(5,INPUT_PULLUP) ; // set pin to input using built in pull up resistor
Pins Configured as OUTPUT
使用 pinMode() 配置为 OUTPUT 的引脚称为处于低阻抗状态。这意味着它们可以为其他电路提供大量的电流。Atmega 引脚可以为其他设备/电路提供高达 40 mA (毫安) 的电流(提供正电流)或吸收(提供负电流)。此电流足以点亮 LED(不要忘记串联电阻)或运行许多传感器,但不足以运行继电器、电磁铁或电机。
如果尝试从输出引脚运行高电流设备,可能会损坏引脚中的输出晶体管或损坏整个 Atmega 芯片。通常,这会导致微控制器中的“死”引脚,但剩余的芯片仍然可以正常工作。出于此原因,最好通过 470Ω 或 1k 电阻将 OUTPUT 引脚连接到其他设备,除非需要最大电流因特定应用而从引脚中提取。
pinMode() Function
pinMode() 函数用于将特定引脚配置为输入或输出。可以使用 INPUT_PULLUP 模式启用内部上拉电阻。此外,INPUT 模式显式禁用内部上拉电阻。
pinMode() Function Syntax
Void setup () {
pinMode (pin , mode);
}
-
pin − 你希望设置其模式的引脚的编号
-
mode − INPUT、OUTPUT 或 INPUT_PULLUP。
Example
int button = 5 ; // button connected to pin 5
int LED = 6; // LED connected to pin 6
void setup () {
pinMode(button , INPUT_PULLUP);
// set the digital pin as input with pull-up resistor
pinMode(button , OUTPUT); // set the digital pin as output
}
void setup () {
If (digitalRead(button ) == LOW) // if button pressed {
digitalWrite(LED,HIGH); // turn on led
delay(500); // delay for 500 ms
digitalWrite(LED,LOW); // turn off led
delay(500); // delay for 500 ms
}
}
digitalWrite() Function
digitalWrite() 函数用于将 HIGH 或 LOW 值写入数字引脚。如果引脚已使用 pinMode() 配置为 OUTPUT,则其电压将设置为相应的值:对于 HIGH,为 5V(对于 3.3V 板为 3.3V);对于 LOW,为 0V(地)。如果引脚配置为 INPUT,digitalWrite() 将启用(HIGH)或禁用(LOW)输入引脚上的内部上拉电阻。建议将 pinMode() 设置为 INPUT_PULLUP 来启用内部上拉电阻。
如果你没有将 pinMode() 设置为 OUTPUT 并将 LED 连接到引脚,则在调用 digitalWrite(HIGH) 时,LED 可能显得昏暗。如果不显式设置 pinMode(),digitalWrite() 将启用内部上拉电阻,该电阻充当大限流电阻。
digitalWrite() Function Syntax
Void loop() {
digitalWrite (pin ,value);
}
-
pin − 你希望设置其模式的引脚的编号
-
value − HIGH 或 LOW。
Example
int LED = 6; // LED connected to pin 6
void setup () {
pinMode(LED, OUTPUT); // set the digital pin as output
}
void setup () {
digitalWrite(LED,HIGH); // turn on led
delay(500); // delay for 500 ms
digitalWrite(LED,LOW); // turn off led
delay(500); // delay for 500 ms
}
analogRead( ) function
Arduino 能够检测到是否向其某个引脚施加电压,并通过 digitalRead() 函数报告。传感物体存在与模拟传感器(其值不断变化)之间有区别。为了读取这种类型的传感器,我们需要不同类型的引脚。
在 Arduino 电路板的右下部分,您将看到六个标记为“Analog In”的针脚。这些特殊针脚不仅可以判断电压是否施加给它们,还可以判断电压值。通过使用 analogRead() 函数,我们可以读取施加给某个针脚的电压。
此函数返回一个介于 0 和 1023 之间的数字,代表 0 到 5 伏之间的电压。例如,如果将 2.5 V 的电压施加到针脚 0,则 analogRead(0) 返回 512。
analogRead() function Syntax
analogRead(pin);
-
pin – 要从中读取模拟输入针脚的数量(大多数电路板为 0 到 5,Mini 和 Nano 为 0 到 7,Mega 为 0 到 15)
Example
int analogPin = 3;//potentiometer wiper (middle terminal)
// connected to analog pin 3
int val = 0; // variable to store the value read
void setup() {
Serial.begin(9600); // setup serial
}
void loop() {
val = analogRead(analogPin); // read the input pin
Serial.println(val); // debug value
}
Arduino - Advanced I/O Function
在本教程中,我们将学习一些高级输入和输出函数。
analogReference() Function
配置用于模拟输入的参考电压(即用作输入范围顶部的值)。选项有 -
-
DEFAULT – 默认模拟基准 5 伏(用于 5V Arduino 电路板)或 3.3 伏(用于 3.3V Arduino 电路板)
-
INTERNAL – 内建参考,等于 ATmega168 或 ATmega328 上的 1.1 伏和 ATmega8 上的 2.56 伏(在 Arduino Mega 上不可用)
-
INTERNAL1V1 – 内建 1.1V 参考(仅限 Arduino Mega)
-
INTERNAL2V56 – 内建 2.56V 参考(仅限 Arduino Mega)
-
EXTERNAL – 施加到 AREF 针脚的电压(仅为 0 到 5V)用作参考
analogReference() Function Syntax
analogReference (type);
type – 可以使用以下任何类型(DEFAULT、INTERNAL、INTERNAL1V1、INTERNAL2V56、EXTERNAL)
不要对 AREF 针脚上的外部参考电压使用低于 0V 或高于 5V 的电压。如果您在 AREF 针脚上使用外部参考,您必须在调用 analogRead() 函数之前将模拟参考设置为 EXTERNAL。否则,您将短路已激活的参考电压(内部产生)和 AREF 针脚,可能损坏您 Arduino 电路板上的微控制器。
或者,您可以通过 5K 电阻将外部参考电压连接到 AREF 针脚,这样就可以在外部参考电压和内部参考电压之间切换。
请注意,电阻器将改变用作参考的电压,因为 AREF 针脚上有一个 32K 电阻器。这两个电阻器充当分压器。例如,通过电阻器施加的 2.5V 将在 AREF 针脚产生 2.5 * 32 / (32 + 5) = ~2.2V。
Example
int analogPin = 3;// potentiometer wiper (middle terminal) connected to analog pin 3
int val = 0; // variable to store the read value
void setup() {
Serial.begin(9600); // setup serial
analogReference(EXTERNAL); // the voltage applied to the AREF pin (0 to 5V only)
// is used as the reference.
}
void loop() {
val = analogRead(analogPin); // read the input pin
Serial.println(val); // debug value
}
Arduino - Character Functions
所有数据都以字符的形式输入计算机,其中包括字母、数字和各种特殊符号。在本节中,我们将讨论 C++ 检查和操作各个字符的能力。
字符处理库包括几个执行有用的字符数据测试和操作的函数。每个函数接收一个表示为 int 的字符,或将 EOF 作为参数。字符通常被作为整数进行操作。
请记住,EOF 通常具有值 –1,并且某些硬件体系结构不允许将负值存储在 char 变量中。因此,字符处理函数将字符作为整数来处理。
下表总结了字符处理库的函数。当使用字符处理库中的函数时,请包含 <cctype> 头。
S.No. |
Prototype & Description |
1 |
int isdigit( int c ) 如果 c 是一个数字,则返回 1,否则返回 0。 |
2 |
int isalpha( int c ) 如果 c 是一个字母,则返回 1,否则返回 0。 |
3 |
int isalnum( int c ) 如果 c 是一个数字或字母,则返回 1,否则返回 0。 |
4 |
int isxdigit( int c ) 如果 c 是一个十六进制数字字符,则返回 1,否则返回 0。(有关二进制数、八进制数、十进制数和十六进制数的详细解释,请参见附录 D,数字系统。) |
5 |
int islower( int c ) 如果 c 是一个小写字母,则返回 1,否则返回 0。 |
6 |
int isupper( int c ) 如果 c 是一个大写字母,则返回 1;否则返回 0。 |
7 |
int isspace( int c ) 如果 c 是一个空白字符(换行 ('\n')、空格(' ')、换页 ('\f')、回车 ('\r')、水平制表符 ('\t') 或垂直制表符 ('\v'))则返回 1,否则返回 0。 |
8 |
int iscntrl( int c ) 如果 c 是一个控制字符,例如换行 ('\n')、换页 ('\f')、回车 ('\r')、水平制表符 ('\t')、垂直制表符 ('\v')、警告 ('\a') 或退格 ('\b'),则返回 1,否则返回 0。 |
9 |
int ispunct( int c ) 如果 c 是空格、数字或字母之外的打印字符,则返回 1,否则返回 0。 |
10 |
int isprint( int c ) 如果 c 是打印字符(包括空格 (' ')),则返回 1,否则返回 0。 |
11 |
int isgraph( int c ) 如果 c 是空格 (' ') 之外的打印字符,则返回 1,否则返回 0。 |
Examples
以下示例演示了函数 isdigit, isalpha, isalnum 和 isxdigit 的用法。函数 isdigit 确定其参数是否是数字 (0-9)。函数 isalpha 确定其参数是否是仅大写字母 (A-Z) 或仅小写字母 (a-z)。函数 isalnum 确定其参数是否是仅大写字母、仅小写字母或数字。函数 isxdigit 确定其参数是否是十六进制数字 (A-F, a-f, 0-9)。
Example 1
void setup () {
Serial.begin (9600);
Serial.print ("According to isdigit:\r");
Serial.print (isdigit( '8' ) ? "8 is a": "8 is not a");
Serial.print (" digit\r" );
Serial.print (isdigit( '8' ) ?"# is a": "# is not a") ;
Serial.print (" digit\r");
Serial.print ("\rAccording to isalpha:\r" );
Serial.print (isalpha('A' ) ?"A is a": "A is not a");
Serial.print (" letter\r");
Serial.print (isalpha('A' ) ?"b is a": "b is not a");
Serial.print (" letter\r");
Serial.print (isalpha('A') ?"& is a": "& is not a");
Serial.print (" letter\r");
Serial.print (isalpha( 'A' ) ?"4 is a":"4 is not a");
Serial.print (" letter\r");
Serial.print ("\rAccording to isalnum:\r");
Serial.print (isalnum( 'A' ) ?"A is a" : "A is not a" );
Serial.print (" digit or a letter\r" );
Serial.print (isalnum( '8' ) ?"8 is a" : "8 is not a" ) ;
Serial.print (" digit or a letter\r");
Serial.print (isalnum( '#' ) ?"# is a" : "# is not a" );
Serial.print (" digit or a letter\r");
Serial.print ("\rAccording to isxdigit:\r");
Serial.print (isxdigit( 'F' ) ?"F is a" : "F is not a" );
Serial.print (" hexadecimal digit\r" );
Serial.print (isxdigit( 'J' ) ?"J is a" : "J is not a" ) ;
Serial.print (" hexadecimal digit\r" );
Serial.print (isxdigit( '7' ) ?"7 is a" : "7 is not a" ) ;
Serial.print (" hexadecimal digit\r" );
Serial.print (isxdigit( '$' ) ? "$ is a" : "$ is not a" );
Serial.print (" hexadecimal digit\r" );
Serial.print (isxdigit( 'f' ) ? “f is a" : "f is not a");
}
void loop () {
}
Result
According to isdigit:
8 is a digit
# is not a digit
According to isalpha:
A is a letter
b is a letter
& is not a letter
4 is not a letter
According to isalnum:
A is a digit or a letter
8 is a digit or a letter
# is not a digit or a letter
According to isxdigit:
F is a hexadecimal digit
J is not a hexadecimal digit
7 is a hexadecimal digit
$ is not a hexadecimal digit
f is a hexadecimal digit
我们对每个函数使用条件运算符 (?:) 来确定字符串 " 是一个 " 或字符串 " 不是一个 " 的内容是否应打印在每个所测试字符的输出中。例如,行 a 表明如果 '8' 是一个数字 - 即如果 isdigit 返回 true(非零)值 - 则打印字符串 "8 是一个 "。如果 '8' 不是一个数字(即如果 isdigit 返回 0),则打印字符串 " 8 不是一个 "。
Example 2
以下示例演示了函数 islower 和 isupper 的用法。函数 islower 确定其参数是否是仅小写字母 (a-z)。函数 isupper 确定其参数是否是仅大写字母 (A-Z)。
int thisChar = 0xA0;
void setup () {
Serial.begin (9600);
Serial.print ("According to islower:\r") ;
Serial.print (islower( 'p' ) ? "p is a" : "p is not a" );
Serial.print ( " lowercase letter\r" );
Serial.print ( islower( 'P') ? "P is a" : "P is not a") ;
Serial.print ("lowercase letter\r");
Serial.print (islower( '5' ) ? "5 is a" : "5 is not a" );
Serial.print ( " lowercase letter\r" );
Serial.print ( islower( '!' )? "! is a" : "! is not a") ;
Serial.print ("lowercase letter\r");
Serial.print ("\rAccording to isupper:\r") ;
Serial.print (isupper ( 'D' ) ? "D is a" : "D is not an" );
Serial.print ( " uppercase letter\r" );
Serial.print ( isupper ( 'd' )? "d is a" : "d is not an") ;
Serial.print ( " uppercase letter\r" );
Serial.print (isupper ( '8' ) ? "8 is a" : "8 is not an" );
Serial.print ( " uppercase letter\r" );
Serial.print ( islower( '$' )? "$ is a" : "$ is not an") ;
Serial.print ("uppercase letter\r ");
}
void setup () {
}
Result
According to islower:
p is a lowercase letter
P is not a lowercase letter
5 is not a lowercase letter
! is not a lowercase letter
According to isupper:
D is an uppercase letter
d is not an uppercase letter
8 is not an uppercase letter
$ is not an uppercase letter
Example 3
以下示例演示了函数 isspace, iscntrl, ispunct, isprint 和 isgraph 的用法。
-
函数 isspace 确定其参数是否是空白字符,例如空格 (' ')、换页 ('\f')、换行 ('\n')、回车 ('\r')、水平制表符 ('\t') 或垂直制表符 ('\v')。
-
函数 iscntrl 确定其参数是否是控制字符,例如水平制表符 ('\t')、垂直制表符 ('\v')、换页 ('\f')、警告 ('\a')、退格 ('\b')、回车 ('\r') 或换行 ('\n')。
-
函数 ispunct 确定其参数是否是空格、数字或字母之外的打印字符,例如 $, #, (, ), [, ], {, }, ;, : 或 %。
-
函数 isprint 确定其参数是否是可在屏幕上显示的字符(包括空格字符)。
-
函数 isgraph 对与 isprint 相同的字符进行测试,但不包括空格字符。
void setup () {
Serial.begin (9600);
Serial.print ( " According to isspace:\rNewline ") ;
Serial.print (isspace( '\n' )? " is a" : " is not a" );
Serial.print ( " whitespace character\rHorizontal tab") ;
Serial.print (isspace( '\t' )? " is a" : " is not a" );
Serial.print ( " whitespace character\n") ;
Serial.print (isspace('%')? " % is a" : " % is not a" );
Serial.print ( " \rAccording to iscntrl:\rNewline") ;
Serial.print ( iscntrl( '\n' )?"is a" : " is not a" ) ;
Serial.print (" control character\r");
Serial.print (iscntrl( '$' ) ? " $ is a" : " $ is not a" );
Serial.print (" control character\r");
Serial.print ("\rAccording to ispunct:\r");
Serial.print (ispunct(';' ) ?"; is a" : "; is not a" ) ;
Serial.print (" punctuation character\r");
Serial.print (ispunct('Y' ) ?"Y is a" : "Y is not a" ) ;
Serial.print ("punctuation character\r");
Serial.print (ispunct('#' ) ?"# is a" : "# is not a" ) ;
Serial.print ("punctuation character\r");
Serial.print ( "\r According to isprint:\r");
Serial.print (isprint('$' ) ?"$ is a" : "$ is not a" );
Serial.print (" printing character\rAlert ");
Serial.print (isprint('\a' ) ?" is a" : " is not a" );
Serial.print (" printing character\rSpace ");
Serial.print (isprint(' ' ) ?" is a" : " is not a" );
Serial.print (" printing character\r");
Serial.print ("\r According to isgraph:\r");
Serial.print (isgraph ('Q' ) ?"Q is a" : "Q is not a" );
Serial.print ("printing character other than a space\rSpace ");
Serial.print (isgraph (' ') ?" is a" : " is not a" );
Serial.print ("printing character other than a space ");
}
void loop () {
}
Result
According to isspace:
Newline is a whitespace character
Horizontal tab is a whitespace character
% is not a whitespace character
According to iscntrl:
Newline is a control character
$ is not a control character
According to ispunct:
; is a punctuation character
Y is not a punctuation character
# is a punctuation character
According to isprint:
$ is a printing character
Alert is not a printing character
Space is a printing character
According to isgraph:
Q is a printing character other than a space
Space is not a printing character other than a space
Arduino - Math Library
Arduino Math 函数库(math.h)包含了许多用于操作浮点数的有用的数学函数。
Example
以下示例显示了如何使用最常用的 math.h 函数库函数 −
double double__x = 45.45 ;
double double__y = 30.20 ;
void setup() {
Serial.begin(9600);
Serial.print("cos num = ");
Serial.println (cos (double__x) ); // returns cosine of x
Serial.print("absolute value of num = ");
Serial.println (fabs (double__x) ); // absolute value of a float
Serial.print("floating point modulo = ");
Serial.println (fmod (double__x, double__y)); // floating point modulo
Serial.print("sine of num = ");
Serial.println (sin (double__x) ) ;// returns sine of x
Serial.print("square root of num : ");
Serial.println ( sqrt (double__x) );// returns square root of x
Serial.print("tangent of num : ");
Serial.println ( tan (double__x) ); // returns tangent of x
Serial.print("exponential value of num : ");
Serial.println ( exp (double__x) ); // function returns the exponential value of x.
Serial.print("cos num : ");
Serial.println (atan (double__x) ); // arc tangent of x
Serial.print("tangent of num : ");
Serial.println (atan2 (double__y, double__x) );// arc tangent of y/x
Serial.print("arc tangent of num : ");
Serial.println (log (double__x) ) ; // natural logarithm of x
Serial.print("cos num : ");
Serial.println ( log10 (double__x)); // logarithm of x to base 10.
Serial.print("logarithm of num to base 10 : ");
Serial.println (pow (double__x, double__y) );// x to power of y
Serial.print("power of num : ");
Serial.println (square (double__x)); // square of x
}
void loop() {
}
Result
cos num = 0.10
absolute value of num = 45.45
floating point modulo =15.25
sine of num = 0.99
square root of num : 6.74
tangent of num : 9.67
exponential value of num : ovf
cos num : 1.55
tangent of num : 0.59
arc tangent of num : 3.82
cos num : 1.66
logarithm of num to base 10 : inf
power of num : 2065.70
Arduino - Trigonometric Functions
您需要实际使用三角函数,比如为移动物体或角速度计算距离。Arduino 提供了传统的三角函数(sin、cos、tan、asin、acos、atan),可以将其概括为编写这些函数的原型。Math.h 包含三角函数的原型。
Trigonometric Exact Syntax
double sin(double x); //returns sine of x radians
double cos(double y); //returns cosine of y radians
double tan(double x); //returns the tangent of x radians
double acos(double x); //returns A, the angle corresponding to cos (A) = x
double asin(double x); //returns A, the angle corresponding to sin (A) = x
double atan(double x); //returns A, the angle corresponding to tan (A) = x
Arduino - Due & Zero
Arduino Due 是一个基于 Atmel SAM3X8E ARM Cortex-M3 CPU 的微控制器电路板。它是第一个基于 32 位 ARM 核微控制器的 Arduino 电路板。
重要功能 −
-
它有 54 个数字输入/输出引脚(其中 12 个可用作 PWM 输出)
-
12 analog inputs
-
4 个 UART(硬件串行端口)
-
84 MHz 时钟,一个 USB OTG 可用连接
-
2 个 DAC(数字转模拟),2 个 TWI,一个电源插孔,一个 SPI 接头,一个 JTAG 接头
-
复位按钮和擦除按钮
Characteristics of the Arduino Due Board
Operating volt |
CPU speed |
Analog in/out |
Digital IO/ PWM |
EEPROM [KB] |
SRAM [KB] |
Flash [KB] |
USB |
UART |
3.3 Volt |
84 Mhz |
12/2 |
54/12 |
- |
96 |
512 |
2 micro |
4 |
Communication
-
4 Hardware UARTs
-
2 I2C
-
1 个 CAN 接口(汽车通信协议)
-
1 SPI
-
1 个接口 JTAG(10 针)
-
1 个 USB 主机(如同 Leonardo)
-
1 Programming Port
与大多数 Arduino 板不同,Arduino Due 板以 3.3V 运行。I/O 针脚可以承受的最大电压为 3.3V。对任何 I/O 针脚施加高于 3.3V 的电压都可能损坏电路板。
该板包含支持微控制器所需的一切。您只需将其连接到计算机上,使用微型 USB 电缆或交流转直流适配器或电池供电即可开始使用。Due 与所有以 3.3V 工作的 Arduino 扩展板兼容。
Arduino Zero
Zero 是 UNO 所建立的平台的简单而强大的 32 位扩展。该 Zero 电路板通过提供更高的性能来扩展该系列产品,为设备提供了各种项目机会,并且作为学习 32 位应用程序开发的优秀教育工具。
重要的功能有 −
-
Zero 应用从智能物联网设备、可穿戴技术、高科技自动化到疯狂机器人,跨越很多领域。
-
该电板由 Atmel 的 SAMD21 MCU 供电,它具有 32 位 ARM Cortex® M0+ 内核。
-
其最重要的功能之一是 Atmel 的嵌入式调试器 (EDBG),它提供了完整调试界面,而无需额外的硬件,极大提升了软件调试的易用性。
-
EDBG 还支持一个虚拟 COM 端口,该端口可用于设备和引导加载程序编程。
Characteristics of the Arduino Zero board
Operating volt |
CPU speed |
Analog in/out |
Digital IO/ PWM |
EEPROM [KB] |
SRAM [KB] |
Flash [KB] |
USB |
UART |
3.3 Volt |
48 Mhz |
6/1 |
14/10 |
- |
32 |
256 |
2 micro |
2 |
与大多数 Arduino 和 Genuino 电路板不同,Zero 以 3.3V 运行。I/O 针脚可以承受的最大电压为 3.3V。对任何 I/O 针脚施加高于 3.3V 的电压都可能损坏电路板。
该板包含支持微控制器所需的一切。您只需将其连接到计算机上,使用微型 USB 电缆或交流转直流适配器或电池供电即可开始使用。Zero 与所有以 3.3V 工作的扩展板兼容。
Arduino - Pulse Width Modulation
脉冲宽度调制或 PWM 是一种常见的技术,用于改变脉冲串中脉冲的宽度。PWM 有许多应用,如控制伺服器和速度控制器,以及限制电机和 LED 的有效功率。
Basic Principle of PWM
脉冲宽度调制基本上是一个具有可变高低时间的方波。基本 PWM 信号如下图所示。
PWM 涉及到各种术语 −
-
On-Time − 信号高电平持续时间。
-
Off-Time − 信号低电平持续时间。
-
Period − 表示为 PWM 信号的导通时间和关断时间的总和。
-
Duty Cycle − 表示为 PWM 信号周期内信号保持导通时间的百分比。
analogWrite() Function
analogWrite() 函数向引脚写入模拟值(PWM 波形)。它可以用来点亮亮度可变的 LED 或驱动速度可变的电机。调用 analogWrite() 函数后,该引脚将生成指定占空比的稳定方波,持续到下一次调用 analogWrite() 或对同一引脚调用 digitalRead() 或 digitalWrite()。大多数引脚上的 PWM 信号频率约为 490 Hz。在 Uno 和类似的电路板上,引脚 5 和 6 的频率约为 980 Hz。Leonardo 上的引脚 3 和 11 也以 980 Hz 的频率运行。
在大多数 Arduino 电路板(带有 ATmega168 或 ATmega328 的电路板)上,此函数在引脚 3、5、6、9、10 和 11 上运行。在 Arduino Mega 上,它在引脚 2 - 13 和 44 - 46 上运行。具有 ATmega8 的较旧 Arduino 电路板仅支持引脚 9、10 和 11 上的 analogWrite() 。
Arduino Due 支持引脚 2 至 13 以及引脚 DAC0 和 DAC1 上的 analogWrite() 。与 PWM 引脚不同,DAC0 和 DAC1 是数模转换器,并作为真正的模拟输出。
在调用 analogWrite() 之前,无需调用 pinMode() 将引脚设置为输出。
analogWrite() Function Syntax
analogWrite ( pin , value ) ;
value —占空比:0(始终关闭)到 255(始终开启)之间的值。
Example
int ledPin = 9; // LED connected to digital pin 9
int analogPin = 3; // potentiometer connected to analog pin 3
int val = 0; // variable to store the read value
void setup() {
pinMode(ledPin, OUTPUT); // sets the pin as output
}
void loop() {
val = analogRead(analogPin); // read the input pin
analogWrite(ledPin, (val / 4)); // analogRead values go from 0 to 1023,
// analogWrite values from 0 to 255
}
Arduino - Random Numbers
要生成随机数,可以使用 Arduino 随机数函数。我们有两个函数:
-
randomSeed(seed)
-
random()
randomSeed (seed)
randomSeed(seed) 函数重置 Arduino 的伪随机数生成器。尽管 random() 返回的数字分布本质上是随机的,但该序列是可预测的。您应该将生成器重置为某个随机值。如果您有未连接的模拟引脚,它可能会从周围环境中拾取随机噪声。这些可能是无线电波、宇宙射线、来自手机、荧光灯等的电磁干扰。
random( )
random 函数生成伪随机数。以下是语法。
random( ) Statements Syntax
long random(max) // it generate random numbers from 0 to max
long random(min, max) // it generate random numbers from min to max
Example
long randNumber;
void setup() {
Serial.begin(9600);
// if analog input pin 0 is unconnected, random analog
// noise will cause the call to randomSeed() to generate
// different seed numbers each time the sketch runs.
// randomSeed() will then shuffle the random function.
randomSeed(analogRead(0));
}
void loop() {
// print a random number from 0 to 299
Serial.print("random1=");
randNumber = random(300);
Serial.println(randNumber); // print a random number from 0to 299
Serial.print("random2=");
randNumber = random(10, 20);// print a random number from 10 to 19
Serial.println (randNumber);
delay(50);
}
现在,让我们复习一些基本概念,例如位和字节。
Arduino - Interrupts
中断停止 Arduino 的当前工作,以便完成一些其他工作。
假设你坐在家里与某人聊天。突然电话响了。您停止聊天,拿起电话与来电者交谈。结束电话交谈后,您回到电话响起之前与那个人聊天。
与之类似,你可以将主例程看作与人聊天,电话铃声会中断聊天。中断服务程序就是打电话的过程。当电话会话结束时,你再回到聊天的主例程中来。此示例准确地阐释了中断如何使处理器执行任务。
主程序正在运行并在电路中执行一些功能。但是,中断发生时,当另一个例程执行时,主程序会暂停。当这个例程结束后,处理器再次回到主例程中来。
Important features
这里有一些关于中断的重要功能 −
-
中断可以来自各种来源。在本例中,我们使用的是一个硬件中断,该中断由一个数字管脚上的状态变化触发。
-
大多数 Arduino 设计有两个硬件中断(分别称为“interrupt0”和“interrupt1”),这两个中断硬连接到数字 I/O 管脚 2 和 3。
-
Arduino Mega 有六个硬件中断,包括管脚 21、20、19 和 18 上的附加中断(“interrupt2”到“interrupt5”)。
-
你可以使用一个称为“中断服务程序”(通常称为 ISR)的特殊函数来定义一个例程。
-
你可以定义该例程并指定上升沿、下降沿或两者。在这些特定条件下,中断将被服务。
-
可以自动执行该函数,每次在输入管脚上发生事件时都会执行。
Types of Interrupts
有两种类型的中断 −
-
Hardware Interrupts − 它们响应于外部事件,例如外部中断管脚变高或变低。
-
Software Interrupts − 它们响应于软件中发送的指令。Arduino 语言支持的唯一类型的中断是 attachInterrupt() 函数。
Using Interrupts in Arduino
在 Arduino 程序中,中断非常有用,因为它有助于解决时序问题。中断的一个很好的应用是读取旋转编码器或观察用户输入。通常,ISR 应尽可能短且快。如果你的草图使用多个 ISR,一次只能运行一个 ISR。其他中断将在当前中断完成之后执行,其执行顺序取决于它们具有的优先级。
通常,全局变量用于在 ISR 和主程序之间传递数据。要确保在 ISR 和主程序之间共享的变量得到正确更新,将其声明为 volatile。
attachInterrupt Statement Syntax
attachInterrupt(digitalPinToInterrupt(pin),ISR,mode);//recommended for arduino board
attachInterrupt(pin, ISR, mode) ; //recommended Arduino Due, Zero only
//argument pin: the pin number
//argument ISR: the ISR to call when the interrupt occurs;
//this function must take no parameters and return nothing.
//This function is sometimes referred to as an interrupt service routine.
//argument mode: defines when the interrupt should be triggered.
预定义了下列三个常量作为有效值 −
-
LOW 只要管脚变低就触发中断。
-
CHANGE 只要管脚值改变就触发中断。
-
FALLING 只要管脚从高变为低就触发中断。
Example
int pin = 2; //define interrupt pin to 2
volatile int state = LOW; // To make sure variables shared between an ISR
//the main program are updated correctly,declare them as volatile.
void setup() {
pinMode(13, OUTPUT); //set pin 13 as output
attachInterrupt(digitalPinToInterrupt(pin), blink, CHANGE);
//interrupt at pin 2 blink ISR when pin to change the value
}
void loop() {
digitalWrite(13, state); //pin 13 equal the state value
}
void blink() {
//ISR function
state = !state; //toggle the state when the interrupt occurs
}
Arduino - Communication
已经定义了数百种通信协议来实现此数据交换。每种协议都可以归类为两类之一:并行或串行。
Parallel Communication
Arduino 和外围设备之间通过输入/输出端口的并行连接是短距离(最长几米)的理想解决方案。然而,在其他情况下,当需要为更长距离的两个设备建立通信时,则无法使用并行连接。并行接口一次传输多位。它们通常需要数据总线——跨八根、十六根或更多根电线传输。数据以巨大的、汹涌的 1 和 0 波传输。
Serial Communication Modules
如今,大多数 Arduino 板都内置了多个用于串行通信的不同系统作为标准设备。
使用以下因素决定使用哪种系统:
-
微控制器需要与多少设备交换数据?
-
数据交换需要多快?
-
这些设备之间的距离是多少?
-
是否需要同时发送和接收数据?
关于串行通信最重要的一件事就是 Protocol ,它应当严格遵守。这套规则必须应用才能让设备正确解释它们之间交换的数据。幸运的是,Arduino 会自动处理好这个过程,这样程序员/用户的工作就简化成简单的写入(发送数据)和读取(接收数据)。
Types of Serial Communications
串行通信还可以进一步分类:
-
Synchronous − 同步设备使用同一时钟,它们的计时相互同步。
-
Asynchronous − 异步设备有自己的时钟,并由前一状态的输出触发。
很容易发现某个设备是同步设备还是异步设备。如果所有连接的设备使用同一时钟,那么它们就是同步设备。如果没有时钟线,那么它们就是异步设备。
例如,UART(通用异步收发器)模块就是异步设备。
异步串行协议包含许多内置规则。这些规则不过是帮助确保数据传输稳健无误的机制。通过放弃外部时钟信号而获得的这些机制包括:
-
Synchronization bits
-
Data bits
-
Parity bits
-
Baud rate
Synchronization Bits
同步位是每次数据包传输时随数据一起传输的两个或三个特殊位。它们是起始位和停止位。顾名思义,这些位分别标记数据包的开始和结束。
起始位只有一个,但停止位的数量可以配置为一个或两个(尽管通常将其保留为一个)。
起始位始终由空闲数据线从 1 变为 0 表示,而停止位将通过将数据线保持在 1 上的状态转换回空闲状态。
Arduino UART
以下代码可以让 Arduino 在启动时发送“hello world”。
void setup() {
Serial.begin(9600); //set up serial library baud rate to 9600
Serial.println("hello world"); //print hello world
}
void loop() {
}
将 Arduino 草图上传到 Arduino 后,打开 Arduino IDE 右上角的串行监视器。
在串行监视器的顶部框中键入任意内容,然后按键盘上的发送或回车。这会向 Arduino 发送一系列字节。
以下代码会返回它收到的任何输入。
以下代码会让 Arduino 根据所提供的输入提供输出。
void setup() {
Serial.begin(9600); //set up serial library baud rate to 9600
}
void loop() {
if(Serial.available()) //if number of bytes (characters) available for reading from {
serial port
Serial.print("I received:"); //print I received
Serial.write(Serial.read()); //send what you read
}
}
请注意, Serial.print 和 Serial.println 会发送回实际的 ASCII 码,而 Serial.write 会发送回实际的文本。有关更多信息,请参见 ASCII 码。
Arduino - Inter Integrated Circuit
集成电路间总线 (I2C) 是一种新一代微控制器和专用集成电路之间进行串行数据交换的系统。当它们之间的距离较短(接收器和发送器通常位于同一块印刷电路板上)时,它会被使用。连接通过两条导线建立。一条用于数据传输,另一条用于同步(时钟信号)。
如图所示,一台设备始终作为主设备。在通信开始之前,它会对一个从设备进行寻址。通过这种方式,一个微控制器可以与 112 个不同的设备通信。波特率通常为 100 Kb/s(标准模式)或 10 Kb/s(低波特率模式)。最近出现了波特率为 3.4 Mb/s 的系统。通过 I2C 总线通信的设备之间的距离限制为几米。
Board I2C Pins
I2C 总线由两个信号组成 - SCL 和 SDA。SCL 是时钟信号,SDA 是数据信号。当前总线主设备始终生成时钟信号。某些从设备有时可能强制将时钟降至低电平,以延迟主设备发送更多数据(或在主设备尝试将其时钟化之前需要更多时间准备数据)。这称为“时钟拉伸”。
以下是不同 Arduino 板的引脚−
-
Uno、Pro Mini A4 (SDA)、A5 (SCL)
-
Mega、Due 20 (SDA)、21 (SCL)
-
Leonardo、Yun 2 (SDA)、3 (SCL)
Master Transmitter / Slave Receiver
现在让我们看看什么是主设备发送器和从设备接收器。
Master Transmitter
以下函数用于初始化 Wire 库,并将作为主设备或从设备加入 I2C 总线。此操作通常只调用一次。
-
Wire.begin(address) − 在我们的例子中,地址是 7 位从机地址,因为没有指定主机,它会作为主机加入总线。
-
Wire.beginTransmission(address) − 使用给定的地址开始向 I2C 从机设备传输。
-
Wire.write(value) − 将字节排队从主机传输到从机设备(介于 beginTransmission() 和 endTransmission() 调用之间)。
-
Wire.endTransmission() − 结束由 beginTransmission() 开始的对从机设备的传输,并传输由 wire.write() 排队的字节。
Example
#include <Wire.h> //include wire library
void setup() //this will run only once {
Wire.begin(); // join i2c bus as master
}
short age = 0;
void loop() {
Wire.beginTransmission(2);
// transmit to device #2
Wire.write("age is = ");
Wire.write(age); // sends one byte
Wire.endTransmission(); // stop transmitting
delay(1000);
}
Slave Receiver
使用以下函数 −
-
Wire.begin(address) − 地址是 7 位从机地址。
-
Wire.onReceive(received data handler) − 从机设备从主机接收数据时调用的函数。
-
Wire.available() − 返回可通过 Wire.read() 检索的字节数。应该在 Wire.onReceive() 处理程序中调用此函数。
Example
#include <Wire.h> //include wire library
void setup() { //this will run only once
Wire.begin(2); // join i2c bus with address #2
Wire.onReceive(receiveEvent); // call receiveEvent when the master send any thing
Serial.begin(9600); // start serial for output to print what we receive
}
void loop() {
delay(250);
}
//-----this function will execute whenever data is received from master-----//
void receiveEvent(int howMany) {
while (Wire.available()>1) // loop through all but the last {
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
}
Master Receiver / Slave Transmitter
现在让我们了解一下什么主机接收器和从机发送器。
Master Receiver
主机被编程为请求,然后读取从唯一寻址的从机 Arduino 发送的数据字节。
使用以下函数 −
Wire.requestFrom(address,number of bytes) − 主机用来从从机设备请求字节。然后可以用 wire.available() 和 wire.read() 函数检索字节。
Example
#include <Wire.h> //include wire library void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop() {
Wire.requestFrom(2, 1); // request 1 bytes from slave device #2
while (Wire.available()) // slave may send less than requested {
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(500);
}
Slave Transmitter
使用以下函数。
Wire.onRequest(handler) − 当主机从该从机设备请求数据时,会调用一个函数。
Example
#include <Wire.h>
void setup() {
Wire.begin(2); // join i2c bus with address #2
Wire.onRequest(requestEvent); // register event
}
Byte x = 0;
void loop() {
delay(100);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Wire.write(x); // respond with message of 1 bytes as expected by master
x++;
}
Arduino - Serial Peripheral Interface
串行外设接口 (SPI) 总线是一种串行通信系统,它使用多达四根导线,通常为三根。一根导线用于接收数据,一根用于发送数据,一根用于同步,一根用于选择要通信的设备。它是一种全双工连接,这意味着可以同时发送和接收数据。它的最大波特率高于 I2C 通信系统中的最大波特率。
Board SPI Pins
SPI 使用以下四根电线 −
-
SCK − 这是由主器件驱动的串行时钟。
-
MOSI − 这是由主器件驱动的发送数据输入/从输入。
-
MISO − 这是由主器件驱动的输入数据输入/从器件输出。
-
SS − 这是从器件选择导线。
用到的函数如下。需要包含 SPI.h。
-
SPI.begin() − 为 SPI 总线设置 SCK、MOSI 和 SS 为输出,将 SCK 和 MOSI 置低,将 SS 置高,从而初始化 SPI 总线。
-
SPI.setClockDivider(divider) − 设置相对于系统时钟的 SPI 时钟分频器。在基于 AVR 的板上,可用的分频器有 2、4、8、16、32、64 或 128。默认设置是 SPI_CLOCK_DIV4,它会将 SPI 时钟设置为系统时钟频率的四分之一(在 20 MHz 的板上为 5 MHz)。
-
Divider − 它可能为 (SPI_CLOCK_DIV2、SPI_CLOCK_DIV4、SPI_CLOCK_DIV8、SPI_CLOCK_DIV16、SPI_CLOCK_DIV32、SPI_CLOCK_DIV64、SPI_CLOCK_DIV128)。
-
SPI.transfer(val) − SPI 传输基于同时发送和接收:接收到的数据将返回到 receivedVal。
-
SPI.beginTransaction(SPISettings(speedMaximum, dataOrder, dataMode)) - speedMaximum 是时钟、dataOrder(MSBFIRST 或 LSBFIRST)、dataMode(SPI_MODE0、SPI_MODE1、SPI_MODE2 或 SPI_MODE3)。
在 SPI 中,我们有四种操作模式,如下所示 −
-
Mode 0 (the default) - 时钟通常为低 (CPOL = 0),数据在从低到高跃变 (前沿) (CPHA = 0) 时取样。
-
Mode 1 - 时钟通常为低 (CPOL = 0),数据在从高到低跃变 (后沿) (CPHA = 1) 时取样。
-
Mode 2 - 时钟通常为高 (CPOL = 1),数据在从高到低跃变 (前沿) (CPHA = 0) 时取样。
-
Mode 3 - 时钟通常为高 (CPOL = 1),数据在从低到高跃变 (后沿) (CPHA = 1) 时取样。
-
SPI.attachInterrupt(handler) - 从设备从主设备接收数据时调用的函数。
现在,我们将连接两个 Arduino UNO 板;一个作为主设备,另一个作为从设备。
-
(SS) : pin 10
-
(MOSI) : pin 11
-
(MISO) : pin 12
-
(SCK) : pin 13
接地是共用的。以下是两个板之间连接的示意图 −
让我们看看作为主设备的 SPI 和作为从设备的 SPI 的示例。
SPI as MASTER
Example
#include <SPI.h>
void setup (void) {
Serial.begin(115200); //set baud rate to 115200 for usart
digitalWrite(SS, HIGH); // disable Slave Select
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8);//divide the clock by 8
}
void loop (void) {
char c;
digitalWrite(SS, LOW); // enable Slave Select
// send test string
for (const char * p = "Hello, world!\r" ; c = *p; p++) {
SPI.transfer (c);
Serial.print(c);
}
digitalWrite(SS, HIGH); // disable Slave Select
delay(2000);
}
SPI as SLAVE
Example
#include <SPI.h>
char buff [50];
volatile byte indx;
volatile boolean process;
void setup (void) {
Serial.begin (115200);
pinMode(MISO, OUTPUT); // have to send on master in so it set as output
SPCR |= _BV(SPE); // turn on SPI in slave mode
indx = 0; // buffer empty
process = false;
SPI.attachInterrupt(); // turn on interrupt
}
ISR (SPI_STC_vect) // SPI interrupt routine {
byte c = SPDR; // read byte from SPI Data Register
if (indx < sizeof buff) {
buff [indx++] = c; // save data in the next index in the array buff
if (c == '\r') //check for the end of the word
process = true;
}
}
void loop (void) {
if (process) {
process = false; //reset the process
Serial.println (buff); //print the array on serial monitor
indx= 0; //reset button to zero
}
}
Arduino - Blinking LED
LED 是小巧、功能强大的灯,用于很多不同的应用。一开始,我们将操作使 LED 闪烁,这是微控制器的 Hello World。这就像开关一盏灯一样简单。建立此重要基线将为你打下坚实的基础,让我们朝更加复杂的实验进军。
Components Required
您将需要以下组件:
-
1 × Breadboard
-
1 × Arduino Uno R3
-
1 × LED
-
1 × 330Ω Resistor
-
2 × Jumper
Procedure
按照电路图并将组件连接到面包板上,如下图所示。
Note − 要找出 LED 的极性,请仔细观察。灯泡扁平边缘朝向两条腿中较短的一条腿表示负极。
为了正确安装面包板插座,像电阻器这样的元件需要将其端子弯曲成 90° 角。您还可以剪短端子。
Arduino Code
/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.
*/
// the setup function runs once when you press reset or power the board
void setup() { // initialize digital pin 13 as an output.
pinMode(2, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(2, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(2, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
Arduino - Fading LED
此示例演示了 analogWrite() 函数在关闭 LED 时如何使用淡出效果。AnalogWrite 使用脉宽调制 (PWM),快速地打开和关闭数字引脚,并使用开和关的不同比率来创建淡出效果。
Components Required
您将需要以下组件:
-
1 × Breadboard
-
1 × Arduino Uno R3
-
1 × LED
-
1 × 330Ω Resistor
-
2 × Jumper
Procedure
按照电路图并将组件连接到面包板上,如下图所示。
Note − 要找出 LED 的极性,请仔细观察。灯泡扁平边缘朝向两条腿中较短的一条腿表示负极。
为了正确安装面包板插座,像电阻器这样的元件需要将其端子弯曲成 90° 角。您还可以剪短端子。
Arduino Code
/*
Fade
This example shows how to fade an LED on pin 9 using the analogWrite() function.
The analogWrite() function uses PWM, so if you want to change the pin you're using, be
sure to use another PWM capable pin. On most Arduino, the PWM pins are identified with
a "~" sign, like ~3, ~5, ~6, ~9, ~10 and ~11.
*/
int led = 9; // the PWM pin the LED is attached to
int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by
// the setup routine runs once when you press reset:
void setup() {
// declare pin 9 to be an output:
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
// set the brightness of pin 9:
analogWrite(led, brightness);
// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;
// reverse the direction of the fading at the ends of the fade:
if (brightness == 0 || brightness == 255) {
fadeAmount = -fadeAmount ;
}
// wait for 30 milliseconds to see the dimming effect
delay(300);
}
Code to Note
将引脚 9 声明为 LED 引脚后,您的代码的 setup() 函数中无需执行任何操作。您将在代码的主循环中使用的 analogWrite() 函数需要两个参数:一个告诉函数要写入哪个引脚,另一个指示要写入的 PWM 值。
为了让 LED 淡入淡出,逐渐增加 PWM 值,从 0(完全关闭)到 255(完全开启),然后回到 0,以完成循环。在上面给出的草图中,使用名为亮度的变量设置 PWM 值。每次通过循环,它都会按变量的值 fadeAmount 增加。
如果亮度处于其值的任何极端(0 或 255),则 fadeAmount 会变为其负值。换句话说,如果 fadeAmount 为 5,则它将设置为 -5。如果为 -5,则将其设置为 5。下一次通过循环,此更改还会导致亮度改变方向。
analogWrite() 可以非常快地更改 PWM 值,因此草图末尾的延迟控制了淡出效果的速度。尝试更改延迟的值,看看它如何改变淡出效果。
Arduino - Reading Analog Voltage
此示例将向你展示如何在模拟引脚 0 上读取模拟输入。输入从 analogRead() 转换为电压,并打印到 Arduino 软件 (IDE) 的串行监视器。
Potentiometer
电位器(或电位计)是一种简单的机电传感器。它将输入操作者的旋转或线性运动转换为电阻变化。此变化(或可以)用于控制从立体声系统的音量到大型集装箱船的方向的任何事物。
我们所知的电位计最初被称为变阻器(基本上是一个可变绕线电阻器)。现有的各种电位计现在非常令人惊讶,对于初学者(特别是)来说,弄清楚哪种类型适合给定的任务可能非常困难。一些不同的电位计类型,所有这些类型都可以用于相同的任务,这使得这项工作更加困难。
左侧图片显示了电位计的标准原理图符号。右侧图片是电位器。
Arduino Code
/*
ReadAnalogVoltage
Reads an analog input on pin 0, converts it to voltage,
and prints the result to the serial monitor.
Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
*/
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
Serial.println(voltage);
}
Code to Note
在下面给出的程序或草图中,在设置函数中你首先做的事情是开始串行通信,在你的主板和你的计算机之间,传输速率为 9600 位/秒,行如下所示 −
Serial.begin(9600);
在代码的主循环中,你需要建立一个变量来存储来自电位器的电阻值(介于 0 到 1023 之间,非常适合 int 数据类型)−
int sensorValue = analogRead(A0);
要将值从 0-1023 更改为与电压相对应的范围,引脚正在读取,你需要创建另一个变量,一个 float,并进行一些计算。要在 0.0 和 5.0 之间缩放数字,将 5.0 除以 1023.0,然后将其乘以 sensorValue −
float voltage= sensorValue * (5.0 / 1023.0);
最后,你需要将此信息打印到你的串行窗口。你可以在代码的最后一行使用 Serial.println() 命令执行此操作 −
Serial.println(voltage)
现在,通过单击顶部绿色栏右侧的图标或按 Ctrl+Shift+M,在 Arduino IDE 中打开串行监视器。
Arduino - LED Bar Graph
此示例向您展示如何读取模拟针脚 0 上的模拟输入,将 analogRead() 中的值转换成电压,并将其打印到 Arduino 软件 (IDE) 的串口监视器中。
Components Required
您将需要以下组件:
-
1 × Breadboard
-
1 × Arduino Uno R3
-
1 × 5k 欧姆可变电阻器(电位计)
-
2 × Jumper
-
8 × LED 或您可以使用(如以下图像中所示的 LED 条形图显示器)
10 Segment LED Bar Graph
这些 10 段条形图 LED 有多种用途。它们占用空间小、连接简单,无论是用于原型设计还是成品都很容易使用。从本质上说,它们是 10 个单独的蓝色 LED 组合在一起,每个 LED 都具有一个单独的阳极和阴极连接。
它们还有黄色、红色和绿色。
Note − 这些条形图上的引脚分配可能与数据表上列出的不同。将设备旋转 180 度将更正更改,使引脚 11 成为第一引脚。
Arduino Code
/*
LED bar graph
Turns on a series of LEDs based on the value of an analog sensor.
This is a simple way to make a bar graph display.
Though this graph uses 8LEDs, you can use any number by
changing the LED count and the pins in the array.
This method can be used to control any series of digital
outputs that depends on an analog input.
*/
// these constants won't change:
const int analogPin = A0; // the pin that the potentiometer is attached to
const int ledCount = 8; // the number of LEDs in the bar graph
int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 9}; // an array of pin numbers to which LEDs are attached
void setup() {
// loop over the pin array and set them all to output:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
pinMode(ledPins[thisLed], OUTPUT);
}
}
void loop() {
// read the potentiometer:
int sensorReading = analogRead(analogPin);
// map the result to a range from 0 to the number of LEDs:
int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);
// loop over the LED array:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
// if the array element's index is less than ledLevel,
// turn the pin for this element on:
if (thisLed < ledLevel) {
digitalWrite(ledPins[thisLed], HIGH);
}else { // turn off all pins higher than the ledLevel:
digitalWrite(ledPins[thisLed], LOW);
}
}
}
Arduino - Keyboard Logout
此示例使用键盘库,当 ARDUINO UNO 上的引脚 2 拉至接地时,使你退出计算机上的用户会话。此草图模拟了同时按两个或三个键的顺序的按键,并且在短延迟后释放它们。
Warning − 当你使用 Keyboard.print() 命令时,Arduino 将接管你的计算机键盘。为确保在使用此函数运行草图时不会失去对计算机的控制,请在调用 Keyboard.print() 之前设置一个可靠的控制系统。此草图设计为仅在引脚拉至接地后发送键盘命令。
Components Required
您将需要以下组件:
-
1 × Breadboard
-
1 × Arduino Leonardo、Micro 或 Due 电路板
-
1 × pushbutton
-
1 × Jumper
Sketch
在计算机上打开 Arduino IDE 软件。使用 Arduino 语言进行编码将控制您的电路。单击“新建”以新建一个草图文件。
以下示例中,需要使用 Arduino IDE 1.6.7
Note − 必须在 Arduino 库文件中包含键盘库。将键盘库文件复制并粘贴到名为 libraries 的文件夹中(高亮),如下面的屏幕截图所示。
Arduino Code
/*
Keyboard logout
This sketch demonstrates the Keyboard library.
When you connect pin 2 to ground, it performs a logout.
It uses keyboard combinations to do this, as follows:
On Windows, CTRL-ALT-DEL followed by ALT-l
On Ubuntu, CTRL-ALT-DEL, and ENTER
On OSX, CMD-SHIFT-q
To wake: Spacebar.
Circuit:
* Arduino Leonardo or Micro
* wire to connect D2 to ground.
*/
#define OSX 0
#define WINDOWS 1
#define UBUNTU 2
#include "Keyboard.h"
// change this to match your platform:
int platform = WINDOWS;
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() {
while (digitalRead(2) == HIGH) {
// do nothing until pin 2 goes low
delay(500);
}
delay(1000);
switch (platform) {
case OSX:
Keyboard.press(KEY_LEFT_GUI);
// Shift-Q logs out:
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press('Q');
delay(100);
// enter:
Keyboard.write(KEY_RETURN);
break;
case WINDOWS:
// CTRL-ALT-DEL:
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(KEY_DELETE);
delay(100);
Keyboard.releaseAll();
//ALT-l:
delay(2000);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press('l');
Keyboard.releaseAll();
break;
case UBUNTU:
// CTRL-ALT-DEL:
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(KEY_DELETE);
delay(1000);
Keyboard.releaseAll();
// Enter to confirm logout:
Keyboard.write(KEY_RETURN);
break;
}
// do nothing:
while (true);
}
Keyboard.releaseAll();
// enter:
Keyboard.write(KEY_RETURN);
break;
case WINDOWS:
// CTRL-ALT-DEL:
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(KEY_DELETE);
delay(100);
Keyboard.releaseAll();
//ALT-l:
delay(2000);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press('l');
Keyboard.releaseAll();
break;
case UBUNTU:
// CTRL-ALT-DEL:
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(KEY_DELETE);
delay(1000);
Keyboard.releaseAll();
// Enter to confirm logout:
Keyboard.write(KEY_RETURN);
break;
}
// do nothing:
while (true);
}
Arduino - Keyboard Message
在此示例中,当按下按钮时,一个文本字符串将作为键盘输入被发送到计算机。该字符串报告按钮被按下的次数。一旦对 Leonardo 进行了编程并将其连接好,打开您最喜欢的文本编辑器查看结果。
Warning − 在您使用 Keyboard.print() 命令时,Arduino 接管了您的电脑键盘。为了确保在使用此功能运行草图时不丢失对您电脑的控制,在调用 Keyboard.print() 之前设置一个可靠的控制系统。此草图包含一个按钮,用于切换键盘,因此只有在按下按钮后才运行此草图。
Components Required
您将需要以下组件:
-
1 × Breadboard
-
1 × Arduino Leonardo、Micro 或 Due 电路板
-
1 × momentary pushbutton
-
1 × 10k 欧姆电阻
Arduino Code
/*
Keyboard Message test For the Arduino Leonardo and Micro,
Sends a text string when a button is pressed.
The circuit:
* pushbutton attached from pin 4 to +5V
* 10-kilohm resistor attached from pin 4 to ground
*/
#include "Keyboard.h"
const int buttonPin = 4; // input pin for pushbutton
int previousButtonState = HIGH; // for checking the state of a pushButton
int counter = 0; // button push counter
void setup() {
pinMode(buttonPin, INPUT); // make the pushButton pin an input:
Keyboard.begin(); // initialize control over the keyboard:
}
void loop() {
int buttonState = digitalRead(buttonPin); // read the pushbutton:
if ((buttonState != previousButtonState)&& (buttonState == HIGH)) // and it's currently pressed: {
// increment the button counter
counter++;
// type out a message
Keyboard.print("You pressed the button ");
Keyboard.print(counter);
Keyboard.println(" times.");
}
// save the current button state for comparison next time:
previousButtonState = buttonState;
}
Arduino - Mouse Button Control
使用鼠标库,你可以用 Arduino Leonardo、Micro 或 Due 控制计算机屏幕上的光标。
此特定示例使用五个按钮来移动屏幕光标。四个按钮是方向性的(上、下、左、右),还有一个用于左键单击。从 Arduino 移动光标始终是相对的。每次读取输入时,光标的位置都相对于其当前位置更新。
只要按下方向按钮中的一个,Arduino 就会移动鼠标,将一个高输入映射到适当方向的 5 个范围。
第五个按钮用于控制鼠标的左键单击。释放按钮时,计算机将识别该事件。
Components Required
您将需要以下组件:
-
1 × Breadboard
-
1 × Arduino Leonardo、Micro 或 Due 电路板
-
5 × 10k 欧姆电阻
-
5 × momentary pushbuttons
Sketch
在计算机上打开 Arduino IDE 软件。使用 Arduino 语言进行编码将控制您的电路。单击“新建”以新建一个草图文件。
以下示例中,需要使用 Arduino IDE 1.6.7
Arduino Code
/*
Button Mouse Control
For Leonardo and Due boards only .Controls the mouse from
five pushbuttons on an Arduino Leonardo, Micro or Due.
Hardware:
* 5 pushbuttons attached to D2, D3, D4, D5, D6
The mouse movement is always relative. This sketch reads
four pushbuttons, and uses them to set the movement of the mouse.
WARNING: When you use the Mouse.move() command, the Arduino takes
over your mouse! Make sure you have control before you use the mouse commands.
*/
#include "Mouse.h"
// set pin numbers for the five buttons:
const int upButton = 2;
const int downButton = 3;
const int leftButton = 4;
const int rightButton = 5;
const int mouseButton = 6;
int range = 5; // output range of X or Y movement; affects movement speed
int responseDelay = 10; // response delay of the mouse, in ms
void setup() {
// initialize the buttons' inputs:
pinMode(upButton, INPUT);
pinMode(downButton, INPUT);
pinMode(leftButton, INPUT);
pinMode(rightButton, INPUT);
pinMode(mouseButton, INPUT);
// initialize mouse control:
Mouse.begin();
}
void loop() {
// read the buttons:
int upState = digitalRead(upButton);
int downState = digitalRead(downButton);
int rightState = digitalRead(rightButton);
int leftState = digitalRead(leftButton);
int clickState = digitalRead(mouseButton);
// calculate the movement distance based on the button states:
int xDistance = (leftState - rightState) * range;
int yDistance = (upState - downState) * range;
// if X or Y is non-zero, move:
if ((xDistance != 0) || (yDistance != 0)) {
Mouse.move(xDistance, yDistance, 0);
}
// if the mouse button is pressed:
if (clickState == HIGH) {
// if the mouse is not pressed, press it:
if (!Mouse.isPressed(MOUSE_LEFT)) {
Mouse.press(MOUSE_LEFT);
}
} else { // else the mouse button is not pressed:
// if the mouse is pressed, release it:
if (Mouse.isPressed(MOUSE_LEFT)) {
Mouse.release(MOUSE_LEFT);
}
}
// a delay so the mouse does not move too fast:
delay(responseDelay);
}
Arduino - Keyboard Serial
此示例侦听来自串行端口的字节。收到后,电路板会向计算机发送回一个击键。发送的击键比接收到的击键高一个,因此,如果您从串行监视器中发送一个“a”,您将从连接到计算机的电路板接收到一个“b”。“1”将返回“2”,依此类推。
Warning − 当您使用 Keyboard.print() 命令时,Leonardo、Micro 或 Due 电路板将接管您计算机的键盘。为了确保在使用此功能运行草图时不会失去对计算机的控制,在调用 Keyboard.print() 之前设置一个可靠的控制系统。此草图设计为只在电路板通过串行端口接收到一个字节后才发送键盘命令。
Sketch
在计算机上打开 Arduino IDE 软件。使用 Arduino 语言进行编码将控制您的电路。单击“新建”以新建一个草图文件。
Notes − 您必须在 Arduino 库文件中包含键盘库。将键盘库文件复制并粘贴到文件内,其中名为“libraries”的文件以黄色突出显示。
Arduino Code
/*
Keyboard test
For the Arduino Leonardo, Micro or Due Reads
a byte from the serial port, sends a keystroke back.
The sent keystroke is one higher than what's received, e.g. if you send a, you get b, send
A you get B, and so forth.
The circuit:
* none
*/
#include "Keyboard.h"
void setup() {
// open the serial port:
Serial.begin(9600);
// initialize control over the keyboard:
Keyboard.begin();
}
void loop() {
// check for incoming serial data:
if (Serial.available() > 0) {
// read incoming serial data:
char inChar = Serial.read();
// Type the next ASCII value from what you received:
Keyboard.write(inChar + 1);
}
}
Arduino - Humidity Sensor
在本节,我们将学习如何将 Arduino 电路板与不同的传感器连接。我们将讨论以下传感器 −
-
Humidity sensor (DHT22)
-
Temperature sensor (LM35)
-
水检测传感器(简单水触发器)
-
PIR SENSOR
-
ULTRASONIC SENSOR
-
GPS
Humidity Sensor (DHT22)
DHT-22(也称为 AM2302)是一种数字输出、相对湿度和温度传感器。它使用电容式湿度传感器和热敏电阻来测量周围空气,并在数据引脚上发送数字信号。
在这个例子里,你将学习如何将该传感器与 Arduino UNO 一起使用。房间温度和湿度将打印到串行监视器中。
Technical Details
-
Power − 3-5V
-
Max Current − 2.5mA
-
Humidity − 0-100%,精度 2-5%
-
Temperature − 40 至 80°C,精度 ±0.5°C
Arduino Code
// Example testing sketch for various DHT humidity/temperature sensors
#include "DHT.h"
#define DHTPIN 2 // what digital pin we're connected to
// Uncomment whatever type you're using!
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors. This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(9600);
Serial.println("DHTxx test!");
dht.begin();
}
void loop() {
delay(2000); // Wait a few seconds between measurements
float h = dht.readHumidity();
// Reading temperature or humidity takes about 250 milliseconds!
float t = dht.readTemperature();
// Read temperature as Celsius (the default)
float f = dht.readTemperature(true);
// Read temperature as Fahrenheit (isFahrenheit = true)
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Compute heat index in Fahrenheit (the default)
float hif = dht.computeHeatIndex(f, h);
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
Serial.print ("Humidity: ");
Serial.print (h);
Serial.print (" %\t");
Serial.print ("Temperature: ");
Serial.print (t);
Serial.print (" *C ");
Serial.print (f);
Serial.print (" *F\t");
Serial.print ("Heat index: ");
Serial.print (hic);
Serial.print (" *C ");
Serial.print (hif);
Serial.println (" *F");
}
Arduino - Temperature Sensor
温度传感器 LM35 系列是精密集成电路温度器件,其输出电压与摄氏温度成线性比例。
LM35 器件比校准为开尔文的线性温度传感器有优势,因为用户不需要从输出中减去一个较大的恒定电压来获得便捷的摄氏度刻度。LM35 器件无需任何外部校准或调整,即可在室温下提供 ±¼°C 的典型精度,并在 −55°C 至 150°C 的全温度范围内提供 ±¾°C 的典型精度。
Technical Specifications
-
直接以摄氏度(摄氏度)为单位进行校准
-
线性 + 10-mV/°C 比例因子
-
0.5°C 确保精度(在 25°C)
-
额定值为 −55°C 至 150°C
-
Suitable for remote applications
Arduino Code
float temp;
int tempPin = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
temp = analogRead(tempPin);
// read analog volt from sensor and save to variable temp
temp = temp * 0.48828125;
// convert the analog volt to its temperature equivalent
Serial.print("TEMPERATURE = ");
Serial.print(temp); // display temperature value
Serial.print("*C");
Serial.println();
delay(1000); // update sensor reading each one second
}
Arduino - Water Detector / Sensor
水传感器砖块专为检测水而设计,可广泛用于检测降雨、水位,甚至液体泄漏。
将水传感器连接到 Arduino 是检测泄漏、溢出、洪水、降雨等的绝佳方式。它可用于检测水是否存在、水位、水量和/或不存在。虽然这可用于提醒你给植物浇水,但有更好的 Grove 传感器可用于此目的。该传感器有一系列暴露的走线,在检测到水时读数为低。
在本章中,我们将水传感器连接到 Arduino 上的数字引脚 8,并将使用非常方便的 LED 来帮助识别水传感器何时与水源接触。
Components Required
您将需要以下组件:
-
1 × Breadboard
-
1 × Arduino Uno R3
-
1 × Water Sensor
-
1 × led
-
1 × 330 欧姆电阻
Arduino Code
#define Grove_Water_Sensor 8 // Attach Water sensor to Arduino Digital Pin 8
#define LED 9 // Attach an LED to Digital Pin 9 (or use onboard LED)
void setup() {
pinMode(Grove_Water_Sensor, INPUT); // The Water Sensor is an Input
pinMode(LED, OUTPUT); // The LED is an Output
}
void loop() {
/* The water sensor will switch LOW when water is detected.
Get the Arduino to illuminate the LED and activate the buzzer
when water is detected, and switch both off when no water is present */
if( digitalRead(Grove_Water_Sensor) == LOW) {
digitalWrite(LED,HIGH);
}else {
digitalWrite(LED,LOW);
}
}
Arduino - PIR Sensor
PIR 传感器让您能够对运动进行感知。它们用于检测人是否在传感器的范围内进出。它们通常出现在家中或企业中使用的装置和小工具中。它们经常被称为 PIR、“被动红外”、“热释电”或“红外运动”传感器。
以下是 PIR 传感器的优势:
-
Small in size
-
Wide lens range
-
Easy to interface
-
Inexpensive
-
Low-power
-
Easy to use
-
Do not wear out
PIR 由热释电传感器制成,传感器是一个圆形金属罐,中间有一个矩形晶体,可以检测红外辐射水平。任何东西都会发出低水平辐射,并且东西越热,发出的辐射就越多。运动探测器中的传感器被分成两半。这是检测运动(变化)而不是平均红外水平。这两个部分连接在一起,以便它们相互抵消。如果半部分比另一半看到更多或更少的红外辐射,则输出将高或低摆动。
PIR 具有可调节设置,并且在 3 针接地/输出/电源焊盘中安装了一个接头。
对于需要检测有人离开或进入指定区域的大多数基本项目或产品而言,PIR 传感器非常好。请注意,PIR 不会告诉您附近的人数或他们与传感器的距离。镜头通常固定在一定距离的某个扫掠范围,并且有时会被家中的宠物触发。
Arduino Code
#define pirPin 2
int calibrationTime = 30;
long unsigned int lowIn;
long unsigned int pause = 5000;
boolean lockLow = true;
boolean takeLowTime;
int PIRValue = 0;
void setup() {
Serial.begin(9600);
pinMode(pirPin, INPUT);
}
void loop() {
PIRSensor();
}
void PIRSensor() {
if(digitalRead(pirPin) == HIGH) {
if(lockLow) {
PIRValue = 1;
lockLow = false;
Serial.println("Motion detected.");
delay(50);
}
takeLowTime = true;
}
if(digitalRead(pirPin) == LOW) {
if(takeLowTime){
lowIn = millis();takeLowTime = false;
}
if(!lockLow && millis() - lowIn > pause) {
PIRValue = 0;
lockLow = true;
Serial.println("Motion ended.");
delay(50);
}
}
}
Arduino - Ultrasonic Sensor
HC-SR04 超声波传感器使用声呐来确定物体的距离,就像蝙蝠一样。它可以从 2 厘米到 400 厘米或 1 英寸到 13 英尺的距离提供非接触式范围检测,具有高精度和稳定的读数,且易于使用。
虽然声音上柔软的材料(例如布料)可能难以检测,但日光或黑色材料不会影响操作。它配有超声波发射器和接收器模块。
Technical Specifications
-
电源 − +5V 直流
-
Quiescent Current − <2mA
-
Working Current − 15mA
-
Effectual Angle − <15°
-
测距 − 2 厘米到 400 厘米/1 英寸到 13 英尺
-
Resolution − 0.3 cm
-
测量角度 − 30 度
Arduino Code
const int pingPin = 7; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 6; // Echo Pin of Ultrasonic Sensor
void setup() {
Serial.begin(9600); // Starting Serial Terminal
}
void loop() {
long duration, inches, cm;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
}
long microsecondsToInches(long microseconds) {
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) {
return microseconds / 29 / 2;
}
Arduino - Connecting Switch
按钮或开关将电路中的两个开口端子连接起来。此示例在按连接到引脚8的按钮开关时打开引脚2上的LED。
Pull-down Resistor
下拉电阻用于电子逻辑电路中,以确保在外部设备断开连接或处于高阻抗时,输入到Arduino会稳定在预期的逻辑电平。因为没有任何东西连接到输入引脚,这并不意味着它是一个逻辑零。下拉电阻连接在接地和设备上相应的引脚之间。
数字电路中的下拉电阻示例如下图所示。按钮开关连接在电源电压和微控制器引脚之间。在这样的电路中,当开关闭合时,微控制器输入处于逻辑高值,但当开关打开时,下拉电阻将输入电压下拉至接地(逻辑零值),防止输入处于未定义状态。
下拉电阻的阻值必须大于逻辑电路的阻抗,否则它可能会将电压下拉得太低,并且无论开关位置如何,引脚上的输入电压仍将保持在恒定的逻辑低值。
Arduino Code
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 8; // the number of the pushbutton pin
const int ledPin = 2; // the number of the LED pin
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}
void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
} else {
// turn LED off:
digitalWrite(ledPin, LOW);
}
}
Arduino - DC Motor
在本章中,我们将演示不同类型的电机与 Arduino 板 (UNO) 的接口,并向您展示如何连接电机并从您的板上进行驱动。
有三种不同类型的电机−
-
DC motor
-
Servo motor
-
Stepper motor
直流电动机是最常见的电动机类型。直流电动机通常只有两个引线,一个正极和一个负极。如果您将这两根引线直接连接到电池上,则电机将旋转。如果您切换引线,电机将朝相反的方向旋转。
Warning − 请勿直接从 Arduino 板引脚驱动电机。这可能会损坏电路板。使用驱动器电路或 IC。
我们将本章分为三个部分−
-
只需让电机旋转
-
Control motor speed
-
控制直流电机的旋转方向
Components Required
您将需要以下组件:
-
1x Arduino UNO board
-
1x PN2222 Transistor
-
1x 小型 6V 直流电机
-
1x 1N4001 diode
-
1x 270 Ω Resistor
Precautions
在进行连接时采取以下预防措施。
-
首先,确保晶体管以正确的方式连接。如排列所示,晶体管的平面侧应面向 Arduino 板。
-
第二,根据图像中所示的排列方式,二极管的条纹端应朝向 +5V 电源线。
Spin ControlArduino Code
int motorPin = 3;
void setup() {
}
void loop() {
digitalWrite(motorPin, HIGH);
}
Motor Speed Control
以下是直流电机示意图,它连接到 Arduino 电路板。
Arduino Code
int motorPin = 9;
void setup() {
pinMode(motorPin, OUTPUT);
Serial.begin(9600);
while (! Serial);
Serial.println("Speed 0 to 255");
}
void loop() {
if (Serial.available()) {
int speed = Serial.parseInt();
if (speed >= 0 && speed <= 255) {
analogWrite(motorPin, speed);
}
}
}
Spin Direction Control
要控制直流电机旋转方向,无需交换引线,你可以使用名为 H-Bridge 的电路。H 桥是一个电子电路,可以驱动电机向两个方向转动。H 桥用于众多不同的应用。最常见的应用之一是控制机器中的电机。之所以称作 H 桥,是因为它使用的四个晶体管连接方式使示意图看起来像一个“H”。
我们将在此处使用 L298 H 桥 IC。L298 可以控制直流电机和步进电机的速度和方向,还可以同时控制两台电机。对每台电机,其额定电流为 2A。然而,在此电流下,你将需要使用散热器。
Components Required
您将需要以下组件:
-
1 × L298 桥接 IC
-
1 × DC motor
-
1 × Arduino UNO
-
1 × breadboard
-
10 × jumper wires
Procedure
以下是直流电机与 Arduino Uno 电路板接口的示意图。
上图展示了如何连接 L298 IC 以便控制两台电机。每台电机都有三个输入引脚,第 1 个输入引脚(IN1)、第 2 个输入引脚(IN2)和第 1 个使能引脚(EN1),用于电机 1;第 3 个输入引脚、第 4 个输入引脚和第 2 个使能引脚,用于电机 2。
由于我们在本示例中只控制一台电机,因此我们将 Arduino 连接到 L298 IC 的 IN1(引脚 5)、IN2(引脚 7)和 Enable1(引脚 6)。引脚 5 和 7 是数字引脚,即 ON 或 OFF 输入,而引脚 6 需要脉宽调制 (PWM) 信号才能控制电机速度。
下表显示了电机将根据 IN1 和 IN2 的数字值旋转的方向。
IN1 |
IN2 |
Motor Behavior |
BRAKE |
||
1 |
FORWARD |
|
1 |
BACKWARD |
|
1 |
1 |
BRAKE |
IC L298 的 IN1 引脚连接到 Arduino 的引脚 8,而 IN2 连接到引脚 9。这两个 Arduino 数字引脚控制电机的方向。IC 的 EN A 引脚连接到 Arduino 的 PWM 引脚 2。这将控制电机的速度。
要设置 Arduino 引脚 8 和 9 的值,我们使用了 digitalWrite() 函数,而要设置引脚 2 的值,我们必须使用 analogWrite() 函数。
Connection Steps
-
将 IC 的 5V 和接地分别连接到 5V 和 Arduino 的接地。
-
将电机连接到 IC 的引脚 2 和 3。
-
将 IC 的 IN1 连接到 Arduino 的引脚 8。
-
将 IC 的 IN2 连接到 Arduino 的引脚 9。
-
将 IC 的 EN1 连接到 Arduino 的引脚 2。
-
将 IC 的 SENS A 引脚连接到接地。
-
使用 Arduino USB 线连接 Arduino,并使用 Arduino IDE 软件将程序上传到 Arduino。
-
使用电源、电池或 USB 线为 Arduino 电路板供电。
Arduino Code
const int pwm = 2 ; //initializing pin 2 as pwm
const int in_1 = 8 ;
const int in_2 = 9 ;
//For providing logic to L298 IC to choose the direction of the DC motor
void setup() {
pinMode(pwm,OUTPUT) ; //we have to set PWM pin as output
pinMode(in_1,OUTPUT) ; //Logic pins are also set as output
pinMode(in_2,OUTPUT) ;
}
void loop() {
//For Clock wise motion , in_1 = High , in_2 = Low
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,LOW) ;
analogWrite(pwm,255) ;
/* setting pwm of the motor to 255 we can change the speed of rotation
by changing pwm input but we are only using arduino so we are using highest
value to driver the motor */
//Clockwise for 3 secs
delay(3000) ;
//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(1000) ;
//For Anti Clock-wise motion - IN_1 = LOW , IN_2 = HIGH
digitalWrite(in_1,LOW) ;
digitalWrite(in_2,HIGH) ;
delay(3000) ;
//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(1000) ;
}
Arduino - Servo Motor
伺服电机是一种具有输出轴的小型设备。通过向伺服发送编码信号,可以将该轴定位到特定的角度位置。只要输入线路上存在编码信号,伺服就会保持轴的角度位置。如果编码信号发生变化,轴的角度位置就会发生变化。在实践中,伺服用于遥控飞机,以定位升降舵和方向舵等控制面。它们还用于遥控汽车、木偶,当然还有机器人。
伺服在机器人技术中非常有用。这些电机小巧,具有内置控制电路,并且相对于其尺寸而言非常强大。标准伺服(如 Futaba S-148)具有 42 oz/inch 的转矩,对于其尺寸来说非常强劲。它还根据机械负载绘制功率。因此,负载较轻的伺服不会消耗太多能量。
伺服电机的内部结构如下图所示。可以看到控制电路、电机、一组齿轮和外壳。还可以看到连接到外部世界的三根电线。一根用于电源(+5 伏)、地线,并且白线是控制线。
Working of a Servo Motor
伺服电机具有一些控制电路和一个电位器(可变电阻器,又称电位器),连接到输出轴上。在上面的图片中,可以在电路板的右侧看到电位器。这个锅允许控制电路监控伺服电机的当前角度。
如果轴处于正确的角度,那么电机就会关闭。如果电路发现角度不正确,它会转动电机直到它达到所需的角度。伺服的输出轴能够移动大约 180 度。通常,它在 210 度范围内某处,但它会根据制造商而有所不同。通常的伺服用于控制 0 到 180 度的角运动。由于内置在主输出齿轮上的机械停止,它在机械上不能转得更远。
施加于电机的功率与它需要行进的距离成正比。因此,如果轴需要转动较大的距离,电机将以全速运转。如果它仅需转动较小的距离,电机将以较慢的速度运转。这被称为 proportional control 。
How Do You Communicate the Angle at Which the Servo Should Turn?
控制线用于传达角度。角度由施加于控制线的脉冲的持续时间决定。这被称为 Pulse Coded Modulation 。伺服器期望每隔20毫秒(0.02 秒)看到一个脉冲。脉冲的长度将决定电机转动多远。例如,1.5毫秒的脉冲将使电机转动到90度位置(通常称为中立位置)。如果脉冲短于1.5毫秒,则电机会将轴转动得更接近0度。如果脉冲长于1.5毫秒,则轴会转动得更接近180度。
Arduino Code
/* Controlling a servo position using a potentiometer (variable resistor) */
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
val = analogRead(potpin);
// reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 180);
// scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15);
}
Code to Note
伺服电机具有三个端子 - 电源、接地和信号。电源线通常为红色,应连接到Arduino上的5V引脚。接地线通常为黑色或棕色,应连接到ULN2003 IC的一个端子(10 -16)。为保护您的Arduino板免受损坏,您将需要一些驱动器IC来完成此任务。在这里,我们使用了ULN2003 IC 来驱动伺服电机。信号线通常为黄色或橙色,应连接到Arduino引脚号9。
Connecting the Potentiometer
分压器/电位分压器是一种串联电路中的电阻器,它将输出电压调整为施加的输入电压的特定比率。以下是电路图 −
V_{out} = (V_{in} \times R_{2})/ (R_{1} + R_{2})
Vout是输出电位,它取决于串联中的施加输入电压(Vin)和电阻器(R1和R2)。这意味着流过R1的电流也将流过R2而不被分流。在上面的等式中,随着R2值的改变,Vout会根据输入电压Vin相应地调整。
通常,电位器是一种电位分压器,它可以根据可变电阻的值来调整电路的输出电压,该值使用旋钮进行调整。它有三个引脚:GND、信号和+5V,如下所示 −
Arduino - Stepper Motor
步进电机是一种无刷同步电机,它将一个完全旋转划分为若干步。与直流无刷电机在施加固定直流电压后持续旋转不同,步进电机以离散的步进角度旋转。
因此,步进电机的每转步数为 12、24、72、144、180 和 200,从而导致每个步的步进角度为 30、15、5、2.5、2 和 1.8 度。可以控制带有或不带有反馈的步进电机。
想象一下遥控飞机上的一个电机。该电机在一个或另一个方向上非常快地旋转。你可以通过提供给电机的功率来改变速度,但你无法告诉螺旋桨在特定位置停止。
现在想象一下打印机。打印机内部有很多运动部件,包括电机。其中一个这样的电机充当送纸器,它旋转辊筒,在纸上打印墨水时移动纸张。该电机需要能够将纸张移动精确的距离,以便能够打印下一行文本或图像的下一行。
连接到螺纹杆的另一个电机来回移动打印头。同样,该螺纹杆需要移动一个精确的量,然后才能依次打印一个字母。这就是步进电机派上用场的地方。
How a Stepper Motor Works?
普通直流电机只能朝一个方向旋转,而步进电机可以以精确的增量旋转。
步进电机可以根据需要旋转精确的角度(或步数)。这使你可以完全控制电机,从而让你可以将它移动到精确的位置并保持该位置。它通过在非常短的时间内为电机内部的线圈供电来实现此目的。缺点是,你必须始终向电机供电,才能使其保持在你所需的位置。
现在,你所需要知道的是:要移动一个步进电机,就是要告诉它向一个方向或另一个方向移动一个确定的步数,并告诉它以什么速度沿该方向移动。步进电机有多种类型。这里描述的方法可用于推断出如何使用教程中未提到的其他电机和驱动器。但是,我们始终建议你查阅你所用的型号的电机和驱动器的说明书和指南。
Arduino Code
/* Stepper Motor Control */
#include <Stepper.h>
const int stepsPerRevolution = 90;
// change this to fit the number of steps per revolution
// for your motor
// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
void setup() {
// set the speed at 60 rpm:
myStepper.setSpeed(5);
// initialize the serial port:
Serial.begin(9600);
}
void loop() {
// step one revolution in one direction:
Serial.println("clockwise");
myStepper.step(stepsPerRevolution);
delay(500);
// step one revolution in the other direction:
Serial.println("counterclockwise");
myStepper.step(-stepsPerRevolution);
delay(500);
}
Arduino - Tone Library
在本教程中,我们将使用 Arduino 音调库。它只不过是一个 Arduino 库,可在任何 Arduino 引脚上生成指定频率(和 50% 占空比)的方波。可以有选择地指定持续时间,否则该波会持续到调用 stop() 函数为止。可以将引脚连接到压电蜂鸣器或扬声器来播放音调。
Warning − 不要将引脚直接连接到任何音频输入。电压远高于标准线路电平电压,并且可能损坏声卡输入等。您可以使用分压器来降低电压。
Sketch
在计算机上打开 Arduino IDE 软件。使用 Arduino 语言进行编码将控制您的电路。单击“新建”以新建一个草图文件。
为制作 pitches.h 文件,请单击串口监视器图标正下方的按钮并选择“新建选项卡”,或使用 Ctrl+Shift+N。
然后粘贴以下代码:
/*************************************************
* Public Constants
*************************************************/
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
将上述代码另存为 pitches.h
Arduino Code
#include "pitches.h"
// notes in the melody:
int melody[] = {
NOTE_C4, NOTE_G3,NOTE_G3, NOTE_GS3, NOTE_G3,0, NOTE_B3, NOTE_C4};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 8, 8, 4,4,4,4,4
};
void setup() {
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 8; thisNote++) {
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
tone(8, melody[thisNote],noteDuration);
//pause for the note's duration plus 30 ms:
delay(noteDuration +30);
}
}
void loop() {
// no need to repeat the melody.
}
Arduino - Wireless Communication
无线收发器模块在 315 Mhz 下工作。它们可以轻松地装入面包板,并且与微控制器配合良好,可以创建非常简单的无线数据链路。在一对收发器上,模块只工作于单向通信数据,但是,你需要两对(不同频率)作为收发器对。
Note - 这些模块是很随意的,并且会收到相当多的噪声。收发器都在常见频率下工作,并且没有 ID。
Receiver Module Specifications
-
Product Model − MX-05V
-
Operating voltage − DC5V
-
Quiescent Current − 4mA
-
Receiving frequency − 315Mhz
-
Receiver sensitivity − -105DB
-
尺寸 - 30 * 14 * 7mm
Transmitter Module Specifications
-
Product Model − MX-FS-03V
-
发射距离 - 20-200 米(不同电压,不同结果)
-
Operating voltage − 3.5-12V
-
尺寸 - 19 * 19mm
-
Operating mode − AM
-
传输速率 - 4KB/S
-
Transmitting power − 10mW
-
Transmitting frequency − 315Mhz
-
外部天线 - 25cm 普通多芯或单芯线路
-
从左→右的引脚排列 - (数据;VCC;GND)
Sketch
在计算机上打开 Arduino IDE 软件。使用 Arduino 语言进行编码将控制您的电路。单击“新建”以新建一个草图文件。
Note - 你必须在你的 Arduino 库文件中包含键盘库。复制 VirtualWire.lib 文件,并像下面给出的屏幕截图中高亮显示的那样将其粘贴到库文件夹中。
Arduino Code for Transmitter
//simple Tx on pin D12
#include <VirtualWire.h>
char *controller;
void setup() {
pinMode(13,OUTPUT);
vw_set_ptt_inverted(true);
vw_set_tx_pin(12);
vw_setup(4000);// speed of data transfer Kbps
}
void loop() {
controller="1" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
delay(2000);
controller="0" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,0);
delay(2000);
}
Arduino Code for Receiver
//simple Rx on pin D12
#include <VirtualWire.h>
void setup() {
vw_set_ptt_inverted(true); // Required for DR3100
vw_set_rx_pin(12);
vw_setup(4000); // Bits per sec
pinMode(5, OUTPUT);
vw_rx_start(); // Start the receiver PLL running
}
void loop() {
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking {
if(buf[0]=='1') {
digitalWrite(5,1);
}
if(buf[0]=='0') {
digitalWrite(5,0);
}
}
}
Arduino - Network Communication
Texas Instruments 的 CC3000 WiFi 模块是一款小型银色封装,它最终为你的 Arduino 项目带来了易于使用、价格低廉的 WiFi 功能。
它使用 SPI 进行通信(而非 UART!),因此你可以按照你想要的速度将数据推送出去。它有一个带 IRQ 引脚的适当中断系统,因此你可以拥有异步连接。它支持 802.11b/g、开放的/WEP/WPA/WPA2 安全性、TKIP 和 AES。一个带有“BSD 套接字”界面的内置 TCP/IP 协议栈,在客户端和服务器模式下都支持 TCP 和 UDP。
Components Required
您将需要以下组件:
-
1 × Arduino Uno
-
1 × Adafruit CC3000 扩展板
-
1 × 5V relay
-
1 × Rectifier diode
-
1 × LED
-
1 × 220 欧姆电阻
-
1 × 面包板和一些跳线
对于此项目,你只需要普通的 Arduino IDE,Adafruit 的 CC3000 库,和 CC3000 MDNS 库。我们还将使用 aREST 库,以便通过 WiFi 向继电器发送命令。
Procedure
按照电路图进行操作,并按照下面给出的图片所示进行连接。
此项目的硬件配置非常简单。
-
将 CC3000 板的 IRQ 引脚连接到 Arduino 板的 3 号引脚。
-
将 VBAT 连接到 5 号引脚,将 CS 连接到 10 号引脚。
-
将 SPI 引脚连接到 Arduino 板:将 MOSI、MISO 和 CLK 分别连接到 11 号、12 号和 13 号引脚。
-
Vin 连接到 Arduino 5V,GND 连接到 GND。
现在,让我们连接继电器。
将继电器放在面包板上之后,您就可以开始识别继电器上的两个重要部分:继电器控制线圈部分和 LED 连接开关部分。
-
首先,将 Arduino 板的 8 号引脚连接到一个线圈引脚。
-
将另一个引脚连接到 Arduino 板的接地。
您还必须将整流二极管(阳极连接到接地引脚)放在线圈引脚上,以便继电器切换时保护电路。
-
将 Arduino 板的 +5V 连接到继电器开关的公共引脚。
-
最后,将开关的另一引脚(通常是继电器断开时未连接的引脚)连接到与 220 欧姆电阻串联的 LED,并将 LED 的另一边连接到 Arduino 板的接地。
Testing Individual Components
您可以使用以下草图对继电器进行测试 −
const int relay_pin = 8; // Relay pin
void setup() {
Serial.begin(9600);
pinMode(relay_pin,OUTPUT);
}
void loop() {
// Activate relay
digitalWrite(relay_pin, HIGH);
// Wait for 1 second
delay(1000);
// Deactivate relay
digitalWrite(relay_pin, LOW);
// Wait for 1 second
delay(1000);
}
Adding WiFi Connectivity
现在,让我们使用 CC3000 WiFi 芯片无线控制继电器。此项目的软件基于 TCP 协议。但是,对于此项目,Arduino 板将运行一个小 web 服务器,以便我们可以“侦听”来自计算机的命令。我们首先处理 Arduino 草图,然后我们了解如何编写服务器端代码并创建漂亮界面。
首先,Arduino 草图。这里的目标是连接到您的 WiFi 网络,创建一个 web 服务器,检查是否有传入的 TCP 连接,然后相应地更改继电器状态。
Important Parts of the Code
#include <Adafruit_CC3000.h>
#include <SPI.h>
#include <CC3000_MDNS.h>
#include <Ethernet.h>
#include <aREST.h>
您需要在代码中定义具体配置的内容,即 WiFi 名称和密码,以及 TCP 通信端口(我们在此处使用了 80)。
// WiFi network (change with your settings!)
#define WLAN_SSID "yourNetwork" // cannot be longer than 32 characters!
#define WLAN_PASS "yourPassword"
#define WLAN_SECURITY WLAN_SEC_WPA2 // This can be WLAN_SEC_UNSEC, WLAN_SEC_WEP,
// WLAN_SEC_WPA or WLAN_SEC_WPA2
// The port to listen for incoming TCP connections
#define LISTEN_PORT 80
然后我们可以创建 CC3000 实例、服务器和 aREST 实例 −
// Server instance
Adafruit_CC3000_Server restServer(LISTEN_PORT); // DNS responder instance
MDNSResponder mdns; // Create aREST instance
aREST rest = aREST();
现在,在草图的设置(setup())部分,我们可以将 CC3000 芯片连接到网络 −
cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
计算机如何知道在哪里发送数据?一种方法是运行一次草图,然后获取 CC3000 板的 IP 地址,然后再次修改服务器代码。但是,我们可以做得更好,CC3000 MDNS 库就在此处发挥作用。我们将使用此库为我们的 CC3000 板分配一个固定名称,以便我们可以直接将此名称写入服务器代码中。
这是通过以下代码完成的 −
if (!mdns.begin("arduino", cc3000)) {
while(1);
}
我们还需要侦听传入连接。
restServer.begin();
接下来,我们将编写草图的 loop() 函数,该函数将持续执行。我们首先必须更新 mDNS 服务器。
mdns.update();
运行在 Arduino 板上的服务器将等待传入连接并处理请求。
Adafruit_CC3000_ClientRef client = restServer.available();
rest.handle(client);
现在,通过 WiFi 测试项目非常容易。确保已用你自己的 WiFi 名称和密码更新了草图,并将草图上传到 Arduino 板。打开 Arduino IDE 串行监视器,并查看电路板的 IP 地址。
让我们假设它类似于 192.168.1.103。
然后,只需转到你最喜欢的网络浏览器并输入以下内容即可:
192.168.1.103/digital/8/1
您应该看到您的继电器自动打开。
Building the Relay Interface
现在,我们将对项目的界面进行编码。这里将有两个部分:包含界面的 HTML 文件和客户端 JavaScript 文件,用于处理界面上的点击。这里的界面基于 aREST.js 项目,该项目旨在从您的计算机轻松控制 WiFi 设备。
让我们首先看看名为 interface.html 的 HTML 文件。第一部分包括导入界面所需的所有库:
<head>
<meta charset = utf-8 />
<title> Relay Control </title>
<link rel = "stylesheet" type = "text/css"
href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" type = "text/css" href = "style.css">
<script type = "text/javascript"
src = "https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type = "text/javascript"
src = "https://cdn.rawgit.com/Foliotek/AjaxQ/master/ajaxq.js"></script>
<script type = "text/javascript"
src = "https://cdn.rawgit.com/marcoschwartz/aREST.js/master/aREST.js"></script>
<script type = "text/javascript"
src = "script.js"></script>
</head>
然后,我们在界面中定义两个按钮,一个用于打开继电器,另一个用于再次将其关闭。
<div class = 'container'>
<h1>Relay Control</h1>
<div class = 'row'>
<div class = "col-md-1">Relay</div>
<div class = "col-md-2">
<button id = 'on' class = 'btn btn-block btn-success'>On</button>
</div>
<div class = "col-md-2">
<button id = 'off' class = 'btn btn-block btn-danger'>On</button>
</div>
</div>
</div>
现在,我们还需要一个客户端 JavaScript 文件来处理按钮上的点击。我们还将创建一个设备,将其链接到 Arduino 设备的 mDNS 名称。如果您在 Arduino 代码中更改了该名称,则还需要在此处修改它。
// Create device
var device = new Device("arduino.local");
// Button
$('#on').click(function() {
device.digitalWrite(8, 1);
});
$('#off').click(function() {
device.digitalWrite(8, 0);
});
该项目的完整代码可以在 GitHub 存储库中找到。转到界面文件夹,然后只需用你最喜欢的浏览器打开 HTML 文件。您应该在浏览器中看到类似的内容:
尝试单击网络界面上的某个按钮;它应该几乎立即更改继电器状态。
如果你成功了,恭喜!您刚刚构建了一个 Wi-Fi 控制的电灯开关。当然,通过该项目,您可以控制的远不止灯。只需确保继电器支持要控制设备所需的功率即可。