kopia lustrzana https://github.com/pimoroni/pimoroni-pico
New driver for SCD4X series CO2 sensors
Submodule Sensirion's embedded-i2c-scd4x driver Add i2c_hal.cpp to binds it to Pimoroni::I2C Port (loosely) scd4x_i2c_example_usage.c to Picopull/174/head
rodzic
9f6ddb86ae
commit
0eeada72d7
|
@ -11,3 +11,6 @@
|
|||
path = drivers/bmp280/src
|
||||
url = https://github.com/pimoroni/BMP280_driver
|
||||
branch = patch-intf-ptr
|
||||
[submodule "drivers/scd4x/src"]
|
||||
path = drivers/scd4x/src
|
||||
url = https://github.com/Sensirion/embedded-i2c-scd4x
|
||||
|
|
|
@ -23,4 +23,5 @@ add_subdirectory(button)
|
|||
add_subdirectory(plasma)
|
||||
add_subdirectory(rgbled)
|
||||
add_subdirectory(icp10125)
|
||||
add_subdirectory(scd4x)
|
||||
add_subdirectory(hub75)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
include(scd4x.cmake)
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Sensirion AG
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Sensirion AG nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sensirion_i2c_hal.h"
|
||||
#include "sensirion_common.h"
|
||||
#include "sensirion_config.h"
|
||||
|
||||
#define SCD4X_I2C_ADDRESS 98
|
||||
|
||||
pimoroni::I2C *__i2c = nullptr;
|
||||
|
||||
/*
|
||||
* INSTRUCTIONS
|
||||
* ============
|
||||
*
|
||||
* Implement all functions where they are marked as IMPLEMENT.
|
||||
* Follow the function specification in the comments.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Select the current i2c bus by index.
|
||||
* All following i2c operations will be directed at that bus.
|
||||
*
|
||||
* THE IMPLEMENTATION IS OPTIONAL ON SINGLE-BUS SETUPS (all sensors on the same
|
||||
* bus)
|
||||
*
|
||||
* @param bus_idx Bus index to select
|
||||
* @returns 0 on success, an error code otherwise
|
||||
*/
|
||||
int16_t sensirion_i2c_hal_select_bus(uint8_t bus_idx) {
|
||||
/* TODO:IMPLEMENT or leave empty if all sensors are located on one single
|
||||
* bus
|
||||
*/
|
||||
return NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all hard- and software components that are needed for the I2C
|
||||
* communication.
|
||||
*/
|
||||
void sensirion_i2c_hal_init(pimoroni::I2C *i2c) {
|
||||
__i2c = i2c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release all resources initialized by sensirion_i2c_hal_init().
|
||||
*/
|
||||
void sensirion_i2c_hal_free(void) {
|
||||
/* TODO:IMPLEMENT or leave empty if no resources need to be freed */
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute one read transaction on the I2C bus, reading a given number of bytes.
|
||||
* If the device does not acknowledge the read command, an error shall be
|
||||
* returned.
|
||||
*
|
||||
* @param address 7-bit I2C address to read from
|
||||
* @param data pointer to the buffer where the data is to be stored
|
||||
* @param count number of bytes to read from I2C and store in the buffer
|
||||
* @returns 0 on success, error code otherwise
|
||||
*/
|
||||
int8_t sensirion_i2c_hal_read(uint8_t address, uint8_t* data, uint16_t count) {
|
||||
int result = __i2c->read_blocking(address, data, count, false);
|
||||
return result >= 0 ? 0 : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute one write transaction on the I2C bus, sending a given number of
|
||||
* bytes. The bytes in the supplied buffer must be sent to the given address. If
|
||||
* the slave device does not acknowledge any of the bytes, an error shall be
|
||||
* returned.
|
||||
*
|
||||
* @param address 7-bit I2C address to write to
|
||||
* @param data pointer to the buffer containing the data to write
|
||||
* @param count number of bytes to read from the buffer and send over I2C
|
||||
* @returns 0 on success, error code otherwise
|
||||
*/
|
||||
int8_t sensirion_i2c_hal_write(uint8_t address, const uint8_t* data,
|
||||
uint16_t count) {
|
||||
int result = __i2c->write_blocking(address, data, count, false);
|
||||
return result >= 0 ? 0 : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep for a given number of microseconds. The function should delay the
|
||||
* execution for at least the given time, but may also sleep longer.
|
||||
*
|
||||
* Despite the unit, a <10 millisecond precision is sufficient.
|
||||
*
|
||||
* @param useconds the sleep time in microseconds
|
||||
*/
|
||||
void sensirion_i2c_hal_sleep_usec(uint32_t useconds) {
|
||||
sleep_us(useconds);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
set(DRIVER_NAME scd4x)
|
||||
add_library(${DRIVER_NAME} INTERFACE)
|
||||
|
||||
target_sources(${DRIVER_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/scd4x_i2c.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/sensirion_common.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/sensirion_i2c.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/i2c_hal.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/scd4x.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${DRIVER_NAME} INTERFACE pimoroni_i2c hardware_i2c)
|
||||
|
||||
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src)
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Sensirion AG
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Sensirion AG nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SENSIRION_I2C_HAL_H
|
||||
#define SENSIRION_I2C_HAL_H
|
||||
|
||||
#include "sensirion_config.h"
|
||||
#include "common/pimoroni_i2c.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Select the current i2c bus by index.
|
||||
* All following i2c operations will be directed at that bus.
|
||||
*
|
||||
* THE IMPLEMENTATION IS OPTIONAL ON SINGLE-BUS SETUPS (all sensors on the same
|
||||
* bus)
|
||||
*
|
||||
* @param bus_idx Bus index to select
|
||||
* @returns 0 on success, an error code otherwise
|
||||
*/
|
||||
int16_t sensirion_i2c_hal_select_bus(uint8_t bus_idx);
|
||||
|
||||
/**
|
||||
* Initialize all hard- and software components that are needed for the I2C
|
||||
* communication.
|
||||
*/
|
||||
void sensirion_i2c_hal_init(pimoroni::I2C *_i2c);
|
||||
|
||||
/**
|
||||
* Release all resources initialized by sensirion_i2c_hal_init().
|
||||
*/
|
||||
void sensirion_i2c_hal_free(void);
|
||||
|
||||
/**
|
||||
* Execute one read transaction on the I2C bus, reading a given number of bytes.
|
||||
* If the device does not acknowledge the read command, an error shall be
|
||||
* returned.
|
||||
*
|
||||
* @param address 7-bit I2C address to read from
|
||||
* @param data pointer to the buffer where the data is to be stored
|
||||
* @param count number of bytes to read from I2C and store in the buffer
|
||||
* @returns 0 on success, error code otherwise
|
||||
*/
|
||||
int8_t sensirion_i2c_hal_read(uint8_t address, uint8_t* data, uint16_t count);
|
||||
|
||||
/**
|
||||
* Execute one write transaction on the I2C bus, sending a given number of
|
||||
* bytes. The bytes in the supplied buffer must be sent to the given address. If
|
||||
* the slave device does not acknowledge any of the bytes, an error shall be
|
||||
* returned.
|
||||
*
|
||||
* @param address 7-bit I2C address to write to
|
||||
* @param data pointer to the buffer containing the data to write
|
||||
* @param count number of bytes to read from the buffer and send over I2C
|
||||
* @returns 0 on success, error code otherwise
|
||||
*/
|
||||
int8_t sensirion_i2c_hal_write(uint8_t address, const uint8_t* data,
|
||||
uint16_t count);
|
||||
|
||||
/**
|
||||
* Sleep for a given number of microseconds. The function should delay the
|
||||
* execution approximately, but no less than, the given time.
|
||||
*
|
||||
* When using hardware i2c:
|
||||
* Despite the unit, a <10 millisecond precision is sufficient.
|
||||
*
|
||||
* When using software i2c:
|
||||
* The precision needed depends on the desired i2c frequency, i.e. should be
|
||||
* exact to about half a clock cycle (defined in
|
||||
* `SENSIRION_I2C_CLOCK_PERIOD_USEC` in `sensirion_sw_i2c_gpio.h`).
|
||||
*
|
||||
* Example with 400kHz requires a precision of 1 / (2 * 400kHz) == 1.25usec.
|
||||
*
|
||||
* @param useconds the sleep time in microseconds
|
||||
*/
|
||||
void sensirion_i2c_hal_sleep_usec(uint32_t useconds);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SENSIRION_I2C_HAL_H */
|
|
@ -0,0 +1 @@
|
|||
Subproject commit bcbb2190324d9d39ae38619dd4a8931a0b8cf049
|
|
@ -20,6 +20,7 @@ add_subdirectory(breakout_bme280)
|
|||
add_subdirectory(breakout_as7262)
|
||||
add_subdirectory(breakout_bh1745)
|
||||
add_subdirectory(breakout_icp10125)
|
||||
add_subdirectory(breakout_scd41)
|
||||
|
||||
add_subdirectory(pico_display)
|
||||
add_subdirectory(pico_display_2)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
set(OUTPUT_NAME scd41_demo)
|
||||
|
||||
add_executable(
|
||||
${OUTPUT_NAME}
|
||||
scd41_demo.cpp
|
||||
)
|
||||
|
||||
# enable usb output, disable uart output
|
||||
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
|
||||
pico_enable_stdio_uart(${OUTPUT_NAME} 1)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib scd4x)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Sensirion AG
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Sensirion AG nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h> // printf
|
||||
|
||||
#include "scd4x_i2c.h"
|
||||
#include "sensirion_common.h"
|
||||
#include "sensirion_i2c_hal.h"
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "common/pimoroni_i2c.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
I2C i2c(BOARD::BREAKOUT_GARDEN);
|
||||
|
||||
/**
|
||||
* TO USE CONSOLE OUTPUT (PRINTF) IF NOT PRESENT ON YOUR PLATFORM
|
||||
*/
|
||||
//#define printf(...)
|
||||
|
||||
int main(void) {
|
||||
stdio_init_all();
|
||||
int16_t error = 0;
|
||||
|
||||
sensirion_i2c_hal_init(&i2c);
|
||||
|
||||
// Clean up potential SCD40 states
|
||||
scd4x_wake_up();
|
||||
scd4x_stop_periodic_measurement();
|
||||
scd4x_reinit();
|
||||
|
||||
uint16_t serial_0;
|
||||
uint16_t serial_1;
|
||||
uint16_t serial_2;
|
||||
error = scd4x_get_serial_number(&serial_0, &serial_1, &serial_2);
|
||||
if (error) {
|
||||
printf("Error executing scd4x_get_serial_number(): %i\n", error);
|
||||
} else {
|
||||
printf("serial: 0x%04x%04x%04x\n", serial_0, serial_1, serial_2);
|
||||
}
|
||||
|
||||
// Start Measurement
|
||||
|
||||
error = scd4x_start_periodic_measurement();
|
||||
if (error) {
|
||||
printf("Error executing scd4x_start_periodic_measurement(): %i\n",
|
||||
error);
|
||||
}
|
||||
|
||||
printf("Waiting for first measurement... (5 sec)\n");
|
||||
|
||||
for (;;) {
|
||||
// Read Measurement
|
||||
sensirion_i2c_hal_sleep_usec(5000000);
|
||||
|
||||
uint16_t co2;
|
||||
int32_t temperature;
|
||||
int32_t humidity;
|
||||
error = scd4x_read_measurement(&co2, &temperature, &humidity);
|
||||
if (error) {
|
||||
printf("Error executing scd4x_read_measurement(): %i\n", error);
|
||||
} else if (co2 == 0) {
|
||||
printf("Invalid sample detected, skipping.\n");
|
||||
} else {
|
||||
printf("CO2: %u\n", co2);
|
||||
printf("Temperature: %ld m°C\n", temperature);
|
||||
printf("Humidity: %ld mRH\n", humidity);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Ładowanie…
Reference in New Issue