Hi,
ich habe mich mal daran versucht, den Grove Color Sensor V2 zu unterstützen und mich dabei an der originalen Library von Seeed-Studio orientiert, um das ganze als „custom block“ zu erzeugen.
Problematisch ist die fehlende Unterstützung von float und double als Zahlenformat, aber auch ein fehlendes bitweises not ("~").
Nichts desto trotz, kann ich erkennen, ob der Sensor angeschlossen ist und bekomme auch RGB-Werte. Aber so richtig kann ich die noch nicht interpretieren. Zumindest die RGB-LED ändert die Farbe bei einem Farbwechsel, wenn sie auch nicht die richtig Farbe anzeigt… ;-).
Vielleicht hat ja jemand Lust, da mal mit drauf zu schauen…
/**
* Use this file to define custom functions and blocks.
* Read more at https://makecode.calliope.cc/blocks/custom
*
* This is a very close clone of the Seed-Studio library
* https://github.com/Seeed-Studio/Grove_I2C_Color_Sensor_TCS3472/blob/master/Adafruit_TCS34725.cpp
*/
const TCS34725_ADDRESS = 0x29;
const TCS34725_COMMAND_BIT = 0x80;
const TCS34725_ENABLE = 0x00;
const TCS34725_ENABLE_AIEN = 0x10; /* RGBC Interrupt Enable */
const notTCS34725_ENABLE_AIEN = 0xef; /* Calliope does not have a binary not operator? */
const TCS34725_ENABLE_WEN = 0x08; /* Wait enable - Writing 1 activates the wait timer */
const TCS34725_ENABLE_AEN = 0x02; /* RGBC Enable - Writing 1 actives the ADC, 0 disables it */
const TCS34725_ENABLE_PON = 0x01; /* Power on - Writing 1 activates the internal oscillator, 0 disables it */
const TCS34725_ATIME = 0x01; /* Integration time */
const TCS34725_WTIME = 0x03; /* Wait time = if TCS34725_ENABLE_WEN is asserted; */
const TCS34725_WTIME_2_4MS = 0xFF; /* WLONG0 = 2.4ms WLONG1 = 0.029s */
const TCS34725_WTIME_204MS = 0xAB; /* WLONG0 = 204ms WLONG1 = 2.45s */
const TCS34725_WTIME_614MS = 0x00; /* WLONG0 = 614ms WLONG1 = 7.4s */
const TCS34725_AILTL = 0x04; /* Clear channel lower interrupt threshold */
const TCS34725_AILTH = 0x05;
const TCS34725_AIHTL = 0x06; /* Clear channel upper interrupt threshold */
const TCS34725_AIHTH = 0x07;
const TCS34725_PERS = 0x0C; /* Persistence register - basic SW filtering mechanism for interrupts */
const TCS34725_PERS_NONE = 0b0000; /* Every RGBC cycle generates an interrupt */
const TCS34725_PERS_1_CYCLE = 0b0001; /* 1 clean channel value outside threshold range generates an interrupt */
const TCS34725_PERS_2_CYCLE = 0b0010; /* 2 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_3_CYCLE = 0b0011; /* 3 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_5_CYCLE = 0b0100; /* 5 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_10_CYCLE = 0b0101; /* 10 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_15_CYCLE = 0b0110; /* 15 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_20_CYCLE = 0b0111; /* 20 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_25_CYCLE = 0b1000; /* 25 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_30_CYCLE = 0b1001; /* 30 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_35_CYCLE = 0b1010; /* 35 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_40_CYCLE = 0b1011; /* 40 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_45_CYCLE = 0b1100; /* 45 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_50_CYCLE = 0b1101; /* 50 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_55_CYCLE = 0b1110; /* 55 clean channel values outside threshold range generates an interrupt */
const TCS34725_PERS_60_CYCLE = 0b1111; /* 60 clean channel values outside threshold range generates an interrupt */
const TCS34725_CONFIG = 0x0D;
const TCS34725_CONFIG_WLONG = 0x02; /* Choose between short and long = 12x; wait times via TCS34725_WTIME */
const TCS34725_CONTROL = 0x0F; /* Set the gain level for the sensor */
const TCS34725_ID = 0x12; /* 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727 */
const TCS34725_STATUS = 0x13;
const TCS34725_STATUS_AINT = 0x10; /* RGBC Clean channel interrupt */
const TCS34725_STATUS_AVALID = 0x01; /* Indicates that the RGBC channels have completed an integration cycle */
const TCS34725_CDATAL = 0x14; /* Clear channel data */
const TCS34725_CDATAH = 0x15;
const TCS34725_RDATAL = 0x16; /* Red channel data */
const TCS34725_RDATAH = 0x17;
const TCS34725_GDATAL = 0x18; /* Green channel data */
const TCS34725_GDATAH = 0x19;
const TCS34725_BDATAL = 0x1A; /* Blue channel data */
const TCS34725_BDATAH = 0x1B;
enum tcs34725IntegrationTime_t {
TCS34725_INTEGRATIONTIME_2_4MS = 0xFF, /**< 2.4ms - 1 cycle - Max Count: 1024 */
TCS34725_INTEGRATIONTIME_24MS = 0xF6, /**< 24ms - 10 cycles - Max Count: 10240 */
TCS34725_INTEGRATIONTIME_50MS = 0xEB, /**< 50ms - 20 cycles - Max Count: 20480 */
TCS34725_INTEGRATIONTIME_101MS = 0xD5, /**< 101ms - 42 cycles - Max Count: 43008 */
TCS34725_INTEGRATIONTIME_154MS = 0xC0, /**< 154ms - 64 cycles - Max Count: 65535 */
TCS34725_INTEGRATIONTIME_700MS = 0x00 /**< 700ms - 256 cycles - Max Count: 65535 */
}
enum tcs34725Gain_t {
TCS34725_GAIN_1X = 0x00, /**< No gain */
TCS34725_GAIN_4X = 0x01, /**< 4x gain */
TCS34725_GAIN_16X = 0x02, /**< 16x gain */
TCS34725_GAIN_60X = 0x03 /**< 60x gain */
}
/**
* Custom blocks
*/
//% weight=100 color=#0fbc11 icon=""
namespace color_Sensor {
let _tcs34725Initialised = false;
let _tcs34725IntegrationTime = tcs34725IntegrationTime_t.TCS34725_INTEGRATIONTIME_50MS;
let _tcs34725Gain = tcs34725Gain_t.TCS34725_GAIN_4X;
function write8(reg: number, value: number): void {
pins.i2cWriteNumber(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | reg, NumberFormat.Int8LE);
pins.i2cWriteNumber(TCS34725_ADDRESS, value & 0xFF, NumberFormat.Int8LE)
}
function read8(reg: number): number {
pins.i2cWriteNumber(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | reg, NumberFormat.Int8LE);
return pins.i2cReadNumber(TCS34725_ADDRESS, NumberFormat.Int8LE);
}
function read16(reg: number): number {
pins.i2cWriteNumber(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | reg, NumberFormat.Int8LE);
return pins.i2cReadNumber(TCS34725_ADDRESS, NumberFormat.UInt16BE);
}
/**
* Turn the device on
*/
function enable() {
write8(TCS34725_ENABLE, TCS34725_ENABLE_PON);
basic.pause(3);
write8(TCS34725_ENABLE, TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN);
}
/**
* Turn the device off to save power
*/
function disable() {
let reg = read8(TCS34725_ENABLE);
write8(TCS34725_ENABLE, reg & 0xfc); // ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN));
}
/**
* Begin using the sensor, will be called automatically if necessary,
* but can be used to check if a sensor is connected.
*
* @param gain Set the timing register to a value from 0-255
*/
//% block
export function begin(): boolean {
/* Make sure we're actually connected */
let x = read8(TCS34725_ID);
if ((x != 0x44) && (x != 0x10)) {
return false;
}
_tcs34725Initialised = true;
/* Set default integration time and gain */
setIntegrationTime(_tcs34725IntegrationTime);
setGain(_tcs34725Gain);
/* Note: by default, the device is in power down mode on bootup */
enable();
return true;
}
/**
* Set integration time
* @param it Set the integration time from 0-255
*/
//% block
export function setIntegrationTime(it: number): void {
if (!_tcs34725Initialised) begin();
/* Update the timing register */
write8(TCS34725_ATIME, it);
/* Update value placeholders */
_tcs34725IntegrationTime = it;
}
/**
* Set gain
* @param gain Set the timing register to a value from 0-255
*/
//% block
export function setGain(gain: number): void {
if (!_tcs34725Initialised) begin();
/* Update the timing register */
write8(TCS34725_CONTROL, gain);
/* Update value placeholders */
_tcs34725Gain = gain;
}
/**
* Get RGB data from sensor
*/
//% block
//% blockSetVariable = number
export function getRgbData(): number {
if (!_tcs34725Initialised) begin();
let c = pins.map(read16(TCS34725_CDATAL), 0, 65535, 0, 255);
let r = pins.map(read16(TCS34725_RDATAL), 0, 65535, 0, 255);
let g = pins.map(read16(TCS34725_GDATAL), 0, 65535, 0, 255);
let b = pins.map(read16(TCS34725_BDATAL), 0, 65535, 0, 255);
/* Set a delay for the integration time */
switch (_tcs34725IntegrationTime) {
case tcs34725IntegrationTime_t.TCS34725_INTEGRATIONTIME_2_4MS:
basic.pause(3);
break;
case tcs34725IntegrationTime_t.TCS34725_INTEGRATIONTIME_24MS:
basic.pause(24);
break;
case tcs34725IntegrationTime_t.TCS34725_INTEGRATIONTIME_50MS:
basic.pause(50);
break;
case tcs34725IntegrationTime_t.TCS34725_INTEGRATIONTIME_101MS:
basic.pause(101);
break;
case tcs34725IntegrationTime_t.TCS34725_INTEGRATIONTIME_154MS:
basic.pause(154);
break;
case tcs34725IntegrationTime_t.TCS34725_INTEGRATIONTIME_700MS:
basic.pause(700);
break;
}
return basic.rgbw(r, g, b, 0); //r, g, b, c;
}
// This function uses float (and powf()) which is not supported by Calliope
// function calculateColorTemperature(r: number, g: number, b: number): number {
// //X, Y, Z; /* RGB to XYZ correlation */
// //xc, yc; /* Chromaticity co-ordinates */
// //n; /* McCamy's formula */
// //cct;
//
// /* 1. Map RGB values to their XYZ counterparts. */
// /* Based on 6500K fluorescent, 3000K fluorescent */
// /* and 60W incandescent values for a wide range. */
// /* Note: Y = Illuminance or lux */
// let X = (-0.14282 * r) + (1.54924 * g) + (-0.95641 * b);
// let Y = (-0.32466 * r) + (1.57837 * g) + (-0.73191 * b);
// let Z = (-0.68202 * r) + (0.77073 * g) + (0.56332 * b);
//
// /* 2. Calculate the chromaticity co-ordinates */
// let xc = (X) / (X + Y + Z);
// let yc = (Y) / (X + Y + Z);
//
// /* 3. Use McCamy's formula to determine the CCT */
// let n = (xc - 0.3320) / (0.1858 - yc);
//
// /* Calculate the final CCT */
// let cct = (449.0 * powf(n, 3)) + (3525.0 * powf(n, 2)) + (6823.3 * n) + 5520.33;
//
// /* Return the results in degrees Kelvin */
// return cct;
// }
// This function uses float which is not supported by Calliope
// function calculateLux(r: number, g: number, b: number): number {
// /* This only uses RGB ... how can we integrate clear or calculate lux */
// /* based exclusively on clear since this might be more reliable? */
// let illuminance = (-0.32466 * r) + (1.57837 * g) + (-0.73191 * b);
//
// return illuminance;
// }
function setInterrupt(i: boolean): void {
let r = read8(TCS34725_ENABLE);
if (i) {
r |= TCS34725_ENABLE_AIEN;
} else {
r &= notTCS34725_ENABLE_AIEN; // ~TCS34725_ENABLE_AIEN; Calliope does not have bitwise not?
}
write8(TCS34725_ENABLE, r);
}
function clearInterrupt(): void {
pins.i2cWriteNumber(TCS34725_ADDRESS, TCS34725_COMMAND_BIT | 0x66, NumberFormat.Int8LE)
}
function setIntLimits(low: number, high: number): void {
write8(0x04, low & 0xFF);
write8(0x05, low >> 8);
write8(0x06, high & 0xFF);
write8(0x07, high >> 8);
}
}
if (color_Sensor.begin()) {
basic.showString("T")
} else {
basic.showString("F")
}
basic.pause(1000)
basic.forever(() => {
basic.setLedColor(color_Sensor.getRgbData())
})