Arduino中国 | Flamingo EDA

CAT | 教程

在之前的文章中,曾经介绍了如何使用RF模块实现对Arduino的无线控制,其原理非常类似于遥控器,能够实现4个按钮的RF无线遥控。不过,对于要进行数据传输的场合,这样的解决办法就显得不太适合了,比如你要将Arduino采集到的光线传感器的数值,无线传输到PC机那端的时候。这种情况技术上称为无线数据传输,或者简称为无线数传。实现无线数传目前有不少解决方案,但最容易同Arduino连接使用的是类似于APC220这样通过串口来实现的无线数传,虽然数据传输的速度可能慢点(受限于串口的波特率),但的确不失为一种简单易用的方式,难怪很多网友都建议为Arduino加上这样的模块支持。

今天找出点时间来摆弄摆弄这个APC220了,厂家寄给我的模块没有任何说明,好在网络上能找到一些说明,另外就得自己摸索了。首先发现的问题是厂家给的USB适配器似乎于APC220不是很匹配:引脚的数目不一样。这个嘛,似乎不难理解,可能为了兼容不同的产品,或者至少可以说这一适配器不是为APC220专门设计的。USB适配器上用的芯片是CP2102,于是先到Silicon Laboratories网站下载相应的驱动程序,我下载的文件为cp210x_vcp_win2k_xp_s2k3.zip,解压缩后是一个exe文件,直接执行然后按照提示一步一步完成驱动的安装。

驱动安装完成之后,将USB适配器插入到PC机的USB接口中,Windows会提示找到相应的硬件,并对其进行相应的安装和配置:

当Windows提示你硬件已经可以使用之后,在设备管理器的“端口(COM 和 LPT)”下面可以找到CP2102虚拟出来的串口:

现在可以将一个APC220模块连接到USB适配器上了,由于USB适配器与APC220的引脚数目并不一致,连接时要注意插入的位置:

打开APC220厂家提供的设置程序RF-ANET,之前CP2102默认找到的串口为COM87,但RF-ANET程序似乎不能正常地打开这一端口。

在设备管理器中将串口设置成COM4后,重新插入USB适配器并打开RF-ANET,单击“Read R”按钮,一切正常,状态栏上显示“read succeed!”,表明已经能够正常地跟APC220通讯上了!

这样PC端APC220的测试环境就建议好了,现在来看Arduino这一端端。APC220模块与Arduino之间的连线有4条:5V, GND, TX和RX,需要注意的是,APC220和Arduino都是单独的串口设备,因此Arduino上的发送端TX应该与APC220上的接收端RX连接起来,同理Arduino上的RX应该与APC220上的TX连接起来:

APC220模块的默认波特率设置为9600,因此先用下面的代码来进行测试,注意在向Aduino下载程序时,先断开同APC220模块TX和RX上的连线,否则会出现下载无法正常的情况。

int val = 0;
int ledPin = 13;
void setup()
{
  Serial.begin(9600);
}

void loop()
{
  val = Serial.read();
  if (-1 != val) {
   if ('A' == val || 'a' == val) {
     Serial.println("Hello from Arduino!");
   }else if ('B' == val || 'b' == val) {
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
    }
  }
}

总结一下,现在我们已经分别在PC和Arduino上连接了一个APC220模块,并且已经向Arduino里面写入了相应的测试代码。一切都准备好之后,现在我们来进行相应的测试。首先要注意的是我们必须用外接电源的方式对Arduino进行供电,这是因为如果连接上USB线的话,相应的FT232模块会被激活,这样FT232实现的串口和ACP220上的串口就会因为冲突导致通信不正常:

在将加电后的Arduino放到房间里的一个角落之后,现在来配置PC端。APC220模块通过其USB适配器之后,其原理上也相当于一个串口,因此我们可以用Arduino自带的开发环境来进行测试,只是这一情况下你的PC上连接的不再是Arduino,而是APC220 USB适配器。连接好APC220 USB适配器后,打开Arduino,在“Tools” -> “Serial Ports”菜单下选择USB适配器虚拟出来的“COM4”(与之前的设置一致)。接着打开Arduino里的“Serial Monitor”,发送A字符,会收到Arduino传回来的“Hello from Arduino!”,发送B字符可以点亮Arduino上的13号LED(持续0.5秒):

May/08

1

Arduino电机驱动扩展板

除了使用传感器对各种外部物理量进行感知之外,能够对实际物体的运动进行相应的控制也是互动设计中不可或缺的一部分。在所有这类动力装置中,电机显然是最常见、最基本、最便宜的解决方案了,常用的电机的种类有很多种,如直流电机,步进电机,伺服电机,减速电机等,并且每一种电机的控制方法都有所不同。

如果你是一个电子高手,控制普通的直流电机用几个三极管就行了,否则话像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;  // switch pin
int dir1Pin = 12;   // direction 1
int dir2Pin = 13;   // direction 2
int speedPin = 9;   // spped pin

void setup() {
  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之间的电阻值:)

No tags

Dec/07

16

Arduino教程七: XBee无线通信

借助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模块的传输性能进行测试。

No tags

Sep/07

16

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,如下图所示:

tutorial_6_serial_monitor.png

该工程运行起来之后会不断调用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模块发送多个字符,来验证这一功能:

tutorial_6_multi_chars.png

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

tutorial_6_circuit.jpg

No tags

Sep/07

8

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”控制,打开串口监视器:

tutorial_5_serial_monitor.png

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

tutorial_5_baud_setting.png

如果一切正常,此时我们就可以在Arduino集成开发环境的Console窗口中看到串口上输出的数据了:

tutorial_5_serial_output.png

为了检查串口上是否有数据发送,一个比较简单的办法是在数字I/O端口的1号管脚(TX)和5V电源之间接一个发光二极管,如下面的原理图所示:

tutorial_5_schematic.png

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

tutorial_5_circuit.jpg

No tags

Older posts >>