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;
        }
    }
}
 
Committer:
Seppe Stas
Date:
Fri Sep 23 15:38:34 2016 +0200
Revision:
1:a2b7889eb4e9
Added library files

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Seppe Stas 1:a2b7889eb4e9 1 #include "PCT2075.h"
Seppe Stas 1:a2b7889eb4e9 2
Seppe Stas 1:a2b7889eb4e9 3 // R/W - Configuration register: contains a single 8-bit data byte to set the
Seppe Stas 1:a2b7889eb4e9 4 // device operating condition; default = 0
Seppe Stas 1:a2b7889eb4e9 5 static const char configuration_register = 0x01;
Seppe Stas 1:a2b7889eb4e9 6 // Read only - Temperature register: contains two 8-bit data bytes to store the
Seppe Stas 1:a2b7889eb4e9 7 // measured Temp data
Seppe Stas 1:a2b7889eb4e9 8 static const char temperature_register = 0x00;
Seppe Stas 1:a2b7889eb4e9 9 // R/W - Overtemperature shutdown threshold register: contains two 8-bit data
Seppe Stas 1:a2b7889eb4e9 10 // bytes to store the overtemperature shutdown T ots limit; default = 80 °C
Seppe Stas 1:a2b7889eb4e9 11 static const char os_temperature_register = 0x03;
Seppe Stas 1:a2b7889eb4e9 12 // R/W - Hysteresis register: contains two 8-bit data bytes to store the
Seppe Stas 1:a2b7889eb4e9 13 // hysteresis T hys limit; default = 75 °C
Seppe Stas 1:a2b7889eb4e9 14 static const char hyst_temperature_register = 0x02;
Seppe Stas 1:a2b7889eb4e9 15 // R/W - Temperature conversion cycle; default = 100 ms
Seppe Stas 1:a2b7889eb4e9 16 static const char idle_time_register = 0x04;
Seppe Stas 1:a2b7889eb4e9 17
Seppe Stas 1:a2b7889eb4e9 18 PCT2075::PCT2075 (I2C &i2c_obj, uint8_t address) : i2c( i2c_obj ) {
Seppe Stas 1:a2b7889eb4e9 19 // I2C uses 7 bit addresses, so the address is left shifted by 1 and added
Seppe Stas 1:a2b7889eb4e9 20 // with the R/W bit before using it
Seppe Stas 1:a2b7889eb4e9 21 address_write = (address << 1)|0;
Seppe Stas 1:a2b7889eb4e9 22 address_read = (address << 1)|1;
Seppe Stas 1:a2b7889eb4e9 23 }
Seppe Stas 1:a2b7889eb4e9 24
Seppe Stas 1:a2b7889eb4e9 25 PCT2075::~PCT2075 () {
Seppe Stas 1:a2b7889eb4e9 26 ;
Seppe Stas 1:a2b7889eb4e9 27 }
Seppe Stas 1:a2b7889eb4e9 28
Seppe Stas 1:a2b7889eb4e9 29 static PCT2075::OSFaultQue parse_os_fault_que(char config_byte) {
Seppe Stas 1:a2b7889eb4e9 30 switch ((config_byte >> 3) & 0x03) {
Seppe Stas 1:a2b7889eb4e9 31 case 0:
Seppe Stas 1:a2b7889eb4e9 32 return PCT2075::OS_FAULT_QUE_1;
Seppe Stas 1:a2b7889eb4e9 33 case 1:
Seppe Stas 1:a2b7889eb4e9 34 return PCT2075::OS_FAULT_QUE_2;
Seppe Stas 1:a2b7889eb4e9 35 case 2:
Seppe Stas 1:a2b7889eb4e9 36 return PCT2075::OS_FAULT_QUE_4;
Seppe Stas 1:a2b7889eb4e9 37 case 3:
Seppe Stas 1:a2b7889eb4e9 38 return PCT2075::OS_FAULT_QUE_6;
Seppe Stas 1:a2b7889eb4e9 39 }
Seppe Stas 1:a2b7889eb4e9 40
Seppe Stas 1:a2b7889eb4e9 41 return PCT2075::OS_FAULT_QUE_1;
Seppe Stas 1:a2b7889eb4e9 42 }
Seppe Stas 1:a2b7889eb4e9 43
Seppe Stas 1:a2b7889eb4e9 44 PCT2075::Configuration PCT2075::get_configuration() {
Seppe Stas 1:a2b7889eb4e9 45 char data;
Seppe Stas 1:a2b7889eb4e9 46
Seppe Stas 1:a2b7889eb4e9 47 i2c.write( address_write, &configuration_register, 1, true);
Seppe Stas 1:a2b7889eb4e9 48 i2c.read( address_read, &data, 1 );
Seppe Stas 1:a2b7889eb4e9 49
Seppe Stas 1:a2b7889eb4e9 50 PCT2075::Configuration config = {
Seppe Stas 1:a2b7889eb4e9 51 parse_os_fault_que(data),
Seppe Stas 1:a2b7889eb4e9 52 ((data >> 2) & 0x01) == 0x00 ? OS_ACTIVE_LOW : OS_ACTIVE_HIGH,
Seppe Stas 1:a2b7889eb4e9 53 ((data >> 1) & 0x01) == 0x00 ? OS_MODE_COMP : OS_MODE_INTERRUPT,
Seppe Stas 1:a2b7889eb4e9 54 (data & 0x01) == 0x00 ? DEVICE_MODE_NORMAL : DEVICE_MODE_SHUTDOWN
Seppe Stas 1:a2b7889eb4e9 55 };
Seppe Stas 1:a2b7889eb4e9 56
Seppe Stas 1:a2b7889eb4e9 57 return config;
Seppe Stas 1:a2b7889eb4e9 58 }
Seppe Stas 1:a2b7889eb4e9 59
Seppe Stas 1:a2b7889eb4e9 60 void PCT2075::set_configuration(Configuration& config) {
Seppe Stas 1:a2b7889eb4e9 61 char command[2] = {configuration_register, 2};
Seppe Stas 1:a2b7889eb4e9 62
Seppe Stas 1:a2b7889eb4e9 63 switch (config.os_fault_que) {
Seppe Stas 1:a2b7889eb4e9 64 case OS_FAULT_QUE_1:
Seppe Stas 1:a2b7889eb4e9 65 break;
Seppe Stas 1:a2b7889eb4e9 66 case OS_FAULT_QUE_2:
Seppe Stas 1:a2b7889eb4e9 67 command[1] |= 1 << 3;
Seppe Stas 1:a2b7889eb4e9 68 break;
Seppe Stas 1:a2b7889eb4e9 69 case OS_FAULT_QUE_4:
Seppe Stas 1:a2b7889eb4e9 70 command[1] |= 2 << 3;
Seppe Stas 1:a2b7889eb4e9 71 break;
Seppe Stas 1:a2b7889eb4e9 72 case OS_FAULT_QUE_6:
Seppe Stas 1:a2b7889eb4e9 73 command[1] |= 3 << 3;
Seppe Stas 1:a2b7889eb4e9 74 break;
Seppe Stas 1:a2b7889eb4e9 75 }
Seppe Stas 1:a2b7889eb4e9 76
Seppe Stas 1:a2b7889eb4e9 77 if (config.os_polarity == OS_ACTIVE_HIGH)
Seppe Stas 1:a2b7889eb4e9 78 command[1] |= 1 << 2;
Seppe Stas 1:a2b7889eb4e9 79 if (config.os_mode == OS_MODE_INTERRUPT)
Seppe Stas 1:a2b7889eb4e9 80 command[1] |= 1 << 1;
Seppe Stas 1:a2b7889eb4e9 81 if (config.device_mode == DEVICE_MODE_SHUTDOWN)
Seppe Stas 1:a2b7889eb4e9 82 command[1] |= 1;
Seppe Stas 1:a2b7889eb4e9 83
Seppe Stas 1:a2b7889eb4e9 84 i2c.write(address_write, command, 2);
Seppe Stas 1:a2b7889eb4e9 85 }
Seppe Stas 1:a2b7889eb4e9 86
Seppe Stas 1:a2b7889eb4e9 87 void PCT2075::set_os_fault_queue(PCT2075::OSFaultQue fault_que) {
Seppe Stas 1:a2b7889eb4e9 88 Configuration conf = get_configuration();
Seppe Stas 1:a2b7889eb4e9 89 conf.os_fault_que = fault_que;
Seppe Stas 1:a2b7889eb4e9 90 set_configuration(conf);
Seppe Stas 1:a2b7889eb4e9 91 }
Seppe Stas 1:a2b7889eb4e9 92
Seppe Stas 1:a2b7889eb4e9 93 void PCT2075::set_os_polarity(PCT2075::OSPolarity polarity) {
Seppe Stas 1:a2b7889eb4e9 94 Configuration conf = get_configuration();
Seppe Stas 1:a2b7889eb4e9 95 conf.os_polarity = polarity;
Seppe Stas 1:a2b7889eb4e9 96 set_configuration(conf);
Seppe Stas 1:a2b7889eb4e9 97 }
Seppe Stas 1:a2b7889eb4e9 98
Seppe Stas 1:a2b7889eb4e9 99 void PCT2075::set_os_mode(PCT2075::OSMode os_mode) {
Seppe Stas 1:a2b7889eb4e9 100 Configuration conf = get_configuration();
Seppe Stas 1:a2b7889eb4e9 101 conf.os_mode = os_mode;
Seppe Stas 1:a2b7889eb4e9 102 set_configuration(conf);
Seppe Stas 1:a2b7889eb4e9 103 }
Seppe Stas 1:a2b7889eb4e9 104
Seppe Stas 1:a2b7889eb4e9 105 void PCT2075::set_device_mode(PCT2075::DeviceMode device_mode) {
Seppe Stas 1:a2b7889eb4e9 106 Configuration conf = get_configuration();
Seppe Stas 1:a2b7889eb4e9 107 conf.device_mode = device_mode;
Seppe Stas 1:a2b7889eb4e9 108 set_configuration(conf);
Seppe Stas 1:a2b7889eb4e9 109 }
Seppe Stas 1:a2b7889eb4e9 110
Seppe Stas 1:a2b7889eb4e9 111 void PCT2075::shutdown_mode() {
Seppe Stas 1:a2b7889eb4e9 112 set_device_mode(DEVICE_MODE_SHUTDOWN);
Seppe Stas 1:a2b7889eb4e9 113 }
Seppe Stas 1:a2b7889eb4e9 114
Seppe Stas 1:a2b7889eb4e9 115 void PCT2075::normal_mode() {
Seppe Stas 1:a2b7889eb4e9 116 set_device_mode(DEVICE_MODE_NORMAL);
Seppe Stas 1:a2b7889eb4e9 117 }
Seppe Stas 1:a2b7889eb4e9 118
Seppe Stas 1:a2b7889eb4e9 119 int16_t PCT2075::read_temperature() {
Seppe Stas 1:a2b7889eb4e9 120 char data[2];
Seppe Stas 1:a2b7889eb4e9 121
Seppe Stas 1:a2b7889eb4e9 122 i2c.write(address_write, &temperature_register, 1, true);
Seppe Stas 1:a2b7889eb4e9 123 i2c.read(address_read, data, 2);
Seppe Stas 1:a2b7889eb4e9 124
Seppe Stas 1:a2b7889eb4e9 125 int16_t temperature = (data[0] << 8) | data[1];
Seppe Stas 1:a2b7889eb4e9 126 temperature = temperature >> 5;
Seppe Stas 1:a2b7889eb4e9 127
Seppe Stas 1:a2b7889eb4e9 128 // temperature should not overflow since 0x3FF * 25 < MaxInt16
Seppe Stas 1:a2b7889eb4e9 129 // and 0x4FF * 25 < MaxUint16
Seppe Stas 1:a2b7889eb4e9 130 return (temperature*25) / 2; // = temperature / 8 * 100
Seppe Stas 1:a2b7889eb4e9 131 }
Seppe Stas 1:a2b7889eb4e9 132
Seppe Stas 1:a2b7889eb4e9 133 int16_t PCT2075::get_os_temperature() {
Seppe Stas 1:a2b7889eb4e9 134 char data[2];
Seppe Stas 1:a2b7889eb4e9 135
Seppe Stas 1:a2b7889eb4e9 136 i2c.write(address_write, &os_temperature_register, 1, true);
Seppe Stas 1:a2b7889eb4e9 137 i2c.read(address_read, data, 2);
Seppe Stas 1:a2b7889eb4e9 138
Seppe Stas 1:a2b7889eb4e9 139 int16_t temperature = (data[0] << 8) | data[1];
Seppe Stas 1:a2b7889eb4e9 140 temperature = temperature >> 7;
Seppe Stas 1:a2b7889eb4e9 141
Seppe Stas 1:a2b7889eb4e9 142 return temperature * 50; // = temperature / 2 * 100
Seppe Stas 1:a2b7889eb4e9 143 }
Seppe Stas 1:a2b7889eb4e9 144
Seppe Stas 1:a2b7889eb4e9 145 void PCT2075::set_os_temperature(int16_t temperature) {
Seppe Stas 1:a2b7889eb4e9 146 char command[3];
Seppe Stas 1:a2b7889eb4e9 147
Seppe Stas 1:a2b7889eb4e9 148 if( temperature > TEMP_MAX ) {
Seppe Stas 1:a2b7889eb4e9 149 temperature = TEMP_MAX;
Seppe Stas 1:a2b7889eb4e9 150 } else if (temperature < TEMP_MIN) {
Seppe Stas 1:a2b7889eb4e9 151 temperature = TEMP_MIN;
Seppe Stas 1:a2b7889eb4e9 152 }
Seppe Stas 1:a2b7889eb4e9 153
Seppe Stas 1:a2b7889eb4e9 154 temperature = temperature / 50; // = temperature / 100 * 2
Seppe Stas 1:a2b7889eb4e9 155 command[0] = os_temperature_register;
Seppe Stas 1:a2b7889eb4e9 156 command[1] = (char)(temperature >> 1); // = << 7 and >> 8
Seppe Stas 1:a2b7889eb4e9 157 command[2] = (char)((temperature << 7) & 0x80);
Seppe Stas 1:a2b7889eb4e9 158
Seppe Stas 1:a2b7889eb4e9 159 i2c.write(address_write, command, 3);
Seppe Stas 1:a2b7889eb4e9 160 }
Seppe Stas 1:a2b7889eb4e9 161
Seppe Stas 1:a2b7889eb4e9 162 int16_t PCT2075::get_hyst_temperature() {
Seppe Stas 1:a2b7889eb4e9 163 char data[2];
Seppe Stas 1:a2b7889eb4e9 164
Seppe Stas 1:a2b7889eb4e9 165 i2c.write(address_write, &hyst_temperature_register, 1, true);
Seppe Stas 1:a2b7889eb4e9 166 i2c.read(address_read, data, 2);
Seppe Stas 1:a2b7889eb4e9 167
Seppe Stas 1:a2b7889eb4e9 168 int16_t temperature = (data[0] << 8) | data[1];
Seppe Stas 1:a2b7889eb4e9 169 temperature = temperature >> 7;
Seppe Stas 1:a2b7889eb4e9 170
Seppe Stas 1:a2b7889eb4e9 171 return temperature * 50; // = temperature / 2 * 100
Seppe Stas 1:a2b7889eb4e9 172 }
Seppe Stas 1:a2b7889eb4e9 173
Seppe Stas 1:a2b7889eb4e9 174 void PCT2075::set_hyst_temperature (int16_t temperature) {
Seppe Stas 1:a2b7889eb4e9 175 char command[3];
Seppe Stas 1:a2b7889eb4e9 176
Seppe Stas 1:a2b7889eb4e9 177 if( temperature > TEMP_MAX ) {
Seppe Stas 1:a2b7889eb4e9 178 temperature = TEMP_MAX;
Seppe Stas 1:a2b7889eb4e9 179 } else if ( temperature < TEMP_MIN ) {
Seppe Stas 1:a2b7889eb4e9 180 temperature = TEMP_MIN;
Seppe Stas 1:a2b7889eb4e9 181 }
Seppe Stas 1:a2b7889eb4e9 182
Seppe Stas 1:a2b7889eb4e9 183 temperature = temperature / 50; // = temperature / 100 * 2
Seppe Stas 1:a2b7889eb4e9 184 command[0] = hyst_temperature_register;
Seppe Stas 1:a2b7889eb4e9 185 command[1] = (char)(temperature >> 1); // = << 7 and >> 8
Seppe Stas 1:a2b7889eb4e9 186 command[2] = (char)((temperature << 7) & 0x80);
Seppe Stas 1:a2b7889eb4e9 187
Seppe Stas 1:a2b7889eb4e9 188 i2c.write(address_write, command, 2);
Seppe Stas 1:a2b7889eb4e9 189 }
Seppe Stas 1:a2b7889eb4e9 190
Seppe Stas 1:a2b7889eb4e9 191 uint16_t PCT2075::get_idle_time() {
Seppe Stas 1:a2b7889eb4e9 192 char data[2];
Seppe Stas 1:a2b7889eb4e9 193
Seppe Stas 1:a2b7889eb4e9 194 i2c.write(address_write, &idle_time_register, 1, true);
Seppe Stas 1:a2b7889eb4e9 195 i2c.read(address_read, data, 1);
Seppe Stas 1:a2b7889eb4e9 196
Seppe Stas 1:a2b7889eb4e9 197 uint16_t time = (uint16_t)data[0];
Seppe Stas 1:a2b7889eb4e9 198 return time * 100;
Seppe Stas 1:a2b7889eb4e9 199 }
Seppe Stas 1:a2b7889eb4e9 200
Seppe Stas 1:a2b7889eb4e9 201 void PCT2075::set_idle_time(uint16_t time) {
Seppe Stas 1:a2b7889eb4e9 202 char command[2];
Seppe Stas 1:a2b7889eb4e9 203
Seppe Stas 1:a2b7889eb4e9 204 if( time > TIDLE_MAX) {
Seppe Stas 1:a2b7889eb4e9 205 time = TIDLE_MAX;
Seppe Stas 1:a2b7889eb4e9 206 } else if( time < TIDLE_MIN ) {
Seppe Stas 1:a2b7889eb4e9 207 time = TIDLE_MIN;
Seppe Stas 1:a2b7889eb4e9 208 }
Seppe Stas 1:a2b7889eb4e9 209
Seppe Stas 1:a2b7889eb4e9 210 command[0] = idle_time_register;
Seppe Stas 1:a2b7889eb4e9 211 command[1] = (char)(time / 100);
Seppe Stas 1:a2b7889eb4e9 212
Seppe Stas 1:a2b7889eb4e9 213 i2c.write(address_write, command, 2);
Seppe Stas 1:a2b7889eb4e9 214 }