From 91a1b3cbaa8d254d3b8ae9860a51ea777c45f9b8 Mon Sep 17 00:00:00 2001 From: mikaelpatel Date: Thu, 5 Oct 2017 23:17:21 +0200 Subject: [PATCH] Adding alarm search example sketch --- README.md | 4 ++- examples/Alarm/Alarm.ino | 69 ++++++++++++++++++++++++++++++++++++ examples/DS18B20/DS18B20.ino | 58 +++++++++++++++++++++++------- examples/DS1990A/DS1990A.ino | 14 ++++---- examples/Scanner/Scanner.ino | 25 +++++++++---- examples/Search/Search.ino | 11 +++--- library.properties | 2 +- mainpage.dox | 2 +- src/Driver/DS18B20.h | 33 ++++++++--------- src/OWI.h | 49 +++++++++++++++---------- 10 files changed, 200 insertions(+), 67 deletions(-) create mode 100644 examples/Alarm/Alarm.ino diff --git a/README.md b/README.md index b925588..4224429 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ The OWI library has been developed to support the implementation of 1-wire device drivers. The library includes an example device driver and a bus scanner. -Version: 1.4 +Version: 1.5 ## Classes @@ -16,6 +16,8 @@ Version: 1.4 * [DS18B20](./examples/DS18B20) * [DS1990A](./examples/DS1990A) * [Scanner](./examples/Scanner) +* [Search](./examples/Search) +* [Alarm](./examples/Alarm) ## Dependencies diff --git a/examples/Alarm/Alarm.ino b/examples/Alarm/Alarm.ino new file mode 100644 index 0000000..3b95634 --- /dev/null +++ b/examples/Alarm/Alarm.ino @@ -0,0 +1,69 @@ +#include "RTC.h" +#include "GPIO.h" +#include "OWI.h" +#include "Software/OWI.h" +#include "Driver/DS18B20.h" + +#if defined(ARDUINO_attiny) +#include "Software/Serial.h" +Software::Serial Serial; +Software::OWI owi; +#else +Software::OWI owi; +#endif + +DS18B20 sensor(owi); +RTC rtc; + +void setup() +{ + Serial.begin(57600); + while (!Serial); + + // Set sensor alarm triggers (20..25 C) and resolution (10 bits) + // Iterate though all thermometers and configure. + uint8_t* rom = sensor.rom(); + int8_t last = owi.FIRST; + do { + last = owi.search_rom(sensor.FAMILY_CODE, rom, last); + if (last == owi.ERROR) break; + sensor.resolution(10); + sensor.set_trigger(20, 25); + sensor.write_scratchpad(); + } while (last != owi.LAST); +} + +void loop() +{ + // Check if any thermometer sersors have exceeded thresholds. + // Broadcast a convert request to all thermometer sensors. + // Print timestamp and sensor identity and temperature. + + int8_t last = owi.FIRST; + uint8_t* rom = sensor.rom(); + bool triggered = false; + + if (!rtc.tick()) return; + if (!sensor.convert_request(true)) return; + do { + last = owi.alarm_search(rom, last); + if (last == owi.ERROR) break; + sensor.read_scratchpad(false); + if (!triggered) { + char daytime[32]; + struct tm now; + rtc.get_time(now); + isotime_r(&now, daytime); + Serial.print(daytime + 11); + triggered = true; + } + Serial.print(F(", ")); + for (size_t i = 1; i < owi.ROM_MAX - 1; i++) { + if (rom[i] < 0x10) Serial.print(0); + Serial.print(rom[i], HEX); + } + Serial.print(F(", ")); + Serial.print(sensor.temperature()); + } while (last != owi.LAST); + if (triggered) Serial.println(); +} diff --git a/examples/DS18B20/DS18B20.ino b/examples/DS18B20/DS18B20.ino index c27ece4..c5c04b9 100644 --- a/examples/DS18B20/DS18B20.ino +++ b/examples/DS18B20/DS18B20.ino @@ -21,29 +21,63 @@ void setup() void loop() { - uint8_t rom[owi.ROM_MAX] = { 0 }; - int8_t last = owi.FIRST; - int i = 0; - // Broadcast a convert request to all thermometer sensors + // Print list of sensors, rom code, and temperature + if (!sensor.convert_request(true)) return; - // Print list of sensors and temperature + int8_t last = owi.FIRST; + uint8_t* rom = sensor.rom(); + int id = 0; do { + // Search for the next digital thermometer last = owi.search_rom(sensor.FAMILY_CODE, rom, last); if (last == owi.ERROR) break; + + // Read the scratchpad with current temperature, tiggers, etc sensor.read_scratchpad(false); - Serial.print(i++); - Serial.print(F(":ROM:")); - for (size_t i = 0; i < sizeof(rom); i++) { - Serial.print(' '); - Serial.print(rom[i], HEX); - } + int8_t low, high; + sensor.get_trigger(low, high); + + // Print sequence number + Serial.print(id++); Serial.print(F(": ")); + + // Print family code + Serial.print(F("family=")); + Serial.print(rom[0], HEX); + + // Print serial number + Serial.print(F(", sn=")); + size_t i = 1; + do { + if (rom[i] < 0x10) Serial.print(0); + Serial.print(rom[i], HEX); + i += 1; + } while (i < owi.ROM_MAX - 1); + + // Print cyclic redundancy check sum + Serial.print(F(", crc=")); + if (rom[i] < 0x10) Serial.print(0); + Serial.print(rom[i], HEX); + + // Print conversion resolution + Serial.print(F(", resolution=")); + Serial.print(sensor.resolution()); + + // Print alarm trigger threshols + Serial.print(F(", trigger=[")); + Serial.print(low); + Serial.print(F("..")); + Serial.print(high); + + // And temperature + Serial.print(F("], temperature=")); Serial.print(sensor.temperature()); Serial.println(F(" C")); + } while (last != owi.LAST); - Serial.println(); + Serial.println(); delay(5000); } diff --git a/examples/DS1990A/DS1990A.ino b/examples/DS1990A/DS1990A.ino index 7879ba9..2fe5753 100644 --- a/examples/DS1990A/DS1990A.ino +++ b/examples/DS1990A/DS1990A.ino @@ -2,13 +2,6 @@ #include "GPIO.h" #include "Software/OWI.h" -// Table with valid keys (64 bit 1-Wire rom code, 8 bytes per entry) -const uint8_t KEY[] PROGMEM = { - 0x01, 0x23, 0x81, 0xa3, 0x09, 0x00, 0x00, 0x7b, - 0x01, 0x29, 0x01, 0x27, 0x09, 0x00, 0x00, 0xa8, - 0x01, 0x26, 0xd9, 0x3e, 0x09, 0x00, 0x00, 0x47 -}; - #if defined(ARDUINO_attiny) GPIO led; Software::OWI owi; @@ -17,6 +10,13 @@ GPIO led; Software::OWI owi; #endif +// Table with valid keys (64 bit 1-Wire rom code, 8 bytes per entry) +const uint8_t KEY[] PROGMEM = { + 0x01, 0x23, 0x81, 0xa3, 0x09, 0x00, 0x00, 0x7b, + 0x01, 0x29, 0x01, 0x27, 0x09, 0x00, 0x00, 0xa8, + 0x01, 0x26, 0xd9, 0x3e, 0x09, 0x00, 0x00, 0x47 +}; + void setup() { led.output(); diff --git a/examples/Scanner/Scanner.ino b/examples/Scanner/Scanner.ino index c488c0a..ff265a0 100644 --- a/examples/Scanner/Scanner.ino +++ b/examples/Scanner/Scanner.ino @@ -18,28 +18,41 @@ void setup() void loop() { + // Scan one-wire bus and print rom code for all detected devices + // Print family, serial number and cyclic redundancy check sum uint8_t rom[owi.ROM_MAX] = { 0 }; int8_t last = owi.FIRST; int id = 0; size_t i; - // Scan one-wire bus and print rom code for all detected devices do { last = owi.search_rom(0, rom, last); if (last == owi.ERROR) break; + + // Print sequence number Serial.print(id++); - Serial.print(':'); + Serial.print(F(": ")); + + // Print family code Serial.print(F("family=")); Serial.print(rom[0], HEX); + + // Print serial number Serial.print(F(", sn=")); - for (i = 1; i < sizeof(rom) - 1; i++) { + size_t i = 1; + do { + if (rom[i] < 0x10) Serial.print(0); Serial.print(rom[i], HEX); - if (i < sizeof(rom) - 2) Serial.print(' '); - } + i += 1; + } while (i < owi.ROM_MAX - 1); + + // Print cyclic redundancy check sum Serial.print(F(", crc=")); + if (rom[i] < 0x10) Serial.print(0); Serial.println(rom[i], HEX); + } while (last != owi.LAST); - Serial.println(); + Serial.println(); delay(5000); } diff --git a/examples/Search/Search.ino b/examples/Search/Search.ino index cda7961..25dc6f3 100644 --- a/examples/Search/Search.ino +++ b/examples/Search/Search.ino @@ -18,18 +18,21 @@ void setup() void loop() { + // Scan one-wire bus and print rom code for all detected devices + // on binary format and indicate discrepancy position. uint8_t rom[owi.ROM_MAX] = { 0 }; int8_t last = owi.FIRST; - - // Scan one-wire bus and print rom code for all detected devices + int i = 0; do { last = owi.search_rom(0, rom, last); if (last == owi.ERROR) break; + int pos = Serial.print(i++); + pos += Serial.print(':'); for (size_t i = 0; i < sizeof(rom); i++) for (uint8_t mask = 0x80; mask != 0; mask >>= 1) - Serial.print(rom[i] & mask ? '1' : '0' ); + Serial.print((rom[i] & mask) != 0); Serial.println(); - for (int i = 0; i < last - 1; i++) Serial.print('-'); + for (int i = 0; i < last - 1 + pos; i++) Serial.print('-'); Serial.println('*'); } while (last != owi.LAST); Serial.println(); diff --git a/library.properties b/library.properties index 9d6662c..ddc8a9d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Arduino-OWI -version=1.4 +version=1.5 author=Mikael Patel maintainer=Mikael Patel sentence=One-Wire Interface (OWI) library for Arduino. diff --git a/mainpage.dox b/mainpage.dox index fb4aa85..39a480a 100644 --- a/mainpage.dox +++ b/mainpage.dox @@ -4,7 +4,7 @@ The OWI library has been developed to support the implementation of 1-wire device drivers. Includes abstract OWI bus manager class, GPIO based Software::OWI bus manager and device driver for DS18B20. -Version: 1.4 +Version: 1.5 */ /** @page License diff --git a/src/Driver/DS18B20.h b/src/Driver/DS18B20.h index 94038b6..bb9808b 100644 --- a/src/Driver/DS18B20.h +++ b/src/Driver/DS18B20.h @@ -33,7 +33,6 @@ * (Dn)----------+-----2-|DQ | | * (VCC)---------------3-|VDD |/ * +------------+ - * * @endcode * * @section References @@ -44,6 +43,9 @@ class DS18B20 : public OWI::Device { /** Device family code. */ static const uint8_t FAMILY_CODE = 0x28; + /** Max conversion time for 12-bit conversion in milli-seconds. */ + static const uint16_t MAX_CONVERSION_TIME = 750; + /** * Construct a DS18B20 device connected to the given 1-Wire bus. * @param[in] owi bus manager. @@ -51,7 +53,7 @@ class DS18B20 : public OWI::Device { */ DS18B20(OWI& owi, uint8_t* rom = NULL) : OWI::Device(owi, rom), - m_start(0L), + m_start(0), m_converting(false) {} @@ -81,9 +83,7 @@ class DS18B20 : public OWI::Device { /** * Get the latest temperature reading from the local memory scratchpad. * Call convert_request() and read_scratchpad() before accessing the - * scratchpad. Returns at highest resolution a fixed point<12,4> - * point number. For 11-bit resolution, bit 0 is undefined, 10-bits - * bit 1 and 0, and so on (LSB). + * scratchpad. * @return temperature */ float temperature() const @@ -114,8 +114,9 @@ class DS18B20 : public OWI::Device { } /** - * Initiate temperature conversion. - * @param[in] broadcast flag. + * Initiate temperature conversion. Call with broadcast parameter + * true(1) to issue skip_rom(). + * @param[in] broadcast flag (default false). * @return true(1) if successful otherwise false(0). */ bool convert_request(bool broadcast = false) @@ -126,7 +127,7 @@ class DS18B20 : public OWI::Device { else { if (!m_owi.match_rom(m_rom)) return (false); } - m_owi.write(CONVERT_T, CHARBITS); + m_owi.write(CONVERT_T); m_start = millis(); m_converting = true; return (true); @@ -135,15 +136,18 @@ class DS18B20 : public OWI::Device { /** * Read the contents of the scratchpad to local memory. An internal * delay will occur if a convert_request() is pending. The delay is - * at most max conversion time (750 ms). - * @param[in] match rom code. + * at most max conversion time (750 ms). Call with match parameter + * false if used with search_rom(). + * @param[in] match rom code (default true). * @return true(1) if successful otherwise false(0). */ bool read_scratchpad(bool match = true) { + // Check if a conversion is in progress if (m_converting) { - int32_t ms = millis() - m_start; + uint16_t ms = millis() - m_start; uint16_t conv_time = (MAX_CONVERSION_TIME >> (12 - resolution())); + // May need to wait for the conversion to complete if (ms < conv_time) { ms = conv_time - ms; delay(ms); @@ -220,12 +224,9 @@ class DS18B20 : public OWI::Device { static const uint8_t CONFIG_MAX = 3; /** Watchdog millis on convert_request(). */ - uint32_t m_start; + uint16_t m_start; /** Convert request pending. */ - uint8_t m_converting; - - /** Max conversion time for 12-bit conversion in milli-seconds. */ - static const uint16_t MAX_CONVERSION_TIME = 750; + bool m_converting; }; #endif diff --git a/src/OWI.h b/src/OWI.h index 47e72af..58a5f9c 100644 --- a/src/OWI.h +++ b/src/OWI.h @@ -1,6 +1,6 @@ /** * @file OWI.h - * @version 1.0 + * @version 1.1 * * @section License * Copyright (C) 2017, Mikael Patel @@ -24,14 +24,14 @@ #endif /** - * One Wire Interface (OWI) abstract class. + * One Wire Interface (OWI) Bus Manager abstract class. */ class OWI { public: - /** ROM size in bytes. */ + /** One Wire device identity ROM size in bytes. */ static const size_t ROM_MAX = 8; - /** ROM size in bits. */ + /** One Wire device identity ROM size in bits. */ static const size_t ROMBITS = ROM_MAX * CHARBITS; /** @@ -45,18 +45,18 @@ class OWI { /** * @override{OWI} * Read the given number of bits from the one wire bus. Default - * number of bits is 8. Calculate partial check-sum. - * @param[in] bits to be read. + * number of bits is CHARBITS (8). Calculates partial check-sum. + * @param[in] bits to be read (default CHARBITS). * @return value read. */ virtual uint8_t read(uint8_t bits = CHARBITS) = 0; /** * Read given number of bytes from one wire bus (device) to given - * buffer. Return true(1) if correctly read otherwise false(0). + * buffer. * @param[in] buf buffer pointer. * @param[in] count number of bytes to read. - * @return bool. + * @return true(1) if correctly read otherwise false(0). */ bool read(void* buf, size_t count) { @@ -71,7 +71,7 @@ class OWI { * Write the given value to the one wire bus. The bits are written * from LSB to MSB. * @param[in] value to write. - * @param[in] bits to be written. + * @param[in] bits to be written (default CHARBITS). */ virtual void write(uint8_t value, uint8_t bits = CHARBITS) = 0; @@ -89,7 +89,7 @@ class OWI { while (count--) write(*bp++); } - /** Search position. */ + /** Search position and return values. */ enum { FIRST = -1, //!< Start position of search. ERROR = -1, //!< Error during search. @@ -98,6 +98,7 @@ class OWI { /** * Search device rom given the last position of discrepancy. + * Return position of difference or negative error code. * @param[in] family code. * @param[in] code device identity. * @param[in] last position of discrepancy (default FIRST). @@ -166,13 +167,13 @@ class OWI { } /** - * Abstract One-Wire Interface Device Driver class. + * One-Wire Interface (OWI) Device Driver abstract class. */ class Device { public: /** - * Construct One-Wire Interface Device Driver with given bus and - * device address. + * Construct One-Wire Interface (OWI) Device Driver with given bus + * and device address. * @param[in] owi bus manager. * @param[in] rom code (default NULL). */ @@ -191,20 +192,29 @@ class OWI { memcpy(m_rom, rom, ROM_MAX); } + /** + * Set device rom code. + * @param[in] rom code in program memory. + */ + void rom_P(const uint8_t* rom) + { + memcpy_P(m_rom, rom, ROM_MAX); + } + /** * Get device rom code. * @return rom code. */ - const uint8_t* rom() + uint8_t* rom() { return (m_rom); } protected: - /** One-Wire Interface Manager. */ + /** One-Wire Bus Manager. */ OWI& m_owi; - /** Device address. */ + /** Device rom idenity code. */ uint8_t m_rom[ROM_MAX]; }; @@ -227,9 +237,10 @@ class OWI { uint8_t m_crc; /** - * Search device rom given the last position of discrepancy. - * @param[in] code device identity. - * @param[in] last position of discrepancy. + * Search device rom given the last position of discrepancy and + * partial or full rom code. + * @param[in] code device identity rom. + * @param[in] last position of discrepancy (default FIRST). * @return position of difference or negative error code. */ int8_t search(uint8_t* code, int8_t last = FIRST)