Arduino中国 | Flamingo EDA

Jul/10

28

电子积木 通用传感器模块

对于大部分简单的传感器来讲,通常有三根连接线就足够了:地GND、电源和信号,为此我们设计了这一通用传感器模块:

该模块左侧的黑色座可以通过传感器连接线连接到传感器扩展板,右侧的绿色座则可以用来连接传感器,比如下面的红外反射开关:

这样我们就可以将这些传感器连接到传感器扩展板上了,从而进一步做到同Arduino的连接:

No tags

Arduino电子积木专用传感器扩展板V4之后,我们推出了新一版本的Arduino电子积木专用传感器扩展板V5:

与V4相比,V5的改动并不算太大,主要是在吸收了用户的反馈意见后,将COM和I2C的接口分开了,这样就可以同时连接基于串口的模块(如串行LCD)或者IIC接口的模块(如EEPROM存储模块)。这一改动同时导致端口0,1,2,3的位置下移了:

至于使用方法则基本上没有做什么改动,仍然是直接插在Arduino的标准版本(如Arduino 2009)就可以了:

Jul/10

18

电子积木 EEPROM 存储模块

如果你的Arduino中要做少量的数据存储,那么使用EEPROM可能是最简单易行的做法了。其实Arduino所使用的芯片ATmega本身就具备一定的EEPROM存储器,只不过数量有限罢了。我们设计的这款外置式EEPROM存储模块使用I2C总线来与Arduino进行连接,并且采用可插拔的芯片,直插式系列,这样在扩展容量时会比较容易,基本上只需要按一个更大容量的EEPROM芯片就可以了。

该存储模块上使用的是AT24C系列的EEPROM芯片,其I2C基地址为0×50,最后三位地址可以根据应用需要进行设置。因此使用时我们首先要对其地址的最后三位进行设置,这是通过4位拨码开关上的A2,A1和A0来完成的,其中A0表示地址的最后一位。拨码开关向上推时相应的位为1,向下推时相应的位为0。也就是说,如果将A2,A1,A0都拨到上方时,相应的地址为0×57;而如果将A2,A1,A0都拨到下方时,相应的地址为0×50。

该存储模块上另外一个需要设置的地方就是开关RS,它是用来设置是否往I2C总线上的SDA和SCL上接入板载的上拉电阻。我们知道,I2C之所以被称为总线,就是因为可以连接多个I2C设备,接照I2C协议的规定,只允许在离控制器最近的一个I2C设备处接上拉电阻。说到这里你可能已经明白了,如果有多个这个的存储模块连接到Arduino的I2C总线上时,我们必须将第一个(离Arduino最近)存储模块的RS开关设置到ON的位置,而其它存储模块上的RS则不能设置到ON的位置:

如果使用的是Arduino专用传感器扩展扩展板V4,注意IIC/COM跳线的位置要设置到IIC这一边,因为此时我们需要用到I2C连接方式:

上述设置完成之后,我们只需要用I2C/COM连接线将EEPROM存储模块连接到传感器扩展板上就完成硬件的连接了:

至于软件部分,Arduino的官方网站上提供了两个不错的链接:I2CEEPROMTWIPROM,需要的话可以参考。下面是我们测试时所用的代码:

#include <Wire.h>
#define EEPROM_ADDR 0x50           // I2C Buss address of 24LC256 256K EEPROM

void setup()
{
  Wire.begin();                        // join I2C bus (address optional for master)
  Serial.begin(9600);

  // TESTS FOR EACH FUNCTION BEGIN HERE
  Serial.println("Writing Test:");
  for (int i=0; i<20; i++){            // loop for first 20 slots
    i2c_eeprom_write_byte(EEPROM_ADDR,i,i+65);   // write address + 65 A or 97 a
    Serial.print(". ");
    delay(10);                         // NEED THIS DELAY!
  }
  Serial.println("");
  delay(500);

  Serial.println("Reading Test:");
  for (int i=0; i<20; i++){            // loop for first 20 slots
    Serial.print(i2c_eeprom_read_byte(EEPROM_ADDR, i),BYTE);
    Serial.print(" ");
  }

  // setup for page tests . . .
  byte PageData[30];                   // array that will hold test data for a page
  byte PageRead[30];                   // array that will hold result of data for a page
  for (int i=0; i<30; i++){            // zero both arrays for next test
    PageData[i] = 0;
    PageRead[i] = 0;
  }
  Serial.println("");
  for (int i=0; i<30; i++) PageData[i] = i+33;  // fill up array for next test char 33 = !

  Serial.println("Writing Page Test:");
  i2c_eeprom_write_page(EEPROM_ADDR, 100, PageData, 28 ); // 28 bytes/page is max

  Serial.println("Reading Page Test:");
  i2c_eeprom_read_buffer( EEPROM_ADDR, 100, PageRead, 28);
  for (int i=0; i<28; i++){
    Serial.print(PageRead[i],BYTE);    // display the array read
    Serial.print(" ");
  }
}

void loop()
{
}

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data )
{
  int rdata = data;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8));    // Address High Byte
  Wire.send((int)(eeaddress & 0xFF));  // Address Low Byte
  Wire.send(rdata);
  Wire.endTransmission();
}

// Address is a page address, 6-bit (63). More and end will wrap around
// But data can be maximum of 28 bytes, because the Wire library has a buffer of 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length )
{
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddresspage >> 8)); // Address High Byte
  Wire.send((int)(eeaddresspage & 0xFF)); // Address Low Byte
  byte c;
  for ( c = 0; c < length; c++)
    Wire.send(data[c]);
  Wire.endTransmission();
  delay(10);                           // need some delay
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress )
{
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8));    // Address High Byte
  Wire.send((int)(eeaddress & 0xFF));  // Address Low Byte
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}

// should not read more than 28 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length )
{
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8));    // Address High Byte
  Wire.send((int)(eeaddress & 0xFF));  // Address Low Byte
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,length);
  //int c = 0;
  for ( int c = 0; c < length; c++ )
    if (Wire.available()) buffer[c] = Wire.receive();
}

上述代码运行时的效果如下图所示:

·

实时钟通常也被称为实时时钟,它能够向电子电路提供日期和时间信息,包括年、月、日、时、分、秒,被广泛应用在需要进行计时的场合中。许多实时钟电路还提供电池供电的方式,这样在发生掉电时仍能准确计时。通常说来,功能稍多一点的实时钟电路还会提供包括警报、看门狗,以及支持高精度要求的校准寄存器等附加功能。

DS1307是DALLAS公司的一款实时种芯片,采用I2C协议与单片机通讯,而Arduino上正好有这一接口,因此连接起来就非常方便了。DS1307中有一个可编程波形输出口,它可以用来驱动LED小灯,或者作为中断来触发某些事件,不过用它去带一些大功率的东西的时候要注意。我们设计的这一款实时钟模块,将Ds1307的I2C接口和可编程波形输出接口SQW都连接出来了,不过一般情况下我们只会用到I2C接口来实现基本的时钟设置/读取功能。需要注意的是,该模块必须先安装上电池才可以正常工作。电池使用的是纽扣电池(型号CR1220),正极朝上:

在电路连接上我们可以使用Arduino专用传感器扩展板V4,不过要将相应的跳线设置到IIC的位置上:

剩下的工作就是用4芯的I2C/COM连接线将传感器扩展板上的专用接口,与实时钟模块上的IIC(I2C其实就是IIC的缩写)端口连接起来了:

硬件连接的工作完成之后,如何在Arduino里对该模块进行编程呢?上网搜索了一下,发现在Arduino上使用DS1307做为时钟芯片的玩家还真不少,而且还封装好了相应的Arduino库,实验时我使用的是Google Code上的这个DS1307库,你也可以在这里下载到我使用的版本。将下载好的压缩文件解压缩到Arduino 0018的libraries目录下后,重新启动Arduino并用它自带的测试程序进行测试:

#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h> // written by  mattt on the Arduino forum and modified by D. Sjunnesson

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

  RTC.stop();
  RTC.set(DS1307_SEC,1);        //set the seconds
  RTC.set(DS1307_MIN,23);     //set the minutes
  RTC.set(DS1307_HR,12);       //set the hours
  RTC.set(DS1307_DOW,4);       //set the day of the week
  RTC.set(DS1307_DATE,15);       //set the date
  RTC.set(DS1307_MTH,7);        //set the month
  RTC.set(DS1307_YR,10);         //set the year
  RTC.start();

}

void loop()
{

  Serial.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true
  Serial.print(":");
  Serial.print(RTC.get(DS1307_MIN,false));//read minutes without update (false)
  Serial.print(":");
  Serial.print(RTC.get(DS1307_SEC,false));//read seconds
  Serial.print("      ");                 // some space for a more happy life
  Serial.print(RTC.get(DS1307_DATE,false));//read date
  Serial.print("/");
  Serial.print(RTC.get(DS1307_MTH,false));//read month
  Serial.print("/");
  Serial.print(RTC.get(DS1307_YR,false)); //read year 
  Serial.println();

  delay(1000);
}

程序读起来应该不算困难,基本上就是使用RTC.set来对时钟进行设置,然后就可以通过RTC.get来读取相应的时间信息了,至于时钟怎么维护,那就是 DS1307 的工作了:)

将程序下载到Arduino里并运行起来之后,就可以通过串口监控窗口来查看相应的输出结果了:

· · ·

Jul/10

6

Arduino XBee扩展板 V03

Arduino XBee扩展板 V03的主要改动是采用了可堆叠的设计,这样在同其它扩展板配合使用的时候会更加方便一些,解决了之前版本无法与其它扩展板配合使用的情况。

另外采用开关而不是跳线来选择Xbee或者USB方式,使用起来更加方便:

使用时依旧是直接连接到Arduino上即可:

·

Older posts >>