Driver for the NXP PCT2075 digital temperature sensor and thermal watchdog

NXP PCT2075 temperature sensor driver for mbed

This library is a driver for the [NXP PCT2075](http://www.nxp.com/products/sensors/i2c-temperature-voltage-monitors/ic-bus-fm-plus-1-degree-c-accuracy-digital-temperature-sensor-and-thermal-watchdog:PCT2075). It only handles the I2C communication with the sensor, it does not handle the OS interrupt line. The [mbed InterruptIn](https://developer.mbed.org/handbook/InterruptIn) library can be used for this.

example usage

#include <mbed.h>
#include <PCT2075.h>
 
Serial s(USBTX, USBRX); // tx, rx
 
InterruptIn TempPinInt(PC4);
LowPowerTicker ticker;
 
static volatile bool temp_int = false;
static volatile bool tick_int = false;
 
int main( void )
{
    TempPinInt.mode(PullUp);
 
    PCT2075::Configuration config = {
        PCT2075::OS_FAULT_QUE_1,
        PCT2075::OS_ACTIVE_LOW,
        PCT2075::OS_MODE_INTERRUPT,
        PCT2075::DEVICE_MODE_SHUTDOWN
    };
    temp_sensor.set_configuration(config);
    temp_sensor.set_idle_time(PCT2075::TIDLE_MAX);
    
    temp_sensor.set_hyst_temperature(2000);
    temp_sensor.set_os_temperature(2500);
    
    TempPinInt.fall(&on_fall);
    ticker.attach(&tick, 2.0);
 
    while(true) {
        sleep(); // wait to be woken up by ticker or temp sensor
 
        if (tick_int) {
            s.printf("Tick\r\n");
            config.device_mode = PCT2075::DEVICE_MODE_NORMAL;
            temp_sensor.set_configuration(config);
            tick_int = false;
        }
 
        if (temp_int) {
            config.device_mode = PCT2075::DEVICE_MODE_SHUTDOWN;
            temp_sensor.set_configuration(config);
            uint16_t t = temp_sensor.read_temperature();
            s.printf("Temperature: %d\r\n", t);
            temp_int = false;
        }
    }
}
 

Files at this revision

API Documentation at this revision

Comitter:
Seppe Stas
Date:
Fri Sep 23 15:38:34 2016 +0200
Parent:
0:396665cc3ea0
Commit message:
Added library files

Changed in this revision

PCT2075.cpp Show annotated file Show diff for this revision Revisions of this file
PCT2075.h Show annotated file Show diff for this revision Revisions of this file
diff -r 396665cc3ea0 -r a2b7889eb4e9 PCT2075.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCT2075.cpp	Fri Sep 23 15:38:34 2016 +0200
@@ -0,0 +1,214 @@
+#include "PCT2075.h"
+
+// R/W - Configuration register: contains a single 8-bit data byte to set the
+// device operating condition; default = 0
+static const char configuration_register    = 0x01;
+// Read only - Temperature register: contains two 8-bit data bytes to store the
+// measured Temp data
+static const char temperature_register      = 0x00;
+// R/W - Overtemperature shutdown threshold register: contains two 8-bit data
+// bytes to store the overtemperature shutdown T ots limit; default = 80 °C
+static const char os_temperature_register   = 0x03;
+// R/W - Hysteresis register: contains two 8-bit data bytes to store the
+// hysteresis T hys limit; default = 75 °C
+static const char hyst_temperature_register = 0x02;
+// R/W - Temperature conversion cycle; default = 100 ms
+static const char idle_time_register        = 0x04;
+
+PCT2075::PCT2075 (I2C &i2c_obj, uint8_t address) : i2c( i2c_obj ) {
+    // I2C uses 7 bit addresses, so the address is left shifted by 1 and added
+    // with the R/W bit before using it
+    address_write = (address << 1)|0;
+    address_read  = (address << 1)|1;
+}
+
+PCT2075::~PCT2075 () {
+    ;
+}
+
+static PCT2075::OSFaultQue parse_os_fault_que(char config_byte) {
+    switch ((config_byte >> 3) & 0x03) {
+    case 0:
+        return PCT2075::OS_FAULT_QUE_1;
+    case 1:
+        return PCT2075::OS_FAULT_QUE_2;
+    case 2:
+        return PCT2075::OS_FAULT_QUE_4;
+    case 3:
+        return PCT2075::OS_FAULT_QUE_6;
+    }
+
+    return PCT2075::OS_FAULT_QUE_1;
+}
+
+PCT2075::Configuration PCT2075::get_configuration() {
+    char data;
+
+    i2c.write( address_write, &configuration_register, 1, true);
+    i2c.read( address_read, &data, 1 );
+
+    PCT2075::Configuration config = {
+        parse_os_fault_que(data),
+        ((data >> 2) & 0x01) == 0x00 ? OS_ACTIVE_LOW : OS_ACTIVE_HIGH,
+        ((data >> 1) & 0x01) == 0x00 ? OS_MODE_COMP : OS_MODE_INTERRUPT,
+        (data & 0x01) == 0x00 ? DEVICE_MODE_NORMAL : DEVICE_MODE_SHUTDOWN
+    };
+
+    return config;
+}
+
+void PCT2075::set_configuration(Configuration& config) {
+    char command[2] = {configuration_register, 2};
+
+    switch (config.os_fault_que) {
+    case OS_FAULT_QUE_1:
+        break;
+    case OS_FAULT_QUE_2:
+        command[1] |= 1 << 3;
+        break;
+    case OS_FAULT_QUE_4:
+        command[1] |= 2 << 3;
+        break;
+    case OS_FAULT_QUE_6:
+        command[1] |= 3 << 3;
+        break;
+    }
+
+    if (config.os_polarity == OS_ACTIVE_HIGH)
+        command[1] |= 1 << 2;
+    if (config.os_mode == OS_MODE_INTERRUPT)
+        command[1] |= 1 << 1;
+    if (config.device_mode == DEVICE_MODE_SHUTDOWN)
+        command[1] |= 1;
+
+    i2c.write(address_write, command, 2);
+}
+
+void PCT2075::set_os_fault_queue(PCT2075::OSFaultQue fault_que) {
+    Configuration conf = get_configuration();
+    conf.os_fault_que = fault_que;
+    set_configuration(conf);
+}
+
+void PCT2075::set_os_polarity(PCT2075::OSPolarity polarity) {
+    Configuration conf = get_configuration();
+    conf.os_polarity = polarity;
+    set_configuration(conf);
+}
+
+void PCT2075::set_os_mode(PCT2075::OSMode os_mode) {
+    Configuration conf = get_configuration();
+    conf.os_mode = os_mode;
+    set_configuration(conf);
+}
+
+void PCT2075::set_device_mode(PCT2075::DeviceMode device_mode) {
+    Configuration conf = get_configuration();
+    conf.device_mode = device_mode;
+    set_configuration(conf);
+}
+
+void PCT2075::shutdown_mode() {
+    set_device_mode(DEVICE_MODE_SHUTDOWN);
+}
+
+void PCT2075::normal_mode() {
+    set_device_mode(DEVICE_MODE_NORMAL);
+}
+
+int16_t PCT2075::read_temperature() {
+    char data[2];
+
+    i2c.write(address_write, &temperature_register, 1, true);
+    i2c.read(address_read, data, 2);
+
+    int16_t temperature = (data[0] << 8) | data[1];
+    temperature = temperature >> 5;
+
+    // temperature should not overflow since 0x3FF * 25 < MaxInt16
+    // and 0x4FF * 25 < MaxUint16
+    return (temperature*25) / 2; // = temperature / 8 * 100
+}
+
+int16_t PCT2075::get_os_temperature() {
+    char data[2];
+
+    i2c.write(address_write, &os_temperature_register, 1, true);
+    i2c.read(address_read, data, 2);
+
+    int16_t temperature = (data[0] << 8) | data[1];
+    temperature = temperature >> 7;
+
+    return temperature * 50; // = temperature / 2 * 100
+}
+
+void PCT2075::set_os_temperature(int16_t temperature) {
+    char command[3];
+
+    if( temperature > TEMP_MAX ) {
+        temperature = TEMP_MAX;
+    } else if (temperature < TEMP_MIN) {
+        temperature = TEMP_MIN;
+    }
+
+    temperature = temperature / 50; // = temperature / 100 * 2
+    command[0] = os_temperature_register;
+    command[1] = (char)(temperature >> 1); // = << 7 and >> 8
+    command[2] = (char)((temperature << 7) & 0x80);
+
+    i2c.write(address_write, command, 3);
+}
+
+int16_t PCT2075::get_hyst_temperature() {
+    char data[2];
+
+    i2c.write(address_write, &hyst_temperature_register, 1, true);
+    i2c.read(address_read, data, 2);
+
+    int16_t temperature = (data[0] << 8) | data[1];
+    temperature = temperature >> 7;
+
+    return temperature * 50; // = temperature / 2 * 100
+}
+
+void PCT2075::set_hyst_temperature (int16_t temperature) {
+    char command[3];
+
+    if( temperature > TEMP_MAX ) {
+        temperature = TEMP_MAX;
+    } else if ( temperature < TEMP_MIN ) {
+        temperature = TEMP_MIN;
+    }
+
+    temperature = temperature / 50; // = temperature / 100 * 2
+    command[0] = hyst_temperature_register;
+    command[1] = (char)(temperature >> 1); // = << 7 and >> 8
+    command[2] = (char)((temperature << 7) & 0x80);
+
+    i2c.write(address_write, command, 2);
+}
+
+uint16_t PCT2075::get_idle_time() {
+    char data[2];
+
+    i2c.write(address_write, &idle_time_register, 1, true);
+    i2c.read(address_read, data, 1);
+
+    uint16_t time = (uint16_t)data[0];
+    return  time * 100;
+}
+
+void PCT2075::set_idle_time(uint16_t time) {
+    char command[2];
+
+    if( time > TIDLE_MAX) {
+        time = TIDLE_MAX;
+    } else if( time < TIDLE_MIN ) {
+        time = TIDLE_MIN;
+    }
+
+    command[0] = idle_time_register;
+    command[1] = (char)(time / 100);
+
+    i2c.write(address_write, command, 2);
+}
diff -r 396665cc3ea0 -r a2b7889eb4e9 PCT2075.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCT2075.h	Fri Sep 23 15:38:34 2016 +0200
@@ -0,0 +1,109 @@
+#ifndef _pct2075_h_
+#define _pct2075_h_
+
+#include "mbed.h"
+
+class PCT2075 {
+  private:
+    I2C     &i2c;
+    uint8_t  address_write;
+    uint8_t  address_read;
+
+  public:
+    static const int16_t  TEMP_MAX  = 12500; // centi-°C
+    static const int16_t  TEMP_MIN  = -5500; // centi-°C
+    static const uint16_t TIDLE_MAX =  3100; // ms
+    static const uint16_t TIDLE_MIN =   100; // ms
+
+    // Fault queue is defined as the number of faults that must occur
+    // consecutively to activate the OS output. It is provided to avoid false
+    // tripping due to noise. Because faults are determined at the end of data
+    // conversions, fault queue is also defined as the number of consecutive
+    // conversions returning a temperature trip.
+    enum OSFaultQue {
+        OS_FAULT_QUE_1 = 0,
+        OS_FAULT_QUE_2 = 1,
+        OS_FAULT_QUE_4 = 2,
+        OS_FAULT_QUE_6 = 3
+    };
+
+    enum OSPolarity {
+        OS_ACTIVE_LOW  = 0,
+        OS_ACTIVE_HIGH = 1
+    };
+
+    enum OSMode {
+        OS_MODE_COMP      = 0,
+        OS_MODE_INTERRUPT = 1
+    };
+
+    // In shutdown mode, the PCT2075 draws a small current of <1.0 µA and the
+    // power dissipation is minimized; the temperature conversion stops, but the
+    // I2C-bus interface remains active and register write/read operation can be
+    // performed. When the shutdown is set, the OS output will be unchanged in
+    // comparator mode and reset in interrupt mode.
+    enum DeviceMode {
+        DEVICE_MODE_NORMAL   = 0,
+        DEVICE_MODE_SHUTDOWN = 1
+    };
+
+    struct Configuration {
+         OSFaultQue os_fault_que;
+         OSPolarity os_polarity;
+         OSMode     os_mode;
+         DeviceMode device_mode;
+    };
+
+    PCT2075 (I2C &i2c_obj, uint8_t address = 0x48);
+
+    ~PCT2075();
+    int16_t PCT2075_os_temp;
+    int16_t PCT2075_hyst_temp;
+    uint8_t PCT2075_temp_idle_cycle;
+
+    Configuration get_configuration();
+    void set_configuration(Configuration& config);
+
+    // Shorthand functions for changing one parameter of the configuration
+    // without changing the other parameters.
+    // Note: When changing multiple parameters it is more efficient to batch
+    // them using set_configuration.
+    void set_os_fault_queue(OSFaultQue fault_que);
+    void set_os_polarity(OSPolarity polarity);
+    void set_os_mode(OSMode mode);
+    void set_device_mode(DeviceMode mode);
+    void shutdown_mode();
+    void normal_mode();
+
+    // Returns the temperature in centi-degrees C,
+    // resolution of .125 degrees, rounded down to .1 degrees
+    int16_t read_temperature();
+
+    // Get the OS temperature in centi-degrees C,
+    // rounded to .5 degrees C
+    int16_t get_os_temperature();
+    // Set the OS temperature in centi-degrees C,
+    // rounded to .5 degrees C
+    void set_os_temperature(int16_t temperature);
+
+    // Get the hysteresis temperature in centi-degrees C,
+    // rounded to .5 degrees C
+    int16_t get_hyst_temperature();
+    // Set the hysteresis temperature in centi-degrees C,
+    // rounded to .5 degrees C
+    void set_hyst_temperature(int16_t temperature);
+
+    // Get idle time in ms, resolution of 100ms (deci-seconds)
+    uint16_t get_idle_time();
+    // Set idle time in ms, rounded down to 100ms (deci-seconds)
+    // In normal operation mode, the temp-to-digital conversion is executed
+    // every 100 ms or other programmed value and the Temp register is updated
+    // at the end of each conversion. During each ‘conversion period’ (Tconv) of
+    // about 100 ms, the device takes only about 28 ms, called ‘temperature
+    // conversion time’ (tconv(T)), to complete a temperature-to-data conversion
+    // and then becomes idle for the time remaining in the period. This feature
+    // is implemented to significantly reduce the device power dissipation.
+    void set_idle_time(uint16_t time);
+};
+
+#endif // _PCT2075_H_