当前位置:首页 >> 机械/仪表 >>

Arduino教程(智能小车)


Arduino 一: 数字输出
Arduino, 教程 11 Comments ?

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;
SEP

01

Arduino 二: 数字输入
Arduino, 教程 3 Comments ?

在数字电路中开关(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 号管脚上:

Arduino 三: 模拟输入
Arduino, 教程 5 Comments ?

Arduino 的优势在于对数字信号的识别和处理,但我们所生活的真实世界并不是数字(digital)化的,简单到只要用 0 和 1 就能够表示 所有的现象。例如温度这一我们已经司空见惯的概念,它只能在一个范围之内连续变化,而不可能发生像从 0 到 1 这样的瞬时跳变,

类似这样的物理量被人们称为是模拟(analog)的。Arduino 是无法理解这些模拟量的,它们必须在经过模数转换后变成数字量后,才 能被 Arduino 进一步处理。 像温度这样的数据必须先被转换成微处理器能够处理的形式(比如电压),才能被 Arduino 处理,这一任务通常由各类传感器(sensor) 来完成的。例如,电路中的温度传感器能够将温度值转换成 0V 到 5V 间的某个电压,比如 0.3V、3.27V、4.99V 等。由于传感器表达 的是模拟信号,它不会像数字信号那样只有简单的高电平和低电平,而有可能是在这两者之间的任何一个数值。至于到底有多少可能 的值则取决于模数转换的精度,精度越高能够得到的值就会越多。 Arduino 所采用的 ATmega8 微处理器一其有 6 个模数转换器 (ADC, Analog to Digital Converter) 每一个模数转换器的精度都是 10bit, , 也就是说能够读取 1024(2^10 = 1024)个状态。在 Arduino 的每一个模拟输入管脚上,电压的变化范畴是从 0V 到 5V,因此 Arduino 能够感知到的最小电压变化是 4.8 毫伏(5/1024 = 4.8mV)。 电位计(potentiometer)是一种最简单的模拟输入设备,它实际上就是一个可变电阻箱,通过控制滑块所在的位置我们可以得到不同 的电压值,而输入信号正是从滑块所在的位置接入到电路中的。

这一实验我们将通过改变电位计的值来控制发光二极管闪烁的频率。电位计上一 共有三个管脚,分别连接到 Arduino 的电源、地和模拟输入的 5 号管脚上,发光二极管则连接到数字 I/O 的 13 号管脚上,原理图如下 所示:

相应的代码为:

int ledPin = 13; int potPin = 5; int value = 0; void setup() { pinMode(ledPin, OUTPUT); }

void loop() { value = analogRead(potPin); digitalWrite(ledPin, HIGH); delay(value); digitalWrite(ledPin, LOW); delay(value); }
在 Arduino 中,对模拟输入端口不需要调用 pinMode()函数将其指定为输入或者是输出模式,这点同数字 I/O 端口是有所不同的。 通过旋转电位计的轴,我们能改变电位计中间那根连线同地之间的电阻量,从而也就能改变从模拟输入的 5 号管脚上所读入的模拟量 的值。当电位计完全旋转到头时,输入到模拟输入管脚上的电压为 0V,用 analogRead()函数读出的值为 0;当电位计完全旋转到另一 头时,输入到模拟 I/O 管脚上的电压为 5V,此时用 analogRead()函数读出的值为 1023;当电位计旋转到中间的某个位置时,输入到 模拟输入管脚上的电压是 0V 到 5V 之间的某个值,而用 analogRead()函数读出的则是位于 0 到 1023 之间的某个对应值。读出的模拟 量在我们的实验中被用来确定发光二极管点亮和熄灭的时间,以反映模拟量的变化。

电位计运用的是分压原理, 通过旋转到不同的位置来得到不同的电压值。 从这 种意义上讲, 它能够被用来对当前旋转到的位置进行度量, 因此可以被用在转 向轮等旋转装置中。 今天发现 PCB 板上另外一个错误,就是将模拟输入对应管脚号标反了,试了 好久才意识到是这一问题。加上之前电源设计上的两个小缺陷, 一共有三个 需要修改的地方。如果有机会再做 PCB 板的话,试着将这些问题解决一下:-)

相应的代码为:

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 四: 模拟输出
Arduino, 教程 2 Comments ?

就像模拟输入一样,在现实的物理世界中我们经常需要输出除了 0 和 1 之外的其他数值。例如,除了想用微控制器找开或者关闭电灯 之外,我们还会想控制灯光的亮度,这时就需要用到模拟输出。由于 Arduino 的微控制器只能产生高电压(5V)或者低电压(0V), 而不能产生变化的电压,因此必须采用脉宽度调制技术(PWM,Pulse Width Modulation)来模仿模拟电压。 PWM 是一种开关式稳压电源应用,它是借助微处理器的数字输出来对模拟电路进行控制的一种非常用效的技术,广泛应用在从测量、 通信到功率控制与变换的许多领域中。简而言之,PWM 是一种对模拟信号电平进行数字编码的方法,它通过对半导体开关器件的导通 和关断进行控制,使输出端得到一系列幅值相等但宽度不相等的脉冲,而这些脉冲能够被用来代替正弦波或其它所需要的波形。 在 Arduino 数字 I/O 管脚 9、10 和 11 上,我们可以通过 analogWrite()函数来产生模拟输出。该函数有两个参数,其中第一个参数是 要产生模拟信号的引脚(9、10 或者 11);第二个参数是用于产生模拟信号的脉冲宽度,取值范围是 0 到 255。脉冲宽度的值取 0 可 以产生 0V 的模拟电压, 255 则可以产生 5V 的模拟电压。 取 不难看出, 脉冲宽度的取值变化 1, 产生的模拟电压将变化 0.0196V (5/255 = 0.0196)。

本实验中我们将用模拟输出来调暗发光二极管(LED),由于正常情况下 LED 对电压的变化非常敏感,因此当脉冲宽度变化时人眼会 感觉到 LED 实际上是在不断地熄灭和点亮,而不是逐渐变暗。解决这一问题可以采用滤波电路,它能使有用频率信号通过而同时抑制 (或大大衰减)无用频率信号。实验中我们采用的是低通滤波器,它的原理非常简单,只需要一个电阻和一个电容,能够很好地过滤 掉电路中超过某一频率的信号。 此处给出的电路并不能校平所有脉冲, 它之所以被称为“低通滤波”是因为它只允许 频率低于某个限度的脉冲通过,对于高于这个限度的脉冲则被平衡为伪模拟电压, 滤波的频率范围由电阻器和电容器的比值决定。 实验中采用的电路原 理如下: 相应的代码为:

int potPin = 0; int ledPin = 11; byte bright_table[] = { 60, 70, 80, 30, 30, 30, 40, 50,

90, 100,110, 120, 130, 140, 150, 160,

170, 180, 190, 200, 210, 220, 230, 240, 250, 250, 240, 230, 220, 210, 200, 190, 180, 170, 160, 150, 140, 130, 120, 110, 100, 40, 30, 30, 30 }; int MAX = 50; int count = 0; int val = 0; void setup() { pinMode(ledPin, OUTPUT); } void loop() { analogWrite(ledPin, bright_table[count]); count ++; if (count > MAX) { count = 0; } val = analogRead(potPin); val = val /4; delay(val); } 90, 80, 70, 60, 50,

该工程调用 analogWrite()函数在数字 I/O 端口的 11 号管脚上模仿模拟输出,每产生一次输出后都设置了相应的延时,而延时的长度 由模拟输入端口 0 号管脚上的电位器来决定。通过调整电位器的位置,我们可以观察到发光二极管逐渐变亮后再逐渐变暗的效果。

Arduino 五: 串口输出
Arduino, 教程 No Comments ?

在许多实际应用场合中我们会要求在 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 六: 串口输入
Arduino, 教程 1 Comment ?

串行通信是在实现在 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.availab le(), DEC); } } }
函数 Serial.available()的功能是返回串口缓 冲区中当前剩余的字符个数,按照 Arduino 提供的该函数的说明,串口缓冲区中最多能 缓冲 128 个字节。我们可以一次给 Arduino 模块发送多个字符,来验证这一功能: 在这一实验中,每当 Arduino 成功收到一个 字符 H,连接在数字 I/O 端口管脚 13 上的发 光二极管就会闪烁一次:

Arduino 七: XBee 无线通信
Arduino, 教程 4 Comments ?

借助 XBee 扩展板我们可以很方便地将 XBee 模块连接到 Arduino 上,XBee 模块的工作原理也非常简单,它与 Arduino 之间其实就是 通过串行接口(即 Tx 和 Rx 引脚)进行通信。对于简单的点对点通信来讲,只需要通过串行接口向 XBee 模块写数据就可以实现数据 的发送;当 XBee 模块通过无线通道接收到数据时,通过读串行接口可以很方便地获得这些数据。 原理弄清楚之后,其实我们可以将 XBee 模块看成是 Arduino 的串口,通过相应的串口操作函数来实现数据的接收和发送。首先请按照 Arduino XBee 模块使用手册中的说明配置好你的两个 XBee 模块,然后 将相应的跳线连接到 XBEE 一端: 这里我们使用一个最简单的工程来进行相应的实验:

int ledPin = 13; int val; void setup() { pinMode(ledPin, OUTPUT); Serial.begin(9600); } void loop() { // send data to another XBee module Serial.print('A'); delay(1000); // receive data from another XBee module val = Serial.read(); if (-1 != val) { if ('A' == val) { digitalWrite(ledPin, HIGH);

delay(500); digitalWrite(ledPin, LOW); delay(500); } } }
该工程首先通过 Serial.print()函数向 XBee 模块发送一个字母 A,该字母会被 XBee 模块通过无线网络发送出去,并被另外一个 XBee 模块接收到。紧接着再通过 Serial.read()函数从 XBee 模块读取从无线网络接收到的数据,如果是字母 A 的话,则点亮相应的发光二极 管。 将该工程编译并分别下载到两个 Arduino 模块中,注意下载的时候不要连接 XBee 扩展板,这是因为 XBee 模块会占用串口,从而导致 下载无法正确完成。 下载完成后将 XBee 扩展板连接到 Arduino 上,并分别给两者上电。这两个 Arduino 模块都会向对方发送字母 A,然后从对方接收字母 A,并对点亮数字 I/O 管脚 13 上连接的发光二极管。你可以试着将两个模块放在房间里的不同位置,来对 XBee 模块的传输性能进行 测试。

Arduino 电机驱动扩展板
Arduino, 基本电路, 教程 11 Comments ?

除了使用传感器对各种外部物理量进行感知之外,能够对实际物体的运动进行相应的控制也是互动设计中不可或缺的一部分。在所有 这类动力装置中,电机显然是最常见、最基本、最便宜的解决方案了,常用的电机的种类有很多种,如直流电机,步进电机,伺服电 机,减速电机等,并且每一种电机的控制方法都有所不同。 如果你是一个电子高手,控制普通的直流电机用几个三极管就行了,否则话像 L293 这样的芯片将是一个更好的选择。L293 芯片的核 心是两个 H-桥,所有的 H-桥芯片都具有如下一些引脚:

? ? ? ? ?

逻辑输入 逻辑电压 电源电压 电源输出 地

其中逻辑电压引脚采用与微控制器相同的电压和电流,电源电压采用与运行电机所需要的电压和电流。逻辑输入引脚连接到用来向 H桥输出控制信号的微控制器上的引脚,而电源输出引脚则连接到电机上。

这么专业的术语翻译到 Arduino 上可以这样来理解。首先,我们需要两套电源,一套用来给 Arduino 供电,一套用来给电机供电。其 次,我们需要用到 Arduino 的数字 I/O 管脚来控制 L293,并把电机接到 L293 上接受控制。说到这里,正好解释一下 Arduino 的供电 系统,通常 Arduino 有三种供电方式:

? ? ?

USB 供电 电池供电 变压器供电

后两者在 Arduino 上统称为外部供电。供电方式的选择是通过 Arduino 上的电源选择跳线来实现的,当把跳线接到“USB”一端时,采用 的是 USB 供电方式,这时整个 Arduino 及其附属电路上的电源都由 PC 的 USB 接口提供,此时电流一般比较小,只能驱动功率比较小 的电路,如 LED 等。当把跳线接到“EXT”一端时,采用的是外部供电方式,这时一般能够驱动比较大的设备,如电机等。Arduino 内部 一套电源转换电路,可以用来将外部供电时的电压(6-12V)转换成内部所需要的 5V 电压,使用 L293 控制电机正是需要这两套电源。 下面这个就是基于 L293D 芯片的 Arduino 专用电机驱动扩展板,它能够用来驱动两个直流电机。

使用该扩展板来驱动直流电机非常简单, 只需要将扩展板插到 Arduino 上, 同时将直流电机连接到扩展板上的 motors 引脚上就可以了。

正如上面所提到的,此时应该采用 Arduino 的外部供电方式,并使用变压器或者电源为 Arduino 提供电力。这里我选用的是 9V 变压器 和 9V 的直流电机:

电机扩展板上 motors 引脚的上面两针是用来接电机 1 的,下面两针是用来接电机 2 的。

电路连接好之后,剩下的工作就是如何用程序进行控制了。使用这一扩展板我们能够控制直流电机的转动方向和转动速度,其中对转 动方向的控制是通过 Arduino 上的数字 I/O 引脚 12 和 13 来实现的,对转速的控制则是通过数字 I/O 引脚 9 和 10 来实现的。 如果要控制直流电机 1,我们需要向引脚 9 输出相应的 PWM 信号来控制电机的速度,同时设置引脚 12 和 13 的高低电压来控制电机的 方向。如果要控制直流电机 2,则需要向引脚 10 输出相应的 PWM 信号来控制电机的速度,此时也是通过设置引脚 12 和 13 的高低电 压来控制电机的方向的。 电机扩展板上带有 S1 和 S2 两个按钮,分别对应于 Arduino 数字 I/O 的 7 号和 6 号管脚 ,并且在按下时为低电平。因此我们可以像下 面的程序这样利用 S1 来控制电机 1 的正反转:

int switchPin = 7; int dir1Pin = 12; int dir2Pin = 13; int speedPin = 9; void setup() {

// switch pin // direction 1 // direction 2 // spped pin

pinMode(switchPin, INPUT); pinMode(dir1Pin, OUTPUT);

pinMode(dir2Pin, OUTPUT); pinMode(speedPin, OUTPUT); } void loop() { // switch is pressed if (digitalRead(switchPin) == LOW) { // set spped analogWrite(speedPin, 250); // set direction digitalWrite(dir1Pin, LOW); digitalWrite(dir2Pin, HIGH); } else { analogWrite(speedPin, 100); digitalWrite(dir1Pin, HIGH); digitalWrite(dir2Pin, LOW); } }
在将上述程序下载到 Arduino 上并运行起来之后,我们就可以通过按 S1 键,来改变电机的旋转速度和方向了:) P.S. 在调试这一电机扩展板的奇遇是,在将其插入到 Arduino Diecimila 的贴片版本上时,发现 MC33269 异常热,并且电机偶尔才能 工作。进一步设计发现如果把整个扩展板很好地插入到 Arduino 上时,5V 和 Gnd 之间居然是短路的。一开始并没有发现问题在哪,后 来才发现扩展板上的电容 C9 与 USB 接头的外壳短路了!将其锡去掉一下,并抬高扩展板时问题得到解决。实际使用时请检查下图电 容下面的引脚是否与 USB 接口的外壳短路了,特别是对于贴片版本来讲,最好在通电前用万用表检查一下 5V 和 Gnd 之间的电阻值:)

Arduino 下载线使用手册
Arduino, DIY, 手册 3 Comments ?

Arduino 使用的是 Atmel 公司的 AVR 单片机,一般为 ATmega8 和 ATmega168,这一系列的单片机都支持 ISP(In System Programmability )编程,无需依赖昂贵的编程器就可以完成程序的下载。Arduino 电路在设计上考虑到了 ISP 功能,也留出了相应的 接口(ICSP),从而允许我们通过 ISP 下载线来完成 bootloader 的下载。 新买来的 Arduino 模块上一般都已经预先下载好了 bootloader,因此上电之后就能够直接通过 Arduino 集成开发环境下载相应的 Arduino 程序。正常情况下我们在用 Arduino 时是不需要 ISP 下载线的,但在某些情况下可能会出现在 Arduino 集成开发环境中无法正 常下载程序的现象,这很可能是由于 bootloader 受损所致。解决的办法就是重新将 bootloader 烧写到 ATmega 芯片中,此时你就需 要用到这里介绍的 ISP 下载线了。 Arduio 网站上给出的并口下载线电路我只成功地更新过 ATmega8 的 bootloader, 而无法为 Diecimila 上的 ATmega168 下载 bootloader。 此外,Arduino 给出的这一下载线电路过于简单,没有做相应的隔离和保护, 经常使用可能会对 Atmega 芯片带来一定的损害。AVR 建议使用一片 74HC244 来隔离并口和 ATmega 芯片,下面是我所使用的下载线的原理图:

以及自制的下载线:

使用并口下载线的时候,我们需要先到计算机的 BIOS 中将并口设为 ECP(The extended capabilities port )模式,同时将 I/O 基 地址设置成 378:

此时在 Windows 的设备管理器中,我们会发现并口已经被标记为 “ECP 打印机端口”: 用鼠标右键单击后从弹出的菜单中选择“属性”命令打开属性对话

框,在“资源”页面中我们会看到相应 I/O 基地址的设置已经生效: 现在就可以用 ISP 下载线连接计算机并口和 Arduino 上的 ICSP 接口 了,请特别留意连接方向:ISP 下载线六口插座上标有小三角的一端应该靠近 Arduino 的 ICSP 接口上标为 1 的一端。虽然计算机并口 能够为下载电路提供一定的电压,但一般我还是建议给 Arduino 模块加上 5V 电压(通过 USB 线和外接电源都可以),以保证下载过程 的稳定。 硬件准备好之后,我们就可以通过相应的软件将 bootloader 烧到 Arduino 中。支持 AVR 下载线的软件比较多,如 AVRDUDE 和 SLISP 等,我们在这里使用的是 PonyProg。下载并安装好 PonyProg v2.07a BETA 版本,启动 PonyProg 时会提示你进行相应的校准和设置工 作。首先选择“Setup”菜单中的“Calibration”命令进行校准,然后再选择“Setup”菜单中的“Intreface Setup…”命令进行相应的并口设 置:

根据你的 Arduino 模块上的芯片类型,从“Device” 菜单中的“AVR micro” 子菜单中选择“ATmega8”或者“ATmega168”。你也可以从工具栏上的 Device 下拉框中进行相应的选择:

首先从“Command”菜单中选择“Read All” 命令,从 Arduino 模块上读出 ATmega 中的当前数据和设置,其中最重要的是之后要设置的熔丝位。 然后选择“File”菜单中的“Open Program (FLASH) File…” 命令, 打开“Open program (FLASH) content file”对话框。从你的 Arduino 安装目录下找出对 应于的 bootloader。对于 Arduino 0010 版本来讲,我们可以在 hardware\bootloaders 目录下找到 atmega8 和 atmega168 两个目录, 分别对应 ATmega8 和 ATmega168 芯片所对应的 bootloader(文件扩展名为.hex),在 atmega168 目录下可以找到 ATmegaBOOT_168_diecimila.hex 和 ATmegaBOOT_168_ng.hex 两个文件,分别对应 Diecimila 和 NG 模块。你需要根据你的 Arduino 模块的具体情况,加载相应的 bootloader 文件。 AVR 通过熔丝来控制芯片内部的一些功能,比如 JTAG,时钟的使用,掉电检测电压,是否允许调试等。熔丝位的配置是为 Arduino 下 载 bootloader 过程中最复杂的一步,而且设置出错很有可能导致芯片锁死,所以一定要仔细。选择“Command”菜单中的“Security and Configuration Bits …”命令,打开相应的熔丝设置对话框。 Arduino 的 bootloader 对熔丝位有一定的要求,主要是同外部时间设置相关的。对于串口模块采用的 ATmega8 来讲,相应的熔丝字节 要设置成 0xCA (Fuse High Byte) 0xFF 和 (Fuse Low Byte) 具体每位的含义可以参见 Wolf Paulus 的文章。 PonyProg 中对 ATmega8 , 在 的熔丝位设置为下图所示:

对于 NG 和 Diecimila 采用的 ATmega168 来讲,相应的熔丝字节要设置成 0xF8 (Extended Fuse Byte), 0xDF(Fuse High Byte)和 0xFF(Fuse Low Byte)。 在 PonyProg 中对 ATmega168 的熔丝位 设置为下图所示: 熔丝位设置好之后,选择“Command”菜 单中的“Write All”命令,将 bootloader 下载到 Arduino 中。 下载过程中 Arduino 上的发光二极管 L 会不断闪烁。下载完 成之后,我们可以通过 Arduino 集成开 发环境下载一个 Arduino 工程,来验证

新下载的 bootloader 是否能够正常工作。

DIY Arduino: Hello World
Arduino, DIY No Comments ?

终于要开始写第一个 Arduino 程序了, 就跟之前学习所有语言一样, 第一个程序自然是 Hello World 了。 不过这次有点特殊, 要让 Arduino 显示一个“Hello World”字符串恐怕有点难度,这是因为 Arduino 模块上没有提供任何可供显示字符的设备。而这对 Arduino 新手来讲, 也就意味着程序的调试将是一个令人头疼的问题。 最简单的办法是在 Arduino 提供的数字端口(Digital I/O)上连接发光二极管,然后通过控制发光二极管的亮灭来表明程序的当前运行 状态,这的的确确可以算得上是最原始的调试方法。 我的第一个 Arduino 程序正是要通过对数字 I/O 的 13 号管脚的控制,来实现与其相连的发光二极的亮灭。之所以要选择 13 号管脚步, 是因为从原理图上可以看出该管脚与 ATmega 的引脚之间连接了一个 1K 的电阻,能够起到限流的作用,以保护二极管不被烧坏。 发光二极管是有正负极性的,因此必须连接正确才能够让其正常发光。刚买来的发光二极腿比较长的一端是正极,需要接在 Arduino 数字 I/O 的 13 号管脚上;腿比较短的一端是负极,需要接在 GND 管脚上。

运行 Arduino 的集成开发环境,选择 File->New 菜单创建一个新的 Arduino 工程

接着在 Arduino 集成开发环境的主窗口中输入相应的代码:

int ledPin = 13; void setup()

{ pinMode(ledPin, OUTPUT); } void loop() { digitalWrite(ledPin, HIGH); delay(1000); digitalWrite(ledPin, LOW); delay(1000); }
不难看出, 一个最简单的 Arduino 程序至少要实现两个函数: setup()和 loop()。 其中 setup()这个函数主要用来完成相应的初始化工作, 在上面的例子中是将数字 I/O 的 13 号管脚设置为数字输出。loop()这个函数则是 Arduino 程序的主函数,相当于 C 语言中的 main()函 数,一个 Arduino 程序要完成的主要功能都在该函数中实现,在上面的例子中是通过变换 13 号管脚的高低电平,并设置一秒的延时, 从而使发光二极管能够间歇性地不断亮灭。 从原理上讲,用 Arduino 语言编写的程序最后会被翻译成相应的 C 代码,再用 AVR-GCC 编译后下载到 ATmega 单片机中运行。因此设 计 Arduino 语言的目的就是简化单片机编程,虽然这样效率上会有一些损失,但却能够极大地促进单片机在更广泛领域内的使用,基 本上算是沿袭了 PC 机上软件设计语言从汇编语言到 C 语言再到高级语言这一过程,因此很多技术和做法其实可以借鉴。 用 Arduino 语言编写的代码需要先验证(Verify),以保证语法的正确性,然后再编译生成相应的机器码。对 Arduino 代码的验证可以 通过 Sketch->Verify/Compile 菜单命令完成,也可以通过工具栏上的按钮完成:

代码成功通过验证和编译之后,就可以将其下载到 Arduino 模块中了。由于昨天已经将 bootloader 成功地烧写到了 ATmega 中,因此 下载 Arduino 应用的任务就可以完全交由 bootloader 来完成了。Arduino 的 bootloader 与集成开发环境的交互是通过串口来完成的, 因此需要用串口线将 Arduino 与 PC 机的串中连接起来。我的串口线是自制的,按照 Arduino 的原理图,只需要接 2,3 和 5 三根线, 其中前两根用于数据的收发,最后一根是地线。 串口线连接好之后,在 Arduino 集成开发环境的 Tools->Serial Port 菜单下选择与 PC 相连的串口:

一开始我很奇怪为什么没有设置波特率和其它串行通信参数的地方,后来在 Arduino 的网站上才知道这些参数都保存在一个名为 preferences.txt 的配置文件中,该文件一般保存在类似于 C:\Documents and Settings\Administrator\Application Data\Arduino 这样 的目录下。下面是我在该文件中找到的与串口通信相关的一些参数: serial.stopbits=1 serial.databits=8 serial.download_rate=19200 serial.parity=N

不难看出,Arduino 模块采用的是 19200 8N1 方式来进行串口通信的。确定了这些之后,按下 Arduino 模块的复位按钮,随后立即执行 File->Upload to I/O Board 菜单命令将编译好的程序下载到 Arduino 模块中。Arduino 的 bootloader 被设计成如果在给定的时间(通 常有 7 到 8 秒)内没有接收到任何来自集成开发环境的命令,就自动运行之前已经下载的程序,所以我们必须保证在正确的时间段内 给 Arduino 模块发送程序下载的指令。除了通过菜单命令外,下载程序也可以通过快捷键 Ctrl+U,或者直接点击工具栏上的相应按钮 来完成:

将 Arduino 程序上传到 Arduino 模块中需要花一些时间,并且取决于工程的大小。当程序上传成功之后,可以在 Arduino 集成开发环 境的 console 窗口中看到上传后的程序大小,以及该 Arduino 模块能够接受的最大程序的大小:

现在再次复位 Arduino 模块,会看到发光二极管立即闪了一下,表明 bootloader 正常工作了。接着再过一段时间,大约 7 到 8 秒,会 看到发光二极管间歇性地不断亮灭,这就表明第一个 Arduino 程序已经成功地运行起来了,CONGRATULATIONS!

我在这期间遇到的唯一问题是刚开始的时候无法通过串口线下载程序,最初怀疑是串口通信的问题,后来慢慢排查发现 Arduino 模块 能够从串口收数据,但却无法从串口发数据。仔细检查了硬件发现原来我在 Arduino 模块上接的是串口的公头,自然收发的两条线没 有同 PC 机完全正常地连接上,后来换成一个母头就一切正常了。这一过程中的另一收区是仔细读了 Arduino 关于串口部分的原理图, 原来这部分还是一个实用的 TTL 转 232 的电平转换电路,其中只用到了电阻、二极管和三极管,省去了一个 MAX232 芯片。 至此,DIY Arduino 模块的工作算是暂告一段落,剩下的是如何对各个硬件功能进行详细的验证,这可以结合实际的项目来完成。我计 划下一步做一些简单的 Arduino 工程,大部分可能都来源于 Arduino 网站或者是网上收集到的资料,以验证我的 Arduino 模块,同时 也可以当作入门的教程供大家参考。 AUG

26

DIY Arduino: PCB 和焊接
Arduino, DIY 7 Comments ?

读了一些有关 Arduino 的介绍性的文章之后,才知道这么一个小东东居然在国外是大红大紫,虽然没有完全想清楚其中的原因,但似 乎并不妨碍自己 DIY 它的决心。 Arduino 采用开放源代码的模式, 其原理图和电路图都可以从其网站免费得到。 在权衡比较了一番之后, 我决定从其采用串口方式的版本开始,这一方面是因为原理相对简单,能够降低组装和调试的难度,另一方面则考虑到 USB 模拟的串 口并不总是那么稳定。

决定开工之后,花了一上午的时间画好了原理图,基本凑和吧。可轮到电路图时可就不一样了,封装和走线对我这业务选手来讲的确 不是件容易的事情。花了两个晚上的时间,最后还是决定放弃,因为 Arduino 官方提供的电路图在我看来确实比自己布的要漂亮多了, 看来这一修养只能在随后的日子里慢慢积累了。 去做电路板时遇到一些问题,由于我问到的制造电路板的厂商基本上只认 Protel,根本不知道还有 Eagle CAD 一说,甚至有人还将其 与 AutoCAD 混为一谈,告诉我这个软件不是用来画电路图的。没有办法,只好回家一顿 Google,将其生成 Gerber 文件后再将送过去。 这一过程也算有点收获,除了知道何为 Gerber 文件以及如何在 Eagle CAD 中生成 Gerber 文件之外,还找到了一个用来查看 Gerber 文件的好工具:CAM350。 电路板从送去到拿到一般需要一周多的时间,这期间的主要任务当然是购买元器件了。一开始并没有注意到 Arduino 串口版本的元件 列表,以为与 NG 版本一样也采用的是 ATmega168,问了好些地方都没得卖,最好只好高价比香港快递过来,估计贵了不止一倍。最 后在组装的时候才发现原来串口版本采用的仍旧是 ATmega8,而这在村里还算是很好买到的,这一个郁闷啊! 元件都准备妥当之后,电路板也做出来了,虽然不是与 Arduino 官方一致的蓝色,但还是挺漂亮的;-)

将元件焊接到 PCB 板上又是一次对基本功的训练,好在这一版本的 Arduino 采用的都是分立元件,焊接上没有遇到太大的麻烦。期间 再一次深刻体会到了工具的重要性,不时幻想自己手中那把最便宜的铬铁啥里也能更新换代一下,虽然他的寿命还不到短短的一个月。

焊接完成之后,万里长征估计还只完成了第一步,要让 Arduino 能够正常的运行起来,肯定还有相当多的调试和排错的工作要做,而 这也正是 DIY 的乐趣所在;-)

Arduino 电子积木 专用传感器扩展板 V4
Arduino, 电子积木 2 Comments ?

真没想到,一块传感器扩展板居然被我改到了第四版,而且估计还会继续修改下去。最初的传感器扩展板在设计的时候,只考虑到了 如何将数字传感器和模拟传感器很方便地连接起来。因此在最初定义数字传感器线序的时候,没有更多可以参照的地方,直到后来有 人提出是否可以考虑与伺服电机(舵机)的连线顺序一样,我才很认真地考虑这一问题,并且在最新的 V4 版本上采用,原因在于:

? ? ?

可以很方便地与舵机相连 不容易出现短路的情况,在接错钱时不会有很严重的后果 可以与模拟传感器接口统一起来,保持通用

用这么多的好处,自然是忍不住在 V4 上做了这么一个大的修改,好处多多,但升级也会给之前的用户一些不便。最主要的影响在于数 字连接线,由于连线的顺序不一样,因此混用的时候会有一定的麻烦;-) 也就是说,使用 V4 之前的传感器扩展板的用户,依旧要使用 以前的数字连接线;而使用 V4 版本的用户,则需要使用另一种数字连接线(我暂时叫它通用传感器连接线)。

V4 上其它的改动还包括:

? ? ? ? ?

调用了模拟传感器座的位置 POWER 区域与最新的 Arduino 保持一致 数字传感器连接座 4 个一组,方便连线 添加了一组适合通用连接线的模拟接口 加入了 4 针的 COM/IIC 连接座

COM/IIC 连接座是为以后的串口模块和 IIC 模块做准备的,通过设置两个跳线进行相应的选择。 从使用上讲,V4 跟之前的版本是一样的,直接连接到标准的 Arduino 上就可以了: 数字传感器可以借助通用传感器连接线与其相应接:

模块传感器则即可以通过模拟传感器连接线,也可以通过通用传感器连接线与传感器扩展板相连:

最后,因为数字传感器接口与舵机接口兼容,这样用传感器扩展板就可以直接驱动舵机了:)

小试电子积木
Arduino, 电子积木 No Comments ?

某君给我描述了他的一个项目,有 8 个继电器输出的激光开关,需要把相应的状态读入到 Arduino 中进行处理。本来电路不算太复杂, 一开始我想是不是可以用万用板搭起来这一外围,后来发现其实用电子积木的思想来构建更加容易和方便:) 首先我用一个 Arduino,一个按钮模块和一个继电器模块来模拟他的激光开关,我要实现的效果是按下按钮时,继电器相应地吸合。这 并不困难,实际应用的时候把按钮模块通过数字模块连接线连接到数字 I/O 管脚 2 上,再把继电器模块通过数字模块连接线连接到数 字 I/O 管脚 8 上:

相应的代码是:

int switchPin = 2; int relayPin = 8; int ledPin = 13; int value = 0; void setup() {

pinMode(switchPin, INPUT); pinMode(relayPin, OUTPUT); pinMode(ledPin, OUTPUT); } void loop() { value = digitalRead(switchPin); if (HIGH == value) { digitalWrite(relayPin, HIGH); digitalWrite(ledPin, HIGH); } else { digitalWrite(relayPin, LOW); digitalWrite(ledPin, LOW); } }
另外一个 Arduino 则是项目中会实际用到的,这里我用到了数字按钮模块的电路板,但没有接按钮,而是用两根线直接连接到继电器 的输出,我们不妨把它称为数字输入模块。这样实际的效果就相当于继电器吸合时,从数字输入模块上会读到高电平,当继电器断开 时,从数字模块上则会读出低电平。电路的连接很简单,数字输入模块的一端与继电器连接,另一端通过一根数字模块连接线连接到 Arduino 数字 I/O 管脚的 2 上:

相应的代码是:

int switchPin = 2; int ledPin = 13; int value = 0; void setup() { pinMode(switchPin, INPUT); pinMode(ledPin, OUTPUT); }

void loop() { value = digitalRead(switchPin); if (HIGH == value) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }
下面是最后连接好的电路图:

代码并不复杂,最后的效果是当你按下最上面的按钮模块后,中间的继电器吸合,此时从最下面的数字输入模块中读出的值为高,同 时下面那块 Arduino 上的 LED 点亮。 使用这些积木部分避免了麻烦的电路连接,但其中比较困难的是如何抽象出所需要的模块,这些模块除了功能性(比如按钮,LED)外, 还可能有部分逻辑功能模块。实践总是检验它们最好的办法,坚持下来慢慢来,也许能发现其中的一些规律吧!


相关文章:
十个中文例程教会你轻松上手制作Arduino智能小车
十个中文例程教会你轻松上手制作Arduino智能小车_电子/电路_工程科技_专业资料。...Arduino 入门笔记(9) :蓝牙模块及第一辆蓝牙遥控小车 Arduino 视频教程(上) ...
Arduino教程(智能小车)
Arduino教程(智能小车)_机械/仪表_工程科技_专业资料。Arduino 一: 数字输出 Arduino, 教程 11 Comments ? Arduino 的数字 I/O 被分成两个部分,其中每个部分都...
智能小车 完整教程材料
19 参考文献: 摘要本小组设计制作的一款智能救援小车,能够实现 2008 年山东省 ...Arduino教程(智能小车) 27页 免费 智能小车资料 暂无评价 41页 免费 智能材料在...
智能小车
2.5 了解 Arduino 的相关知识并会初步运用。 2.6 智能小车的硬件组装,包括电机的焊接,面包板的使用,硬件的连接 2.7 整体项目的软硬件调试 三、 硬件设计 3.1 ...
智能小车实训
智能小车实训报告 院系:电子信息工程 专业:电信 13-02 课程:电子工程系统综合...2.54mm Headers 兼容 Arduino 以太网: RJ45 接口以及可扩展 USB WiFi (未包括...
智能小车
系专班 部: 业: 级: 电气工程器 电气自动化 12 电气自动化 智能小车 ......ARDUINO智能小乌龟是一款单片机学习应用开发系统,以arduino单片机系列atmega-328 为...
智能小车
智能小车_机械/仪表_工程科技_专业资料。摘要本文基于 Arduino、51duino 设计了一种能够智能移动避障及智能抓取分拣 货物的机械装置,由电源模块、超声波传感器模块、...
智能小车
智能小车 9 1 0 1 1 1 2 1 3 1 4 循迹模块 个 2 电压表 个 1 普通杜邦线 根 15 加长杜邦线 根 10 Wifi 模块 高清 USB 摄像头 arduinoR3 主板 ...
Arduino智能小车实验报告
Arduino智能小车实验报告_信息与通信_工程科技_专业资料。“蓝牙手柄避障小车”...智能循迹小车实验报告 12页 1下载券 Arduino教程(智能小车) 27页 免费 智能...
冯聪2091224107Arduino智能小车
36 IV 1.绪论 1.1 智能小车的研究 1.1.1 背景 随着改革开发的三十多年...Arduino教程(智能小车) 27页 免费 动手玩转Arduino(第三期... 16页 免费 ...
更多相关标签:
arduino智能小车 | arduino智能小车代码 | arduino智能小车程序 | arduino智能避障小车 | arduino wifi智能小车 | arduino智能小车源码 | arduino智能循迹小车 | arduino智能小车测距 |