diff --git a/sample-implementations/RaspberryPi_Pico/cMakeLists.txt b/sample-implementations/RaspberryPi_Pico/CMakeLists.txt
similarity index 68%
rename from sample-implementations/RaspberryPi_Pico/cMakeLists.txt
rename to sample-implementations/RaspberryPi_Pico/CMakeLists.txt
index 4a9c75a..f103ec6 100644
--- a/sample-implementations/RaspberryPi_Pico/cMakeLists.txt
+++ b/sample-implementations/RaspberryPi_Pico/CMakeLists.txt
@@ -6,20 +6,21 @@ pico_sdk_init()
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
+add_compile_options(-Wall -Wextra -Werror)
add_executable(main
main.c
- sensirion_i2c.c
- sensirion_i2c.hal.c
- scd4x_i2c.c
- sensirion_common.c)
+ ../../sensirion_i2c.c
+ sensirion_i2c_hal.c
+ ../../scd4x_i2c.c
+ ../../sensirion_common.c)
# pull in common dependencies and additional i2c hardware support
target_link_libraries(main pico_stdlib hardware_i2c)
+# use USB for stdin/stdout, rather than using UART
pico_enable_stdio_usb(main 1)
-
pico_enable_stdio_uart(main 0)
# create map/bin/hex file etc.
pico_add_extra_outputs(main)
-
+
diff --git a/sample-implementations/RaspberryPi_Pico/README.md b/sample-implementations/RaspberryPi_Pico/README.md
new file mode 100644
index 0000000..3cd2fbd
--- /dev/null
+++ b/sample-implementations/RaspberryPi_Pico/README.md
@@ -0,0 +1,39 @@
+SCD4x on the Raspberry Pi Pico
+==============================
+
+
+In this example, an SCD41 is connected to a Raspberry Pi Pico W on GPIO pins 12
+(I2C0 SDA) and 13 (I2C0 SCL). The same code will work for any variant of the
+Pico.
+
+The following shell session is from an Ubuntu machine that had the Pico plugged
+in to USB in boot select mode.
+
+```console
+$ ls
+CMakeLists.txt hardware.jpg main.c README.md sensirion_i2c_hal.c
+
+$ mkdir build
+
+$ cd build
+
+$ cmake -DPICO_SDK_PATH=$HOME/src/pico-sdk ..
+[...]
+
+$ make -j
+[...]
+
+$ ls
+CMakeCache.txt cmake_install.cmake generated main.dis main.elf.map main.uf2 pico-sdk
+CMakeFiles elf2uf2 main.bin main.elf main.hex Makefile pioasm
+
+$ cp main.uf2 /media/$USER/RPI-RP2
+
+$ screen /dev/ttyACM0
+The I2C baudrate is 399361 Hz
+Sensor serial number is: 0x8a7e 0xbb07 0x3ba0
+CO2: 1111 ppm, Temperature: 28.4 C (83.1 F), Humidity: 60.4%
+CO2: 1080 ppm, Temperature: 28.5 C (83.2 F), Humidity: 61.1%
+CO2: 1070 ppm, Temperature: 28.4 C (83.1 F), Humidity: 61.7%
+[...]
+```
diff --git a/sample-implementations/RaspberryPi_Pico/hardware.jpg b/sample-implementations/RaspberryPi_Pico/hardware.jpg
new file mode 100644
index 0000000..263effe
Binary files /dev/null and b/sample-implementations/RaspberryPi_Pico/hardware.jpg differ
diff --git a/sample-implementations/RaspberryPi_Pico/main.c b/sample-implementations/RaspberryPi_Pico/main.c
index 195febe..33a16af 100644
--- a/sample-implementations/RaspberryPi_Pico/main.c
+++ b/sample-implementations/RaspberryPi_Pico/main.c
@@ -1,77 +1,89 @@
+#include "../../scd4x_i2c.h"
+#include
+#include
+#include
-#include "hardware/i2c.h"
-#include "pico/binary_info.h"
-#include "pico/stdlib.h"
-#include "scd4x_i2c.h"
#include
-/// I2C address
-static int addr = 0x62;
-
-// I2C Pins
-static uint sda_pin = 16;
-static uint scl_pin = 17;
-
-// This is the main entry for your c application. U
-// is
-int main() {
-
+int main(void) {
stdio_init_all();
- // Setup I2c using pins 16 & 17
- i2c_init(i2c_default, 400 * 1000);
- gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
- gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
+ // Give us a few seconds to start viewing the output if we're plugged into
+ // the computer over USB.
+ sleep_ms(3000);
- // This variable will hold the return status of the function calls.
- // You can separate each function call result into their own variable or re
- // - use this.
+ // Setup I2C using GPIO pins 12 & 13.
+ const uint desired_clock_hz = 400 * 1000;
+ const uint actual_baudrate = i2c_init(i2c_default, desired_clock_hz);
+ printf("The I2C baudrate is %u Hz\n", actual_baudrate);
+ const uint sda_pin = 12;
+ const uint scl_pin = 13;
+ gpio_set_function(sda_pin, GPIO_FUNC_I2C);
+ gpio_set_function(scl_pin, GPIO_FUNC_I2C);
+ gpio_pull_up(sda_pin);
+ gpio_pull_up(scl_pin);
- int status = 0;
+ // Initialize driver with i2c address
+ scd4x_init(SCD41_I2C_ADDR_62);
- // Stop any readings if occuring
- status = scd4x_stop_periodic_measurement();
+ int status;
- // Perform self test
- uint16_t* selfTest = 0;
- scd4x_perform_self_test(selfTest);
-
- // Get Serial number 3 parts
- uint16_t one;
- uint16_t two;
- uint16_t three;
+ // Stop any ongoing measurement.
+ status = scd4x_stop_periodic_measurement();
+ if (status) {
+ printf("Unable to stop measurement. Error: %d\n", status);
+ return status;
+ }
- scd4x_get_serial_number(&one, &two, &three);
+ // Get serial number.
+ uint16_t serial_number[3] = {0};
+ status = scd4x_get_serial_number(serial_number, 3);
+ if (status) {
+ printf("Unable to get sensor serial number. Error: %d\n", status);
+ return status;
+ }
+ printf("Sensor serial number is: 0x%x 0x%x 0x%x\n", (int)serial_number[0],
+ (int)serial_number[1], (int)serial_number[2]);
// Start the readings.
- status1 = scd4x_start_periodic_measurement();
-
- while (1) {
+ status = scd4x_start_periodic_measurement();
+ if (status) {
+ printf("Unable to start periodic measurement. Error %d\n", status);
+ return status;
+ }
- // Check if data is ready to read
+ for (;;) {
+ // Wait for the measurement to complete.
+ sleep_ms(5000 - 10);
bool dataReady;
- while (dataReady == false) {
-
- status1 = scd4x_get_data_ready_flag(&dataReady);
+ do {
+ sleep_ms(10);
+ status = scd4x_get_data_ready_status(&dataReady);
+ if (status) {
+ printf("Unable to get sensor readiness status. Error %d.\n",
+ status);
+ return status;
+ }
+ } while (!dataReady);
+
+ // Read the measurement data and convert it to common units.
+ uint16_t co2Raw; // ppm
+ int32_t temperatureRaw; // millicelsius
+ int32_t humidityRaw; // millipercent
+ status = scd4x_read_measurement(&co2Raw, &temperatureRaw, &humidityRaw);
+ if (status) {
+ printf("Unable to read measurement data. Error: %d\n", status);
+ return status;
}
- // Get the ticks. The scd4x_read_measurement function is giving
- // incorrect data due to the arthimetic
- uint16_t co2;
- uint16_t temp;
- uint16_t humidity;
- status1 = scd4x_read_measurement_ticks(&co2, &temp, &humidity);
-
- // Arithemtic to change raw data into information
- int tempInCelsius = -45 + 175 * temp / 65536;
- int tempInFarenheit = tempInCelsius * 1.8 + 32;
- int humidityPercent = 100 * humidity / 65536;
-
- // Print results to terminal (output)
- printf("C:%d,T:%d,H:%d", co2, tempInFarenheit, humidityPercent);
+ const int co2Ppm = co2Raw;
+ const float temperatureCelsius = temperatureRaw / 1000.0f;
+ const float temperatureFahrenheit = temperatureCelsius * 1.8f + 32;
+ const float humidityPercent = humidityRaw / 1000.0f;
- // Sleep for 5 seconds.
- sleep_ms(5000);
+ printf("CO2: %d ppm, Temperature: %.1f C (%.1f F), Humidity: %.1f%%\n",
+ co2Ppm, temperatureCelsius, temperatureFahrenheit,
+ humidityPercent);
}
}
diff --git a/sample-implementations/RaspberryPi_Pico/sensirion_i2c_hal.c b/sample-implementations/RaspberryPi_Pico/sensirion_i2c_hal.c
index d7299ba..ae3510f 100644
--- a/sample-implementations/RaspberryPi_Pico/sensirion_i2c_hal.c
+++ b/sample-implementations/RaspberryPi_Pico/sensirion_i2c_hal.c
@@ -1,4 +1,3 @@
-#include
/*
* Copyright (c) 2018, Sensirion AG
* All rights reserved.
@@ -30,49 +29,12 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "sensirion_common.h"
-#include "sensirion_config.h"
-#include "sensirion_i2c_hal.h"
-
-/*
- * 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(void) {
- /* TODO:IMPLEMENT */
-}
+#include "../../sensirion_i2c_hal.h"
+#include "../../sensirion_common.h"
+#include "../../sensirion_config.h"
-/**
- * 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 */
-}
+#include
+#include
/**
* Execute one read transaction on the I2C bus, reading a given number of bytes.
@@ -84,12 +46,10 @@ void sensirion_i2c_hal_free(void) {
* @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 status = i2c_read_blocking(i2c_default, address, data, count, false);
- if (status == 0)
- return 1;
- else
- return 0;
+int8_t sensirion_i2c_hal_read(uint8_t address, uint8_t* data, uint8_t count) {
+ const bool nostop =
+ true; // master retains control of the bus after the read
+ return !i2c_read_blocking(i2c_default, address, data, count, nostop);
}
/**
@@ -104,14 +64,10 @@ int8_t sensirion_i2c_hal_read(uint8_t address, uint8_t* data, uint16_t count) {
* @returns 0 on success, error code otherwise
*/
int8_t sensirion_i2c_hal_write(uint8_t address, const uint8_t* data,
- uint16_t count) {
- // I2C Default is used (I2C0).
- int status = i2c_write_blocking(i2c_default, address, data, count, true);
-
- if (status == 0)
- return 1;
- else
- return 0;
+ uint8_t count) {
+ const bool nostop =
+ true; // master retains control of the bus after the write
+ return !i2c_write_blocking(i2c_default, address, data, count, nostop);
}
/**
@@ -120,8 +76,8 @@ int8_t sensirion_i2c_hal_write(uint8_t address, const uint8_t* data,
*
* Despite the unit, a <10 millisecond precision is sufficient.
*
- * @param useconds the sleep time in microseconds
+ * @param microseconds the sleep time in microseconds
*/
-void sensirion_i2c_hal_sleep_usec(uint32_t useconds) {
- sleep_ms(useconds / 1000);
+void sensirion_i2c_hal_sleep_usec(uint32_t microseconds) {
+ sleep_us(microseconds);
}