From 40662c693d5bb3abd6161c92160c579fdb2ab9ac Mon Sep 17 00:00:00 2001 From: Joe Bechter Date: Thu, 10 Jul 2014 23:20:45 -0400 Subject: [PATCH] initial commit --- DS2438.cpp | 148 ++++++++++++++++++ DS2438.h | 67 ++++++++ LICENSE | 13 ++ README.txt | 8 + examples/DS2438Humidity/DS2438Humidity.ino | 89 +++++++++++ .../DS2438TemperatureAndVoltage.ino | 55 +++++++ 6 files changed, 380 insertions(+) create mode 100644 DS2438.cpp create mode 100644 DS2438.h create mode 100644 LICENSE create mode 100644 README.txt create mode 100644 examples/DS2438Humidity/DS2438Humidity.ino create mode 100644 examples/DS2438TemperatureAndVoltage/DS2438TemperatureAndVoltage.ino diff --git a/DS2438.cpp b/DS2438.cpp new file mode 100644 index 0000000..7befbc4 --- /dev/null +++ b/DS2438.cpp @@ -0,0 +1,148 @@ +/* + * DS2438.cpp + * + * by Joe Bechter + * + * (C) 2012, bechter.com + * + * All files, software, schematics and designs are provided as-is with no warranty. + * All files, software, schematics and designs are for experimental/hobby use. + * Under no circumstances should any part be used for critical systems where safety, + * life or property depends upon it. You are responsible for all use. + * You are free to use, modify, derive or otherwise extend for your own non-commercial purposes provided + * 1. No part of this software or design may be used to cause injury or death to humans or animals. + * 2. Use is non-commercial. + * 3. Credit is given to the author (i.e. portions © bechter.com), and provide a link to the original source. + * + */ + +#include "DS2438.h" + +DS2438::DS2438(OneWire *ow, uint8_t *address) { + _ow = ow; + _address = address; +}; + +void DS2438::begin(uint8_t mode) { + _mode = mode & (DS2438_MODE_CHA | DS2438_MODE_CHB | DS2438_MODE_TEMPERATURE); + _temperature = 0; + _voltageA = 0.0; + _voltageB = 0.0; + _error = true; + _timestamp = 0; +} + +void DS2438::update() { + uint8_t data[9]; + + _error = true; + _timestamp = millis(); + + if (_mode & DS2438_MODE_CHA || _mode == DS2438_MODE_TEMPERATURE) { + boolean doTemperature = _mode & DS2438_MODE_TEMPERATURE; + if (!startConversion(DS2438_CHA, doTemperature)) { + return; + } + if (!readPageZero(data)) + return; + if (doTemperature) { + _temperature = (double)(((((int16_t)data[2]) << 8) | (data[1] & 0x0ff)) >> 3) * 0.03125; + } + if (_mode & DS2438_MODE_CHA) { + _voltageA = (((data[4] << 8) & 0x00300) | (data[3] & 0x0ff)) / 100.0; + } + } + if (_mode & DS2438_MODE_CHB) { + boolean doTemperature = _mode & DS2438_MODE_TEMPERATURE & !(_mode & DS2438_MODE_CHA); + if (!startConversion(DS2438_CHB, doTemperature)) { + return; + } + if (!readPageZero(data)) + return; + if (doTemperature) { + _temperature = (double)(((((int16_t)data[2]) << 8) | (data[1] & 0x0ff)) >> 3) * 0.03125; + } + _voltageB = (((data[4] << 8) & 0x00300) | (data[3] & 0x0ff)) / 100.0; + } + _error = false; +} + +double DS2438::getTemperature() { + return _temperature; +} + +float DS2438::getVoltage(int channel) { + if (channel == DS2438_CHA) { + return _voltageA; + } else if (channel == DS2438_CHB) { + return _voltageB; + } else { + return 0.0; + } +} + +boolean DS2438::isError() { + return _error; +} + +unsigned long DS2438::getTimestamp() { + return _timestamp; +} + +boolean DS2438::startConversion(int channel, boolean doTemperature) { + if (!selectChannel(channel)) + return false; + _ow->reset(); + _ow->select(_address); + if (doTemperature) { + _ow->write(DS2438_TEMPERATURE_CONVERSION_COMMAND, 0); + delay(DS2438_TEMPERATURE_DELAY); + _ow->reset(); + _ow->select(_address); + } + _ow->write(DS2438_VOLTAGE_CONVERSION_COMMAND, 0); + delay(DS2438_VOLTAGE_CONVERSION_DELAY); + return true; +} + +boolean DS2438::selectChannel(int channel) { + uint8_t data[9]; + if (readPageZero(data)) { + if (channel == DS2438_CHB) + data[0] = data[0] | 0x08; + else + data[0] = data[0] & 0xf7; + writePageZero(data); + return true; + } + return false; +} + +void DS2438::writePageZero(uint8_t *data) { + _ow->reset(); + _ow->select(_address); + _ow->write(DS2438_WRITE_SCRATCHPAD_COMMAND, 0); + _ow->write(DS2438_PAGE_0, 0); + for (int i = 0; i < 8; i++) + _ow->write(data[i], 0); + _ow->reset(); + _ow->select(_address); + _ow->write(DS2438_COPY_SCRATCHPAD_COMMAND, 0); + _ow->write(DS2438_PAGE_0, 0); +} + +boolean DS2438::readPageZero(uint8_t *data) { + _ow->reset(); + _ow->select(_address); + _ow->write(DS2438_RECALL_MEMORY_COMMAND, 0); + _ow->write(DS2438_PAGE_0, 0); + _ow->reset(); + _ow->select(_address); + _ow->write(DS2438_READ_SCRATCHPAD_COMMAND, 0); + _ow->write(DS2438_PAGE_0, 0); + for (int i = 0; i < 9; i++) + data[i] = _ow->read(); + return _ow->crc8(data, 8) == data[8]; +} + + diff --git a/DS2438.h b/DS2438.h new file mode 100644 index 0000000..d4f9d0a --- /dev/null +++ b/DS2438.h @@ -0,0 +1,67 @@ +/* + * DS2438.h + * + * by Joe Bechter + * + * (C) 2012, bechter.com + * + * All files, software, schematics and designs are provided as-is with no warranty. + * All files, software, schematics and designs are for experimental/hobby use. + * Under no circumstances should any part be used for critical systems where safety, + * life or property depends upon it. You are responsible for all use. + * You are free to use, modify, derive or otherwise extend for your own non-commercial purposes provided + * 1. No part of this software or design may be used to cause injury or death to humans or animals. + * 2. Use is non-commercial. + * 3. Credit is given to the author (i.e. portions © bechter.com), and provide a link to the original source. + * + */ + +#ifndef DS2438_h +#define DS2438_h + +#include +#include + +#define DS2438_TEMPERATURE_CONVERSION_COMMAND 0x44 +#define DS2438_VOLTAGE_CONVERSION_COMMAND 0xb4 +#define DS2438_WRITE_SCRATCHPAD_COMMAND 0x4e +#define DS2438_COPY_SCRATCHPAD_COMMAND 0x48 +#define DS2438_READ_SCRATCHPAD_COMMAND 0xbe +#define DS2438_RECALL_MEMORY_COMMAND 0xb8 +#define DS2438_PAGE_0 0x00 + +#define DS2438_CHA 0 +#define DS2438_CHB 1 + +#define DS2438_MODE_CHA 0x01 +#define DS2438_MODE_CHB 0x02 +#define DS2438_MODE_TEMPERATURE 0x04 + +#define DS2438_TEMPERATURE_DELAY 10 +#define DS2438_VOLTAGE_CONVERSION_DELAY 8 + +class DS2438 { + public: + DS2438(OneWire *ow, uint8_t *address); + void begin(uint8_t mode=(DS2438_MODE_CHA | DS2438_MODE_CHB | DS2438_MODE_TEMPERATURE)); + void update(); + double getTemperature(); + float getVoltage(int channel=DS2438_CHA); + boolean isError(); + unsigned long getTimestamp(); + private: + OneWire *_ow; + uint8_t *_address; + uint8_t _mode; + double _temperature; + float _voltageA; + float _voltageB; + unsigned long _timestamp; + boolean _error; + boolean startConversion(int channel, boolean doTemperature); + boolean selectChannel(int channel); + void writePageZero(uint8_t *data); + boolean readPageZero(uint8_t *data); +}; + +#endif diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2abb106 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2013, bechter.com - All Rights Reserved + + 1. All files, software, schematics and designs are provided as-is with no warranty. + 2. All files, software, schematics and designs are for experimental/hobby use. + Under no circumstances should any part be used for critical systems where safety, + life or property depends upon it. You are responsible for all use. + 3. You are free to use, modify, derive or otherwise extend for your own non-commercial purposes provided + 1. No part of this software or design may be used to cause injury or death to humans or animals. + 2. Use is non-commercial. + 3. Credit is given to the author (i.e. portions © bechter.com), + and provide a link to this site (http://projects.bechter.com). + + diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..7490368 --- /dev/null +++ b/README.txt @@ -0,0 +1,8 @@ +DS2438 Arduino OneWire Library + +To install, copy the DS2438 folder structure to your Arduino libraries folder. + +Requires Arduino 1.0 or greater and OneWire Arduino library (see http://playground.arduino.cc/Learning/OneWire). + +For additional information see http://projects.bechter.com + diff --git a/examples/DS2438Humidity/DS2438Humidity.ino b/examples/DS2438Humidity/DS2438Humidity.ino new file mode 100644 index 0000000..654925b --- /dev/null +++ b/examples/DS2438Humidity/DS2438Humidity.ino @@ -0,0 +1,89 @@ +/* + * DS2438Humidity + * + * This example demonstrates the use of the DS2438 Library and the Arduino OneWire library + * to read a relative humidity sensor that uses a Dallas Semiconductor DS2438 battery monitor. + * This example is for a 1-Wire device similar to the HobbyBoards H3-R1-A humidity sensor. + * + * by Joe Bechter + * + * (C) 2012, bechter.com + * + * All files, software, schematics and designs are provided as-is with no warranty. + * All files, software, schematics and designs are for experimental/hobby use. + * Under no circumstances should any part be used for critical systems where safety, + * life or property depends upon it. You are responsible for all use. + * You are free to use, modify, derive or otherwise extend for your own non-commercial purposes provided + * 1. No part of this software or design may be used to cause injury or death to humans or animals. + * 2. Use is non-commercial. + * 3. Credit is given to the author (i.e. portions © bechter.com), and provide a link to the original source. + * + */ + +#include +#include +#include + +// define the Arduino digital I/O pin to be used for the 1-Wire network here +const uint8_t ONE_WIRE_PIN = 2; + +// define the 1-Wire address of the DS2438 battery monitor here (lsb first) +uint8_t DS2438_address[] = { 0x26, 0x45, 0xe6, 0xf7, 0x00, 0x00, 0x00, 0x4e }; + +OneWire ow(ONE_WIRE_PIN); +DS2438 ds2438(&ow, DS2438_address); + +float temperature; +float heatindex; +float dewpoint; +float humidity; + +void setup() { + Serial.begin(9600); + ds2438.begin(); +} + +void loop() { + ds2438.update(); + if (ds2438.isError() || ds2438.getVoltage(DS2438_CHA) == 0.0) { + Serial.println("Error reading from DS2438 device"); + } else { + temperature = ds2438.getTemperature(); + heatindex = temperature; + float rh = (ds2438.getVoltage(DS2438_CHA) / ds2438.getVoltage(DS2438_CHB) - 0.16) / 0.0062; + humidity = (float)(rh / (1.0546 - 0.00216 * temperature)); + if (humidity < 0.0) { + humidity = 0.0; + } else if (humidity > 100.0) { + humidity = 100.0; + } + float tempK = temperature + 273.15; + dewpoint = tempK / ((-0.0001846 * log(humidity / 100.0) * tempK) + 1.0) - 273.15; + if (temperature >= 26.7 && humidity >= 40.0) { + float t = temperature * 9.0 / 5.0 + 32.0; // heat index formula assumes degF + rh = humidity; + float heatindexF = -42.38 + 2.049 * t + 10.14 * rh + -0.2248 * t * rh + -0.006838 * t * t + + -0.05482 * rh * rh + 0.001228 * t * t * rh + 0.0008528 * t * rh * rh + + -0.00000199 * t * t * rh * rh; + heatindex = (heatindexF - 32.0) * 5.0 / 9.0; + } + if (heatindex < temperature) + heatindex = temperature; + } + Serial.print("Temperature = "); + Serial.print(temperature, 1); + Serial.print("C ("); + Serial.print(temperature * 9.0 / 5.0 + 32.0, 1); + Serial.print("F), Heat Index = "); + Serial.print(heatindex, 1); + Serial.print("C ("); + Serial.print(heatindex * 9.0 / 5.0 + 32.0, 1); + Serial.print("F), Dewpoint = "); + Serial.print(dewpoint, 1); + Serial.print("C ("); + Serial.print(dewpoint * 9.0 / 5.0 + 32.0, 1); + Serial.print("F), Relative Humidity = "); + Serial.print(humidity, 0); + Serial.println("%."); + delay(500); +} diff --git a/examples/DS2438TemperatureAndVoltage/DS2438TemperatureAndVoltage.ino b/examples/DS2438TemperatureAndVoltage/DS2438TemperatureAndVoltage.ino new file mode 100644 index 0000000..f0f3f1f --- /dev/null +++ b/examples/DS2438TemperatureAndVoltage/DS2438TemperatureAndVoltage.ino @@ -0,0 +1,55 @@ +/* + * DS2438TemperatureAndVoltage + * + * This example demonstrates the use of the DS2438 Library to read temperature and + * voltage from a Dallas Semiconductor DS2438 battery monitor using the Arduino + * OneWire library. + * + * by Joe Bechter + * + * (C) 2012, bechter.com + * + * All files, software, schematics and designs are provided as-is with no warranty. + * All files, software, schematics and designs are for experimental/hobby use. + * Under no circumstances should any part be used for critical systems where safety, + * life or property depends upon it. You are responsible for all use. + * You are free to use, modify, derive or otherwise extend for your own non-commercial purposes provided + * 1. No part of this software or design may be used to cause injury or death to humans or animals. + * 2. Use is non-commercial. + * 3. Credit is given to the author (i.e. portions © bechter.com), and provide a link to the original source. + * + */ + +#include +#include +#include + +// define the Arduino digital I/O pin to be used for the 1-Wire network here +const uint8_t ONE_WIRE_PIN = 2; + +// define the 1-Wire address of the DS2438 battery monitor here (lsb first) +uint8_t DS2438_address[] = { 0x26, 0x45, 0xe6, 0xf7, 0x00, 0x00, 0x00, 0x4e }; + +OneWire ow(ONE_WIRE_PIN); +DS2438 ds2438(&ow, DS2438_address); + +void setup() { + Serial.begin(9600); + ds2438.begin(); +} + +void loop() { + ds2438.update(); + if (ds2438.isError()) { + Serial.println("Error reading from DS2438 device"); + } else { + Serial.print("Temperature = "); + Serial.print(ds2438.getTemperature(), 1); + Serial.print("C, Channel A = "); + Serial.print(ds2438.getVoltage(DS2438_CHA), 1); + Serial.print("v, Channel B = "); + Serial.print(ds2438.getVoltage(DS2438_CHB), 1); + Serial.println("v."); + } + delay(500); +}