You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
RegisterBits<0x0B, 0, 1> OPTREG_INIT_IDX; // Index initialization
Bits
Name
Access
Default
Description
7:1
-
-
0111001
Reserved (write 0000000b)
0
INIT_IDX
RW
1
Auto-init read address
INIT_IDX:
0 = Manual addressing only (for simple I²C masters)
1 = Auto-init to 0x02 (Measurement) or 0x00 (Config) on read
STATUS (0x00 MSB in Measurement State)
RegisterBits<0x00, 15, 1> STATUS_OUTCONVOF; // OUTCONV overflow
RegisterBits<0x00, 14, 1> STATUS_MRESOF; // Result overflow
RegisterBits<0x00, 13, 1> STATUS_ADCOF; // ADC overflow
RegisterBits<0x00, 12, 1> STATUS_LDATA; // Lost data
RegisterBits<0x00, 11, 1> STATUS_NDATA; // New data available
RegisterBits<0x00, 10, 1> STATUS_NOTREADY; // Not ready (measuring)
RegisterBits<0x00, 9, 1> STATUS_STANDBYSTATE; // Current standby state
RegisterBits<0x00, 8, 1> STATUS_POWERSTATE; // Current power state
Bit
Name
Description
7 (15)
OUTCONVOF
OUTCONV 24-bit counter overflow
6 (14)
MRESOF
Any channel result register overflow
5 (13)
ADCOF
ADC input overdrive (reduce gain!)
4 (12)
LDATA
Lost data (results overwritten) - cleared on STATUS read
typedefenum {
AS7331_STATE_CONFIG = 0b010, // Configuration state
AS7331_STATE_MEAS = 0b011, // Measurement state
} as7331_state_t;
Divider (CREG2:DIV)
typedefenum {
AS7331_DIV_2 = 0, // Divide by 2
AS7331_DIV_4 = 1, // Divide by 4
AS7331_DIV_8 = 2, // Divide by 8
AS7331_DIV_16 = 3, // Divide by 16
AS7331_DIV_32 = 4, // Divide by 32
AS7331_DIV_64 = 5, // Divide by 64
AS7331_DIV_128 = 6, // Divide by 128
AS7331_DIV_256 = 7, // Divide by 256
} as7331_divider_t;
Gain vs Clock Frequency Compatibility
Not all gain settings work at higher clock frequencies:
CCLK
1.024 MHz
2.048 MHz
4.096 MHz
8.192 MHz
GAIN=0
2048x
—
—
—
GAIN=1
1024x
1024x
—
—
GAIN=2
512x
512x
512x
—
GAIN=3
256x
256x
256x
256x
GAIN=4
128x
128x
128x
64x
GAIN=5
64x
64x
64x
64x
GAIN=6
32x
32x
32x
16x
GAIN=7
16x
16x
16x
16x
GAIN=8
8x
8x
8x
4x
GAIN=9
4x
4x
4x
4x
GAIN=10
2x
2x
2x
1x
GAIN=11
1x
1x
1x
1x
Multi-Byte Read Order
All multi-byte values are LSB first.
Reading measurement results:
Address 0x02: MRES1_L, MRES1_H (UVA)
Address 0x03: MRES2_L, MRES2_H (UVB)
Address 0x04: MRES3_L, MRES3_H (UVC)
OUTCONV (24-bit, SYND mode only):
Address 0x05: OUTCONV[7:0], OUTCONV[15:8]
Address 0x06: OUTCONV[23:16], 0x00
Temperature (12-bit in 16-bit register):
Bits 11:0 contain the temperature value
Bits 15:12 are zero
Timing Requirements
Startup Times
Parameter
Typical
Maximum
Condition
Power-down startup (TSTARTPD)
1.2 ms
2 ms
OSR:PD 1→0
Standby startup (TSTARTSB)
4 µs
5 µs
After standby exit
SYN Pin Timing
Parameter
Min
Unit
Notes
SYN pulse width
3
1/fCLK
Minimum recognizable pulse
SYN trigger delay
—
3 1/fCLK max
From falling edge to measurement start
Conversion Times (at 1.024 MHz clock)
TIME Setting
Conversion Time
ADC Resolution
0
1 ms
10-bit
6 (default)
64 ms
16-bit
10
1024 ms
20-bit
14
16384 ms
24-bit
Break Time (TBREAK)
Range: 0 to 2040 µs (in 8 µs steps)
Default: 200 µs (0x19)
Value 0 = minimum 3 clock cycles
I²C Timing
Parameter
Min
Max
Unit
Clock frequency
—
400
kHz
SCL high pulse
0.6
—
µs
SCL low pulse
1.3
—
µs
Start hold time
0.6
—
µs
Stop setup time
0.6
—
µs
Data setup time
0.1
—
µs
Data hold (master)
0.02
—
µs
Data hold (slave)
0.3
0.9
µs
Bus free time
1.3
—
µs
Temperature Calculation
The TEMP register contains a 12-bit value. To convert to degrees Celsius:
float temperature_c = (temp_raw * 0.05f) - 66.9f;
Reference point: TEMP = 0x922 (2338 dec) = 50°C
Temperature measurement is available in CONT, CMD, and SYNS modes.
In SYND mode, temperature is only available if EN_TM=1 and OUTCONV > 4096.
Quirks and Gotchas
1. State Machine Behavior
Configuration registers (CREG1-3, BREAK, EDGES, OPTREG) can only be written in Configuration state
Measurement results can only be read in Measurement state
Switching from Measurement → Configuration state clears all result registers
OSR register is always accessible
2. Power-Up Sequence
After power-on or software reset, device is in Configuration state with Power Down ON
Must write OSR:PD=0 to exit power down before measuring
Wait for TSTARTPD (1.2ms typ, 2ms max) after exiting power down
3. Gain Limitations
Higher clock frequencies disable higher gain settings
At 8.192 MHz, maximum gain is 256x (GAIN=3)
Using invalid gain for clock frequency will use the effective gain from the table
4. Integration Time > 64ms
For TIME > 6, ADC resolution exceeds 16 bits
Use the divider (EN_DIV=1) to access upper bits
Without divider, only lower 16 bits are available
5. SYND Mode Special Cases
Set EN_TM=1 to get temperature readings in SYND mode
OUTCONV must be > 4096 clocks for valid temperature
EDGES register value of 0 is treated as 1
6. I²C Communication During Measurement
Do NOT communicate via I²C during conversion (causes measurement distortion)
Use BREAK time for data transfer
READY pin indicates safe time to read (high = ready)
7. Result Register Locking
Reading any result register locks all results until I²C STOP
This prevents partial updates during multi-byte reads
NDATA flag clears on read of STATUS or any result register
LDATA flag only clears on STATUS read
8. READY Pin Wiring
For multiple AS7331 on same READY line: use open-drain mode (RDYOD=1) with pull-up
READY stays low while ANY device is measuring
9. Address Pointer Wrap
In Measurement state, address auto-wraps from 0x04 (or 0x06 if EN_TM=1) back to 0x02
Does NOT wrap if address was set above valid range
10. External Resistor (REXT)
Must use 3.3 MΩ ±1% with TCR ≤ 50ppm/K
Critical for accurate measurements
Function Map (Proposed Public API)
classAdafruit_AS7331 {
public:// Initializationboolbegin(uint8_t addr = AS7331_DEFAULT_ADDRESS, TwoWire *wire = &Wire);
boolreset(); // Software resetuint8_tgetDeviceID(); // Read AGEN register (expect 0x21)// State ManagementboolsetConfigurationState(); // Enter config mode (DOS=010)boolsetMeasurementState(); // Enter measurement mode (DOS=011)boolsetPowerDown(bool enable); // Control power downboolsetStandby(bool enable); // Control standby// Configuration (only in Config state)boolsetGain(as7331_gain_t gain);
boolsetIntegrationTime(as7331_time_t time);
boolsetMeasurementMode(as7331_mode_t mode);
boolsetClockFrequency(as7331_clock_t clock);
boolsetBreakTime(uint8_t time_8us); // 0-255 (units of 8µs)boolsetDivider(bool enable, as7331_divider_t div = AS7331_DIV_2);
boolsetReadyPinMode(bool openDrain);
// Measurement (only in Measurement state)boolstartMeasurement(); // Set SS=1boolstopMeasurement(); // Set SS=0boolisReady(); // Check READY pin or STATUS:NOTREADY// Read ResultsboolreadAllChannels(uint16_t *uva, uint16_t *uvb, uint16_t *uvc);
uint16_treadUVA(); // MRES1uint16_treadUVB(); // MRES2 uint16_treadUVC(); // MRES3floatreadTemperature(); // TEMP → °C// Statusuint8_treadStatus();
boolhasNewData(); // STATUS:NDATAboolhasLostData(); // STATUS:LDATAboolhasOverflow(); // STATUS:MRESOF or ADCOF// One-shot convenience (handles state transitions)booloneShot(uint16_t *uva, uint16_t *uvb, uint16_t *uvc);
protected:boolwriteRegister(uint8_t reg, uint8_t value);
uint8_treadRegister(uint8_t reg);
boolreadRegisters(uint8_t reg, uint8_t *buffer, uint8_t len);
};
Initialization Sequence
Basic Startup
// 1. After power-on, device is in Config state with PD=1// 2. Read AGEN to verify device (expect 0x21)// 3. Configure measurement parameters// 4. Exit power down and enter measurement state// 5. Start measurementwriteRegister(0x06, 0xA6); // CREG1: GAIN=2x, TIME=64mswriteRegister(0x08, 0x50); // CREG3: CMD mode, SB=1, 1MHzwriteRegister(0x00, 0x83); // OSR: SS=1, PD=0, DOS=011 (start measurement)delay(2); // Wait for TSTARTPD// Wait for READY pin high or poll STATUS:NOTREADY
Reading Results
// After READY goes high:writeRegister(0x00, 0x02); // Stay in config to read AGEN, or...// In measurement state, burst read from 0x02:uint8_t buf[6];
readRegisters(0x02, buf, 6);
uint16_t uva = buf[0] | (buf[1] << 8);
uint16_t uvb = buf[2] | (buf[3] << 8);
uint16_t uvc = buf[4] | (buf[5] << 8);