Library for reading temperature from DS1820, DS18B20 and DS1822

Dependencies:   LinkedList

Dependents:   heatmap BLE_Temperature BLE_Temperature_Exercise F334andDS18B20 ... more

Fork of DS1820 by David Pairman

HelloWorld: http://mbed.org/users/Sissors/code/DS1820_HelloWorld/

Library should currently work on all mbed targets, let me know if there is an issue. First however make sure you have latest version of mbed library and this library.

Revision:
5:2cd4928e8147
Parent:
4:29264b0a2c9f
Child:
7:58b61681818f
--- a/DS1820.cpp	Wed Aug 07 11:02:10 2013 +0000
+++ b/DS1820.cpp	Mon Feb 24 21:23:14 2014 +0000
@@ -1,53 +1,61 @@
 #include "DS1820.h"
-#include "mbed.h"
- 
-// Global variables shared between all DS1820 objects
-bool DS1820_done_flag;
-int  DS1820_last_descrepancy;
-char DS1820_search_ROM[8];
+
+LinkedList<node> DS1820::probes;
  
  
-DS1820::DS1820 (PinName data_pin, PinName power_pin) : _datapin(data_pin), _parasitepin(power_pin) {
+DS1820::DS1820 (PinName data_pin, PinName power_pin, bool power_polarity) : _datapin(data_pin), _parasitepin(power_pin) {
     int byte_counter;
-    _parasite_power = true;
-    for(byte_counter=0;byte_counter<8;byte_counter++)
-        ROM[byte_counter] = 0xFF;
+    _power_polarity = power_polarity;
+    if (power_pin != NC)
+        _power_mosfet = true;
+    
     for(byte_counter=0;byte_counter<9;byte_counter++)
         RAM[byte_counter] = 0x00;
+    
+    if (!unassignedProbe(&_datapin, _ROM))
+        error("No unassigned DS1820 found!\n");
+    else {
+        _datapin.input();
+        probes.append(this);
+        _parasite_power = !read_power_supply();
+    }
 }
-DS1820::DS1820 (PinName data_pin) : _datapin(data_pin), _parasitepin(NC) {
-    int byte_counter;
-    _parasite_power = false;
-    for(byte_counter=0;byte_counter<8;byte_counter++)
-        ROM[byte_counter] = 0xFF;
-    for(byte_counter=0;byte_counter<9;byte_counter++)
-        RAM[byte_counter] = 0x00;
+
+DS1820::~DS1820 (void) {
+    node *tmp;
+    for(int i=1; i<=probes.length(); i++)
+    {
+        tmp = probes.pop(i);
+        if (tmp->data == this)
+            probes.remove(i);
+    }
 }
+
  
-bool DS1820::onewire_reset() {
+bool DS1820::onewire_reset(DigitalInOut *pin) {
 // This will return false if no devices are present on the data bus
     bool presence=false;
-    _datapin.output();
-    _datapin = 0;           // bring low for 500 us
+    pin->output();
+    pin->write(0);          // bring low for 500 us
     wait_us(500);
-    _datapin.input();       // let the data line float high
+    pin->input();       // let the data line float high
     wait_us(90);            // wait 90us
-    if (_datapin.read()==0) // see if any devices are pulling the data line low
+    if (pin->read()==0) // see if any devices are pulling the data line low
         presence=true;
     wait_us(410);
     return presence;
 }
  
-void DS1820::onewire_bit_out (bool bit_data) {
-    _datapin.output();
-    _datapin = 0;
+void DS1820::onewire_bit_out (DigitalInOut *pin, bool bit_data) {
+    pin->output();
+    pin->write(0);
     wait_us(3);                 // DXP modified from 5
     if (bit_data) {
-        _datapin.input(); // bring data line high
+        pin->input(); // bring data line high
         wait_us(55);
     } else {
         wait_us(55);            // keep data line low
-        _datapin.input();
+        pin->input();
         wait_us(10);            // DXP added to allow bus to float high before next bit_out
     }
 }
@@ -55,19 +63,19 @@
 void DS1820::onewire_byte_out(char data) { // output data character (least sig bit first).
     int n;
     for (n=0; n<8; n++) {
-        onewire_bit_out(data & 0x01);
+        onewire_bit_out(&this->_datapin, data & 0x01);
         data = data >> 1; // now the next bit is in the least sig bit position.
     }
 }
  
-bool DS1820::onewire_bit_in() {
+bool DS1820::onewire_bit_in(DigitalInOut *pin) {
     bool answer;
-    _datapin.output();
-    _datapin = 0;
+    pin->output();
+    pin->write(0);
     wait_us(3);                 // DXP modofied from 5
-    _datapin.input();
+    pin->input();
     wait_us(10);                // DXP modified from 5
-    answer = _datapin.read();
+    answer = pin->read();
     wait_us(45);                // DXP modified from 50
     return answer;
 }
@@ -77,41 +85,47 @@
     int i;
     for (i=0; i<8; i++) {
         answer = answer >> 1; // shift over to make room for the next bit
-        if (onewire_bit_in())
+        if (onewire_bit_in(&this->_datapin))
             answer = answer | 0x80; // if the data port is high, make this bit a 1
     }
     return answer;
 }
- 
-bool DS1820::search_ROM() {
-    return search_ROM_routine(0xF0);    // Search ROM command
+
+bool DS1820::unassignedProbe(PinName pin) {
+    DigitalInOut _pin(pin);
+    char ROM_address[8];
+    return search_ROM_routine(&_pin, 0xF0, ROM_address);
 }
  
-bool DS1820::search_alarm() {
-    return search_ROM_routine(0xEC);    // Search Alarm command
+bool DS1820::unassignedProbe(DigitalInOut *pin, char *ROM_address) {
+    return search_ROM_routine(pin, 0xF0, ROM_address);
 }
  
-bool DS1820::search_ROM_routine(char command) {
-    extern bool DS1820_done_flag;
-    extern int DS1820_last_descrepancy;
-    extern char DS1820_search_ROM[8];
+bool DS1820::search_ROM_routine(DigitalInOut *pin, char command, char *ROM_address) {
+    bool DS1820_done_flag = false;
+    int DS1820_last_descrepancy = 0;
+    char DS1820_search_ROM[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    
     int descrepancy_marker, ROM_bit_index;
     bool return_value, Bit_A, Bit_B;
     char byte_counter, bit_mask;
  
     return_value=false;
-    if (!DS1820_done_flag) {
-        if (!onewire_reset()) {
-            DS1820_last_descrepancy = 0; // no devices present
+    while (!DS1820_done_flag) {
+        if (!onewire_reset(pin)) {
+            return false;
         } else {
             ROM_bit_index=1;
             descrepancy_marker=0;
-            onewire_byte_out(command); // Search ROM command or Search Alarm command
+            for (int n=0; n<8; n++) {           // Search ROM command or Search Alarm command
+                onewire_bit_out(pin, command & 0x01);
+                command = command >> 1; // now the next bit is in the least sig bit position.
+            } 
             byte_counter = 0;
             bit_mask = 0x01;
             while (ROM_bit_index<=64) {
-                Bit_A = onewire_bit_in();
-                Bit_B = onewire_bit_in();
+                Bit_A = onewire_bit_in(pin);
+                Bit_B = onewire_bit_in(pin);
                 if (Bit_A & Bit_B) {
                     descrepancy_marker = 0; // data read error, this should never happen
                     ROM_bit_index = 0xFF;
@@ -137,7 +151,7 @@
                             }
                         }
                     }
-                    onewire_bit_out (DS1820_search_ROM[byte_counter] & bit_mask);
+                    onewire_bit_out (pin, DS1820_search_ROM[byte_counter] & bit_mask);
                     ROM_bit_index++;
                     if (bit_mask & 0x80) {
                         byte_counter++;
@@ -149,12 +163,32 @@
             }
             DS1820_last_descrepancy = descrepancy_marker;
             if (ROM_bit_index != 0xFF) {
-                for(byte_counter=0;byte_counter<8;byte_counter++)
-                    ROM[byte_counter] = DS1820_search_ROM[byte_counter];
-                if (ROM_checksum_error())           // Check the CRC
-                    DS1820_last_descrepancy = 0;    // Abort any more search
-                else
-                    return_value = true;
+                int i = 1;
+                node *list_container;
+                while(1) {
+                    list_container = probes.pop(i);
+                    if (list_container == NULL) {                             //End of list, or empty list
+                        if (ROM_checksum_error(DS1820_search_ROM)) {          // Check the CRC
+                            return false;
+                        }
+                        for(byte_counter=0;byte_counter<8;byte_counter++)
+                            ROM_address[byte_counter] = DS1820_search_ROM[byte_counter];
+                        return true;
+                    } else {                    //Otherwise, check if ROM is already known
+                        bool equal = true;
+                        DS1820 *pointer = (DS1820*) list_container->data;
+                        char *ROM_compare = pointer->_ROM;
+                        
+                        for(byte_counter=0;byte_counter<8;byte_counter++) {
+                            if ( ROM_compare[byte_counter] != DS1820_search_ROM[byte_counter])
+                                equal = false;
+                        }
+                        if (equal)
+                            break;
+                        else
+                            i++;
+                    }
+                }                        
             }
         }
         if (DS1820_last_descrepancy == 0)
@@ -163,49 +197,28 @@
     return return_value;
 }
  
-void DS1820::search_ROM_setup() {
-    extern bool DS1820_done_flag;
-    extern int DS1820_last_descrepancy;
-    extern char DS1820_search_ROM[8];
-    DS1820_done_flag = false;
-    DS1820_last_descrepancy = 0;
-    int i;
-    for (i=0; i<8; i++)
-        DS1820_search_ROM[i]=0x00;
-}
- 
-void DS1820::read_ROM() {
-    // NOTE: This command can only be used when there is one DS1820 on the bus. If this command
-    // is used when there is more than one slave present on the bus, a data collision will occur
-    // when all the DS1820s attempt to respond at the same time.
-    int i;
-    onewire_reset();
-    onewire_byte_out(0x33);   // Read ROM id
-    for (i=0; i<8; i++)
-        ROM[i]=onewire_byte_in();
-}
- 
 void DS1820::match_ROM() {
 // Used to select a specific device
     int i;
-    onewire_reset();
+    onewire_reset(&this->_datapin);
     onewire_byte_out( 0x55);  //Match ROM command
-    for (i=0;i<8;i++)
-        onewire_byte_out(ROM[i]);
+    for (i=0;i<8;i++) {
+        onewire_byte_out(_ROM[i]);
+    }
 }
  
 void DS1820::skip_ROM() {
-    onewire_reset();
+    onewire_reset(&this->_datapin);
     onewire_byte_out(0xCC);   // Skip ROM command
 }
  
-bool DS1820::ROM_checksum_error() {
+bool DS1820::ROM_checksum_error(char *_ROM_address) {
     char CRC=0x00;
     int i;
     for(i=0;i<7;i++) // Only going to shift the lower 7 bytes
-        CRC = CRC_byte(CRC, ROM[i]);
+        CRC = CRC_byte(CRC, _ROM_address[i]);
     // After 7 bytes CRC should equal the 8th byte (ROM CRC)
-    return (CRC!=ROM[7]); // will return true if there is a CRC checksum mis-match         
+    return (CRC!=_ROM_address[7]); // will return true if there is a CRC checksum mis-match         
 }
  
 bool DS1820::RAM_checksum_error() {
@@ -249,7 +262,7 @@
 return CRC;
 }
  
-int DS1820::convert_temperature(bool wait, devices device) {
+int DS1820::convertTemperature(bool wait, devices device) {
     // Convert temperature into scratchpad RAM for all devices at once
     int delay_time = 750; // Default delay time
     char resolution;
@@ -257,7 +270,7 @@
         skip_ROM();          // Skip ROM command, will convert for ALL devices
     else {
         match_ROM();
-        if (FAMILY_CODE == FAMILY_CODE_DS18B20 ) {
+        if ((FAMILY_CODE == FAMILY_CODE_DS18B20 ) || (FAMILY_CODE == FAMILY_CODE_DS1822 )) {
             resolution = RAM[4] & 0x60;
             if (resolution == 0x00) // 9 bits
                 delay_time = 94;
@@ -267,12 +280,20 @@
                 delay_time = 375;
         }
     }
+    
     onewire_byte_out( 0x44);  // perform temperature conversion
     if (_parasite_power) {
-        _parasitepin = 1;     // Parasite power strong pullup
-        wait_ms(delay_time);
-        _parasitepin = 0;
-        delay_time = 0;
+        if (_power_mosfet) {
+            _parasitepin = _power_polarity;     // Parasite power strong pullup
+            wait_ms(delay_time);
+            _parasitepin = !_power_polarity;
+            delay_time = 0;
+        } else {
+            _datapin.output();
+            _datapin.write(1);
+            wait_ms(delay_time);
+            _datapin.input();
+        }
     } else {
         if (wait) {
             wait_ms(delay_time);
@@ -296,7 +317,7 @@
 //       crcerr = 1;
 }
 
-bool DS1820::set_configuration_bits(unsigned int resolution) {
+bool DS1820::setResolution(unsigned int resolution) {
     bool answer = false;
     resolution = resolution - 9;
     if (resolution < 4) {
@@ -309,13 +330,6 @@
     return answer;
 }
  
-int DS1820::read_scratchpad() {
-    int answer;
-    read_RAM();
-    answer = (RAM[2]<<8) + RAM[3];
-    return answer;
-}
- 
 void DS1820::write_scratchpad(int data) {
     RAM[3] = data;
     RAM[2] = data>>8;
@@ -323,43 +337,11 @@
     onewire_byte_out(0x4E);   // Copy scratchpad into DS1820 ram memory
     onewire_byte_out(RAM[2]); // T(H)
     onewire_byte_out(RAM[3]); // T(L)
-    if ( FAMILY_CODE == FAMILY_CODE_DS18B20 ) {
+    if ((FAMILY_CODE == FAMILY_CODE_DS18B20 ) || (FAMILY_CODE == FAMILY_CODE_DS1822 )) {
         onewire_byte_out(RAM[4]); // Configuration register
     }
 }
  
-void DS1820::store_scratchpad(devices device) {
-    if (device==all_devices)
-        skip_ROM();          // Skip ROM command, will store for ALL devices
-    else
-        match_ROM();
-    onewire_byte_out(0x48);   // Write scratchpad into E2 command
-    if (_parasite_power)
-        _parasitepin=1;
-    wait_ms(10);            // Parasite power strong pullup for 10ms
-    if (_parasite_power)
-        _parasitepin=0;
-}
- 
-int DS1820::recall_scratchpad(devices device) {
-// This copies the E2 values into the DS1820's memory.
-// If you specify all_devices this will return zero, otherwise
-// it will return the value of the scratchpad memory.
-    int answer=0;
-    if (device==all_devices)
-        skip_ROM();          // Skip ROM command, will recall for ALL devices
-    else
-        match_ROM();
-    onewire_byte_out(0xB8);   // Recall E2 data to scratchpad command
-    wait_ms(10); // not sure I like polling for completion
-                 // it could cause an infinite loop
-    if (device==DS1820::this_device) {
-        read_RAM();
-        answer = read_scratchpad();
-    }
-    return answer;
-}    
- 
 float DS1820::temperature(char scale) {
 // The data specs state that count_per_degree should be 0x10 (16), I found my devices
 // to have a count_per_degree of 0x4B (75). With the standard resolution of 1/2 deg C
@@ -378,7 +360,7 @@
             reading = 0-((reading ^ 0xffff) + 1); // 2's comp then convert to signed int
         }
         answer = reading +0.0; // convert to floating point
-        if ( FAMILY_CODE == FAMILY_CODE_DS18B20 ) {
+        if ((FAMILY_CODE == FAMILY_CODE_DS18B20 ) || (FAMILY_CODE == FAMILY_CODE_DS1822 )) {
             answer = answer / 8.0;
         }
         else {
@@ -403,7 +385,7 @@
     else
         match_ROM();
     onewire_byte_out(0xB4);   // Read power supply command
-    return onewire_bit_in();
+    return onewire_bit_in(&this->_datapin);
 }