Arduino中国 | Flamingo EDA

CAT | 电子积木

对于要在Arduino上使用彩色屏幕进行显示的项目来讲,这里要介绍的这款彩色Nokia LCD模块应该是个不错的选择,该彩色LCD电子积木使用SPI接口与Arduino进行通信,能够提供132 x 132的显示区域:

彩色LCD电子积木与Arduino之间最重要的连接是SPI接口,这可以通过我们的IDC扩展板和相应的连接线来完成:

除了SPI接口之外,彩色LCD电子积木模块上还有另外两个引脚:RESET和LIGHT,分别用来控制对LCD模拟的复位和背光。这两个引脚我们可以使用Arduino专用传感器扩展板和相应的传感器连接线,来与Arduino相应的引脚进行连接。彩色LCD电子积木在设计的时候主要使用的是Arduino上的PORTB引脚,根据之后的测试代码,我们需要将RESET引脚接到Arduino的12号引脚上,而LIGHT引脚则接到Arduino的3号引脚上:

电路连接好之后,我们就可以往里面写入相应的代码了。这一款Nokia LCD屏幕有两种控制芯片,分别是Epson和Philips。我们目前测试的是一款基于Philips控制器的屏幕,你可以下载我们所使用的测试代码LCD_Philips(代码大部分参考了Gravitech的例子)。

以下是运行时的效果图:

下载我们所使用的测试代码

对射型的红外开关一般由两个结点组成:一个发射端和一个接收端,其工作原理是发射端发出相应的红外光线(一般是15度角的锥形),接收端有一个对红外光线敏感的元件用来检测发送端发送出来的红外光线。如果发射端和接收端之间正好有物体遮挡的话,那接收端就无法接收到发射端发送出来的红外光线,从而能够判断出发射端和接收端之间是否有物体存在。

对射型红外开关的特点决定了其在现场安装的时候可能会有一定的难度,一是要保证发射端和接收端对准在一条直线上,另外在有多对红外开关存在的情况下,还要注意如何避免相邻的两个红外开关之间不致于相互影响。红外对射开关接照功率的不同有不同的作用距离,我们这里介绍的这对红外开关的作用距离最远可以达到8米,不过工作的距离越长,相应的发射出来的红外光线的锥体也就越大,对邻近的红外开关的影响也就越大,这点在实际项目中需要考虑到,特别是多个红外开关共同使用的时候。

对射型红外开关的发射端只是用来发射相应的红外信号,一般不需要进行控制,所以我们可以用5V的供电模块直接给发射端供电:

注意连线的时候绿色线要接5V供电模块的地(GND),而红色线则要接5V供电模块的输出端(OUT):

对射型红外开关的接收端是用来判断是否有物体经过的,我们可以将其相应的输出信号通过Arduino读取出来,然后根据读出来的值进行相应的控制,比如传给计算机做进一步的处理等。接收端与Arduino的连接可以借助于我们提供的Arduino专用传感器扩展板,其中红外接收端三条线的连接顺序分别是GND(绿)、5V(红)和信号(黄):

下面是整个电路的连接图:右侧是红外发射端,其通过5V供电模块直接供电,负责不间断地发射红外光线;左侧是红外接收端,当有或者没有物体位于发射端和接收端之间时,接收端送给Arduino的信号是有所不同的:

下面是我们测试时使用的代码,通过从红外接收端读出来的信号的不同,Arduino会点亮或者熄灭位于13号数字I/O引脚上所连接的LED:

int ledPin = 13;
int switchPin = 7;
int value = 0; 

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

void loop() {
  value = digitalRead(switchPin);
  if (HIGH == value) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
  //delay(100);
}

No tags

RFID射频识别是一种非接触式的物体识别技术,它可以通过射频信号自动识别目标对象并获取相关数据,因此许多互动项目正是借用这一特性来实现对物体的识别的。通常来讲,一个最基本的RFID识系统主要由以下三部分组成:

  • 标签(Tag):由耦合元件及芯片组成,每个标签具有唯一的电子编码,附着在物体上标识目标对象;
  • 阅读器(Reader):读取(有时还可以写入)标签信息的设备,可设计为手持式或固定式;
  • 天线(Antenna):在标签和读取器间传递射频信号。

目前能够使用的RFID模块比较多,与Arduino之间的接口也有所区别,我们设计的这两款RFID模块都是通过串口来与Arduino连接的,两者的功能和连接方式完全一样,只是天线的形式有所区别而已。

下图这款是阅读器和天线分离的,分别位于两块电路板上,由于天线的面积相对较大,因此检测距离可以达到10cm:

而下图这款则是阅读器和天线集成在一块电路板上的,检测距离为6cm:

RFID的工作原理其实并不复杂,当标签进入到读卡器的工作区域之后,读卡器就可以通过天线所产生的磁场,读出标签里所存储的数据:

根据具体使用场景的不同,我们可以使用不同类型的标签,不同类型的标签作用范围有所区别:

在实际使用的过程中,我们可以先用读卡器读出不同标签中的ID,此时可以使用我们之前介绍的USB转串口模块Serial Dongle:

电路连接好之后,用串口调试工具打开Serial Dongle对应的串口,将波特率设置为19200,然后以HEX格式发送读卡的命令 AA BB 02 20 22(一共5个字节):

如果此时没有卡在读卡器的作用区间之内,RFID模块将通过串口返回HEX格式的AA BB 02 DF DD(五个字节):

但如果此时有卡在读卡器的作用区间之内,RFID模块上的红色LED会点亮,同时通过串口返回HEX格式的AA BB 06 20 5E 97 25 C7 0D(9个字节),其中从20之后开始的4个字节5E 97 25 C7即是标签的ID。不同标签返回的ID值是不一样的,而我们正是通过对该ID值的判断来区分不同的物体的。

在得到了相应标签的ID值后,我们就可以在Arduino中来进行识别了,硬件连接上依然是通过传感器扩展板上的COM接口来连接我们的串口RFID模块:

与之对应的Arduino代码如下所示,其中我们要检测的标签ID是5E 97 25 C7,当Arduino检测到相应的标签后,会将13号数字I/O端口上的LED点亮1秒钟:

int val = 0;
int ledPin = 13;
int status = 0;
unsigned char searchCMD[] = {0xAA, 0xBB,0x02, 0x20, 0x22};
unsigned char searchRES[4];

void setup()
{
  Serial.begin(19200);
  pinMode(13, OUTPUT);
}

int searchCard()
{
  Serial.write(searchCMD, 5);
  delay(100);
  status = 0;
  while(true) {
    if (Serial.available() > 0) {
      val = Serial.read();

      switch (status) {
        case 0:  // parse 0xAA
          if (val == 0xAA) status = 1;
          break;
        case 1: // parse 0xBB
          if (val == 0xBB) status = 2;
          else return -1;
          break;
        case 2:
          if (val == 0x06) status = 3;
          else return -1;
          break;
        case 3:
          if (val == 0x20) status = 4;
          else return -1;
          break;
        case 4:
        case 5:
        case 6:
        case 7:
          searchRES[status - 4] = val;
          status ++;
          break;
        case 8:
          return 0; // read successfully
          break;
        default:
          return -1;
          break;
      }

    }
  }
}

void loop()
{
  if (searchCard() != -1) {
    if (searchRES[0] == 0x5E && searchRES[1] == 0x97 && searchRES[2] == 0x25 && searchRES[3] == 0xC7) {
      digitalWrite(13, HIGH);
      delay(1000);
      digitalWrite(13, LOW);
      delay(1000);
    }
  }
}

No tags

FlexiForce传感器由由美国Tekscan公司生产的一种电阻元件,其特点是电导率与负载之间能够呈现高度的线性关系。在完全没有压力的状况下,该传感器所表现出来的电阻值非常大,可 以说基本上是一个开放式电路;但随着压力增加,电阻值开始下降,最后可以达到10千欧或者更低的水平。

FlexiForce压力传感器在实际使用的时候需要搭配相应的放大电路,因此我们设计了这一电子积木,以便在实际工程中能够很方便地运用这一传感器:

同其他电子积木一样,在使用的时候只需要用传感器连接线,将该模块与传感器扩展板连接起来就可以了:

对Arduino来讲,读取该传感器输出的值与其它模拟传感器的做法是一样的,下面是相应的测试代码:

int sensorPin = 5;
int value = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  value = analogRead(sensorPin);
  Serial.println(value, DEC);
  delay(10);
}

· ·

RS232串口是我们非常熟悉的一种Arduino与计算机之间进行数据交换的手段,虽然最新的Arduino在设计时都采用了USB转串口的方式,但最初一版的Arduino的确是基于RS232串口的。直到现在,RS232仍然在实际的工程项目中大量用到,不过这种方式有两个致命的弱点:一是传输距离不能太长,二是只能实现两个设备之间的点对点通信。我们这里要介绍的RS485模块正好解决了这两个问题:

RS485串行总线接口标准以差分平衡方式传输信号,具有很强的抗共模干扰的能力,允许一对双绞线上一个发送器驱动多个 负载设备,其理论的通讯距离是1200米,速率高达20Mbps,并可以用在强噪声的环境中正常工作,因此在工业通讯领域中被广泛应用。 当我们在Arduino上使用RS485时,更多的可能是借助其互连功能,将多个Arduino连接成一个RS485网络,来实现各个Arduino之间的通信。

在由RS485构成的多机串行通信系统中,一般采用的都是主从式结构:也就是说主机负责所有的通信协调过程,从机一般被动地接收主机发送过来的数据,或者根据主机的命令向主机反馈相应的数据,各个从机之间一般不进行数据交换,而是通过主机进行中转。之所以采用这种方式是因为于RS485是一种半双工通讯,发送和接收共用同一物理信道,在任一时刻都只允许一台设备处于发送状态。如果在时序上配合不好,就会发生总线冲突,使整个系统的通讯瘫痪,从而无法正常工作。

我们以一个三个结点的网络为例,介绍如何利用RS485串口模块来构建一个RS485网络,该网络中包括一台作为主机使用的Arduino(S)和两台作为从机使用的Arduino(CA, CB)。对于网络中的每一台Arduino来讲,硬件连接上我们都需要一块Arduino专用传感器扩展板、一条COM连接线和一条通用传感器连接线,其中COM连接线用来将RS485串口模块与传感器扩展板上的COM口连接起来,而通用传感器连接线则用来将RS485串口模块上的RE/DE引脚和标号为2的数字I/O口连接起来:

我们之前已经介绍过,RS485网络上的任何时候都只有一台设备处于发送状态,而其它设备则应该全部都处于接收状态。Arduino正是通过对RE/DE引脚的控制,来指定该设备是向RS485网络中发送数据,还是从RS485网络中接收数据。为了说明上的方便,在我们的例子中主设备S一直都处于发送状态,相应的RE/DE引脚一直处于高电平状态;两台从设备CA和CB一直处于接收状态,相应的RE/DE引脚则一直处于低电平状态。

在RS485串口模块上另一个需要引起我们注意的就是标记为“TERM?”的开关,它是用来控制终端电阻的,目的是为了吸收RS485网络中的反射信号,以保证正常传输的信号不受到干扰。不过该电阻只能在RS485总线上的最后一台设备上出现,这也是为什么叫做终端电阻的原因。在我们上面给出的网络拓朴图中不难看出,从机CB是总线上的最后一台设置,因此我们需要在该设备所对应的RS485串口模块上将“TERM?”开关拨到“Y”的位置:

而在主机S和从机CA上该开关都需要设置到与之相反的位置上:

由于是要将三个Arduino连接成一个RS485网络,因此我们还需要将RS485 串口模块两两连接起来,这是通过RS485串口模块上的“485 IN”和“485 THU”两个插座来实现的。具体说来,就是我们需要将前一个RS485串口模块的“485 THU”接口,与下一个RS485串口模块的“485 IN”接口连接起来,连接的时候我们可以使用模拟传感器连接线,或者是普通的杜邦线。对于我们正在构建的三个结点的RS485网络来讲,则是要求主机S的“485 THU”与从机CA的“485 IN”连接起来,然后再将从机CA的“485 THU”与从机CB的“485 IN”连接起来,实验中我们使用的是长度为2米的模拟传感器连接线。下图中从左至右依次为主机S,从机CA和从机CB:

硬件都连接好之后,下面我们就可以为各个Arduino来编写相应的程序了。下面是主机S的代码:

int EN = 2;

void setup()
{
  pinMode(EN, OUTPUT);
  Serial.begin(19200);
}

void loop()
{
// send data 
  digitalWrite(EN, HIGH);//使能发送
  Serial.print('A');
  Serial.print('B');
  delay(1000);
}

从主机S的代码不难看出,虽然采用的是RS485串口协议,但编程时使用的还是普通的串口操作语句。

下面是从机CA所使用的代码:

int ledPin = 13;
int EN = 2;
int val;

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

void loop()
{
  // receive data
 digitalWrite(EN, LOW);//使能接收
 val = Serial.read();
  if (-1 != val) {
    if ('A' == val) {
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(500);
    }
 }
}

下面是从机CB所使用的代码:

int ledPin = 13;
int EN = 2;
int val;

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

void loop()
{
  // receive data
 digitalWrite(EN, LOW);//使能接收
 val = Serial.read();
  if (-1 != val) {
    if ('B' == val) {
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(500);
    }
 }
}

从代码中不难看出,CA和CB分别响应主机S发送过来的字母A或者B,然后做相应的反应:点亮一个LED灯。在将三台Arduino都分别通电之后,你就可以看到作为主机的CA和CB在接到主机S发过来的命令之后,分别做相应的点灯动作。

最后需要说明的一点是,虽然在我们的例子中演示的是主机S不断向从机CA和CB发送数据的单向通信过程,但其实在RS485网络中也是可以实现双向通信的,只但需要在代码上做更多的工作,并且需要在主机和从面之间根据应用的需要定义一个相应的数据通信协议。

· ·

<< Latest posts

Older posts >>

Theme Design by devolux.nh2.me