Arduino零基础入门

Arduino零基础入门
arduino学习笔记1 - 什么是arduino?
要了解arduino就先要了解什么是单片机,arduino平台的基础就是AVR指令集的单片机。

1、什么是单片机?它与个人计算机有什么不同?
一台能够工作的计算机要有这样几个部份构成:中央处理单元CPU(进行运算、控制)、随机存储器RAM(数据存储)、存储器ROM(程序存储)、输入/输出设备I/O(串行口、并行输出口等)。在个人计算机(PC)上这些部份被分成若干块芯片,安装在一个被称之为主板的印刷线路板上。而在单片机中,这些部份全部被做到一块集成电路芯片中了,所以就称为单片(单芯片)机,而且有一些单片机中除了上述部份外,还集成了其它部份如模拟量/数字量转换(A/D)和数字量/模拟量转换(D/A)等。

2、单片机有什么用?
实际工作中并不是任何需要计算机的场合都要求计算机有很高的性能,一个控制电冰箱温度的计算机难道要用酷睿处理器吗?应用的关键是看是否够用,是否有很好的性能价格比。如果一台冰箱都需要用酷睿处理起来进行温度控制,那价格就是天价了。

单片机通常用于工业生产的控制、生活中与程序和控制有关(如:电子琴、冰箱、智能空调等)的场合。

下图就是一个Atmega328P-PU单片机,基于AVR指令集的8位处理器,频率20MHz,存储器空间32KB。

什么是Arduino?

Arduino是一个能够用来感应和控制现实物理世界的一套工具。 它由一个基于单片机并且开放源码的硬件平台,和一套为Arduino板编写程序 的开发环境组成。
Arduino可以用来开发交互产品,比如它可以读取大量的开关和传感器信号,并且可以控制各式各样的电灯、电机和其他物理设备。Arduino项目可以是单独的,也可以在运行时和你电脑中运行的程序(例如:Flash,Processing,MaxMSP)进行通讯。Arduino板你可以选择自己去手动组装或是购买已经组装好的;Arduino开源的IDE可以免费下载得到。

Arduino的编程语言就像似在对一个类似于物理的计算平台进行相应的连线,它基于处理多媒体的编程环境。

为什么要使用Arduino?

有很多的单片机和单片机平台都适合用做交互式系统的设计。例如:Parallax Basic Stamp, Netmedia’s BX-24,Phidgets,MIT’s Handyboard 和其它等等提供类似功能的。 所有这些工具,你都不需要去关心单片机编程繁琐的细节,提供给你的是一套容易使用的工具包。 Arduino同样也简化了同单片机工作的流程,但同其它系统相比Arduino在很多地方更具有优越性,特别适合老师,学生和一些业余爱好者们使用:

便宜 - 和其它平台相比,Arduino板算是相当便宜了。最便宜的Arduino版本可以自己动手制作,即使是组装好的成品,其价格也不会超过200元。
跨平台 - Arduino软件可以运行在Windows,Macintosh OSX,和Linux操作系统。大部分其它的单片机系统都只能运行在Windows上。
简易的编程环境 - 初学者很容易就能学会使用Arduino编程环境,同时它又能为高级用户提供足够多的高级应用。对于老师们来说,一般都能很方便的使用Processing 编程环境,所以如果学生学习过使用Processing 编程环境的话,那他们在使用Arduino开发环境的时候就会觉得很相似很熟悉。
软件开源并可扩展 - Arduino软件是开源的,对于有经验的程序员可以对其进行扩展。Arduino编程语言可以通过C++库进行扩展,如果有人想去了解技术上的细节,可以跳过Arduino语言而直接使用AVR C 编程语言(因为Arduino语言实际上是基于AVR C的)。类似的,如果你需要的话,你也可以直接往你的Arduino程序中添加AVR-C 代码。
硬件开源并可扩展 - Arduino板基于 Atmel 的ATMEGA8 和ATMEGA168/328 单片机。Arduino基于Creative Commons 许可协议,所以有经验的电路设计师能够根据需求设计自己的模块,可以对其扩展或改进。甚至是对于一些相对没有什么经验的用户,也可以通过制作试验板来理解Arduino是怎么工作的,省钱又省事。

Arduino基于AVR平台,对AVR库进行了二次编译封装,把端口都打包好了,寄存器啦、地址指针之类的基本不用管。大大降低了软件开发难度,适宜非专业爱好者使用。优点和缺点并存,因为是二次编译封装,代码不如直接使用AVR代码编写精练,代码执行效率与代码体积都弱于AVR直接编译。

性能:
Digital I/O 数字输入/输出端口0—13。
Analog I/O 模拟输入/输出端口0-5。
支持ICSP下载,支持TX/RX。
输入电压:USB接口供电或者5V-12V外部电源供电。
输出电压:支持3.3V级5V DC输出。
处理器:使用Atmel Atmega168 328处理器,因其支持者众多,已有公司开发出来32位的MCU平台支持arduino。

目前arduino的控制板最新的为Arduino Uno,如下图:

国内使用比较多的为Arduino Duemilanove 2009,主要原因是Uno的usb控制芯片封装方式改变,制造成本上升,其他变化不大,性价比还是Arduino Duemilanove 2009比较好。

因其开源特性,生产arduino控制板的厂商众多,同样的Duemilanove 2009就有很多种颜色。

对于一些对电路板大小要求比较严格的地方,arduino团队提供了arduino Nano,此板体积做的非常小。如下图:

arduino板子上基本端口如图描述,对几个比较特殊的端口下面详细说明下:

VIN端口:VIN是input voltage的缩写,表示有外部电源时的输入端口。

AREF:Reference voltage for the analog inputs(模拟输入的基准电压)。使用analogReference()命令调用。

ICSP:也有称为ISP(In System Programmer),就是一种线上即时烧录,目前比较新的芯片都支持这种烧录模式,包括大家常听说的8051系列的芯片,也都慢慢采用这种简便的烧录方式。我们都知道传统的烧录方式,都是将被烧录的芯片,从线路板上拔起,有的焊死在线路板上的芯片,还得先把芯片焊接下来才能烧录。为了解决这种问题,发明了ICSP线上即时烧录方式。只需要准备一条R232线(连接烧录器),以及一条连接烧录器与烧录芯片针脚的连接线就可以。电源的+5V,GND,两条负责传输烧录信息的针脚,再加上一个烧录电压针脚,这样就可以烧录了。

arduino学习笔记2
通过Arduino编译器查看串口数据
最简单的例子:

void setup()
{
Serial.begin(9600); // 打开串口,设置波特率为9600 bps
}
void loop()
{
int val;
val=analogRead(5);//传感器接到模拟口5,数值根据自己的需要可变
Serial.println(val,DEC);//从串口发送字符串并换行
delay(100);
}

如果电路安装正确,按照示例代码运行、上传,然后点击编译器的Serial Monitor按钮,就可以看到从代码定义的输入口(这儿是模拟口5)获取的数据了。
arduino学习笔记3 arduino语言
Arduino语言是建立在C/C++基础上的,其实也就是基础的C语言,Arduino语言只不过把AVR单片机(微控制器)相关的一些参数设置都函数化,不用我们去了解他的底层,让我们不了解AVR单片机(微控制器)的朋友也能轻松上手。
在与Arduino DIYER接触的这段时间里,发现有些朋友对Arduino语言还是比较难入手,那么这里我就简单的注释一下Arduino语言(本人也是半罐子水,有错的地方还请各位指正)。
/基础C语言/
关键字:
if
if…else
for
switch case
while
do… while
break
continue
return
goto
语法符号:
;
{}
//
/* */
运算符:

/
%

!=
<

<=

=
&&
||
!
++

+=
-=
=
/=
数据类型:
boolean 布尔类型
char
byte 字节类型
int
unsigned int
long
unsigned long
float
double
string
array
void
数据类型转换:
char()
byte()
int()
long()
float()
常量:
HIGH | LOW 表示数字IO口的电平,HIGH 表示高电平(1),LOW 表示低电平(0)。
INPUT | OUTPUT 表示数字IO口的方向,INPUT 表示输入(高阻态),OUTPUT 表示输出(AVR能提供5V电压 40mA电流)。
true | false true 表示真(1),false表示假(0)。
/
/
以上为基础c语言的关键字和符号,有c语言基础的都应该了解其含义,这里也不作过多的解释。
/Arduino 语言/
结构
void setup() 初始化变量,管脚模式,调用库函数等
void loop() 连续执行函数内的语句
功能
数字 I/O
pinMode(pin, mode) 数字IO口输入输出模式定义函数,pin表示为0~13, mode表示为INPUT或OUTPUT。
digitalWrite(pin, value) 数字IO口输出电平定义函数,pin表示为0~13,value表示为HIGH或LOW。比如定义HIGH可以驱动LED。
int digitalRead(pin) 数字IO口读输入电平函数,pin表示为0~13,value表示为HIGH或LOW。比如可以读数字传感器。
模拟 I/O
int analogRead(pin) 模拟IO口读函数,pin表示为0~5(Arduino Diecimila为0~5,Arduino nano为0~7)。比如可以读模拟传感器(10位AD,0~5V表示为0~1023)。
analogWrite(pin, value) - PWM 数字IO口PWM输出函数,Arduino数字IO口标注了PWM的IO口可使用该函数,pin表示3, 5, 6, 9, 10, 11,value表示为0~255。比如可用于电机PWM调速或音乐播放。
扩展 I/O
shiftOut(dataPin, clockPin, bitOrder, value) SPI外部IO扩展函数,通常使用带SPI接口的74HC595做8个IO扩展,dataPin为数据口,clockPin为时钟口,bitOrder为数据传输方向(MSBFIRST高位在前,LSBFIRST低位在前),value表示所要传送的数据(0~255),另外还需要一个IO口做74HC595的使能控制。
unsigned long pulseIn(pin, value) 脉冲长度记录函数,返回时间参数(us),pin表示为0~13,value为HIGH或LOW。比如value为HIGH,那么当pin输入为高电平时,开始计时,当pin输入为低电平时,停止计时,然后返回该时间。
时间函数
unsigned long millis() 返回时间函数(单位ms),该函数是指,当程序运行就开始计时并返回记录的参数,该参数溢出大概需要50天时间。
delay(ms) 延时函数(单位ms)。
delayMicroseconds(us) 延时函数(单位us)。
数学函数
min(x, y) 求最小值
max(x, y) 求最大值
abs(x) 计算绝对值
constrain(x, a, b) 约束函数,下限a,上限b,x必须在ab之间才能返回。
map(value, fromLow, fromHigh, toLow, toHigh) 约束函数,value必须在fromLow与toLow之间和fromHigh与toHigh之间。
pow(base, exponent) 开方函数,base的exponent次方。
sq(x) 平方
sqrt(x) 开根号
三角函数
sin(rad)
cos(rad)
tan(rad)
随机数函数
randomSeed(seed) 随机数端口定义函数,seed表示读模拟口analogRead(pin)函数 。
long random(max) 随机数函数,返回数据大于等于0,小于max。
long random(min, max) 随机数函数,返回数据大于等于min,小于max。
外部中断函数
attachInterrupt(interrupt, , mode) 外部中断只能用到数字IO口2和3,interrupt表示中断口初始0或1,表示一个功能函数,mode:LOW低电平中断,CHANGE有变化就中断,RISING上升沿中断,FALLING 下降沿中断。
detachInterrupt(interrupt) 中断开关,interrupt=1 开,interrupt=0 关。
中断使能函数
interrupts() 使能中断
noInterrupts() 禁止中断
串口收发函数
Serial.begin(speed) 串口定义波特率函数,speed表示波特率,如9600,19200等。
int Serial.available() 判断缓冲器状态。
int Serial.read() 读串口并返回收到参数。
Serial.flush() 清空缓冲器。
Serial.print(data) 串口输出数据。
Serial.println(data) 串口输出数据并带回车符。
/
/
/Arduino语言库文件
/
官方库文件
EEPROM - EEPROM读写程序库
Ethernet - 以太网控制器程序库
LiquidCrystal - LCD控制程序库
Servo - 舵机控制程序库
SoftwareSerial - 任何数字IO口模拟串口程序库
Stepper - 步进电机控制程序库
Wire - TWI/I2C总线程序库
Matrix - LED矩阵控制程序库
Sprite - LED矩阵图象处理控制程序库
非官方库文件
DateTime - a library for keeping track of the current date and time in software.
Debounce - for reading noisy digital inputs (e.g. from buttons)
Firmata - for communicating with applications on the computer using a standard serial protocol.
GLCD - graphics routines for LCD based on the KS0108 or equivalent chipset.
LCD - control LCDs (using 8 data lines)
LCD 4 Bit - control LCDs (using 4 data lines)
LedControl - for controlling LED matrices or seven-segment displays with a MAX7221 or MAX7219.
LedControl - an alternative to the Matrix library for driving multiple LEDs with Maxim chips.
Messenger - for processing text-based messages from the computer
Metro - help you time actions at regular intervals
MsTimer2 - uses the timer 2 interrupt to trigger an action every N milliseconds.
OneWire - control devices (from Dallas Semiconductor) that use the One Wire protocol.
PS2Keyboard - read characters from a PS2 keyboard.
Servo - provides software support for Servo motors on any pins.
Servotimer1 - provides hardware support for Servo motors on pins 9 and 10
Simple Message System - send messages between Arduino and the computer
SSerial2Mobile - send text messages or emails using a cell phone (via AT commands over software serial)
TextString - handle strings
TLC5940 - 16 channel 12 bit PWM controller.
X10 - Sending X10 signals over AC power lines
/
**********************************/
arduino学习笔记4 数据类型
有多种类型的变量,如下所述
boolean 布尔
char 字符
byte 字节
int 整数
unsigned int 无符号整数
long 长整数
unsigned long 无符号长整数
float 浮点
double 双字节浮点
string 字符串
array 数组

arduino学习笔记5 Arduuino复合运算符
+= , -= , *= , /=
Description描述
Perform a mathematical operation on a variable with another constant or variable. The += (et al) operators are just a convenient shorthand for the expanded syntax, listed below.
对一个变量和另一个参数或变量完成一个数学运算。+=(以及其他)可以缩短语法长度。
Syntax语法
x += y; // equivalent to the expression x = x + y; // 等价于 x = x + y;
x -= y; // equivalent to the expression x = x - y; // 等价于 x = x - y;
x *= y; // equivalent to the expression x = x * y; // 等价于 x = x * y;
x /= y; // equivalent to the expression x = x / y; // 等价于 x = x / y;
Parameters参数
x: any variable type
x:任何变量类型
y: any variable type or constant
y:任何变量类型或常数
Examples范例
x = 2;
x += 4; // x now contains 6 // x现在为6
x -= 3; // x now contains 3 // x现在为3
x *= 10; // x now contains 30 // x现在为30
x /= 2; // x now contains 15 // x现在为15

Syntax语法
x++; // increment x by one and returns the old value of x
// 将x的值加1并返回原来的x的值。 ++x; // increment x by one and returns the new value of x // 将x的值加1并返回现在的x的值。
x-- ; // decrement x by one and returns the old value of x // 将x的值减1并返回原来的x的值。
–x ; // decrement x by one and returns the new value of x // 将x的值减1并返回现在的x的值。
Parameters参数
x: an integer or long (possibly unsigned)
x:一个整数或长整数(可以无符号)
Returns返回
The original or newly incremented / decremented value of the variable.
返回变量原始值或增加/消耗后的新值。
Examples范例
x = 2;
y = ++x; // x now contains 3, y contains 3 // x现在为3,y为3
y = x–; // x contains 2 again, y still contains 3 // x现在仍然为2,y将为3
arduino学习笔记6 Arduino基础
在学语言之间,还要做的一个功课就是要明白程序的构架,这个也同样简单,大体可分为几个部分。

1、声明变量及接口名称(int val;int ledPin=13;)。

2、setup()——函数在程序开始时使用,可以初始化变量、接口模式、启用库等(例如:pinMode(ledPin,OUTUPT);)。

3、loop()——在setup()函数之后,即初始化之后,loop() 让你的程序循环地被执行。使用它来运转Arduino。

接下来就开始学习一下几个基本函数。

1、pinMode(接口名称,OUTPUT或INPUT)将——接口定义为输入或输出接口,用在setup()函数里。

2、digitalWrite(接口名称, HIGH或LOW)——将数字接口值至高或低。

3、digitalRead(接口名称)——读出数字接口的值。

4、analogWrite(接口名称, 数值)——给一个接口写入模拟值(PWM波)。对于 ATmega168芯片的Arduino(包括Mini或BT),该函数可以工作于 3, 5, 6, 9, 10和 11号接口。老的 ATmega8芯片的USB和 serial Arduino仅仅支持 9, 10和11号接口。

5、analogRead(接口名称)——从指定的模拟接口读取值,Arduino对该模拟值进行10-bit的数字转换,这个方法将输入的0-5电压值转换为 0到1023间的整数值。

6、delay()——延时一段时间,delay(1000)为一秒。

7、Serial.begin(波特率)——设置串行每秒传输数据的速率(波特率)。在同计算机通讯时,使用下面这些值:300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600或 115200。你也可以在任何时候使用其它的值,比如,与0号或1号插口通信就要求特殊的波特率。用在setup()函数里

8、Serial.read()——读取持续输入的数据。

9、Serial.print(数据,数据的进制)——从串行端口输出数据。Serial.print(数据)默认为十进制等于Serial.print(数据,DEC)。

10、Serial.println(数据,数据的进制)——从串行端口输出数据,跟随一个回车和一个换行符。这个函数所取得的值与 Serial.print()一样。

以上几个函数是常用基本函数,还有很多以后会慢慢学习
arduino学习笔记7函数
输入输出函数
Arduino 内含了一些处理输出与输入的切换功能,相信已经从书中程式范例略知一二。

pinMode(pin, mode)

将数位脚位(digital pin)指定为输入或输出。

范例 :

pinMode(7,INPUT); // 将脚位 7 设定为输入模式

digitalWrite(pin, value)

将数位脚位指定为开或关。脚位必须先透过pinMode明示为输入或输出模式digitalWrite才能生效。

范例 :

digitalWrite(8,HIGH); //将脚位 8设定输出高电位

int digitalRead(pin)

将输入脚位的值读出,当感测到脚位处于高电位时时回传HIGH,否则回传LOW。

范例 :

val = digitalRead(7); // 读出脚位 7 的值并指定给 val

int analogRead(pin)

读出类比脚位的电压并回传一个 0到1023 的数值表示相对应的0到5的电压值。

范例 :

val = analogRead(0); //读出类比脚位 0 的值并指定给 val变数

analogWrite(pin, value)

改变PWM脚位的输出电压值,脚位通常会在3、5、6、9、10与11。Value变数范围0-255,例如:输出电压2.5伏特(V),该值大约是128。

范例 :

analogWrite(9,128); // 输出电压约2.5伏特(V)

unsigned long pulseIn(pin, value)

设定读取脚位状态的持续时间,例如使用红外线、加速度感测器测得某一项数值时,在时间单位内不会改变状态。

范例 :

time = pulsein(7,HIGH); // 设定脚位7的状态在时间单位内保持为HIGH

shiftOut(dataPin, clockPin, bitOrder, value)

把资料传给用来延伸数位输出的暂存器,函式使用一个脚位表示资料、一个脚位表示时脉。bitOrder用来表示位元间移动的方式(LSBFIRST最低有效位元或是MSBFIRST最高有效位元),最后value会以byte形式输出。此函式通常使用在延伸数位的输出。

范例 :

shiftOut(dataPin, clockPin, LSBFIRST, 255);

时间函数
控制与计算晶片执行期间的时间

unsigned long millis()

回传晶片开始执行到目前的毫秒

范例:

duration = millis()-lastTime; // 表示自"lastTime"至当下的时间

delay(ms)

暂停晶片执行多少毫秒

范例:

delay(500); //暂停半秒(500毫秒)

delay Microseconds(us)

暂停晶片执行多少微秒

范例:

delayMicroseconds(1000); //暂停1豪秒

数学函式
三角函数以及基本的数学运算

min(x, y)

回传两数之间较小者

范例:

val = min(10,20); // 回传10

max(x, y)

回传两数之间较大者

范例:

val = max(10,20); // 回传20

abs(x)

回传该数的绝对值,可以将负数转正数。

范例:

val = abs(-5); // 回传5

constrain(x, a, b)

判断x变数位于a与b之间的状态。x若小于a回传a;介于a与b之间回传x本身;大于b回传b

范例:

val = constrain(analogRead(0), 0, 255); // 忽略大于255的数

map(value, fromLow, fromHigh, toLow, toHigh)

将value变数依照fromLow与fromHigh范围,对等转换至toLow与toHigh范围。时常使用于读取类比讯号,转换至程式所需要的范围值。

例如:

val = map(analogRead(0),0,1023,100, 200); // 将analog0 所读取到的讯号对等转换至100 – 200之间的数值。

double pow(base, exponent)

回传一个数(base)的指数(exponent)值。

范例:

double x = pow(y, 32); // 设定x为y的32次方

double sqrt(x)

回传double型态的取平方根值。

范例:

double a = sqrt(1138); // 回传1138平方根的近似值 33.73425674438

double sin(rad)

回传角度(radians)的三角函数sine值。

范例:

double sine = sin(2); // 近似值 0.90929737091

double cos(rad)

回传角度(radians)的三角函数cosine值。

范例:

double cosine = cos(2); //近似值-0.41614685058

double tan(rad)

回传角度(radians)的三角函数tangent值。

范例:

double tangent = tan(2); //近似值-2.18503975868

乱数函式
产生乱数

randomSeed(seed)

事实上在Arduino里的乱数是可以被预知的。所以如果需要一个真正的乱数,可以呼叫此函式重新设定产生乱数种子。你可以使用乱数当作乱数的种子,以确保数字以随机的方式出现,通常会使用类比输入当作乱数种子,藉此可以产生与环境有关的乱数(例如:无线电波、宇宙雷射线、电话和萤光灯发出的电磁波等)。

范例:

randomSeed(analogRead(5)); // 使用类比输入当作乱数种子

long random(max)

long random(min, max)

回传指定区间的乱数,型态为long。如果没有指定最小值,预设为0。

范例:

long randnum = random(0, 100); // 回传0 – 99 之间的数字

long randnum = random(11); // 回传 0 -10之间的数字

序列通讯
你可以在第五章看见一些使用序列埠与电脑交换讯息的范例,以下是函式解释。

Serial.begin(speed)

你可以指定Arduino从电脑交换讯息的速率,通常我们使用9600 bps。当然也可以使用其他的速度,但是通常不会超过115,200 bps(每秒位元组)。

范例:

Serial.begin(9600);

Serial.print(data)

Serial.print(data, encoding)

经序列埠传送资料,提供编码方式的选项。如果没有指定,预设以一般文字传送。

范例:

Serial.print(75); // 列印出 “75”

Serial.print(75, DEC); //列印出 “75”

Serial.print(75, HEX); // “4B” (75 的十六进位)

Serial.print(75, OCT); // “113” (75 in的八进位)

Serial.print(75, BIN); // “1001011” (75的二进位)

Serial.print(75, BYTE); // “K” (以byte进行传送,显示以ASCII编码方式)

Serial.println(data)

Serial.println(data, encoding)

与Serial.print()相同,但会在资料尾端加上换行字元( )。意思如同你在键盘上打了一些资料后按下Enter。

范例:

Serial.println(75); //列印出"75 "

Serial.println(75, DEC); //列印出"75 "

Serial.println(75, HEX); // "4B "

Serial.println(75, OCT); // "113 "

Serial.println(75, BIN); // "1001011 "

Serial.println(75, BYTE); // "K "

int Serial.available()

回传有多少位元组(bytes)的资料尚未被read()函式读取,如果回传值是0代表所有序列埠上资料都已经被read()函式读取。

范例:

int count = Serial.available();

int Serial.read()

读取1byte的序列资料

范例:

int data = Serial.read();

Serial.flush()

有时候因为资料速度太快,超过程式处理资料的速度,你可以使用此函式清除缓冲区内的资料。经过此函式可以确保缓冲区(buffer)内的资料都是最新的。

范例:

Serial.flush();
arduino学习笔记8数字输入
在数字电路中开关(switch)是一种基本的输入形式,它的作用是保持电路的连接或者断开。Arduino从数字I/O管脚上只能读出高电平(5V)或者低电平(0V),因此我们首先面临到的一个问题就是如何将开关的开/断状态转变成Arduino能够读取的高/低电平。解决的办法是通过上 /下拉电阻,按照电路的不同通常又可以分为正逻辑(Positive Logic)和负逻辑(Inverted Logic)两种。
在正逻辑电路中,开关一端接电源,另一端则通过一个10K的下拉电阻接地,输入信号从开关和电阻间引出。当开关断开的时候,输入信号被电阻“拉”向地,形成低电平(0V);当开关接通的时候,输入信号直接与电源相连,形成高电平。对于经常用到的按压式开关来讲,就是按下为高,抬起为低。

在负逻辑电路中,开关一端接地,另一端则通过一个10K的上拉电阻接电源,输入信号同样也是从开关和电阻间引出。当开关断开时,输入信号被电阻“拉”向电源,形成高电平(5V);当开关接通的时候,输入信号直接与地相连,形成低电平。对于经常用到的按压式开关来讲,就是按下为低,抬起为高。

为了验证Arduino数字I/O的输入功能,我们可以将开关接在Arduino的任意一个数字I/O管脚上(13除外),并通过读取它的接通或者断开状态,来控制其它数字I/O管脚的高低。本实验采用的原理图如下所示,其中开关接在数字I/O的7号管脚上,被控的发光二极管接在数字I/O的13号 管脚上:

相应的代码为:
int ledPin = 13;
int switchPin = 7;
int value = 0;

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(switchPin, INPUT);
}

void loop() {
value = digitalRead(switchPin);
if (HIGH == value) {
// turn LED off
digitalWrite(ledPin, LOW);
} else {
// turn LED on
digitalWrite(ledPin, HIGH);
}
}
由于采用的是负逻辑电路,开关按下时用digitalRead()函数读取到的值为LOW,此时再用digitalWrite()函数将发光二极管所在的管脚置为高,点亮发光二极管。同理,当开关抬起时,发光二极管将被熄灭,这样我们就实现了用开关来控制发光二极管的功能。
arduino学习笔记9 Arduino的数字输出
Arduino的数字I/O被分成两个部分,其中每个部分都包含有6个可用的I/O管脚,即管脚2 到管脚7和管脚8到管脚13。除了管脚13上接了一个1K的电阻之外,其他各个管脚都直接连接到ATmega上。我们可以利用一个6位的数字跑马灯,来对 Arduino数字I/O的输出功能进行验证。
电路中在每个I/O管脚上加的那个1K电阻被称为限流电阻,由于发光二极管在电路中没有等效电阻值,使用限流电阻可以使元件上通过的电流不至于过大,能够起到保护的作用。
该工程对应的代码为:
int BASE = 2;
int NUM = 6;
int index = 0;

void setup()
{
for (int i = BASE; i < BASE + NUM; i ++) {
pinMode(i, OUTPUT);
}
}

void loop()
{
for (int i = BASE; i < BASE + NUM; i ++) {
digitalWrite(i, LOW);
}
digitalWrite(BASE + index, HIGH);
index = (index + 1) % NUM;
delay(100);
}
下载并运行该工程,连接在Arduino数字I/O管脚2到管脚7上的发光二极管会依次点亮0.1秒,然后再熄灭:

这个实验可以用来验证数字I/O输出的正确性。Arduino上一共有十二个数字I/O管脚,我们可以用同样的办法验证其他六个管脚的正确性,而这只需要对上述工程的第一行做相应的修改就可以了:
int BASE = 8;
arduino学习笔记10 Arduino的串口输入
串行通信是在实现在PC机与微控制器进行交互的最简单的办法。之前的PC机上一般都配有标准的 RS-232或者RS-422接口来实现串行通信,但现在这种情况已经发生了一些改变,大家更倾向于使用USB这样一种更快速但同时也更加复杂的方式来实现串行通信。尽管在有些计算机上现在已经找不到RS-232或者RS-422接口了,但我们仍可以通过USB/串口或者PCMCIA/串口这样的转换器, 在这些设备上得到传统的串口。
通过串口连接的Arduino在交互式设计中能够为PC机提供一种全新的交互方式,比如用PC机控制一些之前看来非常复杂的事情,像声音和视频等。很多场合中都要求Arduino能够通过串口接收来自于PC机的命令,并完成相应的功能,这可以通过Arduino语言中提供的 Serial.read()函数来实现。
在这一实验中我们同样不需要任何额外的电路,而只需要用串口线将Arduino和PC机连起来就可以了,相应的Arduino工程代码为:
int ledPin = 13;
int val;

void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}

void loop() {
val = Serial.read();
if (-1 != val) {
if (‘H’ == val) {
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
}
}
}

把工程下载到Arduino模块中之后,在Arduino集成开发环境中打开串口监视器并将波特率设置为9600,然后向Arduino模块发送字符H,如下图所示:

该工程运行起来之后会不断调用Serial.read()函数从串口获得数据。Arduino语言提供的这个函数是不阻塞的,也就是说不论串口上是否真的有数据到达,该函数都会立即返回。Serial.read()函数每次只读取一个字节的数据,当串口上有数据到达的时候,该函数的返回值为到达的数 据中第一个字符的ASCII码;当串口上没有数据到达的时候,该函数的返回值则为-1。
Arduino语言的参考手册中没 有对Serial.read()函数做过多的说明,我的一个疑问是如果PC机一次发送的数据太多,Arduino是否提供相应的串口缓存功能来保证数据不会丢失?Arduino语言中提供的另外一个函数Serial.available()或许能够帮助我们用实验来进行验证:
int ledPin = 13;
int val;

void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}

void loop() {
val = Serial.read();
if (-1 != val) {
if (‘H’ == val) {
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);

Serial.print("Available: ");
Serial.println(Serial.available(), DEC);
}
}
}

函数Serial.available()的功能是返回串口缓冲区中当前剩余的字符个数,按照Arduino提供的该函数的说明,串口缓冲区中最多能缓冲128个字节。我们可以一次给Arduino模块发送多个字符,来验证这一功能:

在这一实验中,每当Arduino成功收到一个字符H,连接在数字I/O端口管脚13上的发光二极管就会闪烁一次:

arduino学习笔记11 Arduino的串口输出
在许多实际应用场合中我们会要求在Arduino和其它设备之间实现相互通信,而最常见通常也是最简单的办法就是使用串行通信。在串行通信中,两个设备之间一个接一个地来回发送数字脉冲,它们之间必须严格遵循相应的协议以保证通信的正确性。
在PC机上上最常见的串行通信协议是RS-232串行协议,而在各种微控制器(单片机)上采用的则是TTL串行协议。由于这两者的电平有很大的不同,因此在实现PC机和微控制器的通信时,必须进行相应的转换。完成RS-232电平和TTL电平之间的转换一般采用专用芯片,如MAX232等,但在 Arduino上是用相应的电平转换电路来完成的。
根据Arduino的原理图我们不难看出,ATmega的RX和TX引脚一方面直接接到了数字I/O端口的0号和1号管脚,另一方面又通过电平转换电路接到了串口的母头上。因此,当我们需要用Arduino与PC机通信时,可以用串口线将两者连接起来;当我们需要用 Arduino与微控制器(如另一块Arduino)通信时,则可以用数字I/O端口的0号和1号管脚。
串行通信的难点在于参数的设置,如波特率、数据位、停止位等,在Arduino语言可以使用Serial.begin()函数来简化这一任务。为了实现数据的发送,Arduino则提供了Serial.print()和Serial.println()两个函数,它们的区别在于后者会在请求发送的数 据后面加上换行符,以提高输出结果的可读性。
在这一实验中没有用到额外的电路, 我们只需要用串口线将Arduino和PC机连起来就可以了,相应的代码为:
void setup() {
Serial.begin(9600);
}

void loop() {
Serial.println(“Hello World!”);
delay(1000);
}
在将工程下载到Arduino模块中之后,在Arduino集成开发环境的工具栏中单击“Serial Monitor”控制,打开串口监视器:

接着将波特率设置为9600,即保持与工程中的设置相一致:

如果一切正常,此时我们就可以在Arduino集成开发环境的Console窗口中看到串口上输出的数据了:
为了检查串口上是否有数据发送,一个比较简单的办法是在数字I/O端口的1号管脚(TX)和5V电源之间接一个发光二极管,如下面的原理图所示:

这样一旦Arduino在通过串口向PC机发送数据时,相应的发光二极管就会闪烁,实际应用中这是一个非常方便的调试手段;-)

arduino学习笔记17蜂鸣器实验
本次实验所用的为下图所示的这种小型无源蜂鸣器

通过上网查询参数,得到其工作电压为5V,和arduino控制板数字端口输出电压一致,所以不需要接电阻。可直接接上使用。

先简单介绍一下这种小型蜂鸣器。

小型蜂鸣器因其体积小(直径只有6mm)、重量轻、价格低、结构牢靠,而广泛地应用在各种需要发声的电器设备、电子制作和单片机等电路中。这种蜂鸣器分有源蜂鸣器与无源蜂鸣器

下图为有源蜂鸣器

下图为无源蜂鸣器

从外观上看,两种蜂鸣器好像一样,如果将蜂鸣器引脚朝上时,可以看到,有绿色电路板的是一种无源蜂鸣器,没有电路板而使用黑胶密封的是一种有源蜂鸣器。从外观上并不能绝对的区分出有源与无源,最可靠的做法除了查看产品的参数手册以外,还有就是使用万用表测试蜂鸣器电阻,只有8Ω或者16Ω的是无源蜂鸣器,电阻在几百欧以上的是有源蜂鸣器。

有源蜂鸣器直接接上额定电源(新的蜂鸣器在标签上都有注明)就可以连续发声,而无源蜂鸣器则和电磁扬声器一样,需要接在音频输出电路中才能发声。

简单介绍完蜂鸣器以后先看一下硬件连接示意图

把下面的代码上传到arduino控制板上,看看实验结果。
int buzzer=7;//设置控制蜂鸣器的数字IO脚
void setup()
{
pinMode(buzzer,OUTPUT);//设置数字IO脚模式,OUTPUT为输出
}
void loop()
{
unsigned char i,j;//定义变量
while(1)
10. {
11. for(i=0;i<80;i++)//输出一个频率的声音
12. {
13. digitalWrite(buzzer,HIGH);//发声音
14. delay(1);//延时1ms
15. digitalWrite(buzzer,LOW);//不发声音
16. delay(1);//延时ms
17. }
18. for(i=0;i<100;i++)//输出另一个频率的声音
19. {
20. digitalWrite(buzzer,HIGH);//发声音
21. delay(2);//延时2ms
22. digitalWrite(buzzer,LOW);//不发声音
23. delay(2);//延时2ms
24. }
25. }
26. }

arduino学习笔记19按键实验
按键是一种常用的控制电器元件,常用来接通或断开电路,从而达到控制电机或者其他设备运行的开关。按键的外观多种多样,本次实验使用的是这种微型按键,6mm的,如下图。
此种按键有4个脚,从背面看是这样子的。
在按键没有按下去的时候1,2号脚相连,3,4号脚相连。按键按下去的时候,1,2,3,4号脚就全部接通。

本次实验使用按键来控制led的亮或者灭。
一般情况是直接把按键开关串联在led的电路中来开关,这种应用情况比较单一。
这次实验通过间接的方法来控制,按键接通后判断按键电路中的输出电压,如果电压大于4.88V,就使给LED电路输出高电平,反之就输出低电平。使用逻辑判断的方法来控制LED亮或者灭,此种控制方法应用范围较广。

本次连接方法如下图。按键开关两段一端连接5V接口,一端连接模拟5号口。LED长针脚串联220Ω电阻连接数字7号口,短针脚连接GND。

把下面的代码上传到arduino控制板上,看看效果。
int key=7;//设置LED的数字IO脚
void setup()
{
pinMode(key,OUTPUT);//设置数字IO引脚为输出模式
}
void loop()
{
int i;//定义变量
while(1)
{
i=analogRead(5);//读取模拟5口电压值
if(i>1000)//如果电压值大于1000(即4.88V)
digitalWrite(key,HIGH);//设置第七引脚为高电平,点亮led灯
else
digitalWrite(key,LOW);//设置第七引脚为低电平,熄灭led灯
}
}

本次实验使用到analogRead()这个新命令。
analogRead()作用是读取模拟口的数值。默认是把0-5V的输入电压分成1024份,每一份大约为0.049V,其数值在0-1023之间。
在本次程序代码中的读取数值如果大于512则给LED输出高电平, 所对应的电压也就为大于2.5V。
analogRead()命令输入的范围与分辨率可以使用analogReference()命令进行改动。

刚开始本实验选用的判断标准是512,也就是2.5V。但是有网友按照教程的方法进行试验发现有问题,有时不需要按按钮灯就会自己亮。根据多次试验与分析后,确定其为各种干扰所致。比如感应电流等等不少都是大于2.5V的,所以为了提高准确度,只能提高判断的电压,本次实验就是提高到1000(4.88V)。人体自身也带电,早中晚还个不一样。下面的实验就是把模拟5号口判断标准定位512,用手去触摸模拟5号口导线就可以点亮LED。

arduino学习笔记20 PWM控制LED实验 PWM讲解
本次实验通过PWM来控制一盏LED灯,让它慢慢变亮再慢慢变暗,如此循环。下面是接线图:

/*
本次实验演示如何通过analogWrite()命令使连接9号端口的LED灯亮度逐渐变化
*/
int brightness = 0; //定义整数型变量brightness与其初始值,此变量用来表示LED的亮度。
int fadeAmount = 5; //定义整数型变量fadeAmount,此变量用来做亮度变化的增减量。

void setup() {

pinMode(9, OUTPUT);// 设置9号口为输出端口:
}

void loop() {

analogWrite(9, brightness);//把brightness的值写入9号端口

brightness = brightness + fadeAmount;//改变brightness值,使亮度在下一次循环发生改变

if (brightness == 0 || brightness == 255) {
fadeAmount = -fadeAmount ; //在亮度最高与最低时进行翻转
}

delay(30); //延时30毫秒
}

analogWrite()

其作用是给端口写入一个模拟值(PWM波)。可以用来控制LED灯的亮度变化,或者以不同的速度驱动马达。当执行analogWrite()命令后,端口会输出一个稳定的占空比的方波。除非有下一个命令来改变它。PWM信号的频率大约为490Hz.

在使用ATmega168与ATmega328的arduino控制板上,其工作在3,5,6,9,10,11端口。Arduino Mega控制板,可以工作于2-13号端口。在更古老的基于ATmega8的arduino控制板上,analogWrite()命令只能工作于9,10,11号端口。在使用analogWrite()命令前,可以不使用pinMode()命令把端口定义为输出端口,当然如果定义了更好,这样利于程序语言规范。

语法
analogWrite(pin, value)

参数
pin:写入的端口
value:占空比:在0-255之间。

注释与已知问题
当PWM输出与5,6号端口的时候,会产生比预期更高的占空比。原因是PWM输出所使用的内部时钟,millis()与delay()两函数也在使用。所以要注意使用5,6号端口时,空占比要设置的稍微低一些,或者会产生5,6号端口无法输出完全关闭的信号。

PWM(Pulse-width modulation)脉宽调制

PWM是使用数字手段来控制模拟输出的一种手段。使用数字控制产生占空比不同的方波(一个不停在开与关之间切换的信号)来控制模拟输出。额~~这个说的太专业了,还是说的通俗点。
以本次实验来看,端口的输入电压只有两个0V与5V。如我我想要3V的输出电压怎么办。。。有同学说串联电阻,对滴,这个方法是正确滴。但是如果我想1V,3V,3.5V等等之间来回变动怎么办呢?不可能不停地切换电阻吧。这种情况下。。。就需要使用PWM了。他是怎么控制的呢,对于arduino的数字端口电压输出只有LOW与HIGH两个开关,对应的就是0V与5V的电压输出,咱本把LOW定义为0,HIGH定义为1.一秒内让arduino输出500个0或者1的信号。如果这500个全部为1,那就是完整的5V,如果全部为0,那就是0V。如果010101010101这样输出,刚好一半一半,输出端口就感觉是2.5V的电压输出了。这个和咱们放映电影是一个道理,咱们所看的电影并不是完全连续的,它其实是每秒输出25张图片,在这种情况下人的肉眼是分辨不出来的,看上去就是连续的了。PWM也是同样的道理,如果想要不同的电压,就控制0与1的输出比例控制就ok~当然。。。这和真实的连续输出还是有差别的,单位时间内输出的0,1信号越多,控制的就越精确。

在下图中,绿线之间代表一个周期,其值也是PWM频率的倒数。换句话说,如果arduino PWM的频率是500Hz,那么两绿线之间的周期就是2毫秒。 analogWrite() 命令中可以操控的范围为0-255, analogWrite(255)表示100%占空比(常开), analogWrite(127)占空比大约为50%(一半的时间)。

传统方法实现PWM

除了使用analogWrite()命令实现PWM,还可以通过传统方法来控制电平的开关时间来设置。
请看如下代码
void setup()
{
pinMode(13, OUTPUT);//设定13号端口为输出
}

void loop()
{
digitalWrite(13, HIGH);
delayMicroseconds(100); // 大约10%占空比的1KHz方波
digitalWrite(13, LOW);
delayMicroseconds(900);
}
这种方法的的优点是他可以使用任意数字端口做输出端口。而且可以自己随意设定占空比与频率。一个主要的缺点是任何中断都会影响时钟,这样就会导致很大的抖动,除非你禁用中断。第二个却就是CPU在处理输出的时候,就无法做其他事情了。

上面的代码用到了一个新的命令

delayMicroseconds()

其作用是产生一个延时,计量单位是微秒,1000微秒=1毫秒。目前delayMicroseconds()最大值为16383。如果值大于1000,推荐使用delay() 命令。

arduino学习笔记22光控LED实验
光敏电阻又称光导管,常用的制作材料为硫化镉,另外还有硒、硫化铝、硫化铅和硫化铋等材料。这些制作材料具有在特定波长的光照下,其阻值迅速减小的特性。这是由于光照产生的载流子都参与导电,在外加电场的作用下漂移运动,从而使光敏电阻的阻值迅速下降。

光敏电阻的工作原理基于内光电效应。在半导体光敏材料的两端装上电极引线,将其封装在带有透明窗的管壳里就构成光敏电阻,为了增加灵敏度,两电极常做成梳状。在有光照射时,射入的光强,电阻减小,射入的光弱,电阻增大。

下图就是一个光敏电阻

本次实验设计的效果是,当光照正常的时候led灯是灭的,当周围变暗时led灯变亮。

因为光敏电阻受不同光照影响变化很大,所以本次实验的参数是在60W三基色节能灯照射下实验(无日光照射),同样亮度的日光下光敏电阻的阻值会比日光灯下低不少,估计和不同光的波段有关系。不同环境下实验使用的参数不同,大家根据原理进行调整。

实验前先测量一下当前环境下光敏电阻的亮阻值与暗阻值

下图是测出来的LED亮阻值,为9.1KΩ

下图是测出来的LED暗阻值,为32.4KΩ

硬件连接图如下

根据测出来的亮阻9.1KΩ,暗阻32.4欧姆。选定分压电阻为10KΩ。因为当有遮挡物的后,阻值会变大。假设亮阻为10KΩ(对于光敏电阻来说,与测量出来的9.1KΩ差别不大,计算起来更加方便了),分压阻值为10K欧姆。模拟2号口所测量的触发电压为10KΩ分压电阻的,在5V电源供电下,亮与暗转换的触发电压为5×10÷(10+10)=2.5V。当光线越暗,光敏电阻的阻值也就越大,分压两端电压也就越小。所以触发条件就为≤2.5V。(不同光照条件下触发电压不同,请根据实验环境进行调整。)

程序代码如下
int photocellPin = 2; //定义变量photocellsh=2,为电压读取端口。
int ledPin = 12; //定义变量ledPin=12,为led电平输出端口
int val = 0; //定义val变量的起始值

void setup() {
pinMode(ledPin, OUTPUT); //使ledPin为输出模式
}

void loop() {
val = analogRead(photocellPin); //从传感器读取值
if(val<=512){ //512=2.5V,想让传感器敏感一些的时候,把数值调高,想让传感器迟钝的时候把数值调低。
digitalWrite(ledPin, HIGH); //当val小于512(2.5V)的时候,led亮。
}
else{
digitalWrite(ledPin, LOW);
}
}
arduino学习笔记27 DHT11数字温湿度传感器的使用
概述
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术
和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC 测
温元件,并与一个高性能8 位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优
点。每个DHT11 传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP 内存中,传感器内
部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的
功耗,信号传输距离可达20 米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。
DHT11 数字温湿度传感器模块为3 针PH2.0 封装。连接方便。

性能描述
1. 供电电压:3-5.5V
2. 供电电流:最大2.5Ma
3. 温度范围:0-50℃ 误差±2℃
4. 湿度范围:20-90%RH 误差±5%RH
5. 响应时间: 1/e(63%) 6-30s
6. 测量分辨率分别为 8bit(温度)、8bit(湿度)
7. 采样周期间隔不得低于1 秒钟
8. 模块尺寸:30x20mm

传感器的时序
DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和
整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式:
8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,
送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。

模块的使用
将 DHT11 模块接到Arduino 传感器扩展板的模拟口0
代码如下:
#define DHT11_PIN 0 // ADC0 接到模拟口0
byte read_dht11_dat()
{
byte i = 0;
byte result=0;
for(i=0; i< 8; i++){
while(!(PINC & _BV(DHT11_PIN))); // wait for 50us
delayMicroseconds(30);
if(PINC & _BV(DHT11_PIN))
result |=(1<<(7-i));
while((PINC & _BV(DHT11_PIN))); // wait ‘1’ finish
}
return result;
}
void setup()
{
DDRC |= _BV(DHT11_PIN);
PORTC |= _BV(DHT11_PIN);
Serial.begin(19200);
Serial.println(“Ready”);
}
void loop()
{
byte dht11_dat[5];
byte dht11_in;
byte i;
// start condition
// 1. pull-down i/o pin from 18ms
PORTC &= ~_BV(DHT11_PIN);
delay(18);
PORTC |= _BV(DHT11_PIN);
delayMicroseconds(40);
DDRC &= ~_BV(DHT11_PIN);
delayMicroseconds(40);
dht11_in= PINC & _BV(DHT11_PIN);
if(dht11_in){
Serial.println(“dht11 start condition 1 not met”);
return;
}
delayMicroseconds(80);
dht11_in = PINC & _BV(DHT11_PIN);
if(!dht11_in){
Serial.println(“dht11 start condition 2 not met”);
return;
}
delayMicroseconds(80);
// now ready for data reception
for (i=0; i<5; i++)
dht11_dat[i] = read_dht11_dat();
DDRC |= _BV(DHT11_PIN);
PORTC |= _BV(DHT11_PIN);
byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
// check check_sum
if(dht11_dat[4]!= dht11_check_sum)
{
Serial.println(“DHT11 checksum error”);
}
Serial.print(“Current humdity = “);
Serial.print(dht11_dat[0], DEC);
Serial.print(”.”);
Serial.print(dht11_dat[1], DEC);
Serial.print("% ");
Serial.print(“temperature = “);
Serial.print(dht11_dat[2], DEC);
Serial.print(”.”);
Serial.print(dht11_dat[3], DEC);
Serial.println("C ");
delay(2000);
}
编译代码后下载到Arduino 中,打开串口助手即可看见实际测量的温度与湿度。

来自:亿方互动科技 仅用于学习。

你可能感兴趣的:(Arduino)