Initial commit - Complete Adafruit SPA06_003 Arduino library

Features:
- Fixed coefficient parsing with correct bit field extraction
- Temperature and pressure compensation algorithms
- Pressure readings in hPa (hectopascals)
- Adafruit_Sensor unified interface compatibility
- Complete register access and configuration API
- FIFO support and interrupt handling

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ladyada 2025-08-26 16:52:29 -04:00
commit 42528b07aa
11 changed files with 1685 additions and 0 deletions

118
.clang-format Normal file
View file

@ -0,0 +1,118 @@
---
Language: Cpp
BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 8
UseTab: Never

View file

@ -0,0 +1,16 @@
{
"permissions": {
"allow": [
"Bash(arduino-cli lib examples:*)",
"Bash(arduino-cli compile:*)",
"Bash(arduino-cli upload:*)",
"Bash(arduino-cli board:*)",
"Bash(git init:*)",
"WebFetch(domain:raw.githubusercontent.com)",
"Bash(\"/c/Program Files/TortoiseGit/bin/puttygen\" \"C:\\Users\\ladyada\\Dropbox\\shared\\github.ppk\" -O private-openssh -o ~/.ssh/id_rsa)",
"Bash(python3:*)"
],
"deny": [],
"ask": []
}
}

32
.github/workflows/githubci.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Arduino Library CI
on: [pull_request, push, repository_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- uses: actions/checkout@v4
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: clang
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
- name: test platforms
run: python3 ci/build_platform.py main_platforms
- name: doxy
env:
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
PRETTYNAME : "Adafruit SPA06_003 Arduino Library"
run: bash ci/doxy_gen_and_deploy.sh

57
.gitignore vendored Normal file
View file

@ -0,0 +1,57 @@
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Doxygen documentation
doc/
# Arduino build files
build/
# IDE files
.vscode/
*.swp
*.swo
*~
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Datasheet files
*.pdf
*.txt
output.txt
# Claude Code development files
CLAUDE.md

753
Adafruit_SPA06_003.cpp Normal file
View file

@ -0,0 +1,753 @@
/*!
* @file Adafruit_SPA06_003.cpp
*
* @mainpage Adafruit SPA06_003 Digital Pressure Sensor
*
* @section intro_sec Introduction
*
* This is the documentation for Adafruit's SPA06_003 driver for the
* Arduino platform. It is designed specifically to work with the
* Adafruit SPA06_003 breakout: https://www.adafruit.com/products/xxxx
*
* These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
* to interface with the breakout.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* @section author Author
*
* Written by Limor 'ladyada' Fried with assistance from Claude Code
* for Adafruit Industries.
*
* @section license License
*
* MIT license, all text here must be included in any redistribution.
*
*/
#include "Adafruit_SPA06_003.h"
/*!
* @brief Instantiates a new SPA06_003 class
*/
Adafruit_SPA06_003::Adafruit_SPA06_003() {}
/*!
* @brief Cleans up the SPA06_003
*/
Adafruit_SPA06_003::~Adafruit_SPA06_003() {
if (i2c_dev) {
delete i2c_dev;
}
if (temp_sensor) {
delete temp_sensor;
}
if (pressure_sensor) {
delete pressure_sensor;
}
}
/*!
* @brief Sets up the hardware and initializes I2C
* @param i2c_addr
* The I2C address to be used.
* @param wire
* The Wire object to be used for I2C connections.
* @return True if initialization was successful, otherwise false.
*/
bool Adafruit_SPA06_003::begin(uint8_t i2c_addr, TwoWire *wire) {
if (i2c_dev) {
delete i2c_dev;
}
i2c_dev = new Adafruit_I2CDevice(i2c_addr, wire);
if (!i2c_dev->begin()) {
return false;
}
Adafruit_BusIO_Register chip_id =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_ID, 1);
if (chip_id.read() != 0x11) {
return false;
}
// Perform soft reset
if (!reset()) {
return false;
}
delay(10);
// Wait for coefficients and sensor to be ready
while (!isCoeffReady() || !isSensorReady()) {
delay(10);
}
// Read calibration coefficients
if (!readCoefficients()) {
return false;
}
// Set measurement mode to continuous both
setMeasurementMode(SPA06_003_MEAS_CONTINUOUS_BOTH);
return true;
}
/*!
* @brief Reads the 24-bit raw pressure data from registers
* @return 24-bit pressure data as uint32_t
*/
uint32_t Adafruit_SPA06_003::getPressureData() {
Adafruit_BusIO_Register psr_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_PSR_B2, 3, MSBFIRST);
uint32_t psr_data = psr_reg.read();
if (psr_data & 0x800000) {
psr_data |= 0xFF000000;
}
return psr_data;
}
/*!
* @brief Reads the 24-bit raw temperature data from registers
* @return 24-bit temperature data as uint32_t
*/
uint32_t Adafruit_SPA06_003::getTemperatureData() {
Adafruit_BusIO_Register tmp_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_TMP_B2, 3, MSBFIRST);
uint32_t tmp_data = tmp_reg.read();
if (tmp_data & 0x800000) {
tmp_data |= 0xFF000000;
}
return tmp_data;
}
/*!
* @brief Gets the pressure measurement rate
* @return Current pressure measurement rate setting
*/
spa06_003_rate_t Adafruit_SPA06_003::getPressureMeasureRate() {
Adafruit_BusIO_Register prs_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_PRS_CFG, 1);
Adafruit_BusIO_RegisterBits pm_rate_bits =
Adafruit_BusIO_RegisterBits(&prs_cfg_reg, 4, 4);
return (spa06_003_rate_t)pm_rate_bits.read();
}
/*!
* @brief Sets the pressure measurement rate
* @param rate The pressure measurement rate to set
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setPressureMeasureRate(spa06_003_rate_t rate) {
Adafruit_BusIO_Register prs_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_PRS_CFG, 1);
Adafruit_BusIO_RegisterBits pm_rate_bits =
Adafruit_BusIO_RegisterBits(&prs_cfg_reg, 4, 4);
return pm_rate_bits.write(rate);
}
/*!
* @brief Gets the temperature measurement rate
* @return Current temperature measurement rate setting
*/
spa06_003_rate_t Adafruit_SPA06_003::getTemperatureMeasureRate() {
Adafruit_BusIO_Register tmp_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_TMP_CFG, 1);
Adafruit_BusIO_RegisterBits tmp_rate_bits =
Adafruit_BusIO_RegisterBits(&tmp_cfg_reg, 4, 4);
return (spa06_003_rate_t)tmp_rate_bits.read();
}
/*!
* @brief Sets the temperature measurement rate
* @param rate The temperature measurement rate to set
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setTemperatureMeasureRate(spa06_003_rate_t rate) {
Adafruit_BusIO_Register tmp_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_TMP_CFG, 1);
Adafruit_BusIO_RegisterBits tmp_rate_bits =
Adafruit_BusIO_RegisterBits(&tmp_cfg_reg, 4, 4);
return tmp_rate_bits.write(rate);
}
/*!
* @brief Gets the pressure oversampling rate
* @return Current pressure oversampling rate setting
*/
spa06_003_oversample_t Adafruit_SPA06_003::getPressureOversampling() {
Adafruit_BusIO_Register prs_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_PRS_CFG, 1);
Adafruit_BusIO_RegisterBits pm_prc_bits =
Adafruit_BusIO_RegisterBits(&prs_cfg_reg, 4, 0);
return (spa06_003_oversample_t)pm_prc_bits.read();
}
/*!
* @brief Sets the pressure oversampling rate
* @param prc The pressure oversampling rate to set
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setPressureOversampling(spa06_003_oversample_t prc) {
Adafruit_BusIO_Register prs_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_PRS_CFG, 1);
Adafruit_BusIO_RegisterBits pm_prc_bits =
Adafruit_BusIO_RegisterBits(&prs_cfg_reg, 4, 0);
if (!pm_prc_bits.write(prc)) {
return false;
}
return setPresShift(prc > SPA06_003_OVERSAMPLE_8);
}
/*!
* @brief Gets the temperature oversampling rate
* @return Current temperature oversampling rate setting
*/
spa06_003_oversample_t Adafruit_SPA06_003::getTemperatureOversampling() {
Adafruit_BusIO_Register tmp_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_TMP_CFG, 1);
Adafruit_BusIO_RegisterBits tmp_prc_bits =
Adafruit_BusIO_RegisterBits(&tmp_cfg_reg, 4, 0);
return (spa06_003_oversample_t)tmp_prc_bits.read();
}
/*!
* @brief Sets the temperature oversampling rate
* @param prc The temperature oversampling rate to set
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setTemperatureOversampling(
spa06_003_oversample_t prc) {
Adafruit_BusIO_Register tmp_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_TMP_CFG, 1);
Adafruit_BusIO_RegisterBits tmp_prc_bits =
Adafruit_BusIO_RegisterBits(&tmp_cfg_reg, 4, 0);
if (!tmp_prc_bits.write(prc)) {
return false;
}
return setTempShift(prc > SPA06_003_OVERSAMPLE_8);
}
/*!
* @brief Checks if calibration coefficients are ready
* @return True if coefficients are ready, false otherwise
*/
bool Adafruit_SPA06_003::isCoeffReady() {
Adafruit_BusIO_Register meas_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_MEAS_CFG, 1);
Adafruit_BusIO_RegisterBits coef_rdy_bit =
Adafruit_BusIO_RegisterBits(&meas_cfg_reg, 1, 7);
return coef_rdy_bit.read();
}
/*!
* @brief Checks if sensor is ready
* @return True if sensor is ready, false otherwise
*/
bool Adafruit_SPA06_003::isSensorReady() {
Adafruit_BusIO_Register meas_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_MEAS_CFG, 1);
Adafruit_BusIO_RegisterBits sensor_rdy_bit =
Adafruit_BusIO_RegisterBits(&meas_cfg_reg, 1, 6);
return sensor_rdy_bit.read();
}
/*!
* @brief Checks if temperature data is ready
* @return True if temperature data is ready, false otherwise
*/
bool Adafruit_SPA06_003::isTempDataReady() {
Adafruit_BusIO_Register meas_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_MEAS_CFG, 1);
Adafruit_BusIO_RegisterBits tmp_rdy_bit =
Adafruit_BusIO_RegisterBits(&meas_cfg_reg, 1, 5);
return tmp_rdy_bit.read();
}
/*!
* @brief Checks if pressure data is ready
* @return True if pressure data is ready, false otherwise
*/
bool Adafruit_SPA06_003::isPresDataReady() {
Adafruit_BusIO_Register meas_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_MEAS_CFG, 1);
Adafruit_BusIO_RegisterBits prs_rdy_bit =
Adafruit_BusIO_RegisterBits(&meas_cfg_reg, 1, 4);
return prs_rdy_bit.read();
}
/*!
* @brief Gets the current measurement mode
* @return Current measurement mode setting
*/
spa06_003_meas_mode_t Adafruit_SPA06_003::getMeasurementMode() {
Adafruit_BusIO_Register meas_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_MEAS_CFG, 1);
Adafruit_BusIO_RegisterBits meas_ctrl_bits =
Adafruit_BusIO_RegisterBits(&meas_cfg_reg, 3, 0);
return (spa06_003_meas_mode_t)meas_ctrl_bits.read();
}
/*!
* @brief Sets the measurement mode
* @param mode The measurement mode to set
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setMeasurementMode(spa06_003_meas_mode_t mode) {
Adafruit_BusIO_Register meas_cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_MEAS_CFG, 1);
Adafruit_BusIO_RegisterBits meas_ctrl_bits =
Adafruit_BusIO_RegisterBits(&meas_cfg_reg, 3, 0);
return meas_ctrl_bits.write(mode);
}
/*!
* @brief Sets the interrupt polarity
* @param polarity The interrupt polarity to set
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setInterruptPolarity(
spa06_003_int_polarity_t polarity) {
Adafruit_BusIO_Register cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_CFG_REG, 1);
Adafruit_BusIO_RegisterBits int_hl_bit =
Adafruit_BusIO_RegisterBits(&cfg_reg, 1, 7);
return int_hl_bit.write(polarity);
}
/*!
* @brief Sets the interrupt sources
* @param fifo Enable FIFO interrupt
* @param temp_ready Enable temperature ready interrupt
* @param pres_ready Enable pressure ready interrupt
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setInterruptSource(bool fifo, bool temp_ready,
bool pres_ready) {
Adafruit_BusIO_Register cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_CFG_REG, 1);
Adafruit_BusIO_RegisterBits int_fifo_bit =
Adafruit_BusIO_RegisterBits(&cfg_reg, 1, 6);
Adafruit_BusIO_RegisterBits int_tmp_bit =
Adafruit_BusIO_RegisterBits(&cfg_reg, 1, 5);
Adafruit_BusIO_RegisterBits int_prs_bit =
Adafruit_BusIO_RegisterBits(&cfg_reg, 1, 4);
return int_fifo_bit.write(fifo) && int_tmp_bit.write(temp_ready) &&
int_prs_bit.write(pres_ready);
}
/*!
* @brief Sets the temperature result bit shift
* @param enable True to enable bit shift, false to disable
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setTempShift(bool enable) {
Adafruit_BusIO_Register cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_CFG_REG, 1);
Adafruit_BusIO_RegisterBits t_shift_bit =
Adafruit_BusIO_RegisterBits(&cfg_reg, 1, 3);
return t_shift_bit.write(enable);
}
/*!
* @brief Sets the pressure result bit shift
* @param enable True to enable bit shift, false to disable
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::setPresShift(bool enable) {
Adafruit_BusIO_Register cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_CFG_REG, 1);
Adafruit_BusIO_RegisterBits p_shift_bit =
Adafruit_BusIO_RegisterBits(&cfg_reg, 1, 2);
return p_shift_bit.write(enable);
}
/*!
* @brief Enables or disables FIFO
* @param enable True to enable FIFO, false to disable
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::enableFIFO(bool enable) {
Adafruit_BusIO_Register cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_CFG_REG, 1);
Adafruit_BusIO_RegisterBits fifo_en_bit =
Adafruit_BusIO_RegisterBits(&cfg_reg, 1, 1);
return fifo_en_bit.write(enable);
}
/*!
* @brief Checks if FIFO is enabled
* @return True if FIFO is enabled, false otherwise
*/
bool Adafruit_SPA06_003::isFIFOEnabled() {
Adafruit_BusIO_Register cfg_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_CFG_REG, 1);
Adafruit_BusIO_RegisterBits fifo_en_bit =
Adafruit_BusIO_RegisterBits(&cfg_reg, 1, 1);
return fifo_en_bit.read();
}
/*!
* @brief Checks if FIFO is empty
* @return True if FIFO is empty, false otherwise
*/
bool Adafruit_SPA06_003::isFIFOEmpty() {
Adafruit_BusIO_Register fifo_sts_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_FIFO_STS, 1);
Adafruit_BusIO_RegisterBits fifo_empty_bit =
Adafruit_BusIO_RegisterBits(&fifo_sts_reg, 1, 0);
return fifo_empty_bit.read();
}
/*!
* @brief Checks if FIFO is full
* @return True if FIFO is full, false otherwise
*/
bool Adafruit_SPA06_003::isFIFOFull() {
Adafruit_BusIO_Register fifo_sts_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_FIFO_STS, 1);
Adafruit_BusIO_RegisterBits fifo_full_bit =
Adafruit_BusIO_RegisterBits(&fifo_sts_reg, 1, 1);
return fifo_full_bit.read();
}
/*!
* @brief Gets the interrupt status flags
* @return Interrupt status register value with flags
*/
uint8_t Adafruit_SPA06_003::getStatusFlags() {
Adafruit_BusIO_Register int_sts_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_INT_STS, 1);
return int_sts_reg.read() & 0x07;
}
/*!
* @brief Flushes the FIFO buffer
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::flushFIFO() {
Adafruit_BusIO_Register reset_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_RESET, 1);
Adafruit_BusIO_RegisterBits fifo_flush_bit =
Adafruit_BusIO_RegisterBits(&reset_reg, 1, 7);
return fifo_flush_bit.write(1);
}
/*!
* @brief Performs a soft reset of the sensor
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::reset() {
Adafruit_BusIO_Register reset_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_RESET, 1);
Adafruit_BusIO_RegisterBits soft_rst_bits =
Adafruit_BusIO_RegisterBits(&reset_reg, 4, 0);
return soft_rst_bits.write(0x09);
}
/*!
* @brief Reads calibration coefficients from sensor registers
* @return True if successful, false otherwise
*/
bool Adafruit_SPA06_003::readCoefficients() {
if (!isCoeffReady()) {
return false;
}
// Read all coefficient data (21 bytes from 0x10 to 0x24)
uint8_t coef_data[21];
Adafruit_BusIO_Register coef_reg =
Adafruit_BusIO_Register(i2c_dev, SPA06_003_REG_COEF, 21);
if (!coef_reg.read(coef_data, 21)) {
return false;
}
// Parse coefficients according to datasheet table
// c0: 12-bit (0x10-0x11)
c0 = (int16_t)((coef_data[0] << 4) | (coef_data[1] >> 4));
if (c0 & 0x800) {
c0 |= 0xF000; // Sign extend
}
// c1: 12-bit (0x11-0x12)
c1 = (int16_t)(((coef_data[1] & 0x0F) << 8) | coef_data[2]);
if (c1 & 0x800) {
c1 |= 0xF000; // Sign extend
}
// c00: 20-bit (0x13-0x15)
uint32_t c00_temp = (((uint32_t)coef_data[3] << 12) & 0xFF000) |
(((uint16_t)coef_data[4] << 4) & 0x00FF0) |
((coef_data[5] >> 4) & 0x0000F);
if (c00_temp & 0x80000) {
c00 = (int32_t)(c00_temp | 0xFFF00000); // Sign extend
} else {
c00 = (int32_t)c00_temp;
}
// c10: 20-bit (0x15-0x17)
uint32_t c10_temp = (((uint32_t)coef_data[5] << 16) & 0xF0000) |
(((uint16_t)coef_data[6] << 8) & 0x0FF00) | coef_data[7];
if (c10_temp & 0x80000) {
c10 = (int32_t)(c10_temp | 0xFFF00000); // Sign extend
} else {
c10 = (int32_t)c10_temp;
}
// c01: 16-bit (0x18-0x19)
c01 = (int16_t)((coef_data[8] << 8) | coef_data[9]);
// c11: 16-bit (0x1A-0x1B)
c11 = (int16_t)((coef_data[10] << 8) | coef_data[11]);
// c20: 16-bit (0x1C-0x1D)
c20 = (int16_t)((coef_data[12] << 8) | coef_data[13]);
// c21: 16-bit (0x1E-0x1F)
c21 = (int16_t)((coef_data[14] << 8) | coef_data[15]);
// c30: 16-bit (0x20-0x21)
c30 = (int16_t)((coef_data[16] << 8) | coef_data[17]);
// c31: 12-bit (0x22 + 0x23 bits 7:4)
c31 = (int16_t)(((coef_data[18] << 4) & 0xFF0) |
((coef_data[19] >> 4) & 0x00F));
if (c31 & 0x800) {
c31 |= 0xF000; // Sign extend
}
// c40: 12-bit (0x23 bits 3:0 + 0x24)
c40 = (int16_t)(((coef_data[19] & 0x0F) << 8) | coef_data[20]);
if (c40 & 0x800) {
c40 |= 0xF000; // Sign extend
}
return true;
}
/*!
* @brief Gets scaling factor based on oversampling setting
* @param oversample The oversampling rate
* @return Scaling factor for compensation calculation
*/
float Adafruit_SPA06_003::getScalingFactor(spa06_003_oversample_t oversample) {
switch (oversample) {
case SPA06_003_OVERSAMPLE_1:
return 524288; // Single
case SPA06_003_OVERSAMPLE_2:
return 1572864; // 2x
case SPA06_003_OVERSAMPLE_4:
return 3670016; // 4x
case SPA06_003_OVERSAMPLE_8:
return 7864320; // 8x
case SPA06_003_OVERSAMPLE_16:
return 253952; // 16x
case SPA06_003_OVERSAMPLE_32:
return 516096; // 32x
case SPA06_003_OVERSAMPLE_64:
return 1040384; // 64x
case SPA06_003_OVERSAMPLE_128:
return 2088960; // 128x
default:
return 524288; // Default to single
}
}
/*!
* @brief Reads compensated temperature value in Celsius
* @return Temperature in degrees Celsius
*/
float Adafruit_SPA06_003::readTemperature() {
// Get current temperature oversampling setting and scale factor
spa06_003_oversample_t oversample = getTemperatureOversampling();
float kT = getScalingFactor(oversample);
// Read raw temperature data (24-bit 2's complement)
uint32_t temp_raw = getTemperatureData();
// Convert to signed 32-bit
int32_t temp_raw_signed = (int32_t)temp_raw;
// Calculate scaled measurement result
float temp_raw_sc = (float)temp_raw_signed / kT;
// Calculate compensated temperature: Tcomp = c0*0.5 + c1*Traw_sc
float temp_comp = (float)c0 * 0.5f + (float)c1 * temp_raw_sc;
return temp_comp;
}
/*!
* @brief Reads compensated pressure value in hectopascals
* @return Pressure in hectopascals (hPa)
*/
float Adafruit_SPA06_003::readPressure() {
// Get scaling factors based on current oversampling settings
float kP = getScalingFactor(getPressureOversampling());
float kT = getScalingFactor(getTemperatureOversampling());
// Read raw pressure and temperature data (24-bit 2's complement)
uint32_t pres_raw = getPressureData();
uint32_t temp_raw = getTemperatureData();
// Convert to signed 32-bit
int32_t pres_raw_signed = (int32_t)pres_raw;
int32_t temp_raw_signed = (int32_t)temp_raw;
// Calculate scaled measurement results
float pres_raw_sc = (float)pres_raw_signed / kP;
float temp_raw_sc = (float)temp_raw_signed / kT;
// Calculate powers of Praw_sc for the compensation formula
float pres_raw_sc_2 = pres_raw_sc * pres_raw_sc;
float pres_raw_sc_3 = pres_raw_sc_2 * pres_raw_sc;
float pres_raw_sc_4 = pres_raw_sc_3 * pres_raw_sc;
// Calculate compensated pressure using the formula:
// Pcomp = c00 + c10*Praw_sc + c20*Praw_sc^2 + c30*Praw_sc^3 + c40*Praw_sc^4 +
// Traw_sc*(c01 + c11*Praw_sc + c21*Praw_sc^2 + c31*Praw_sc^3)
float pres_comp =
(float)c00 + (float)c10 * pres_raw_sc + (float)c20 * pres_raw_sc_2 +
(float)c30 * pres_raw_sc_3 + (float)c40 * pres_raw_sc_4 +
temp_raw_sc * ((float)c01 + (float)c11 * pres_raw_sc +
(float)c21 * pres_raw_sc_2 + (float)c31 * pres_raw_sc_3);
// Convert from Pascals to hectopascals (hPa)
return pres_comp / 100.0f;
}
/*!
* @brief Gets the Adafruit_Sensor object for temperature readings
* @return Adafruit_Sensor pointer for temperature
*/
Adafruit_Sensor *Adafruit_SPA06_003::getTemperatureSensor() {
if (!temp_sensor) {
temp_sensor = new Adafruit_SPA06_003_Temp(this);
}
return temp_sensor;
}
/*!
* @brief Gets the Adafruit_Sensor object for pressure readings
* @return Adafruit_Sensor pointer for pressure
*/
Adafruit_Sensor *Adafruit_SPA06_003::getPressureSensor() {
if (!pressure_sensor) {
pressure_sensor = new Adafruit_SPA06_003_Pressure(this);
}
return pressure_sensor;
}
/*!
* @brief Gets the sensor_t device data for temperature sensor
* @param sensor Pointer to sensor_t device info struct
*/
void Adafruit_SPA06_003_Temp::getSensor(sensor_t *sensor) {
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy(sensor->name, "SPA06_003", sizeof(sensor->name) - 1);
sensor->name[sizeof(sensor->name) - 1] = 0;
sensor->version = 1;
sensor->sensor_id = _sensorID;
sensor->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
sensor->min_delay = 0;
sensor->min_value = -40.0; // Datasheet minimum
sensor->max_value = 85.0; // Datasheet maximum
sensor->resolution = 0.01; // Datasheet resolution
}
/*!
* @brief Gets the latest sensor event for temperature
* @param event Pointer to sensors_event_t struct
* @return True on successful event generation
*/
bool Adafruit_SPA06_003_Temp::getEvent(sensors_event_t *event) {
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
event->timestamp = millis();
event->temperature = _theSPA06003->readTemperature();
return true;
}
/*!
* @brief Gets the sensor_t device data for pressure sensor
* @param sensor Pointer to sensor_t device info struct
*/
void Adafruit_SPA06_003_Pressure::getSensor(sensor_t *sensor) {
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy(sensor->name, "SPA06_003", sizeof(sensor->name) - 1);
sensor->name[sizeof(sensor->name) - 1] = 0;
sensor->version = 1;
sensor->sensor_id = _sensorID;
sensor->type = SENSOR_TYPE_PRESSURE;
sensor->min_delay = 0;
sensor->min_value = 300.0; // Datasheet minimum in hPa
sensor->max_value = 1100.0; // Datasheet maximum in hPa
sensor->resolution = 0.012; // Datasheet resolution in hPa
}
/*!
* @brief Gets the latest sensor event for pressure
* @param event Pointer to sensors_event_t struct
* @return True on successful event generation
*/
bool Adafruit_SPA06_003_Pressure::getEvent(sensors_event_t *event) {
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->type = SENSOR_TYPE_PRESSURE;
event->timestamp = millis();
event->pressure = _theSPA06003->readPressure();
return true;
}

256
Adafruit_SPA06_003.h Normal file
View file

@ -0,0 +1,256 @@
/*!
* @file Adafruit_SPA06003.h
*
* This is part of Adafruit's SPA06003 driver for the Arduino platform. It is
* designed specifically to work with the Adafruit SPA06003 breakout:
* https://www.adafruit.com/products/xxxx
*
* These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
* to interface with the breakout.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Limor 'ladyada' Fried with assistance from Claude Code
* for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef _ADAFRUIT_SPA06_003_H
#define _ADAFRUIT_SPA06_003_H
#include <Adafruit_BusIO_Register.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include "Arduino.h"
// Forward declarations
class Adafruit_SPA06_003_Temp;
class Adafruit_SPA06_003_Pressure;
/*=========================================================================
I2C ADDRESS/BITS
-----------------------------------------------------------------------*/
/**
* @brief Default I2C address for SPA06_003
*/
#define SPA06_003_DEFAULT_ADDR 0x77
/*=========================================================================
REGISTERS
-----------------------------------------------------------------------*/
/**
* @brief Pressure data registers
*/
#define SPA06_003_REG_PSR_B2 0x00
#define SPA06_003_REG_PSR_B1 0x01
#define SPA06_003_REG_PSR_B0 0x02
/**
* @brief Temperature data registers
*/
#define SPA06_003_REG_TMP_B2 0x03
#define SPA06_003_REG_TMP_B1 0x04
#define SPA06_003_REG_TMP_B0 0x05
/**
* @brief Configuration registers
*/
#define SPA06_003_REG_PRS_CFG 0x06
#define SPA06_003_REG_TMP_CFG 0x07
#define SPA06_003_REG_MEAS_CFG 0x08
#define SPA06_003_REG_CFG_REG 0x09
/**
* @brief Status registers
*/
#define SPA06_003_REG_INT_STS 0x0A
#define SPA06_003_REG_FIFO_STS 0x0B
/**
* @brief Control registers
*/
#define SPA06_003_REG_RESET 0x0C
#define SPA06_003_REG_ID 0x0D
/**
* @brief Calibration coefficient registers
*/
#define SPA06_003_REG_COEF 0x10
/*=========================================================================
INTERRUPT STATUS FLAGS (INT_STS register 0x0A)
-----------------------------------------------------------------------*/
/**
* @brief Interrupt status flag definitions
*/
#define SPA06_003_INT_FIFO_FULL 0x04 ///< FIFO full flag
#define SPA06_003_INT_TMP_RDY 0x02 ///< Temperature measurement ready flag
#define SPA06_003_INT_PRS_RDY 0x01 ///< Pressure measurement ready flag
/*=========================================================================*/
/**
* @brief Measurement rate options (pressure and temperature)
*/
typedef enum {
SPA06_003_RATE_1 = 0x00, ///< 1 measurements per second
SPA06_003_RATE_2 = 0x01, ///< 2 measurements per second
SPA06_003_RATE_4 = 0x02, ///< 4 measurements per second
SPA06_003_RATE_8 = 0x03, ///< 8 measurements per second
SPA06_003_RATE_16 = 0x04, ///< 16 measurements per second
SPA06_003_RATE_32 = 0x05, ///< 32 measurements per second
SPA06_003_RATE_64 = 0x06, ///< 64 measurements per second
SPA06_003_RATE_128 = 0x07, ///< 128 measurements per second
SPA06_003_RATE_25_16 = 0x08, ///< 25/16 samples per second
SPA06_003_RATE_25_8 = 0x09, ///< 25/8 samples per second
SPA06_003_RATE_25_4 = 0x0A, ///< 25/4 samples per second
SPA06_003_RATE_25_2 = 0x0B, ///< 25/2 samples per second
SPA06_003_RATE_25 = 0x0C, ///< 25 samples per second
SPA06_003_RATE_50 = 0x0D, ///< 50 samples per second
SPA06_003_RATE_100 = 0x0E, ///< 100 samples per second
SPA06_003_RATE_200 = 0x0F ///< 200 samples per second
} spa06_003_rate_t;
/**
* @brief Oversampling rate options (shared by pressure and temperature)
*/
typedef enum {
SPA06_003_OVERSAMPLE_1 = 0x00, ///< Single
SPA06_003_OVERSAMPLE_2 = 0x01, ///< 2 times
SPA06_003_OVERSAMPLE_4 = 0x02, ///< 4 times
SPA06_003_OVERSAMPLE_8 = 0x03, ///< 8 times
SPA06_003_OVERSAMPLE_16 = 0x04, ///< 16 times
SPA06_003_OVERSAMPLE_32 = 0x05, ///< 32 times
SPA06_003_OVERSAMPLE_64 = 0x06, ///< 64 times
SPA06_003_OVERSAMPLE_128 = 0x07 ///< 128 times
} spa06_003_oversample_t;
/**
* @brief Measurement mode options
*/
typedef enum {
SPA06_003_MEAS_IDLE = 0x00, ///< Idle / Stop background measurement
SPA06_003_MEAS_PRESSURE = 0x01, ///< Pressure measurement (Command Mode)
SPA06_003_MEAS_TEMPERATURE =
0x02, ///< Temperature measurement (Command Mode)
SPA06_003_MEAS_CONTINUOUS_PRESSURE =
0x05, ///< Continuous pressure measurement (Background Mode)
SPA06_003_MEAS_CONTINUOUS_TEMPERATURE =
0x06, ///< Continuous temperature measurement (Background Mode)
SPA06_003_MEAS_CONTINUOUS_BOTH =
0x07 ///< Continuous pressure and temperature measurement (Background
///< Mode)
} spa06_003_meas_mode_t;
/**
* @brief Interrupt polarity options
*/
typedef enum {
SPA06_003_INT_ACTIVE_LOW = 0x00, ///< Interrupt active low
SPA06_003_INT_ACTIVE_HIGH = 0x01 ///< Interrupt active high
} spa06_003_int_polarity_t;
/*!
* @brief Class that stores state and functions for interacting with SPA06_003
*/
class Adafruit_SPA06_003 {
public:
Adafruit_SPA06_003();
~Adafruit_SPA06_003();
bool begin(uint8_t i2c_addr = SPA06_003_DEFAULT_ADDR, TwoWire *wire = &Wire);
uint32_t getPressureData();
uint32_t getTemperatureData();
spa06_003_rate_t getPressureMeasureRate();
bool setPressureMeasureRate(spa06_003_rate_t rate);
spa06_003_rate_t getTemperatureMeasureRate();
bool setTemperatureMeasureRate(spa06_003_rate_t rate);
spa06_003_oversample_t getPressureOversampling();
bool setPressureOversampling(spa06_003_oversample_t prc);
spa06_003_oversample_t getTemperatureOversampling();
bool setTemperatureOversampling(spa06_003_oversample_t prc);
bool isCoeffReady();
bool isSensorReady();
bool isTempDataReady();
bool isPresDataReady();
spa06_003_meas_mode_t getMeasurementMode();
bool setMeasurementMode(spa06_003_meas_mode_t mode);
bool setInterruptPolarity(spa06_003_int_polarity_t polarity);
bool setInterruptSource(bool fifo, bool temp_ready, bool pres_ready);
bool setTempShift(bool enable);
bool setPresShift(bool enable);
bool enableFIFO(bool enable);
bool isFIFOEnabled();
bool isFIFOEmpty();
bool isFIFOFull();
uint8_t getStatusFlags();
bool flushFIFO();
bool reset();
float readTemperature();
float readPressure();
Adafruit_Sensor *getTemperatureSensor();
Adafruit_Sensor *getPressureSensor();
private:
Adafruit_I2CDevice *i2c_dev;
// Adafruit Sensor objects
Adafruit_SPA06_003_Temp *temp_sensor = NULL;
Adafruit_SPA06_003_Pressure *pressure_sensor = NULL;
// Calibration coefficients
int16_t c0, c1;
int32_t c00, c10; // 20-bit 2's complement
int16_t c01, c11, c20, c21, c30; // 16-bit 2's complement
int16_t c31; // 12-bit 2's complement
int16_t c40; // 12-bit 2's complement
bool readCoefficients();
float getScalingFactor(spa06_003_oversample_t oversample);
};
/*!
* @brief Adafruit Unified Sensor interface for temperature component of
* SPA06_003
*/
class Adafruit_SPA06_003_Temp : public Adafruit_Sensor {
public:
/** @brief Create an Adafruit_Sensor compatible object for the temp sensor
@param parent A pointer to the SPA06_003 class */
Adafruit_SPA06_003_Temp(Adafruit_SPA06_003 *parent) {
_theSPA06003 = parent;
}
bool getEvent(sensors_event_t *);
void getSensor(sensor_t *);
private:
int _sensorID = 60003;
Adafruit_SPA06_003 *_theSPA06003 = NULL;
};
/*!
* @brief Adafruit Unified Sensor interface for pressure component of SPA06_003
*/
class Adafruit_SPA06_003_Pressure : public Adafruit_Sensor {
public:
/** @brief Create an Adafruit_Sensor compatible object for the pressure sensor
@param parent A pointer to the SPA06_003 class */
Adafruit_SPA06_003_Pressure(Adafruit_SPA06_003 *parent) {
_theSPA06003 = parent;
}
bool getEvent(sensors_event_t *);
void getSensor(sensor_t *);
private:
int _sensorID = 60003;
Adafruit_SPA06_003 *_theSPA06003 = NULL;
};
#endif

135
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,135 @@
<!--
SPDX-FileCopyrightText: 2014 Coraline Ada Ehmke
SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries
SPDX-License-Identifier: CC-BY-4.0
-->
# Adafruit Community Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and leaders pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level or type of
experience, education, socio-economic status, nationality, personal appearance,
race, religion, or sexual identity and orientation.
## Our Standards
We are committed to providing a friendly, safe and welcoming environment for
all.
Examples of behavior that contributes to creating a positive environment
include:
* Be kind and courteous to others
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Collaborating with other community members
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and sexual attention or advances
* The use of inappropriate images, including in a community member's avatar
* The use of inappropriate language, including in a community member's nickname
* Any spamming, flaming, baiting or other attention-stealing behavior
* Excessive or unwelcome helping; answering outside the scope of the question
asked
* Trolling, insulting/derogatory comments, and personal or political attacks
* Promoting or spreading disinformation, lies, or conspiracy theories against
a person, group, organisation, project, or community
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate
The goal of the standards and moderation guidelines outlined here is to build
and maintain a respectful community. We ask that you don't just aim to be
"technically unimpeachable", but rather try to be your best self.
We value many things beyond technical expertise, including collaboration and
supporting others within our community. Providing a positive experience for
other community members can have a much more significant impact than simply
providing the correct answer.
## Our Responsibilities
Project leaders are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project leaders have the right and responsibility to remove, edit, or
reject messages, comments, commits, code, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any community member for other behaviors that they deem
inappropriate, threatening, offensive, or harmful.
## Moderation
Instances of behaviors that violate the Adafruit Community Code of Conduct
may be reported by any member of the community. Community members are
encouraged to report these situations, including situations they witness
involving other community members.
You may report in the following ways:
In any situation, you may send an email to <support@adafruit.com>.
On the Adafruit Discord, you may send an open message from any channel
to all Community Moderators by tagging @community moderators. You may
also send an open message from any channel, or a direct message to
@kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442,
@sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175.
Email and direct message reports will be kept confidential.
In situations on Discord where the issue is particularly egregious, possibly
illegal, requires immediate action, or violates the Discord terms of service,
you should also report the message directly to Discord.
These are the steps for upholding our community's standards of conduct.
1. Any member of the community may report any situation that violates the
Adafruit Community Code of Conduct. All reports will be reviewed and
investigated.
2. If the behavior is an egregious violation, the community member who
committed the violation may be banned immediately, without warning.
3. Otherwise, moderators will first respond to such behavior with a warning.
4. Moderators follow a soft "three strikes" policy - the community member may
be given another chance, if they are receptive to the warning and change their
behavior.
5. If the community member is unreceptive or unreasonable when warned by a
moderator, or the warning goes unheeded, they may be banned for a first or
second offense. Repeated offenses will result in the community member being
banned.
## Scope
This Code of Conduct and the enforcement policies listed above apply to all
Adafruit Community venues. This includes but is not limited to any community
spaces (both public and private), the entire Adafruit Discord server, and
Adafruit GitHub repositories. Examples of Adafruit Community spaces include
but are not limited to meet-ups, audio chats on the Adafruit Discord, or
interaction at a conference.
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. As a community
member, you are representing our community, and are expected to behave
accordingly.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.4, available at
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
For other projects adopting the Adafruit Community Code of
Conduct, please contact the maintainers of those projects for enforcement.
If you wish to use this code of conduct for your own project, consider
explicitly mentioning your moderation policy or making a copy with your
own moderation policy so as to avoid confusion.

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Adafruit Industries
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

61
README.md Normal file
View file

@ -0,0 +1,61 @@
# Adafruit SPA06_003 [![Build Status](https://github.com/adafruit/Adafruit_SPA06_003/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_SPA06_003/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_SPA06_003/html/index.html)
<a href="https://www.adafruit.com/product/xxxx"><img src="https://cdn-shop.adafruit.com/xxxx" width="500px"><br/>
<i>Adafruit SPA06_003 Breakout</i></a>
This is the Adafruit SPA06_003 Digital Pressure Sensor library for Arduino.
Tested and works great with the Adafruit SPA06_003 Breakout Board.
## About the SPA06_003
The SPA06_003 is a miniaturized Digital Barometric Air Pressure Sensor with high accuracy and low current consumption. Key features:
* Pressure range: 300 ... 1100hPa (+9000m ... -500m relating to sea level)
* Temperature Range: -40...+85°C
* Supply voltage: 1.7 ... 3.6V (VDD), 1.08... 3.6V (VDDIO)
* Small footprint: 2.0mm x 2.5mm; Super-flat: 0.95mm
* Relative accuracy: typ.±0.03hPa, equiv. to ±0.25 m
* Absolute accuracy: typ. ±0.3hPa (300 ... 1100hPa)
* Temperature accuracy: typ. ± 1°C
* Measurement time: 3.6ms for low precision mode
* Average current consumption: 1.7 µA for pressure measurement, 1.5 µA for temperature measurement at 1Hz sampling rate
* I2C and SPI interface
* FIFO: Stores latest 32 pressure or temperature measurements
* Embedded 24-bit ADC
## Installation
To install, use the Arduino Library Manager and search for "Adafruit SPA06_003" and install the library.
## Dependencies
This library depends on the [Adafruit BusIO library](https://github.com/adafruit/Adafruit_BusIO)
## Contributing
Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/Adafruit_SPA06_003/blob/main/CODE_OF_CONDUCT.md)
before contributing to help this project stay welcoming.
## Documentation and doxygen
Documentation is produced by doxygen. Contributions should include documentation for any new features.
## Formatting and clang-format
This library uses [`clang-format`](https://releases.llvm.org/download.html) to standardize the formatting of `.cpp` and `.h` files.
Contributions should be formatted using `clang-format`:
The `-i` flag will make the changes to the file.
```bash
clang-format -i *.cpp *.h
```
If you prefer to make the changes yourself, running `clang-format` without the `-i` flag will print out a formatted version of the file. You can save this to a file and diff it against the original to see the changes.
Note that the formatting output by `clang-format` is what the automated formatting checker will expect. Any irrelevant changes (such as un-necessary whitespace changes) will result in a failed build until they are addressed. Using the `-i` flag is highly recommended.
## About this Driver
Written by Limor 'ladyada' Fried with assistance from Claude Code for Adafruit Industries. MIT license, check license.txt for more information All text above must be included in any redistribution
To install, use the Arduino Library Manager and search for "Adafruit SPA06_003" and install the library.

View file

@ -0,0 +1,226 @@
/*
Basic test sketch for SPA06_003 Digital Pressure Sensor
This sketch initializes the sensor and verifies communication.
Written by Limor 'ladyada' Fried with assistance from Claude Code
for Adafruit Industries.
MIT license, check license.txt for more information
*/
#include <Adafruit_SPA06_003.h>
Adafruit_SPA06_003 spa;
void printMeasureRate(spa06_003_rate_t rate) {
switch (rate) {
case SPA06_003_RATE_1:
Serial.println(F("1 measurements per second"));
break;
case SPA06_003_RATE_2:
Serial.println(F("2 measurements per second"));
break;
case SPA06_003_RATE_4:
Serial.println(F("4 measurements per second"));
break;
case SPA06_003_RATE_8:
Serial.println(F("8 measurements per second"));
break;
case SPA06_003_RATE_16:
Serial.println(F("16 measurements per second"));
break;
case SPA06_003_RATE_32:
Serial.println(F("32 measurements per second"));
break;
case SPA06_003_RATE_64:
Serial.println(F("64 measurements per second"));
break;
case SPA06_003_RATE_128:
Serial.println(F("128 measurements per second"));
break;
case SPA06_003_RATE_25_16:
Serial.println(F("25/16 samples per second"));
break;
case SPA06_003_RATE_25_8:
Serial.println(F("25/8 samples per second"));
break;
case SPA06_003_RATE_25_4:
Serial.println(F("25/4 samples per second"));
break;
case SPA06_003_RATE_25_2:
Serial.println(F("25/2 samples per second"));
break;
case SPA06_003_RATE_25:
Serial.println(F("25 samples per second"));
break;
case SPA06_003_RATE_50:
Serial.println(F("50 samples per second"));
break;
case SPA06_003_RATE_100:
Serial.println(F("100 samples per second"));
break;
case SPA06_003_RATE_200:
Serial.println(F("200 samples per second"));
break;
default:
Serial.println(F("Unknown rate"));
break;
}
}
void printOversampling(spa06_003_oversample_t prc) {
switch (prc) {
case SPA06_003_OVERSAMPLE_1:
Serial.println(F("Single"));
break;
case SPA06_003_OVERSAMPLE_2:
Serial.println(F("2 times"));
break;
case SPA06_003_OVERSAMPLE_4:
Serial.println(F("4 times"));
break;
case SPA06_003_OVERSAMPLE_8:
Serial.println(F("8 times"));
break;
case SPA06_003_OVERSAMPLE_16:
Serial.println(F("16 times"));
break;
case SPA06_003_OVERSAMPLE_32:
Serial.println(F("32 times"));
break;
case SPA06_003_OVERSAMPLE_64:
Serial.println(F("64 times"));
break;
case SPA06_003_OVERSAMPLE_128:
Serial.println(F("128 times"));
break;
default:
Serial.println(F("Unknown"));
break;
}
}
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("SPA06_003 test!");
if (!spa.begin()) {
Serial.println("Could not find a valid SPA06_003 sensor, check wiring!");
while (1) delay(10);
}
Serial.println(F("SPA06_003 sensor found and initialized!"));
Serial.println(F("Setting measurement mode to continuous both..."));
spa.setMeasurementMode(SPA06_003_MEAS_CONTINUOUS_BOTH);
Serial.print(F("Current measurement mode: "));
spa06_003_meas_mode_t current_mode = spa.getMeasurementMode();
switch (current_mode) {
case SPA06_003_MEAS_IDLE:
Serial.println(F("Idle"));
break;
case SPA06_003_MEAS_PRESSURE:
Serial.println(F("Pressure (Command Mode)"));
break;
case SPA06_003_MEAS_TEMPERATURE:
Serial.println(F("Temperature (Command Mode)"));
break;
case SPA06_003_MEAS_CONTINUOUS_PRESSURE:
Serial.println(F("Continuous pressure"));
break;
case SPA06_003_MEAS_CONTINUOUS_TEMPERATURE:
Serial.println(F("Continuous temperature"));
break;
case SPA06_003_MEAS_CONTINUOUS_BOTH:
Serial.println(F("Continuous both"));
break;
default:
Serial.println(F("Unknown"));
break;
}
spa.enableFIFO(false);
spa.setInterruptPolarity(SPA06_003_INT_ACTIVE_HIGH);
spa.setInterruptSource(false /*fifo*/, true /*temp_ready*/, true /*pres_ready*/);
spa.setTemperatureOversampling(SPA06_003_OVERSAMPLE_8);
spa06_003_oversample_t temp_prc = spa.getTemperatureOversampling();
Serial.print(F("Current temperature oversampling: "));
printOversampling(temp_prc);
spa.setTemperatureMeasureRate(SPA06_003_RATE_64);
spa06_003_rate_t temp_rate = spa.getTemperatureMeasureRate();
Serial.print(F("Current temperature measurement rate: "));
printMeasureRate(temp_rate);
spa.setPressureMeasureRate(SPA06_003_RATE_128);
spa06_003_rate_t current_rate = spa.getPressureMeasureRate();
Serial.print(F("Current pressure measurement rate: "));
printMeasureRate(current_rate);
spa.setPressureOversampling(SPA06_003_OVERSAMPLE_8);
spa06_003_oversample_t current_prc = spa.getPressureOversampling();
Serial.print(F("Current pressure oversampling: "));
printOversampling(current_prc);
}
void loop() {
if (spa.isTempDataReady()) {
Serial.print(F("Temperature: "));
Serial.print(spa.readTemperature());
Serial.print(F("°C"));
}
if (spa.isPresDataReady()) {
Serial.print(F(", Pressure: "));
Serial.print(spa.readPressure());
Serial.print(F(" hPa"));
}
uint8_t status_flags = spa.getStatusFlags();
Serial.print(F(", Status flags: 0x"));
Serial.print(status_flags, HEX);
Serial.print(F(" ["));
if (status_flags & SPA06_003_INT_FIFO_FULL) {
Serial.print(F("FIFO_FULL "));
}
if (status_flags & SPA06_003_INT_TMP_RDY) {
Serial.print(F("TMP_RDY "));
}
if (status_flags & SPA06_003_INT_PRS_RDY) {
Serial.print(F("PRS_RDY "));
}
if (status_flags == 0) {
Serial.print(F("NONE"));
}
Serial.println(F("]"));
Serial.print(F(", FIFO: "));
if (spa.isFIFOEnabled()) {
Serial.print(F("enabled "));
if (spa.isFIFOEmpty()) {
Serial.print(F("(empty)"));
} else if (spa.isFIFOFull()) {
Serial.print(F("(full)"));
} else {
Serial.print(F("(partial)"));
}
} else {
Serial.print(F("disabled"));
}
Serial.println();
delay(1000);
}

10
library.properties Normal file
View file

@ -0,0 +1,10 @@
name=Adafruit SPA06_003
version=1.0.0
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for SPA06_003 digital pressure sensor
paragraph=Arduino library for the SPA06_003 miniaturized digital barometric air pressure sensor with high accuracy and low current consumption. Supports I2C communication and includes FIFO buffer for 32 measurements.
category=Sensors
url=https://github.com/adafruit/Adafruit_SPA06_003
architectures=*
depends=Adafruit BusIO