Porti BH1745 to Pimoroni I2C

This commit is contained in:
Phil Howard 2021-07-12 13:21:14 +01:00
parent 54169f4150
commit ea6acf2207
4 changed files with 59 additions and 104 deletions

View File

@ -6,4 +6,4 @@ target_sources(bh1745 INTERFACE
target_include_directories(bh1745 INTERFACE ${CMAKE_CURRENT_LIST_DIR}) target_include_directories(bh1745 INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need # Pull in pico libraries that we need
target_link_libraries(bh1745 INTERFACE pico_stdlib hardware_i2c) target_link_libraries(bh1745 INTERFACE pico_stdlib hardware_i2c pimoroni_i2c)

View File

@ -3,47 +3,44 @@
namespace pimoroni { namespace pimoroni {
int BH1745::init() { int BH1745::init() {
i2c_init(i2c, 400000);
gpio_set_function(sda, GPIO_FUNC_I2C); gpio_pull_up(sda);
gpio_set_function(scl, GPIO_FUNC_I2C); gpio_pull_up(scl);
reset(); reset();
if (this->get_chip_id() != CHIP_ID || this->get_manufacturer() != MANUFACTURER) { if (this->get_chip_id() != BH1745_CHIP_ID || this->get_manufacturer() != BH1745_MANUFACTURER) {
return 1; return 1;
} }
this->reset(); reset();
this->clear_bits(REG_SYSTEM_CONTROL, 6); // Clear INT reset bit i2c->clear_bits(address, BH1745_REG_SYSTEM_CONTROL, 6); // Clear INT reset bit
this->set_measurement_time_ms(640); set_measurement_time_ms(640);
this->set_bits(REG_MODE_CONTROL2, 4); // Enable RGBC i2c->set_bits(address, BH1745_REG_MODE_CONTROL2, 4); // Enable RGBC
this->set_bits(REG_MODE_CONTROL3, 0, 0xff); // Turn on sensor i2c->set_bits(address, BH1745_REG_MODE_CONTROL3, 0, 0xff); // Turn on sensor
this->set_threshold_high(0x0000); // Set threshold so int will always fire set_threshold_high(0x0000); // Set threshold so int will always fire
this->set_threshold_low(0xFFFF); // this lets us turn on the LEDs with the int pin set_threshold_low(0xFFFF); // this lets us turn on the LEDs with the int pin
this->clear_bits(REG_INTERRUPT, 4); // Enable interrupt latch i2c->clear_bits(address, BH1745_REG_INTERRUPT, 4); // Enable interrupt latch
sleep_ms(320); sleep_ms(320);
return 0; return 0;
} }
i2c_inst_t* BH1745::get_i2c() const {
return i2c->get_i2c();
}
uint8_t BH1745::get_chip_id() { uint8_t BH1745::get_chip_id() {
uint8_t chip_id; uint8_t chip_id = i2c->reg_read_uint8(address, BH1745_REG_SYSTEM_CONTROL);
this->read_bytes(REG_SYSTEM_CONTROL, &chip_id, 1);
return chip_id & 0b00111111; return chip_id & 0b00111111;
} }
uint8_t BH1745::get_manufacturer() { uint8_t BH1745::get_manufacturer() {
uint8_t manufacturer; uint8_t manufacturer = i2c->reg_read_uint8(address, BH1745_REG_MANUFACTURER);
this->read_bytes(REG_MANUFACTURER, &manufacturer, 1);
return manufacturer; return manufacturer;
} }
void BH1745::reset() { void BH1745::reset() {
this->set_bits(REG_SYSTEM_CONTROL, 7); i2c->set_bits(address, BH1745_REG_SYSTEM_CONTROL, 7);
while (this->get_bits(REG_SYSTEM_CONTROL, 7)) { while (i2c->get_bits(address, BH1745_REG_SYSTEM_CONTROL, 7)) {
sleep_ms(100); sleep_ms(100);
} }
} }
@ -70,24 +67,24 @@ namespace pimoroni {
reg = 0b101; reg = 0b101;
break; break;
} }
this->write_bytes(REG_MODE_CONTROL1, &reg, 1); i2c->write_bytes(address, BH1745_REG_MODE_CONTROL1, &reg, 1);
} }
void BH1745::set_threshold_high(uint16_t value) { void BH1745::set_threshold_high(uint16_t value) {
this->write_bytes(REG_THRESHOLD_HIGH, (uint8_t *)&value, 2); i2c->write_bytes(address, BH1745_REG_THRESHOLD_HIGH, (uint8_t *)&value, 2);
} }
void BH1745::set_threshold_low(uint16_t value) { void BH1745::set_threshold_low(uint16_t value) {
this->write_bytes(REG_THRESHOLD_LOW, (uint8_t *)&value, 2); i2c->write_bytes(address, BH1745_REG_THRESHOLD_LOW, (uint8_t *)&value, 2);
} }
void BH1745::set_leds(bool state) { void BH1745::set_leds(bool state) {
if(state){ if(state){
this->set_bits(REG_INTERRUPT, 0); i2c->set_bits(address, BH1745_REG_INTERRUPT, 0);
} }
else else
{ {
this->clear_bits(REG_INTERRUPT, 0); i2c->clear_bits(address, BH1745_REG_INTERRUPT, 0);
} }
} }
@ -109,7 +106,7 @@ namespace pimoroni {
} }
rgbc_t BH1745::get_rgb_clamped() { rgbc_t BH1745::get_rgb_clamped() {
rgbc_t rgbc = this->get_rgbc_raw(); rgbc_t rgbc = get_rgbc_raw();
uint16_t vmax = std::max(rgbc.r, std::max(rgbc.g, rgbc.b)); uint16_t vmax = std::max(rgbc.r, std::max(rgbc.g, rgbc.b));
@ -121,52 +118,15 @@ namespace pimoroni {
} }
rgbc_t BH1745::get_rgbc_raw() { rgbc_t BH1745::get_rgbc_raw() {
while(this->get_bits(REG_MODE_CONTROL2, 7) == 0) { while(i2c->get_bits(address, BH1745_REG_MODE_CONTROL2, 7) == 0) {
sleep_ms(1); sleep_ms(1);
} }
rgbc_t colour_data; rgbc_t colour_data;
this->read_bytes(REG_COLOUR_DATA, (uint8_t *)&colour_data, 8); i2c->read_bytes(address, BH1745_REG_COLOUR_DATA, (uint8_t *)&colour_data, 8);
colour_data.r *= this->channel_compensation[0]; colour_data.r *= channel_compensation[0];
colour_data.g *= this->channel_compensation[1]; colour_data.g *= channel_compensation[1];
colour_data.b *= this->channel_compensation[2]; colour_data.b *= channel_compensation[2];
colour_data.c *= this->channel_compensation[3]; colour_data.c *= channel_compensation[3];
return colour_data; return colour_data;
} }
// i2c functions
int BH1745::write_bytes(uint8_t reg, uint8_t *buf, int len) {
uint8_t buffer[len + 1];
buffer[0] = reg;
for(int x = 0; x < len; x++) {
buffer[x + 1] = buf[x];
}
return i2c_write_blocking(this->i2c, this->address, buffer, len + 1, false);
};
int BH1745::read_bytes(uint8_t reg, uint8_t *buf, int len) {
i2c_write_blocking(this->i2c, this->address, &reg, 1, true);
i2c_read_blocking(this->i2c, this->address, buf, len, false);
return len;
};
uint8_t BH1745::get_bits(uint8_t reg, uint8_t shift, uint8_t mask) {
uint8_t value;
this->read_bytes(reg, &value, 1);
return value & (mask << shift);
}
void BH1745::set_bits(uint8_t reg, uint8_t shift, uint8_t mask) {
uint8_t value;
this->read_bytes(reg, &value, 1);
value |= mask << shift;
this->write_bytes(reg, &value, 1);
}
void BH1745::clear_bits(uint8_t reg, uint8_t shift, uint8_t mask) {
uint8_t value;
this->read_bytes(reg, &value, 1);
value &= ~(mask << shift);
this->write_bytes(reg, &value, 1);
}
} }

View File

@ -2,24 +2,22 @@
#include "hardware/i2c.h" #include "hardware/i2c.h"
#include "hardware/gpio.h" #include "hardware/gpio.h"
#include "common/pimoroni_i2c.hpp"
#define REG_SYSTEM_CONTROL 0x40 #define BH1745_REG_SYSTEM_CONTROL 0x40
#define REG_MODE_CONTROL1 0x41 #define BH1745_REG_MODE_CONTROL1 0x41
#define REG_MODE_CONTROL2 0x42 #define BH1745_REG_MODE_CONTROL2 0x42
#define REG_MODE_CONTROL3 0x44 #define BH1745_REG_MODE_CONTROL3 0x44
#define REG_COLOUR_DATA 0x50 #define BH1745_REG_COLOUR_DATA 0x50
#define REG_DINT_DATA 0x58 #define BH1745_REG_DINT_DATA 0x58
#define REG_INTERRUPT 0x60 #define BH1745_REG_INTERRUPT 0x60
#define REG_PERSISTENCE 0x61 #define BH1745_REG_PERSISTENCE 0x61
#define REG_THRESHOLD_LOW 0x64 #define BH1745_REG_THRESHOLD_LOW 0x64
#define REG_THRESHOLD_HIGH 0x62 #define BH1745_REG_THRESHOLD_HIGH 0x62
#define REG_MANUFACTURER 0x92 #define BH1745_REG_MANUFACTURER 0x92
#define CHIP_ID 0b001011 #define BH1745_CHIP_ID 0b001011
#define MANUFACTURER 0xe0 #define BH1745_MANUFACTURER 0xe0
#define I2C_ADDR 0x38
#define I2C_ADDR_ALT 0x39
namespace pimoroni { namespace pimoroni {
typedef struct { typedef struct {
@ -31,14 +29,19 @@ namespace pimoroni {
class BH1745 { class BH1745 {
public: public:
BH1745() {}; static const uint8_t DEFAULT_I2C_ADDRESS = 0x38;
static const uint8_t I2C_ADDRESS_ALTERNATE = 0x39;
BH1745(uint8_t addr) : address(addr) {}; BH1745(I2C *i2c, uint8_t address = DEFAULT_I2C_ADDRESS) :
i2c(i2c), address(address) {}
BH1745(i2c_inst_t *i2c, uint8_t addr, uint8_t sda, uint8_t scl, uint8_t interrupt) : BH1745(i2c_inst_t *i2c, uint8_t addr, uint8_t sda, uint8_t scl, uint interrupt) :
i2c(i2c), address(addr), sda(sda), scl(scl), interrupt(interrupt) {}; BH1745(new I2C(sda, scl), address) {};
int init(); int init();
i2c_inst_t* get_i2c() const;
uint8_t get_chip_id(); uint8_t get_chip_id();
uint8_t get_manufacturer(); uint8_t get_manufacturer();
void set_threshold_high(uint16_t value); void set_threshold_high(uint16_t value);
@ -51,21 +54,12 @@ namespace pimoroni {
void set_leds(bool state=true); void set_leds(bool state=true);
private: private:
i2c_inst_t *i2c = i2c0; I2C *i2c;
// interface pins with our standard defaults where appropriate // interface pins with our standard defaults where appropriate
int8_t address = 0x38; int8_t address = DEFAULT_I2C_ADDRESS;
int8_t sda = 4; uint interrupt = 22;
int8_t scl = 5;
int8_t interrupt = 22;
float channel_compensation[4] = {2.2f, 1.0f, 1.8f, 10.0f}; float channel_compensation[4] = {2.2f, 1.0f, 1.8f, 10.0f};
// From i2cdevice
int write_bytes(uint8_t reg, uint8_t *buf, int len);
int read_bytes(uint8_t reg, uint8_t *buf, int len);
uint8_t get_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1);
void set_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1);
void clear_bits(uint8_t reg, uint8_t shift, uint8_t mask=0b1);
}; };
} }

View File

@ -7,10 +7,11 @@
using namespace pimoroni; using namespace pimoroni;
BH1745 bh1745(0x39); I2C i2c(BOARD::BREAKOUT_GARDEN);
BH1745 bh1745(&i2c, BH1745::DEFAULT_I2C_ADDRESS);
int main() { int main() {
setup_default_uart(); stdio_init_all();
if (bh1745.init() == 1) { if (bh1745.init() == 1) {
printf("Failed to set up sensor\n"); printf("Failed to set up sensor\n");