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; } } }
Revision 1:a2b7889eb4e9, committed 2016-09-23
- 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_