分享

arduino学习笔记27

 开启美好每一天 2014-01-14

本次实验我使用的是购买的一个DS1307 RTC模块,上面集成了一个DS18B20温度传感器,还集成了另外一个存储芯片~~
先上图


IMGP5813_调整大小.JPG 

IMGP5818_调整大小.JPG 

再看下硬件连接图,DS1307是I2C接口SCL接模拟5号口,SDA接模拟4号口。DS18B20是单总线模式,他的DS接口接数字2号口。

DS1307_Module.jpg 

IMGP5820_调整大小.JPG 

DS18B20:

IMGP6090_调整大小.JPG 

DS18x20系列数字温度传感器主要有DS18S20和DS18B20(DS18S20只有9位一种工作模式,分辨率只到0.5摄氏度,DS18B20有9、10、11、12位四种工作可编程控制的模式,分辨率最高为0.0625摄氏度。),都是由美国Dallas半导体公司(现在改名叫Maxim)生产的。这个系列最大的特点就是采用了Maxim的专利技术1-Wire。顾名思义,1-Wire就是采用单一信号线,但可像I2C,SPI一样,同时传输时钟(clock)又传输数据(data),而且数据传输是双向的。1-Wire 使用较低的数据传输速率,通常是用来沟通小型device,如数位温度计。通过1-Wire技术可以在单一信号线的基础上构成传感器网络,Maxim起名”MicroLan”。

DS18x20的供电主要有两种模式:

Parasite power mode/寄生供电


schematic-dallas-18s20.gif 

所谓的寄生供电是指DS18x20只需要两根接线,一根数据线,一根接地线,数据线上还要接一个4.7k上拉电阻连电源,数据线同时也提供了电能。DS18x20内置了电容,高电平期时把电能储存在内部电容里,低电平期内消耗内部电容里的能量工作,直到下次高电平期内再次电容充电。虽然这样的模式简化了线路同时也带来了一些缺陷:

1. 电路的电流一般很小,只有当DS18x20进行温度转化或者写EEPROM时会高达1.5mA,当DS18x20进行上述操作时,数据线必须保持电平拉高状态直到操作结束,期间master端的Arduino不能做任何操作,DS18x20温度转化时这个时间间隔大概是750ms。

2.如果要求DS18x20有精确的转化,数据线在温度转化期间必须保证足够的能量,但当你使用多个DS18x20构成MicroLan进行多点测温时,单靠4.7k的上拉电阻无法提供足够的能量,会导致较大的测温误差。

Normal (external supply) mode/标准(外部供电)


normal_mode.png 

标准外部供电模式,相比寄生供电模式,每个DS18x20需要多一条独立的电源线接独立电源。虽然多用些线,但由于外部供电,保证了每个设备的进精确度和稳定性。而且没有了上述温度转换期间Arduino不能做任何事的问题。
直接进入实战,调用DS18B20,需要使用OneWire库。
把下面代码下载进入arduino控制板。

  1. #include <OneWire.h> 
  2.   
  3. // DS18S20 Temperature chip i/o 
  4. OneWire ds(2);  // on pin 2 
  5.   
  6. void setup(void) { 
  7.   // initialize inputs/outputs 
  8.   // start serial port 
  9.   Serial.begin(9600); 
  10.   
  11. void loop(void) { 
  12.   byte i; 
  13.   byte present = 0; 
  14.   byte data[12]; 
  15.   byte addr[8]; 
  16.   
  17.   if ( !ds.search(addr)) { 
  18.     Serial.print("No more addresses.\n"); 
  19.     ds.reset_search(); 
  20.     return; 
  21.   } 
  22.   
  23.   Serial.print("R="); 
  24.   for( i = 0; i < 8; i++) { 
  25.     Serial.print(addr[i], HEX); 
  26.     Serial.print(" "); 
  27.   } 
  28.   
  29.   if ( OneWire::crc8( addr, 7) != addr[7]) { 
  30.     Serial.print("CRC is not valid!\n"); 
  31.     return; 
  32.   } 
  33.   
  34.   if ( addr[0] == 0x10) { 
  35.     Serial.print("Device is a DS18S20 family device.\n"); 
  36.   } 
  37.   else if ( addr[0] == 0x28) { 
  38.     Serial.print("Device is a DS18B20 family device.\n"); 
  39.   } 
  40.   else { 
  41.     Serial.print("Device family is not recognized: 0x"); 
  42.     Serial.println(addr[0],HEX); 
  43.     return; 
  44.   } 
  45.   
  46.   ds.reset(); 
  47.   ds.select(addr); 
  48.   ds.write(0x44,1);         // start conversion, with parasite power on at the end 
  49.   
  50.   delay(1000);     // maybe 750ms is enough, maybe not 
  51.   // we might do a ds.depower() here, but the reset will take care of it. 
  52.   
  53.   present = ds.reset(); 
  54.   ds.select(addr); 
  55.   ds.write(0xBE);         // Read Scratchpad 
  56.   
  57.   Serial.print("P="); 
  58.   Serial.print(present,HEX); 
  59.   Serial.print(" "); 
  60.   for ( i = 0; i < 9; i++) {           // we need 9 bytes 
  61.     data[i] = ds.read(); 
  62.     Serial.print(data[i], HEX); 
  63.     Serial.print(" "); 
  64.   } 
  65.   Serial.print(" CRC="); 
  66.   Serial.print( OneWire::crc8( data, 8), HEX); 
  67.   Serial.println(); 


代码下载好以后打开串口编辑器,然后就会出现下面这样子的画面。

2011-11-18 10-37-49.jpg 

虽然我们读到了Scratchpad的数据,但是显示的是HEX16进制代码,我们还需要转化成我们能读的温度格式。这里推荐一个叫Dallas Temperature Control的Library,大大简化了这个过程。官方地址:http://www./?titl ... ure_Control_Library

 

  1. #include <OneWire.h> 
  2. #include <DallasTemperature.h> 
  3.   
  4. // Data wire is plugged into port 2 on the Arduino 
  5. #define ONE_WIRE_BUS 2 
  6.   
  7. // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) 
  8. OneWire oneWire(ONE_WIRE_BUS); 
  9.   
  10. // Pass our oneWire reference to Dallas Temperature.  
  11. DallasTemperature sensors(&oneWire); 
  12.   
  13. void setup(void) 
  14.   // start serial port 
  15.   Serial.begin(9600); 
  16.   Serial.println("Dallas Temperature IC Control Library Demo"); 
  17.   
  18.   // Start up the library 
  19.   sensors.begin(); 
  20.   
  21. void loop(void) 
  22. {  
  23.   // call sensors.requestTemperatures() to issue a global temperature  
  24.   // request to all devices on the bus 
  25.   Serial.print("Requesting temperatures..."); 
  26.   sensors.requestTemperatures(); // Send the command to get temperatures 
  27.   Serial.println("DONE"); 
  28.   
  29.   Serial.print("Temperature for the device 1 (index 0) is: "); 
  30.   Serial.println(sensors.getTempCByIndex(0));   

代码下载好以后,打开串口监视器,就可以看到当前室温了。

2011-11-18 23-32-12.jpg 

下面我们试用一下DS1307时钟芯片功能。
先把下面库自带测试代码下载进入arduino控制板

  1. #include <WProgram.h> 
  2. #include <Wire.h> 
  3. #include <DS1307.h> 
  4.   
  5. int rtc[7]; 
  6. int ledPin =  13; 
  7. void setup() 
  8.   DDRC|=_BV(2) |_BV(3);  // POWER:Vcc Gnd 
  9.   PORTC |=_BV(3);  // VCC PINC3 
  10.   pinMode(ledPin, OUTPUT);   
  11.   Serial.begin(9600); 
  12.   
  13.   RTC.stop(); 
  14.   RTC.set(DS1307_SEC,1); 
  15.   RTC.set(DS1307_MIN,57); 
  16.   RTC.set(DS1307_HR,17); 
  17.   RTC.set(DS1307_DOW,2); 
  18.   RTC.set(DS1307_DATE,18); 
  19.   RTC.set(DS1307_MTH,1); 
  20.   RTC.set(DS1307_YR,10); 
  21.   RTC.start(); 
  22.   
  23. void loop() 
  24.   RTC.get(rtc,true); 
  25.   
  26.   for(int i=0; i<7; i++) 
  27.   { 
  28.     Serial.print(rtc[i]); 
  29.     Serial.print(" "); 
  30.   } 
  31.   Serial.println(); 
  32.         digitalWrite(ledPin, HIGH);  
  33.         delay(500); 
  34.         digitalWrite(ledPin, LOW); 
  35.         delay(500); 


然后打开串口监视器,就能看到类似下图的样子。
2011-11-20 20-15-49.jpg 

这个模块上还有一个T24C32A EEPROM存储器。。。下面上一个全面一点的代码,对各个期间进行测试。其中刚开始会对I2C器件进行扫描。。。代码不错,大家可以参考下。

 

  1. /** 
  2.  * I2CScanner.pde -- I2C bus scanner for Arduino 
  3.  * 
  4.  * 2009, Tod E. Kurt, [url]http:///blog/[/url] 
  5.  * 
  6.  */ 
  7. #include <OneWire.h> 
  8. #include "Wire.h" 
  9. #include <WProgram.h> 
  10. #include <DS1307.h> 
  11. #include <avr/io.h> 
  12. extern "C" {  
  13. #include "utility/twi.h"  // from Wire library, so we can do bus scanning 
  14.   
  15.   
  16. byte start_address = 1; 
  17. byte end_address = 127; 
  18. OneWire  ds(2);  // on pin 2 
  19. byte Tdata[12]; 
  20. int sensorValue = 0;        // value read from the pot 
  21. int rtc[7]; 
  22. float TT=0.0; 
  23.   
  24. // Scan the I2C bus between addresses from_addr and to_addr. 
  25. // On each address, call the callback function with the address and result. 
  26. // If result==0, address was found, otherwise, address wasn't found 
  27. // (can use result to potentially get other status on the I2C bus, see twi.c) 
  28. // Assumes Wire.begin() has already been called 
  29. void scanI2CBus(byte from_addr, byte to_addr,  
  30.                 void(*callback)(byte address, byte result) )  
  31.   byte rc; 
  32.   byte data = 0; // not used, just an address to feed to twi_writeTo() 
  33.   for( byte addr = from_addr; addr <= to_addr; addr++ ) { 
  34.     rc = twi_writeTo(addr, &data, 0, 1); 
  35.     if(rc==0) callback( addr, rc ); 
  36.   } 
  37.   
  38. // Called when address is found in scanI2CBus() 
  39. // Feel free to change this as needed 
  40. // (like adding I2C comm code to figure out what kind of I2C device is there) 
  41. void scanFunc( byte addr, byte result ) { 
  42.   Serial.print("addr: "); 
  43.   Serial.print(addr,DEC); 
  44.   addr = addr<<1; 
  45.   Serial.print("\t HEX: 0x"); 
  46.   Serial.print(addr,HEX); 
  47.   Serial.println( (result==0) ? "\t found!":"   "); 
  48. //  Serial.print( (addr%4) ? "\t":"\n"); 
  49.   
  50.   
  51.   void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) { 
  52.     int rdata = data; 
  53.     Wire.beginTransmission(deviceaddress); 
  54.     Wire.send((int)(eeaddress >> 8)); // MSB 
  55.     Wire.send((int)(eeaddress & 0xFF)); // LSB 
  56.     Wire.send(rdata); 
  57.     Wire.endTransmission(); 
  58.   } 
  59.   
  60.   // WARNING: address is a page address, 6-bit end will wrap around 
  61.   // also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes 
  62.   void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) { 
  63.     Wire.beginTransmission(deviceaddress); 
  64.     Wire.send((int)(eeaddresspage >> 8)); // MSB 
  65.     Wire.send((int)(eeaddresspage & 0xFF)); // LSB 
  66.     byte c; 
  67.     for ( c = 0; c < length; c++) 
  68.       Wire.send(data[c]); 
  69.     Wire.endTransmission(); 
  70.   } 
  71.   
  72.   byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) { 
  73.     byte rdata = 0xFF; 
  74.     Wire.beginTransmission(deviceaddress); 
  75.     Wire.send((int)(eeaddress >> 8)); // MSB 
  76.     Wire.send((int)(eeaddress & 0xFF)); // LSB 
  77.     Wire.endTransmission(); 
  78.     Wire.requestFrom(deviceaddress,1); 
  79.     if (Wire.available()) rdata = Wire.receive(); 
  80.     return rdata; 
  81.   } 
  82.   
  83.   // maybe let's not read more than 30 or 32 bytes at a time! 
  84.   void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) { 
  85.     Wire.beginTransmission(deviceaddress); 
  86.     Wire.send((int)(eeaddress >> 8)); // MSB 
  87.     Wire.send((int)(eeaddress & 0xFF)); // LSB 
  88.     Wire.endTransmission(); 
  89.     Wire.requestFrom(deviceaddress,length); 
  90.     int c = 0; 
  91.     for ( c = 0; c < length; c++ ) 
  92.       if (Wire.available()) buffer[c] = Wire.receive(); 
  93.   } 
  94. void DS1302_SetOut(byte data ) { 
  95.     Wire.beginTransmission(B1101000); 
  96.     Wire.send(7); // LSB 
  97.     Wire.send(data); 
  98.     Wire.endTransmission(); 
  99. byte DS1302_GetOut(void) { 
  100.     byte rdata = 0xFF; 
  101.     Wire.beginTransmission(B1101000); 
  102.     Wire.send(7); // LSB 
  103.     Wire.endTransmission(); 
  104.     Wire.requestFrom(B1101000,1); 
  105.     if (Wire.available()) { 
  106.       rdata = Wire.receive(); 
  107.       Serial.println(rdata,HEX); 
  108.     } 
  109.     return rdata; 
  110. void showtime(void){ 
  111.   byte i; 
  112.   Serial.print("Time="); 
  113.   DS1302_SetOut(0x00); 
  114.   RTC.get(rtc,true);   
  115.   for(int i=0; i<7; i++)        { 
  116.   Serial.print(rtc[i]); 
  117.   Serial.print(" "); 
  118.   } 
  119.   
  120. void readBatVcc(void){ 
  121.     sensorValue = analogRead(A1); 
  122.     TT = sensorValue*0.0047; 
  123.     Serial.print("Battery: "); 
  124.     Serial.print(TT); 
  125.     Serial.print("V"); 
  126.   
  127. // standard Arduino setup() 
  128. void setup() 
  129.     DDRC|=_BV(2) |_BV(3); 
  130.     PORTC |=_BV(3); 
  131.     Wire.begin(); 
  132.   
  133.     Serial.begin(19200); 
  134.     Serial.println("--- I2C Bus Scanner Test---"); 
  135.     Serial.print("starting scanning of I2C bus from "); 
  136.     Serial.print(start_address,DEC); 
  137.     Serial.print(" to "); 
  138.     Serial.print(end_address,DEC); 
  139.     Serial.println("..."); 
  140.   
  141.     // start the scan, will call "scanFunc()" on result from each address 
  142.     scanI2CBus( start_address, end_address, scanFunc ); 
  143.   
  144.     Serial.println("\n"); 
  145.     Serial.println("--- EEPROM Test---"); 
  146.     char somedata[] = "this is data from the eeprom"; // data to write 
  147.     i2c_eeprom_write_page(0x50, 0, (byte *)somedata, sizeof(somedata)); // write to EEPROM  
  148.     delay(100); //add a small delay 
  149.     Serial.println("Written Done");     
  150.     delay(10); 
  151.     Serial.print("Read EERPOM:"); 
  152.     byte b = i2c_eeprom_read_byte(0x50, 0); // access the first address from the memory 
  153.     int addr=0; //first address 
  154.     while (b!=0)  
  155.     { 
  156.       Serial.print((char)b); //print content to serial port 
  157.       addr++; //increase address 
  158.       b = i2c_eeprom_read_byte(0x50, addr); //access an address from the memory 
  159.     } 
  160.    Serial.println("\n"); 
  161.   Serial.println(""); 
  162.   Serial.println("--- DS11307 RTC Test---");   
  163.   showtime(); 
  164.   if(rtc[6]<2011){ 
  165.     RTC.stop(); 
  166.     RTC.set(DS1307_SEC,1); 
  167.     RTC.set(DS1307_MIN,52); 
  168.     RTC.set(DS1307_HR,16); 
  169.     RTC.set(DS1307_DOW,2); 
  170.     RTC.set(DS1307_DATE,25); 
  171.     RTC.set(DS1307_MTH,1); 
  172.     RTC.set(DS1307_YR,11); 
  173.     RTC.start(); 
  174.     Serial.println("SetTime:"); 
  175.     showtime();     
  176.   } 
  177.   
  178.   Serial.println("\n\n"); 
  179.   Serial.println("--- Reserve Power Test---"); 
  180.   Serial.println("  Close POWER!:"); 
  181.    PORTC &=~_BV(3); 
  182.    byte time; 
  183.    for(time=0;time<5;time++){ 
  184.      digitalWrite(13,HIGH); 
  185.      delay(500); 
  186.      digitalWrite(13,LOW); 
  187.      delay(500);      
  188.      readBatVcc(); 
  189.      Serial.println("");  
  190.    } 
  191.     PORTC |=_BV(3); 
  192.    Serial.println("\n  POWER On!"); 
  193.       delay(500); 
  194.       showtime(); 
  195.   
  196.     Serial.println("\n"); 
  197.     Serial.println("===  Done   ==="); 
  198.     Serial.println("\n"); 
  199.   
  200. // standard Arduino loop() 
  201. void loop()  
  202.     byte i; 
  203.     byte present = 0; 
  204.     unsigned int Temper=0; 
  205.   
  206.   
  207. readBatVcc(); 
  208.   
  209.     ds.reset(); 
  210.     ds.write(0xCC,1); 
  211.     ds.write(0x44,1);         // start conversion, with parasite power on at the end 
  212.     digitalWrite(13,HIGH); 
  213.     delay(450); 
  214.     digitalWrite(13,LOW); 
  215.     delay(450); 
  216.     present = ds.reset(); 
  217.     ds.write(0xCC,1);     
  218.     ds.write(0xBE);         // Read Scratchpad 
  219.     for ( i = 0; i < 9; i++) {           // we need 9 bytes 
  220.       Tdata[i] = ds.read(); 
  221.     }     
  222.     Temper = (Tdata[1]<<8 | Tdata[0]); 
  223.     TT =Temper*0.0625; 
  224.     if(TT>200){ 
  225.      Serial.println("\t DS18B20 Not installed!"); 
  226.     }else{ 
  227.       Serial.print("\t Temperature="); 
  228.       Serial.println(TT); 
  229.     } 
  230.     Serial.println(""); 

然后打开串口监视器,波特率要调节为19200.
2011-11-20 20-20-35.jpg 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约