kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Add BH1745 driver
rodzic
9e1eb6723d
commit
54169f4150
|
@ -13,5 +13,6 @@ add_subdirectory(is31fl3731)
|
||||||
add_subdirectory(fatfs)
|
add_subdirectory(fatfs)
|
||||||
add_subdirectory(sdcard)
|
add_subdirectory(sdcard)
|
||||||
add_subdirectory(as7262)
|
add_subdirectory(as7262)
|
||||||
|
add_subdirectory(bh1745)
|
||||||
add_subdirectory(button)
|
add_subdirectory(button)
|
||||||
add_subdirectory(rgbled)
|
add_subdirectory(rgbled)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
include(bh1745.cmake)
|
|
@ -0,0 +1,9 @@
|
||||||
|
add_library(bh1745 INTERFACE)
|
||||||
|
|
||||||
|
target_sources(bh1745 INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/bh1745.cpp)
|
||||||
|
|
||||||
|
target_include_directories(bh1745 INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
|
# Pull in pico libraries that we need
|
||||||
|
target_link_libraries(bh1745 INTERFACE pico_stdlib hardware_i2c)
|
|
@ -0,0 +1,172 @@
|
||||||
|
#include "bh1745.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace pimoroni {
|
||||||
|
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();
|
||||||
|
|
||||||
|
if (this->get_chip_id() != CHIP_ID || this->get_manufacturer() != MANUFACTURER) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->reset();
|
||||||
|
this->clear_bits(REG_SYSTEM_CONTROL, 6); // Clear INT reset bit
|
||||||
|
this->set_measurement_time_ms(640);
|
||||||
|
this->set_bits(REG_MODE_CONTROL2, 4); // Enable RGBC
|
||||||
|
this->set_bits(REG_MODE_CONTROL3, 0, 0xff); // Turn on sensor
|
||||||
|
this->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
|
||||||
|
this->clear_bits(REG_INTERRUPT, 4); // Enable interrupt latch
|
||||||
|
|
||||||
|
sleep_ms(320);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t BH1745::get_chip_id() {
|
||||||
|
uint8_t chip_id;
|
||||||
|
this->read_bytes(REG_SYSTEM_CONTROL, &chip_id, 1);
|
||||||
|
return chip_id & 0b00111111;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t BH1745::get_manufacturer() {
|
||||||
|
uint8_t manufacturer;
|
||||||
|
this->read_bytes(REG_MANUFACTURER, &manufacturer, 1);
|
||||||
|
return manufacturer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BH1745::reset() {
|
||||||
|
this->set_bits(REG_SYSTEM_CONTROL, 7);
|
||||||
|
|
||||||
|
while (this->get_bits(REG_SYSTEM_CONTROL, 7)) {
|
||||||
|
sleep_ms(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BH1745::set_measurement_time_ms(uint16_t value) {
|
||||||
|
uint8_t reg = 0;
|
||||||
|
switch(value) {
|
||||||
|
case 160:
|
||||||
|
reg = 0b000;
|
||||||
|
break;
|
||||||
|
case 320:
|
||||||
|
reg = 0b001;
|
||||||
|
break;
|
||||||
|
case 640:
|
||||||
|
reg = 0b010;
|
||||||
|
break;
|
||||||
|
case 1280:
|
||||||
|
reg = 0b011;
|
||||||
|
break;
|
||||||
|
case 2560:
|
||||||
|
reg = 0b100;
|
||||||
|
break;
|
||||||
|
case 5120:
|
||||||
|
reg = 0b101;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->write_bytes(REG_MODE_CONTROL1, ®, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BH1745::set_threshold_high(uint16_t value) {
|
||||||
|
this->write_bytes(REG_THRESHOLD_HIGH, (uint8_t *)&value, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BH1745::set_threshold_low(uint16_t value) {
|
||||||
|
this->write_bytes(REG_THRESHOLD_LOW, (uint8_t *)&value, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BH1745::set_leds(bool state) {
|
||||||
|
if(state){
|
||||||
|
this->set_bits(REG_INTERRUPT, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->clear_bits(REG_INTERRUPT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rgbc_t BH1745::get_rgb_scaled() {
|
||||||
|
rgbc_t rgbc = this->get_rgbc_raw();
|
||||||
|
|
||||||
|
if(rgbc.c > 0) {
|
||||||
|
rgbc.r = (uint16_t)((uint32_t)rgbc.r * 255 / rgbc.c) & 0xff;
|
||||||
|
rgbc.g = (uint16_t)((uint32_t)rgbc.g * 255 / rgbc.c) & 0xff;
|
||||||
|
rgbc.b = (uint16_t)((uint32_t)rgbc.b * 255 / rgbc.c) & 0xff;
|
||||||
|
} else {
|
||||||
|
rgbc.r = 0;
|
||||||
|
rgbc.g = 0;
|
||||||
|
rgbc.b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rgbc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgbc_t BH1745::get_rgb_clamped() {
|
||||||
|
rgbc_t rgbc = this->get_rgbc_raw();
|
||||||
|
|
||||||
|
uint16_t vmax = std::max(rgbc.r, std::max(rgbc.g, rgbc.b));
|
||||||
|
|
||||||
|
rgbc.r = (uint16_t)((uint32_t)rgbc.r * 255 / vmax);
|
||||||
|
rgbc.g = (uint16_t)((uint32_t)rgbc.g * 255 / vmax);
|
||||||
|
rgbc.b = (uint16_t)((uint32_t)rgbc.b * 255 / vmax);
|
||||||
|
|
||||||
|
return rgbc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgbc_t BH1745::get_rgbc_raw() {
|
||||||
|
while(this->get_bits(REG_MODE_CONTROL2, 7) == 0) {
|
||||||
|
sleep_ms(1);
|
||||||
|
}
|
||||||
|
rgbc_t colour_data;
|
||||||
|
this->read_bytes(REG_COLOUR_DATA, (uint8_t *)&colour_data, 8);
|
||||||
|
colour_data.r *= this->channel_compensation[0];
|
||||||
|
colour_data.g *= this->channel_compensation[1];
|
||||||
|
colour_data.b *= this->channel_compensation[2];
|
||||||
|
colour_data.c *= this->channel_compensation[3];
|
||||||
|
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, ®, 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hardware/i2c.h"
|
||||||
|
#include "hardware/gpio.h"
|
||||||
|
|
||||||
|
#define REG_SYSTEM_CONTROL 0x40
|
||||||
|
#define REG_MODE_CONTROL1 0x41
|
||||||
|
#define REG_MODE_CONTROL2 0x42
|
||||||
|
#define REG_MODE_CONTROL3 0x44
|
||||||
|
#define REG_COLOUR_DATA 0x50
|
||||||
|
#define REG_DINT_DATA 0x58
|
||||||
|
#define REG_INTERRUPT 0x60
|
||||||
|
#define REG_PERSISTENCE 0x61
|
||||||
|
#define REG_THRESHOLD_LOW 0x64
|
||||||
|
#define REG_THRESHOLD_HIGH 0x62
|
||||||
|
#define REG_MANUFACTURER 0x92
|
||||||
|
|
||||||
|
#define CHIP_ID 0b001011
|
||||||
|
#define MANUFACTURER 0xe0
|
||||||
|
|
||||||
|
#define I2C_ADDR 0x38
|
||||||
|
#define I2C_ADDR_ALT 0x39
|
||||||
|
|
||||||
|
namespace pimoroni {
|
||||||
|
typedef struct {
|
||||||
|
uint16_t r;
|
||||||
|
uint16_t g;
|
||||||
|
uint16_t b;
|
||||||
|
uint16_t c;
|
||||||
|
} rgbc_t;
|
||||||
|
|
||||||
|
class BH1745 {
|
||||||
|
public:
|
||||||
|
BH1745() {};
|
||||||
|
|
||||||
|
BH1745(uint8_t addr) : address(addr) {};
|
||||||
|
|
||||||
|
BH1745(i2c_inst_t *i2c, uint8_t addr, uint8_t sda, uint8_t scl, uint8_t interrupt) :
|
||||||
|
i2c(i2c), address(addr), sda(sda), scl(scl), interrupt(interrupt) {};
|
||||||
|
|
||||||
|
int init();
|
||||||
|
uint8_t get_chip_id();
|
||||||
|
uint8_t get_manufacturer();
|
||||||
|
void set_threshold_high(uint16_t value);
|
||||||
|
void set_threshold_low(uint16_t value);
|
||||||
|
void set_measurement_time_ms(uint16_t value);
|
||||||
|
rgbc_t get_rgbc_raw();
|
||||||
|
rgbc_t get_rgb_clamped();
|
||||||
|
rgbc_t get_rgb_scaled();
|
||||||
|
void reset();
|
||||||
|
void set_leds(bool state=true);
|
||||||
|
|
||||||
|
private:
|
||||||
|
i2c_inst_t *i2c = i2c0;
|
||||||
|
|
||||||
|
// interface pins with our standard defaults where appropriate
|
||||||
|
int8_t address = 0x38;
|
||||||
|
int8_t sda = 4;
|
||||||
|
int8_t scl = 5;
|
||||||
|
int8_t interrupt = 22;
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
}
|
|
@ -28,3 +28,4 @@ add_subdirectory(pico_trackball_display)
|
||||||
add_subdirectory(pico_audio)
|
add_subdirectory(pico_audio)
|
||||||
add_subdirectory(pico_wireless)
|
add_subdirectory(pico_wireless)
|
||||||
add_subdirectory(breakout_as7262)
|
add_subdirectory(breakout_as7262)
|
||||||
|
add_subdirectory(breakout_bh1745)
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
add_executable(
|
||||||
|
breakout_bh1745
|
||||||
|
demo.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pull in pico libraries that we need
|
||||||
|
target_link_libraries(breakout_bh1745 pico_stdlib hardware_spi bh1745)
|
||||||
|
|
||||||
|
# create map/bin/hex file etc.
|
||||||
|
pico_add_extra_outputs(breakout_bh1745)
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
#include "bh1745.hpp"
|
||||||
|
|
||||||
|
using namespace pimoroni;
|
||||||
|
|
||||||
|
BH1745 bh1745(0x39);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
setup_default_uart();
|
||||||
|
|
||||||
|
if (bh1745.init() == 1) {
|
||||||
|
printf("Failed to set up sensor\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t chip_id = bh1745.get_chip_id();
|
||||||
|
printf("Found BH1745. Chip ID: 0x%02x\n", chip_id);
|
||||||
|
|
||||||
|
bh1745.set_leds(true);
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
rgbc_t colour = bh1745.get_rgbc_raw();
|
||||||
|
printf("Colour: %d %d %d %d\n", colour.r, colour.g, colour.b, colour.c);
|
||||||
|
colour = bh1745.get_rgb_clamped();
|
||||||
|
printf("Clamped: %d %d %d %d\n", colour.r, colour.g, colour.b, colour.c);
|
||||||
|
colour = bh1745.get_rgb_scaled();
|
||||||
|
printf("Scaled: %d %d %d %d\n\n", colour.r, colour.g, colour.b, colour.c);
|
||||||
|
sleep_ms(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Ładowanie…
Reference in New Issue