mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
272 lines
5.1 KiB
C++
272 lines
5.1 KiB
C++
//
|
|
// FILE: mcp9808.cpp
|
|
// AUTHOR: Rob Tillaart
|
|
// VERSION: 0.2.1
|
|
// PURPOSE: Arduino Library for I2C mcp9808 temperature sensor
|
|
// DATE: 2020-05-03
|
|
// URL: https://github.com/RobTillaart/MCP9808_RT
|
|
//
|
|
// HISTORY:
|
|
// 0.1.0 2020-05-03 initial version
|
|
// 0.1.1 2020-11-12 refactor
|
|
// 0.1.2 2020-11-16 removed hasAlert, removed setAlertPin,
|
|
// added 2 alert examples, refactor low level
|
|
// 0.1.3 2021-01-01 Arduino-ci + unit test
|
|
// 0.1.4 2021-11-08 update build-CI, badges
|
|
// default offset for offset
|
|
// default Wire for I2C bus - setAddress()
|
|
// 0.2.0 2021-11-19 fix #7 negative temperature
|
|
// 0.2.1 2021-12-21 update library.json, license, minor edits
|
|
|
|
|
|
#include "mcp9808.h"
|
|
|
|
#define MCP9808_RFU 0x00
|
|
#define MCP9808_CONFIG 0x01
|
|
#define MCP9808_TUPPER 0x02
|
|
#define MCP9808_TLOWER 0x03
|
|
#define MCP9808_TCRIT 0x04
|
|
#define MCP9808_TA 0x05
|
|
#define MCP9808_MID 0x06
|
|
#define MCP9808_DID 0x07
|
|
#define MCP9808_RES 0x08
|
|
|
|
|
|
/*
|
|
0000 = RFU, Reserved for Future Use (Read-Only register)
|
|
0001 = Configuration register (CONFIG)
|
|
0010 = Alert Temperature Upper Boundary Trip register (TUPPER)
|
|
0011 = Alert Temperature Lower Boundary Trip register (TLOWER)
|
|
0100 = Critical Temperature Trip register (TCRIT)
|
|
0101 = Temperature register (TA)
|
|
0110 = Manufacturer ID register
|
|
0111 = Device ID/Revision register
|
|
1000 = Resolution register
|
|
1xxx = Reserved(1)
|
|
*/
|
|
|
|
|
|
#if defined(ESP8266) || defined(ESP32)
|
|
MCP9808::MCP9808(const uint8_t address, const uint8_t dataPin, const uint8_t clockPin)
|
|
{
|
|
_address = address;
|
|
if ((address < 24) || (_address > 31)) return;
|
|
_wire = &Wire;
|
|
|
|
if ((dataPin < 255) && (clockPin < 255))
|
|
{
|
|
_wire->begin(dataPin, clockPin);
|
|
} else {
|
|
_wire->begin();
|
|
}
|
|
}
|
|
#else
|
|
MCP9808::MCP9808(const uint8_t address)
|
|
{
|
|
MCP9808::setAddress(address, &Wire);
|
|
}
|
|
#endif
|
|
|
|
|
|
bool MCP9808::setAddress(const uint8_t address, TwoWire *wire)
|
|
{
|
|
if ((address < 24) || (address > 31)) return false;
|
|
_address = address;
|
|
_wire = wire;
|
|
_wire->begin();
|
|
return true;
|
|
}
|
|
|
|
|
|
bool MCP9808::isConnected()
|
|
{
|
|
Wire.beginTransmission(_address);
|
|
return (Wire.endTransmission() == 0);
|
|
}
|
|
|
|
|
|
void MCP9808::setConfigRegister(uint16_t configuration)
|
|
{
|
|
writeReg16(MCP9808_CONFIG, configuration);
|
|
}
|
|
|
|
|
|
uint16_t MCP9808::getConfigRegister()
|
|
{
|
|
return readReg16(MCP9808_CONFIG);
|
|
}
|
|
|
|
|
|
void MCP9808::setTupper(float temperature)
|
|
{
|
|
writeFloat(MCP9808_TUPPER, temperature);
|
|
}
|
|
|
|
|
|
float MCP9808::getTupper()
|
|
{
|
|
return readFloat(MCP9808_TUPPER);
|
|
}
|
|
|
|
|
|
void MCP9808::setTlower(float temperature)
|
|
{
|
|
writeFloat(MCP9808_TLOWER, temperature);
|
|
}
|
|
|
|
|
|
float MCP9808::getTlower()
|
|
{
|
|
return readFloat(MCP9808_TLOWER);
|
|
}
|
|
|
|
|
|
void MCP9808::setTcritical(float temperature)
|
|
{
|
|
writeFloat(MCP9808_TCRIT, temperature);
|
|
}
|
|
|
|
|
|
float MCP9808::getTcritical()
|
|
{
|
|
return readFloat(MCP9808_TCRIT);
|
|
}
|
|
|
|
|
|
void MCP9808::setOffset(float offset)
|
|
{
|
|
_offset = offset;
|
|
};
|
|
|
|
|
|
float MCP9808::getOffset()
|
|
{
|
|
return _offset;
|
|
};
|
|
|
|
|
|
float MCP9808::getTemperature()
|
|
{
|
|
return readFloat(MCP9808_TA) + _offset;
|
|
}
|
|
|
|
|
|
uint8_t MCP9808::getStatus()
|
|
{
|
|
return _status;
|
|
}
|
|
|
|
|
|
uint16_t MCP9808::getManufacturerID()
|
|
{
|
|
return readReg16(MCP9808_MID);
|
|
}
|
|
|
|
|
|
uint8_t MCP9808::getDeviceID()
|
|
{
|
|
return readReg16(MCP9808_DID) >> 8;
|
|
}
|
|
|
|
|
|
uint8_t MCP9808::getRevision()
|
|
{
|
|
return readReg16(MCP9808_DID) & 0xFF;
|
|
}
|
|
|
|
|
|
void MCP9808::setResolution(uint8_t resolution)
|
|
{
|
|
if (resolution < 4) writeReg8(MCP9808_RES, resolution);
|
|
}
|
|
|
|
|
|
uint8_t MCP9808::getResolution()
|
|
{
|
|
return readReg8(MCP9808_RES);
|
|
}
|
|
|
|
|
|
uint16_t MCP9808::getRFU()
|
|
{
|
|
return readReg16(MCP9808_RFU);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//
|
|
// PRIVATE
|
|
//
|
|
void MCP9808::writeFloat(uint8_t reg, float f)
|
|
{
|
|
bool neg = (f < 0.0);
|
|
if (neg) f = -f;
|
|
uint16_t val = uint16_t(f * 4 + 0.5) * 4;
|
|
if (neg) val |= 0x1000;
|
|
writeReg16(reg, val);
|
|
}
|
|
|
|
|
|
float MCP9808::readFloat(uint8_t reg)
|
|
{
|
|
uint16_t val = readReg16(reg);
|
|
if (reg == MCP9808_TA)
|
|
{
|
|
_status = (val & 0xE000) >> 13;
|
|
}
|
|
if (val & 0x1000) // negative value
|
|
{
|
|
return ((val & 0x0FFF) * 0.0625) - 256.0;
|
|
}
|
|
return (val & 0x0FFF) * 0.0625;
|
|
}
|
|
|
|
|
|
void MCP9808::writeReg8(uint8_t reg, uint8_t value)
|
|
{
|
|
if (reg > MCP9808_RES) return; // see p.16
|
|
Wire.beginTransmission(_address);
|
|
Wire.write(reg);
|
|
Wire.write(value);
|
|
Wire.endTransmission();
|
|
}
|
|
|
|
|
|
uint8_t MCP9808::readReg8(uint8_t reg)
|
|
{
|
|
if (reg > MCP9808_RES) return 0; // see p.16
|
|
Wire.beginTransmission(_address);
|
|
Wire.write(reg);
|
|
Wire.endTransmission();
|
|
Wire.requestFrom(_address, (uint8_t)1);
|
|
return Wire.read();
|
|
}
|
|
|
|
|
|
void MCP9808::writeReg16(uint8_t reg, uint16_t value)
|
|
{
|
|
if (reg > MCP9808_RES) return; // see p.16
|
|
Wire.beginTransmission(_address);
|
|
Wire.write(reg);
|
|
Wire.write(value >> 8); // hi byte
|
|
Wire.write(value & 0xFF); // lo byte
|
|
Wire.endTransmission();
|
|
}
|
|
|
|
|
|
uint16_t MCP9808::readReg16(uint8_t reg)
|
|
{
|
|
if (reg > MCP9808_RES) return 0; // see p.16
|
|
Wire.beginTransmission(_address);
|
|
Wire.write(reg);
|
|
Wire.endTransmission();
|
|
Wire.requestFrom(_address, (uint8_t)2);
|
|
uint16_t val = Wire.read() << 8;
|
|
val += Wire.read();
|
|
return val;
|
|
}
|
|
|
|
|
|
// -- END OF FILE --
|
|
|