dev: add interface for opt4048 lux/colour sensor
This commit is contained in:
parent
9c389117c4
commit
93788beab4
3 changed files with 115 additions and 0 deletions
|
|
@ -30,6 +30,7 @@ add_executable(ensaht
|
|||
src/bmp.c
|
||||
src/aht.c
|
||||
src/ens.c
|
||||
src/opt4048.c
|
||||
)
|
||||
|
||||
# Add the standard include files to the build
|
||||
|
|
|
|||
23
include/opt4048.h
Normal file
23
include/opt4048.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
// SPDX-FileCopyrightText: 2026 A.M. Rowsell <amr@frzn.dev>
|
||||
|
||||
#ifndef OPT4048_H
|
||||
#define OPT4048_H
|
||||
|
||||
#include "hardware/i2c.h"
|
||||
|
||||
#define OPT_ADDR 0x44
|
||||
|
||||
/* Structure to hold the calculated color and lux data */
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float lux;
|
||||
} OPT4048_Data;
|
||||
|
||||
OPT4048_Data calculate_color_data(float ch0, float ch1, float ch2);
|
||||
int initOPT(i2c_inst_t *i2c);
|
||||
int getOPTData(i2c_inst_t *i2c, float *ch0, float *ch1, float *ch2);
|
||||
|
||||
#endif // OPT4048_H
|
||||
91
src/opt4048.c
Normal file
91
src/opt4048.c
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
// SPDX-FileCopyrightText: 2026 A.M. Rowsell <amr@frzn.dev>
|
||||
|
||||
#include "include/opt4048.h"
|
||||
|
||||
OPT4048_Data calculate_color_data(float ch0, float ch1, float ch2) {
|
||||
OPT4048_Data result;
|
||||
|
||||
const float m0x = 2.34892992e-04f;
|
||||
const float m1x = 4.07467441e-05f;
|
||||
const float m2x = 9.28619404e-05f;
|
||||
|
||||
const float m0y = -1.89652390e-05f;
|
||||
const float m1y = 1.98958202e-04f;
|
||||
const float m2y = -1.69739553e-05f;
|
||||
|
||||
const float m0z = 1.20811684e-05f;
|
||||
const float m1z = -1.58848115e-05f;
|
||||
const float m2z = 6.74021520e-04f;
|
||||
|
||||
const float m1l = 2.15e-3f;
|
||||
|
||||
result.x = (ch0 * m0x) + (ch1 * m1x) + (ch2 * m2x);
|
||||
result.y = (ch0 * m0y) + (ch1 * m1y) + (ch2 * m2y);
|
||||
result.z = (ch0 * m0z) + (ch1 * m1z) + (ch2 * m2z);
|
||||
|
||||
result.lux = ch1 * m1l;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int initOPT(i2c_inst_t *i2c) {
|
||||
int result = 0;
|
||||
int bytesWritten = 0;
|
||||
// all registers are 16 bits!
|
||||
// Need to init regs as follows:
|
||||
// write setup to CONFIG (0x0A/0x0B)
|
||||
// this sets it to 100ms sample time, auto-range lux
|
||||
static const uint8_t config[5] = {0x0A, 0b00110010, 0b00001000, 0b10000000,
|
||||
0b00011101};
|
||||
// we'll be doing single-shot measurements
|
||||
bytesWritten = i2c_write_blocking(i2c, OPT_ADDR, config, 4, false);
|
||||
result = (bytesWritten == 4) ? 0 : 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
int getOPTData(i2c_inst_t *i2c, float *ch0, float *ch1, float *ch2) {
|
||||
int result = 0;
|
||||
int bytesWritten = 0, bytesRead = 0;
|
||||
uint8_t lightData[16] = {0};
|
||||
uint32_t mantissaCH0 = 0;
|
||||
uint32_t mantissaCH1 = 0;
|
||||
uint32_t mantissaCH2 = 0;
|
||||
uint8_t exponentCH0 = 0;
|
||||
uint8_t exponentCH1 = 0;
|
||||
uint8_t exponentCH2 = 0;
|
||||
static const uint8_t triggerMeas[2] = {0x0B, 0b00101000};
|
||||
static const uint8_t dataReg = 0x00;
|
||||
// force a one-shot measurement
|
||||
bytesWritten = i2c_write_blocking(i2c, OPT_ADDR, triggerMeas, 2, false);
|
||||
if (bytesWritten != 2) {
|
||||
result = 1;
|
||||
}
|
||||
sleep_ms(410); // 4 channels @ 100ms each plus a little buffer time
|
||||
|
||||
bytesWritten = i2c_write_blocking(i2c, OPT_ADDR, &dataReg, 1, true);
|
||||
if (bytesWritten != 1) {
|
||||
result = 1;
|
||||
}
|
||||
bytesRead = i2c_read_blocking(i2c, OPT_ADDR, lightData, 16, false);
|
||||
if (bytesRead != 16) {
|
||||
result = 1;
|
||||
}
|
||||
// now take all the measurement data and convert them to the proper
|
||||
// representation
|
||||
mantissaCH0 = ((uint32_t)(lightData[0] & 0x0FUL) << 16) |
|
||||
((uint32_t)lightData[1] << 8) | (uint32_t)lightData[2];
|
||||
mantissaCH1 = ((uint32_t)(lightData[4] & 0x0FUL) << 16) |
|
||||
((uint32_t)lightData[5] << 8) | (uint32_t)lightData[6];
|
||||
mantissaCH2 = ((uint32_t)(lightData[8] & 0x0FUL) << 16) |
|
||||
((uint32_t)lightData[9] << 8) | (uint32_t)lightData[10];
|
||||
exponentCH0 = (lightData[0] & 0xF0) >> 4;
|
||||
exponentCH1 = (lightData[4] & 0xF0) >> 4;
|
||||
exponentCH2 = (lightData[8] & 0xF0) >> 4;
|
||||
|
||||
*ch0 = (float)(mantissaCH0 << exponentCH0);
|
||||
*ch1 = (float)(mantissaCH1 << exponentCH1);
|
||||
*ch2 = (float)(mantissaCH2 << exponentCH2);
|
||||
|
||||
return result;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue