add helpers to write to i2c registers (#778)

* add helpers to write to i2c registers

* fixing defaults

* remove register format

* fix typo

* adding color sensor

* adding color sensor impl

* missing files

* moving project

* stick with 8bit LE
This commit is contained in:
Peli de Halleux 2019-04-02 11:12:45 -07:00 коммит произвёл GitHub
Родитель d4f1512d63
Коммит 0e31464554
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 352 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,3 @@
# Color Sensor
Ambient light sensor

Просмотреть файл

@ -0,0 +1,22 @@
namespace sensors {
export interface ColorSensor {
/**
* Reads an RGB color from the sensor
*/
color(): number;
}
}
namespace input {
let _colorSensor: sensors.ColorSensor;
/**
* Uses a color sensor to capture the ambient color as a RGB value.
*/
//% blockId=sensor_lightcolor block="light color"
export function lightColor(): number {
if (!_colorSensor)
_colorSensor = new sensors.TCS34725();
return _colorSensor.color();
}
}

Просмотреть файл

@ -0,0 +1,16 @@
{
"name": "color-sensor",
"description": "Color sensor (TCS24725)",
"files": [
"README.md",
"colorsensor.ts",
"tcs34725.ts"
],
"testFiles": [
"test.ts"
],
"public": true,
"dependencies": {
"core": "file:../core"
}
}

Просмотреть файл

@ -0,0 +1,272 @@
/**
* Makecode package for the TCS34725 Color sensor.
*
* More details here: https://ams.com/documents/20143/36005/TCS3472_DS000390_2-00.pdf/6e452176-2407-faaf-a590-d526c78c7432
*/
namespace sensors {
const TCS34725_I2C_ADDRESS = 0x29 //I2C address of the TCS34725 (Page 34)
/* TCS34725 register addresses (Page 20)*/
const TCS34725_REGISTER_COMMAND = 0x80 // Specifies register address
const TCS34725_REGISTER_ENABLE = 0x00 // Enables states and interrupts
const TCS34725_REGISTER_AIEN_ENABLE = 0x10 // RGBC interrupt enable. When asserted, permits RGBC interrupts to be generated.
const TCS34725_REGISTER_WEN_ENABLE = 0x08 // Wait enable. This bit activates the wait feature. Writing a 1 activates the wait timer. Writing a 0 disables the wait timer.
const TCS34725_REGISTER_AEN_ENABLE = 0x02 // RGBC enable. This bit actives the two-channel ADC. Writing a 1 activates the RGBC. Writing a 0 disables the RGBC.
const TCS34725_REGISTER_PON_ENABLE = 0x01 // Power ON. This bit activates the internal oscillator to permit the timers and ADC channels to operate. Writing a 1 activates the oscillator. Writing a 0 disables the oscillator
const TCS34725_REGISTER_ATIME = 0x01 // The RGBC timing register controls the internal integration time of the RGBC clear and IR channel ADCs in 2.4-ms increments.
const TCS34725_REGISTER_WTIME = 0x03 // Wait time is set 2.4 ms increments unless the WLONG bit is asserted, in which case the wait times are 12× longer. WTIME is programmed as a 2s complement number.
const TCS34725_REGISTER_AILTL = 0x04 // Clear interrupt low threshold low byte
const TCS34725_REGISTER_AILTH = 0x05 // Clear interrupt low threshold high byte
const TCS34725_REGISTER_AIHTL = 0x06 // Clear interrupt high threshold low byte
const TCS34725_REGISTER_AIHTH = 0x07 // Clear interrupt high threshold high byte
const TCS34725_REGISTER_PERS = 0x0C // The persistence register controls the filtering interrupt capabilities of the device.
const TCS34725_REGISTER_CONFIG = 0x0D // The configuration register sets the wait long time.
const TCS34725_REGISTER_CONFIG_WLONG = 0x02 // Configuration: Wait Long. When asserted, the wait cycles are increased by a factor 12× from that programmed in the WTIME register
const TCS34725_REGISTER_CONTROL = 0x0F // The Control register provides eight bits of miscellaneous control to the analog block. These bits typically control functions such as gain settings and/or diode selection
const TCS34725_REGISTER_ID = 0x12 // The ID Register provides the value for the part number. The ID register is a read-only register.
const TCS34725_REGISTER_STATUS = 0x13 // The Status Register provides the internal status of the device. This register is read only.
const TCS34725_REGISTER_STATUS_AINT = 0x10 // Device status: RGBC clear channel Interrupt
const TCS34725_REGISTER_STATUS_AVALID = 0x01 // Device status: RGBC Valid. Indicates that the RGBC channels have completed an integration cycle
const TCS34725_REGISTER_CDATAL = 0x14 // Clear data low byte
const TCS34725_REGISTER_CDATAH = 0x15 // Clear data high byte
const TCS34725_REGISTER_RDATAL = 0x16 // Red data low byte
const TCS34725_REGISTER_RDATAH = 0x17 // Red data high byte
const TCS34725_REGISTER_GDATAL = 0x18 // Green data low byte
const TCS34725_REGISTER_GDATAH = 0x19 // Green data high byte
const TCS34725_REGISTER_BDATAL = 0x1A // Blue data low byte
const TCS34725_REGISTER_BDATAH = 0x1B // Blue data high byte
/* #region Enums for Modes, etc */
// Parameters for setting the internal integration time of the RGBC clear and IR channel.
export enum TCS34725_ATIME {
ATIME_2_4_MS = 0xFF, // 1 2.4 ms 1024
ATIME_24_MS = 0xF6, // 10 24 ms 10240
ATIME_100_MS = 0xD5, // 42 101 ms 43008
ATIME_154_MS = 0xC0, // 64 154 ms 65535
ATIME_700_MS = 0x00 // 256 700 ms 65535
}
// Parameters for setting the wait time register.
enum TCS34725_WTIME {
WTIME_2_4_MS = 0xFF, // 1 2.4 ms 0.029 sec
WTIME_204_MS = 0xAB, // 85 204 ms 2.45 sec
WTIME_614_MS = 0x00 // 256 614 ms 7.4 sec
}
// Parameters for setting the persistence register. The persistence register controls the filtering interrupt capabilities of the device.
enum TCS34725_APERS {
APERS_0_CLEAR = 0b0000, // Every RGBC cycle generates an interrupt
APERS_1_CLEAR = 0b0001, // 1 clear channel value outside of threshold range
APERS_2_CLEAR = 0b0010, // 2 clear channel consecutive values out of range
APERS_3_CLEAR = 0b0011, // 3 clear channel consecutive values out of range
APERS_5_CLEAR = 0b0100, // 5 clear channel consecutive values out of range
APERS_10_CLEAR = 0b0101, // 10 clear channel consecutive values out of range
APERS_15_CLEAR = 0b0110, // 15 clear channel consecutive values out of range
APERS_20_CLEAR = 0b0111, // 20 clear channel consecutive values out of range
APERS_25_CLEAR = 0b1000, // 25 clear channel consecutive values out of range
APERS_30_CLEAR = 0b1001, // 30 clear channel consecutive values out of range
APERS_35_CLEAR = 0b1010, // 35 clear channel consecutive values out of range
APERS_40_CLEAR = 0b1011, // 40 clear channel consecutive values out of range
APERS_45_CLEAR = 0b1100, // 45 clear channel consecutive values out of range
APERS_50_CLEAR = 0b1101, // 50 clear channel consecutive values out of range
APERS_55_CLEAR = 0b1110, // 55 clear channel consecutive values out of range
APERS_60_CLEAR = 0b1111, // 60 clear channel consecutive values out of range
}
// Parameters for setting the gain of the sensor.
enum TCS34725_AGAIN {
AGAIN_1X = 0x0, // 1x gain
AGAIN_4X = 0x1, // 4x gain
AGAIN_16X = 0x2, // 16x gain
AGAIN_60X = 0x3 // 60x gain
}
export class TCS34725 implements sensors.ColorSensor {
isConnected: boolean;
atimeIntegrationValue: TCS34725_ATIME;
gainSensorValue: TCS34725_AGAIN;
constructor() {
this.isConnected = false;
this.atimeIntegrationValue = 0;
this.gainSensorValue = 0;
this.start(TCS34725_ATIME.ATIME_2_4_MS, TCS34725_AGAIN.AGAIN_1X);
}
private connect() {
let retry = 0;
while (!this.isConnected && retry < 5) {
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER READ: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_ID (0x12)
const device_id = pins.i2cReadRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_ID)
//Check that device Identification has one of 2 i2c addresses
if ((device_id == 0x44) || (device_id == 0x10))
this.isConnected = true;
retry++;
}
}
private turnSensorOn() {
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER VALUE: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_ENABLE (0x00)
//REGISTER WRITE: TCS34725_REGISTER_PON_ENABLE (0x01)
pins.i2cWriteRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_ENABLE, TCS34725_REGISTER_PON_ENABLE);
basic.pause(300);
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER VALUE: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_ENABLE (0x00)
//REGISTER WRITE: TCS34725_REGISTER_PON_ENABLE (0x01) | TCS34725_REGISTER_AEN_ENABLE (0x02)
pins.i2cWriteRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_ENABLE, TCS34725_REGISTER_PON_ENABLE | TCS34725_REGISTER_AEN_ENABLE);
this.pauseSensorForIntegrationTime();
}
private pauseSensorForIntegrationTime() {
switch (this.atimeIntegrationValue) {
case TCS34725_ATIME.ATIME_2_4_MS: {
basic.pause(2.4);
break;
}
case TCS34725_ATIME.ATIME_24_MS: {
basic.pause(24);
break;
}
case TCS34725_ATIME.ATIME_100_MS: {
basic.pause(100);
break;
}
case TCS34725_ATIME.ATIME_154_MS: {
basic.pause(154);
break;
}
case TCS34725_ATIME.ATIME_700_MS: {
basic.pause(700);
break;
}
}
}
private turnOff() {
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER READ: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_ID (0x12)
let sensorReg = pins.i2cReadNumber(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_ENABLE);
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER VALUE: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_ENABLE (0x00)
//REGISTER WRITE: sensorReg & ~(TCS34725_REGISTER_PON_ENABLE (0x01) | TCS34725_REGISTER_AEN_ENABLE (0x02))
pins.i2cWriteRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_ENABLE, sensorReg & ~(TCS34725_REGISTER_PON_ENABLE | TCS34725_REGISTER_AEN_ENABLE));
}
setATIMEintegration(atime: TCS34725_ATIME) {
//Always make sure the color sensor is connected. Useful for cases when this block is used but the sensor wasn't set randomly.
this.connect();
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER VALUE: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_ATIME (0x01)
//REGISTER WRITE: atime
pins.i2cWriteRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_ATIME, atime)
this.atimeIntegrationValue = atime;
}
setGAINsensor(gain: TCS34725_AGAIN) {
//Always make sure the color sensor is connected. Useful for cases when this block is used but the sensor wasn't set randomly.
this.connect();
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER VALUE: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_CONTROL (0x0F)
//REGISTER WRITE: gain
pins.i2cWriteRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_CONTROL, gain)
this.gainSensorValue = gain;
}
private start(atime: TCS34725_ATIME, gain: TCS34725_AGAIN) {
this.connect();
this.setATIMEintegration(atime);
this.setGAINsensor(gain);
this.turnSensorOn();
}
color(): number {
//Always check that sensor is/was turned on
this.connect();
if (!this.isConnected)
return 0;
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER READ: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_RDATAL (0x16)
const redColorValue = pins.i2cReadRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_RDATAL, NumberFormat.UInt16LE);
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER READ: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_GDATAL (0x18)
const greenColorValue = pins.i2cReadRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_GDATAL, NumberFormat.UInt16LE);
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER READ: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_BDATAL (0x1A)
const blueColorValue = pins.i2cReadRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_BDATAL, NumberFormat.UInt16LE);
//REGISTER FORMAT: CMD | TRANSACTION | ADDRESS
//REGISTER READ: TCS34725_REGISTER_COMMAND (0x80) | TCS34725_REGISTER_CDATAL (0x14)
const clearColorValue = pins.i2cReadRegister(TCS34725_I2C_ADDRESS, TCS34725_REGISTER_COMMAND | TCS34725_REGISTER_CDATAL, NumberFormat.UInt16LE);
this.pauseSensorForIntegrationTime();
let sum = clearColorValue;
let r = 0;
let g = 0;
let b = 0;
if (clearColorValue == 0)
return 0;
else {
r = (redColorValue / sum * 255) & 0xff;
g = (greenColorValue / sum * 255) & 0xff;
b = (blueColorValue / sum * 255) & 0xff;
return (r << 16) | (g << 8) | b;
}
}
}
}
/*
let strip: neopixel.Strip = null
strip = neopixel.create(DigitalPin.P1, 30, NeoPixelMode.RGB)
strip.setBrightness(255)
TCS34725.start(TCS34725_ATIME.ATIME_2_4_MS, TCS34725_AGAIN.AGAIN_1X);
basic.forever(function () {
basic.pause(2000);
serial.writeLine(TCS34725.isConnected + "");
let a = TCS34725.getSensorRGB();
strip.showColor(neopixel.rgb(a.red, a.green, a.blue));
})
*/

Просмотреть файл

@ -0,0 +1 @@
// tests

Просмотреть файл

@ -16,12 +16,48 @@ namespace pins {
*/
//% help=pins/i2c-write-number weight=4 group="i2c"
//% blockId=i2c_writenumber block="i2c write number|at address %address|with value %value|of format %format|repeated %repeated"
export function i2cWriteNumber(address: number, value: number, format: NumberFormat, repeated?: boolean): void {
export function i2cWriteNumber(address: number, value: number, format?: NumberFormat, repeated?: boolean): void {
if (format == undefined)
format = NumberFormat.UInt8LE;
const buf = control.createBuffer(pins.sizeOf(format))
buf.setNumber(format, 0, value)
pins.i2cWriteBuffer(address, buf, repeated)
}
/**
* Writes a value in a I2C register.
* @param address I2c address of the device
* @param register register index
* @param value value to write
* @param valueFormat format of the value, default is UInt8LE
*/
//% weight=3 group="i2c"
//% blockId=i2c_writereg block="i2c write register|at address $address|at register $register|value $value"
export function i2cWriteRegister(address: number, register: number, value: number, valueFormat?: NumberFormat): void {
if (valueFormat === undefined)
valueFormat = NumberFormat.UInt8LE;
const valueSize = pins.sizeOf(valueFormat);
const buf = control.createBuffer(1 + valueSize);
buf.setNumber(NumberFormat.UInt8LE, 0, register);
buf.setNumber(valueFormat, 1, value);
pins.i2cWriteBuffer(address, buf);
}
/**
* Reads the value from a I2C register.
* @param address I2c address of the device
* @param register register index
* @param valueFormat format of the value, default is UInt8LE
*/
//% weight=3 group="i2c"
//% blockId=i2c_readreg block="i2c read register|at address $addfress|at register $register"
export function i2cReadRegister(address: number, register: number, valueFormat?: NumberFormat): number {
if (valueFormat === undefined)
valueFormat = NumberFormat.UInt8LE;
pins.i2cWriteNumber(address, register, NumberFormat.UInt8LE);
return pins.i2cReadNumber(address, valueFormat);
}
/**
* Read `size` bytes from a 7-bit I2C `address`.
*/

Просмотреть файл

@ -35,6 +35,7 @@
"libs/lora",
"libs/power",
"libs/controller",
"libs/color-sensor",
"libs/edge-connector"
]
}