Browse Source

I2C sensors using new i2c interface

softuart
Xose Pérez 6 years ago
parent
commit
947f9bab73
8 changed files with 137 additions and 210 deletions
  1. +7
    -0
      code/espurna/config/prototypes.h
  2. +1
    -1
      code/espurna/config/sensors.h
  3. +109
    -5
      code/espurna/i2c.ino
  4. +2
    -31
      code/espurna/sensors/BH1750Sensor.h
  5. +6
    -42
      code/espurna/sensors/EmonADC121Sensor.h
  6. +2
    -47
      code/espurna/sensors/EmonADS1X15Sensor.h
  7. +2
    -34
      code/espurna/sensors/SHT3XI2CSensor.h
  8. +8
    -50
      code/espurna/sensors/SI7021Sensor.h

+ 7
- 0
code/espurna/config/prototypes.h View File

@ -66,12 +66,19 @@ unsigned char i2cFindAndLock(size_t size, unsigned char * addresses);
bool i2cGetLock(unsigned char address); bool i2cGetLock(unsigned char address);
bool i2cReleaseLock(unsigned char address); bool i2cReleaseLock(unsigned char address);
void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len);
void i2c_write_uint8(uint8_t address, uint8_t value);
void i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value); void i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value);
void i2c_write_uint16(uint8_t address, uint16_t value);
void i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value);
uint8_t i2c_read_uint8(uint8_t address);
uint8_t i2c_read_uint8(uint8_t address, uint8_t reg); uint8_t i2c_read_uint8(uint8_t address, uint8_t reg);
uint16_t i2c_read_uint16(uint8_t address);
uint16_t i2c_read_uint16(uint8_t address, uint8_t reg); uint16_t i2c_read_uint16(uint8_t address, uint8_t reg);
uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg); uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg);
int16_t i2c_read_int16(uint8_t address, uint8_t reg); int16_t i2c_read_int16(uint8_t address, uint8_t reg);
int16_t i2c_read_int16_le(uint8_t address, uint8_t reg); int16_t i2c_read_int16_le(uint8_t address, uint8_t reg);
void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// GPIO // GPIO


+ 1
- 1
code/espurna/config/sensors.h View File

@ -272,7 +272,7 @@
#define EMON_ADS1X15_I2C_ADDRESS 0x00 // 0x00 means auto #define EMON_ADS1X15_I2C_ADDRESS 0x00 // 0x00 means auto
#define EMON_ADS1X15_TYPE ADS1X15_CHIP_ADS1115 #define EMON_ADS1X15_TYPE ADS1X15_CHIP_ADS1115
#define EMON_ADS1X15_GAIN ADS1X15_REG_CONFIG_PGA_4_096V #define EMON_ADS1X15_GAIN ADS1X15_REG_CONFIG_PGA_4_096V
#define EMON_ADS1X15_MASK 0x0F // A0=1 A1=2 A2=4 A4=8
#define EMON_ADS1X15_MASK 0x0F // A0=1 A1=2 A2=4 A3=8
#if EMON_ADS1X15_SUPPORT #if EMON_ADS1X15_SUPPORT
#undef I2C_SUPPORT #undef I2C_SUPPORT


+ 109
- 5
code/espurna/i2c.ino View File

@ -108,38 +108,142 @@ int _i2cClearbus(int sda, int scl) {
// I2C API // I2C API
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
void i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value) {
#if I2C_USE_BRZO
void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len) {
brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
brzo_i2c_write_uint8(buffer, len, false);
brzo_i2c_end_transaction();
}
void i2c_write_uint8(uint8_t address, uint8_t value) {
uint8_t buffer[1] = {value};
brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
brzo_i2c_write_uint8(buffer, 1, false);
brzo_i2c_end_transaction();
}
uint8_t i2c_read_uint8(uint8_t address) {
uint8_t buffer[1] = {reg};
brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
brzo_i2c_read(buffer, 1, false);
brzo_i2c_end_transaction();
return buffer[0];
};
uint8_t i2c_read_uint8(uint8_t address, uint8_t reg) {
uint8_t buffer[1] = {reg};
brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
brzo_i2c_write_uint8(buffer, 1, false);
brzo_i2c_read(buffer, 1, false);
brzo_i2c_end_transaction();
return buffer[0];
};
uint16_t i2c_read_uint16(uint8_t address) {
uint8_t buffer[2] = {reg, 0};
brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
brzo_i2c_read(buffer, 2, false);
brzo_i2c_end_transaction();
return (buffer[0] * 256) | buffer[1];
};
uint16_t i2c_read_uint16(uint8_t address, uint8_t reg) {
uint8_t buffer[2] = {reg, 0};
brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
brzo_i2c_write_uint8(buffer, 1, false);
brzo_i2c_read(buffer, 2, false);
brzo_i2c_end_transaction();
return (buffer[0] * 256) | buffer[1];
};
void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len) {
brzo_i2c_start_transaction(address, _i2c_scl_frequency);
brzo_i2c_read(buffer, len, false);
brzo_i2c_end_transaction();
}
#else // not I2C_USE_BRZO
void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len) {
Wire.beginTransmission((uint8_t) address);
Wire.write(buffer, len);
Wire.endTransmission();
}
void i2c_write_uint8(uint8_t address, uint8_t value) {
Wire.beginTransmission((uint8_t) address); Wire.beginTransmission((uint8_t) address);
Wire.write((uint8_t) reg);
Wire.write((uint8_t) value); Wire.write((uint8_t) value);
Wire.endTransmission(); Wire.endTransmission();
} }
uint8_t i2c_read_uint8(uint8_t address) {
uint8_t value;
Wire.beginTransmission((uint8_t) address);
Wire.requestFrom((uint8_t) address, (uint8_t) 1);
value = Wire.read();
Wire.endTransmission();
return value;
};
uint8_t i2c_read_uint8(uint8_t address, uint8_t reg) { uint8_t i2c_read_uint8(uint8_t address, uint8_t reg) {
uint8_t value; uint8_t value;
Wire.beginTransmission((uint8_t) address); Wire.beginTransmission((uint8_t) address);
Wire.write((uint8_t) reg); Wire.write((uint8_t) reg);
Wire.endTransmission(); Wire.endTransmission();
Wire.requestFrom((uint8_t)address, (uint8_t) 1);
Wire.requestFrom((uint8_t) address, (uint8_t) 1);
value = Wire.read(); value = Wire.read();
Wire.endTransmission(); Wire.endTransmission();
return value; return value;
}; };
uint16_t i2c_read_uint16(uint8_t address) {
uint16_t value;
Wire.beginTransmission((uint8_t) address);
Wire.requestFrom((uint8_t) address, (uint8_t) 2);
value = (Wire.read() * 256) | Wire.read();
Wire.endTransmission();
return value;
};
uint16_t i2c_read_uint16(uint8_t address, uint8_t reg) { uint16_t i2c_read_uint16(uint8_t address, uint8_t reg) {
uint16_t value; uint16_t value;
Wire.beginTransmission((uint8_t) address); Wire.beginTransmission((uint8_t) address);
Wire.write((uint8_t) reg); Wire.write((uint8_t) reg);
Wire.endTransmission(); Wire.endTransmission();
Wire.requestFrom((uint8_t) address, (uint8_t) 2); Wire.requestFrom((uint8_t) address, (uint8_t) 2);
value = (Wire.read() << 8) | Wire.read();
value = (Wire.read() * 256) | Wire.read();
Wire.endTransmission(); Wire.endTransmission();
return value; return value;
}; };
void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len) {
Wire.beginTransmission((uint8_t) address);
Wire.requestFrom(address, (uint8_t) len);
for (int i=0; i<len; i++) buffer[i] = Wire.read();
Wire.endTransmission();
}
#endif // I2C_USE_BRZO
void i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value) {
uint8_t buffer[2] = {reg, value};
i2c_write_buffer(address, buffer, 2);
}
void i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value) {
uint8_t buffer[3] = {reg, value >> 8, value & 0xFF};
i2c_write_buffer(address, buffer, 3);
}
void i2c_write_uint16(uint8_t address, uint16_t value) {
uint8_t buffer[2] = {value >> 8, value & 0xFF};
i2c_write_buffer(address, buffer, 2);
}
uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg) { uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg) {
uint16_t temp = i2c_read_uint16(address, reg); uint16_t temp = i2c_read_uint16(address, reg);
return (temp >> 8) | (temp << 8);
return (temp / 256) | (temp * 256);
}; };
int16_t i2c_read_int16(uint8_t address, uint8_t reg) { int16_t i2c_read_int16(uint8_t address, uint8_t reg) {


+ 2
- 31
code/espurna/sensors/BH1750Sensor.h View File

@ -9,11 +9,6 @@
#include "Arduino.h" #include "Arduino.h"
#include "I2CSensor.h" #include "I2CSensor.h"
#if I2C_USE_BRZO
#include <brzo_i2c.h>
#else
#include <Wire.h>
#endif
#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1lx resolution. Measurement time is approx 120ms. #define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1lx resolution. Measurement time is approx 120ms.
#define BH1750_CONTINUOUS_HIGH_RES_MODE_2 0x11 // Start measurement at 0.5lx resolution. Measurement time is approx 120ms. #define BH1750_CONTINUOUS_HIGH_RES_MODE_2 0x11 // Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
@ -99,23 +94,11 @@ class BH1750Sensor : public I2CSensor {
protected: protected:
void _configure() { void _configure() {
#if I2C_USE_BRZO
uint8_t buffer[1] = {_mode};
brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
brzo_i2c_write(buffer, 1, false);
brzo_i2c_end_transaction();
#else
Wire.beginTransmission(_address);
Wire.write(_mode);
Wire.endTransmission();
#endif
i2c_write_uint8(_address, _mode);
} }
double _read() { double _read() {
double level;
uint8_t buffer[2];
// For one-shot modes reconfigure sensor & wait for conversion // For one-shot modes reconfigure sensor & wait for conversion
if (_mode & 0x20) { if (_mode & 0x20) {
@ -131,19 +114,7 @@ class BH1750Sensor : public I2CSensor {
} }
#if I2C_USE_BRZO
brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
brzo_i2c_read(buffer, 2, false);
brzo_i2c_end_transaction();
#else
Wire.beginTransmission(_address);
Wire.requestFrom(_address, (unsigned char) 2);
buffer[0] = Wire.read();
buffer[1] = Wire.read();
Wire.endTransmission();
#endif
level = buffer[0] * 256 + buffer[1];
double level = (double) i2c_read_uint16(_address);
return level / 1.2; return level / 1.2;
} }


+ 6
- 42
code/espurna/sensors/EmonADC121Sensor.h View File

@ -10,12 +10,6 @@
#include "Arduino.h" #include "Arduino.h"
#include "EmonSensor.h" #include "EmonSensor.h"
#if I2C_USE_BRZO
#include <brzo_i2c.h>
#else
#include <Wire.h>
#endif
// ADC121 Registers // ADC121 Registers
#define ADC121_REG_RESULT 0x00 #define ADC121_REG_RESULT 0x00
#define ADC121_REG_ALERT 0x01 #define ADC121_REG_ALERT 0x01
@ -59,19 +53,7 @@ class EmonADC121Sensor : public EmonSensor {
if (_address == 0) return; if (_address == 0) return;
// Init sensor // Init sensor
#if I2C_USE_BRZO
uint8_t buffer[2];
buffer[0] = ADC121_REG_CONFIG;
buffer[1] = 0x00;
brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
brzo_i2c_write(buffer, 2, false);
brzo_i2c_end_transaction();
#else
Wire.beginTransmission(_address);
Wire.write(ADC121_REG_CONFIG);
Wire.write(0x00);
Wire.endTransmission();
#endif
_init();
// Just one channel // Just one channel
_count = _magnitudes; _count = _magnitudes;
@ -159,32 +141,14 @@ class EmonADC121Sensor : public EmonSensor {
// Protected // Protected
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
unsigned int readADC(unsigned char channel) {
void _init() {
i2c_write_uint8(_address, ADC121_REG_CONFIG, 0);
}
unsigned int readADC(unsigned char channel) {
(void) channel; (void) channel;
unsigned int value;
#if I2C_USE_BRZO
uint8_t buffer[2];
buffer[0] = ADC121_REG_RESULT;
brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
brzo_i2c_write(buffer, 1, false);
brzo_i2c_read(buffer, 2, false);
brzo_i2c_end_transaction();
value = (buffer[0] & 0x0F) << 8;
value |= buffer[1];
#else
Wire.beginTransmission(_address);
Wire.write(ADC121_REG_RESULT);
Wire.endTransmission();
Wire.requestFrom(_address, (unsigned char) 2);
value = (Wire.read() & 0x0F) << 8;
value = value + Wire.read();
#endif
unsigned int value = i2c_read_uint16(_address, ADC121_REG_RESULT) & 0x0FFF;
return value; return value;
} }
}; };


+ 2
- 47
code/espurna/sensors/EmonADS1X15Sensor.h View File

@ -10,12 +10,6 @@
#include "Arduino.h" #include "Arduino.h"
#include "EmonSensor.h" #include "EmonSensor.h"
#if I2C_USE_BRZO
#include <brzo_i2c.h>
#else
#include <Wire.h>
#endif
#define ADS1X15_CHANNELS (4) #define ADS1X15_CHANNELS (4)
#define ADS1X15_CHIP_ADS1015 (0) #define ADS1X15_CHIP_ADS1015 (0)
@ -326,21 +320,7 @@ class EmonADS1X15Sensor : public EmonSensor {
#endif #endif
// Write config register to the ADC // Write config register to the ADC
#if I2C_USE_BRZO
uint8_t buffer[3];
buffer[0] = ADS1X15_REG_POINTER_CONFIG;
buffer[1] = config >> 8;
buffer[2] = config & 0xFF;
brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
brzo_i2c_write(buffer, 3, false);
brzo_i2c_end_transaction();
#else
Wire.beginTransmission(_address);
Wire.write((uint8_t) ADS1X15_REG_POINTER_CONFIG);
Wire.write((uint8_t) (config >> 8));
Wire.write((uint8_t) (config & 0xFF));
Wire.endTransmission();
#endif
i2c_write_uint16(_address, ADS1X15_REG_POINTER_CONFIG, config);
} }
@ -363,36 +343,11 @@ class EmonADS1X15Sensor : public EmonSensor {
} }
unsigned int readADC(unsigned char channel) { unsigned int readADC(unsigned char channel) {
(void) channel; (void) channel;
unsigned int value = 0;
#if I2C_USE_BRZO
uint8_t buffer[3];
buffer[0] = ADS1X15_REG_POINTER_CONVERT;
brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
brzo_i2c_write(buffer, 1, false);
brzo_i2c_read(buffer, 2, false);
brzo_i2c_end_transaction();
value |= buffer[0] << 8;
value |= buffer[1];
#else
Wire.beginTransmission(_address);
Wire.write(ADS1X15_REG_POINTER_CONVERT);
Wire.endTransmission();
Wire.requestFrom(_address, (unsigned char) 2);
value |= Wire.read() << 8;
value |= Wire.read();
#endif
unsigned int value = i2c_read_uint16(_address, ADS1X15_REG_POINTER_CONVERT);
if (_type = ADS1X15_CHIP_ADS1015) value >>= ADS1015_BIT_SHIFT; if (_type = ADS1X15_CHIP_ADS1015) value >>= ADS1015_BIT_SHIFT;
delayMicroseconds(500); delayMicroseconds(500);
return value; return value;
} }
unsigned char _type = ADS1X15_CHIP_ADS1115; unsigned char _type = ADS1X15_CHIP_ADS1115;


+ 2
- 34
code/espurna/sensors/SHT3XI2CSensor.h View File

@ -9,11 +9,6 @@
#include "Arduino.h" #include "Arduino.h"
#include "I2CSensor.h" #include "I2CSensor.h"
#if I2C_USE_BRZO
#include <brzo_i2c.h>
#else
#include <Wire.h>
#endif
class SHT3XI2CSensor : public I2CSensor { class SHT3XI2CSensor : public I2CSensor {
@ -67,36 +62,9 @@ class SHT3XI2CSensor : public I2CSensor {
void pre() { void pre() {
unsigned char buffer[6]; unsigned char buffer[6];
#if I2C_USE_BRZO
buffer[0] = 0x2C;
buffer[1] = 0x06;
brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
brzo_i2c_write(buffer, 2, false);
#else
Wire.beginTransmission(_address);
Wire.write(0x2C);
Wire.write(0x06);
if (Wire.endTransmission() != 0) {
_error = SENSOR_ERROR_TIMEOUT;
return;
}
#endif
i2c_write_uint8(_address, 0x2C, 0x06);
delay(500); delay(500);
#if I2C_USE_BRZO
brzo_i2c_read(buffer, 6, false);
brzo_i2c_end_transaction();
#else
Wire.requestFrom(_address, (unsigned char) 6);
for (int i=0; i<6; i++) buffer[i] = Wire.read();
delay(50);
if (Wire.available() != 0) {
_error = SENSOR_ERROR_CRC;
return;
}
#endif
i2c_read_buffer(_address, buffer, 6);
// cTemp msb, cTemp lsb, cTemp crc, humidity msb, humidity lsb, humidity crc // cTemp msb, cTemp lsb, cTemp crc, humidity msb, humidity lsb, humidity crc
_temperature = ((((buffer[0] * 256.0) + buffer[1]) * 175) / 65535.0) - 45; _temperature = ((((buffer[0] * 256.0) + buffer[1]) * 175) / 65535.0) - 45;


+ 8
- 50
code/espurna/sensors/SI7021Sensor.h View File

@ -9,11 +9,6 @@
#include "Arduino.h" #include "Arduino.h"
#include "I2CSensor.h" #include "I2CSensor.h"
#if I2C_USE_BRZO
#include <brzo_i2c.h>
#else
#include <Wire.h>
#endif
#define SI7021_SCL_FREQUENCY 200 #define SI7021_SCL_FREQUENCY 200
@ -53,21 +48,8 @@ class SI7021Sensor : public I2CSensor {
if (_address == 0) return; if (_address == 0) return;
// Check device // Check device
#if I2C_USE_BRZO
uint8_t buffer[2] = {0xFC, 0xC9};
brzo_i2c_start_transaction(_address, SI7021_SCL_FREQUENCY);
brzo_i2c_write(buffer, 2, false);
brzo_i2c_read(buffer, 1, false);
brzo_i2c_end_transaction();
_chip = buffer[0];
#else
Wire.beginTransmission(_address);
Wire.write(0xFC);
Wire.write(0xC9);
Wire.endTransmission();
Wire.requestFrom(_address, (unsigned char) 1);
_chip = Wire.read();
#endif
i2c_write_uint8(_address, 0xFC, 0xC9);
_chip = i2c_read_uint8(_address);
if ((_chip != SI7021_CHIP_SI7021) & (_chip != SI7021_CHIP_HTU21D)) { if ((_chip != SI7021_CHIP_SI7021) & (_chip != SI7021_CHIP_HTU21D)) {
i2cReleaseLock(_address); i2cReleaseLock(_address);
@ -104,7 +86,6 @@ class SI7021Sensor : public I2CSensor {
// Current value for slot # index // Current value for slot # index
double value(unsigned char index) { double value(unsigned char index) {
if (index < _count) { if (index < _count) {
_error = SENSOR_ERROR_OK;
double value; double value;
if (index == 0) { if (index == 0) {
value = read(SI7021_CMD_TMP_NOHOLD); value = read(SI7021_CMD_TMP_NOHOLD);
@ -129,17 +110,8 @@ class SI7021Sensor : public I2CSensor {
unsigned int read(uint8_t command) { unsigned int read(uint8_t command) {
unsigned char bytes = (command == 0xE0) ? 2 : 3;
#if I2C_USE_BRZO
uint8_t buffer[2] = {command, 0x00};
brzo_i2c_start_transaction(_address, SI7021_SCL_FREQUENCY);
brzo_i2c_write(buffer, 1, false);
#else
Wire.beginTransmission(_address);
Wire.write(command);
Wire.endTransmission();
#endif
// Request measurement
i2c_write_uint8(_address, command);
// When not using clock stretching (*_NOHOLD commands) delay here // When not using clock stretching (*_NOHOLD commands) delay here
// is needed to wait for the measurement. // is needed to wait for the measurement.
@ -147,28 +119,14 @@ class SI7021Sensor : public I2CSensor {
unsigned long start = millis(); unsigned long start = millis();
while (millis() - start < 50) delay(1); while (millis() - start < 50) delay(1);
#if I2C_USE_BRZO
brzo_i2c_read(buffer, 2, false);
brzo_i2c_end_transaction();
unsigned int msb = buffer[0];
unsigned int lsb = buffer[1];
#else
Wire.requestFrom(_address, bytes);
if (Wire.available() != bytes) {
_error = SENSOR_ERROR_CRC;
return 0;
}
unsigned int msb = Wire.read();
unsigned int lsb = Wire.read();
#endif
// Clear the last to bits of LSB to 00. // Clear the last to bits of LSB to 00.
// According to datasheet LSB of RH is always xxxxxx10 // According to datasheet LSB of RH is always xxxxxx10
lsb &= 0xFC;
unsigned int value = (msb << 8) | lsb;
unsigned int value = i2c_read_uint16(_address) & 0xFFFC;
// We should be checking there are no pending bytes in the buffer
// and raise a CRC error if there are
_error = SENSOR_ERROR_OK; _error = SENSOR_ERROR_OK;
return value; return value;
} }


Loading…
Cancel
Save