library for AMS ENS210 temperature and humidity sensor
Dependents: rIoTwear-temp-humid
Diff: AMS_ENS210.cpp
- Revision:
- 0:7088b1bdc2e5
- Child:
- 1:94a79c88c105
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AMS_ENS210.cpp Tue Jan 17 14:23:13 2017 +0000 @@ -0,0 +1,221 @@ + +#include "AMS_ENS201.h" + +AMS_ENS210::AMS_ENS210(I2C * i2c) : + _temp_mode(CONFIG_TEMP_OP_MODE), + _humid_mode(CONFIG_HUMID_OP_MODE), + _power_mode(CONFIG_POWER_MODE), + _reset(0) +{ + _i2c = i2c; +} + +AMS_ENS210::AMS_ENS210(I2C * i2c, bool temp_single_shot, bool humid_single_shot) : + _temp_mode(temp_single_shot), + _humid_mode(humid_single_shot), + _power_mode(CONFIG_POWER_MODE), + _reset(0) +{ + _i2c = i2c; +} + +AMS_ENS210::AMS_ENS210(I2C * i2c, bool temp_single_shot, bool humid_single_shot, bool low_power) : + _temp_mode(temp_single_shot), + _humid_mode(humid_single_shot), + _power_mode(low_power), + _reset(0) +{ + _i2c = i2c; +} + +AMS_ENS210::AMS_ENS210() {} + +bool AMS_ENS210::init() { + + return write_config(); + +} + +bool AMS_ENS210::reset() { + + _reset = true; + bool success = write_config(true, false); + _reset = false; + + return success; + +} + +bool AMS_ENS210::power_mode(bool low_power) { + _power_mode = low_power; + write_config(true, false); +} + +bool AMS_ENS210::power_mode() { + return read_config(true, false)[0] & 1; // just mask bit 0 +} + +bool AMS_ENS210::temp_mode(bool single_shot) { + _temp_mode = single_shot; + write_config(false, true); +} + +bool AMS_ENS210::temp_mode() { + return read_config(false, true)[0] & 1; // just mask bit 0 +} + +bool AMS_ENS210::humid_mode(bool single_shot) { + _humid_mode = single_shot; + write_config(false, true); +} + +bool AMS_ENS210::humid_mode() { + return read_config(false, true)[0] & 0b10; // just mask bit 1 +} + +void AMS_ENS210::i2c_interface(I2C * i2c) { + _i2c = i2c; +} + +bool AMS_ENS210::start(bool temp, bool humid) { + char cmd[2] = {SENS_START, 0 | temp | (humid << 1)} + return _i2c->write(SLAVE_ADDR, cmd, 2) == 2; +} + +bool AMS_ENS210::stop(bool temp, bool humid) { + char cmd[2] = {SENS_STOP, 0 | temp | (humid << 1)} + return _i2c->write(SLAVE_ADDR, cmd, 2) == 2; +} + +bool AMS_ENS210::temp_is_measuring() { + char[1] output; + i2c_read(SENS_STATUS, output, 1); + return output[0] & 1; +} + +bool AMS_ENS210::humid_is _measuring() { + char[1] output; + i2c_read(SENS_STATUS, output, 1); + return output[0] >> 1 & 1; +} + +bool AMS_ENS210::temp_has_data() { + if (temp_mode()) { // when in single shot mode make sure sensor has started first + if (!temp_is_measuring()) + start(true, false); // set start bit if sensor is idle + } + + char output[3]; + i2c_read(SENS_TEMP, output, 3); + + // do crc7 + // Store read data to avoid reading from I2C again + temp_reading = 0 | output[0] | (output[1] << 8); // bytes 1 and 2 make the 16 bit data + + return output[3] & 1; // bit 0 of byte 3 is the valid flag +} + +bool AMS_ENS210::humid_has_data() { + if (humid_mode()) { // when in single shot mode make sure sensor has started first + if (!humid_is_measuring()) + start(false, true); // set start bit if sensor is idle + } + + char output[3]; + i2c_read(SENS_HUMID, output, 3); + + // do crc7 + // Store read data to avoid reading from I2C again + temp_reading = 0 | output[0] | (output[1] << 8); // bytes 1 and 2 make the 16 bit data + + return output[3] & 1; // bit 0 of byte 3 is the valid flag +} + +uint16_t AMS_ENS210::temp_read() { + + uint16_t reading = 0; + + if (temp_mode()) { // when in single shot mode, data is read and saved in temp_has_data() + reading = temp_reading; + } else { + char output[3]; + i2c_read(SENS_TEMP, output, 3); + + // do crc7 + if (output[3] & 1) // bit 0 of byte 3 is the valid flag + reading = 0 | output[0] | (output[1] << 8); // bytes 1 and 2 make the 16 bit data + } + + return reading; +} + +uint16_t AMS_ENS210::humid_read() { + uint16_t reading = 0; + + if (humid_mode()) { // when in single shot mode, data is read and saved in humid_has_data() + reading = humid_reading; + } else { + char output[3]; + i2c_read(SENS_HUMID, output, 3); + + // do crc7 + if (output[3] & 1) // bit 0 of byte 3 is the valid flag + reading = 0 | output[0] | (output[1] << 8); // bytes 1 and 2 make the 16 bit data + } + + return reading; +} + +/*** Private ***/ + +bool AMS_ENS210::write_config(bool system, bool sensor) { + int w_bytes = 0; + char cmd[2]; + + if (system) { + cmd[0] = SYS_CONFIG; + cmd[1] = 0 | _power_mode | _reset << 7; // bit 0 of SYS_CTRL is power mode, bit 7 is reset + w_bytes += _i2c->write(SLAVE_ADDR, cmd, 2); + } + + if (sensor) { + cmd[0] = SENS_OP_MODE; + cmd[1] = 0 | _temp_mode | (_humid_mode << 1); // bit 0 is temp mode, bit 1 is humid mode + w_bytes += _i2c->write(SLAVE_ADDR, cmd, 2); + } + + return w_bytes == (system + sensor)*2; // add error reporting/handling later... +} + +const char *AMS_ENS210::read_config(bool system, bool sensor) { + + static char output[2]; + + if (system) + i2c_read(SYS_CONFIG, output, 1); + + if (sensor) + i2c_read(SYS_CONFIG, output+system, 1); + + return output; + +} + +int AMS_ENS210::i2c_read(char reg_addr, char* output, int len) { + + int read_count = 0; + + _i2c->start(); // send start condition for write + if(_i2c->write(SLAVE_ADDR_W) == 1) { // write slave address + if(_i2c->write(reg_addr) == 1) { // write register address + _i2c->start(); // send another start condition for read + for (int i = 0; < len) { // read len bytes + output[i] = _i2c->read(i < len-1 ? 1 : 0); // ack all reads aside from the final one (i == len-1) + read_count++; + } + } + } + _i2c->stop(); // send stop condition + + return read_count; +} \ No newline at end of file