add test
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
#include "scd30.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -26,14 +25,29 @@ static uint8_t calculate_crc8(const uint8_t *data, size_t len) {
|
||||
return crc;
|
||||
}
|
||||
|
||||
void scd30_init(void) {
|
||||
i2c_master_config_t i2c_config = {
|
||||
scd30_handle_t *scd30_init(int sda_gpio, int scl_gpio) {
|
||||
static scd30_handle_t handle;
|
||||
i2c_master_bus_config_t bus_config = {
|
||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||
.i2c_port = I2C_NUM_0,
|
||||
.scl_io_num = scl_gpio,
|
||||
.sda_io_num = sda_gpio,
|
||||
.glitch_ignore_cnt = 7,
|
||||
.flags.enable_internal_pullup = true
|
||||
};
|
||||
ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &handle.bus_handle));
|
||||
|
||||
i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = SCD30_I2C_ADDRESS,
|
||||
.scl_speed_hz = 100000,
|
||||
.scl_wait_us = 150000 // Clock stretching
|
||||
};
|
||||
i2c_master_init(I2C_NUM_0, &i2c_config);
|
||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(handle.bus_handle, &dev_cfg, &handle.dev_handle));
|
||||
return &handle;
|
||||
}
|
||||
|
||||
void scd30_start_measurement(void) {
|
||||
void scd30_start_measurement(scd30_handle_t *handle) {
|
||||
uint8_t command[5] = {
|
||||
(SCD30_CMD_START_MEASUREMENT >> 8) & 0xFF,
|
||||
SCD30_CMD_START_MEASUREMENT & 0xFF,
|
||||
@@ -41,11 +55,18 @@ void scd30_start_measurement(void) {
|
||||
0x00 // Placeholder for CRC
|
||||
};
|
||||
command[4] = calculate_crc8(&command[2], 2);
|
||||
|
||||
i2c_master_write_to_device(I2C_NUM_0, SCD30_I2C_ADDRESS, command, sizeof(command), 1000 / portTICK_PERIOD_MS);
|
||||
i2c_master_transmit(handle->dev_handle, command, sizeof(command), 1000);
|
||||
}
|
||||
|
||||
int scd30_read_data(scd30_data_t *data) {
|
||||
// Helper to convert Big Endian IEEE754 bytes to float
|
||||
static float bytes_to_float(uint8_t mmsb, uint8_t mlsb, uint8_t lmsb, uint8_t llsb) {
|
||||
uint32_t val = ((uint32_t)mmsb << 24) | ((uint32_t)mlsb << 16) | ((uint32_t)lmsb << 8) | (uint32_t)llsb;
|
||||
float f;
|
||||
memcpy(&f, &val, 4);
|
||||
return f;
|
||||
}
|
||||
|
||||
int scd30_read_data(scd30_handle_t *handle, scd30_data_t *data) {
|
||||
uint8_t ready_command[2] = {
|
||||
(SCD30_CMD_READY_STATUS >> 8) & 0xFF,
|
||||
SCD30_CMD_READY_STATUS & 0xFF
|
||||
@@ -54,7 +75,7 @@ int scd30_read_data(scd30_data_t *data) {
|
||||
|
||||
// Poll until data is ready
|
||||
do {
|
||||
i2c_master_write_read_device(I2C_NUM_0, SCD30_I2C_ADDRESS, ready_command, sizeof(ready_command), ready_status, sizeof(ready_status), 1000 / portTICK_PERIOD_MS);
|
||||
i2c_master_transmit_receive(handle->dev_handle, ready_command, sizeof(ready_command), ready_status, sizeof(ready_status), 1000);
|
||||
} while (ready_status[1] != 0x01);
|
||||
|
||||
uint8_t read_command[2] = {
|
||||
@@ -64,7 +85,8 @@ int scd30_read_data(scd30_data_t *data) {
|
||||
uint8_t buffer[18];
|
||||
|
||||
// Read 18 bytes of data
|
||||
i2c_master_write_read_device(I2C_NUM_0, SCD30_I2C_ADDRESS, read_command, sizeof(read_command), buffer, sizeof(buffer), 1000 / portTICK_PERIOD_MS);
|
||||
// Format: CO2_MSB, CO2_LSB, CRC, CO2_LMSB, CO2_LLSB, CRC, ...
|
||||
i2c_master_transmit_receive(handle->dev_handle, read_command, sizeof(read_command), buffer, sizeof(buffer), 1000);
|
||||
|
||||
// Validate CRC for each pair of data
|
||||
for (int i = 0; i < 18; i += 3) {
|
||||
@@ -73,10 +95,13 @@ int scd30_read_data(scd30_data_t *data) {
|
||||
}
|
||||
}
|
||||
|
||||
// Parse data
|
||||
data->co2 = (float)((buffer[0] << 8) | buffer[1]);
|
||||
data->temp = (float)((buffer[3] << 8) | buffer[4]);
|
||||
data->humidity = (float)((buffer[6] << 8) | buffer[7]);
|
||||
// Parse IEEE754 floats (Big Endian)
|
||||
// Structure: [Byte1, Byte2, CRC, Byte3, Byte4, CRC]
|
||||
// 0 1 2 3 4 5
|
||||
|
||||
data->co2 = bytes_to_float(buffer[0], buffer[1], buffer[3], buffer[4]);
|
||||
data->temp = bytes_to_float(buffer[6], buffer[7], buffer[9], buffer[10]);
|
||||
data->humidity = bytes_to_float(buffer[12], buffer[13], buffer[15], buffer[16]);
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define SCD30_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "driver/i2c_master.h"
|
||||
|
||||
// Data structure to hold SCD30 sensor data
|
||||
typedef struct {
|
||||
@@ -10,9 +11,34 @@ typedef struct {
|
||||
float humidity; // Relative humidity in percentage
|
||||
} scd30_data_t;
|
||||
|
||||
// Function prototypes
|
||||
void scd30_init(void);
|
||||
void scd30_start_measurement(void);
|
||||
int scd30_read_data(scd30_data_t *data);
|
||||
typedef struct {
|
||||
i2c_master_bus_handle_t bus_handle;
|
||||
i2c_master_dev_handle_t dev_handle;
|
||||
} scd30_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the SCD30 sensor
|
||||
*
|
||||
* @param sda_gpio SDA GPIO number
|
||||
* @param scl_gpio SCL GPIO number
|
||||
* @return scd30_handle_t* Pointer to the sensor handle
|
||||
*/
|
||||
scd30_handle_t *scd30_init(int sda_gpio, int scl_gpio);
|
||||
|
||||
/**
|
||||
* @brief Start continuous measurement
|
||||
*
|
||||
* @param handle Sensor handle
|
||||
*/
|
||||
void scd30_start_measurement(scd30_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief Read data from the SCD30 sensor
|
||||
*
|
||||
* @param handle Sensor handle
|
||||
* @param data Pointer to store the read data
|
||||
* @return int 0 on success, -1 on error
|
||||
*/
|
||||
int scd30_read_data(scd30_handle_t *handle, scd30_data_t *data);
|
||||
|
||||
#endif // SCD30_H
|
||||
@@ -1,2 +1,2 @@
|
||||
idf_component_register(SRCS "blink_example_main.c"
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/* Blink Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "led_strip.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
/* Use project configuration menu (idf.py menuconfig) to choose the GPIO to blink,
|
||||
or you can edit the following line and set a number here.
|
||||
*/
|
||||
#define BLINK_GPIO CONFIG_BLINK_GPIO
|
||||
|
||||
static uint8_t s_led_state = 0;
|
||||
|
||||
#ifdef CONFIG_BLINK_LED_STRIP
|
||||
|
||||
static led_strip_handle_t led_strip;
|
||||
|
||||
static void blink_led(void)
|
||||
{
|
||||
/* If the addressable LED is enabled */
|
||||
if (s_led_state) {
|
||||
/* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
|
||||
led_strip_set_pixel(led_strip, 0, 16, 16, 16);
|
||||
/* Refresh the strip to send data */
|
||||
led_strip_refresh(led_strip);
|
||||
} else {
|
||||
/* Set all LED off to clear all pixels */
|
||||
led_strip_clear(led_strip);
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_led(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Example configured to blink addressable LED!");
|
||||
/* LED strip initialization with the GPIO and pixels number*/
|
||||
led_strip_config_t strip_config = {
|
||||
.strip_gpio_num = BLINK_GPIO,
|
||||
.max_leds = 1, // at least one LED on board
|
||||
};
|
||||
#if CONFIG_BLINK_LED_STRIP_BACKEND_RMT
|
||||
led_strip_rmt_config_t rmt_config = {
|
||||
.resolution_hz = 10 * 1000 * 1000, // 10MHz
|
||||
.flags.with_dma = false,
|
||||
};
|
||||
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip));
|
||||
#elif CONFIG_BLINK_LED_STRIP_BACKEND_SPI
|
||||
led_strip_spi_config_t spi_config = {
|
||||
.spi_bus = SPI2_HOST,
|
||||
.flags.with_dma = true,
|
||||
};
|
||||
ESP_ERROR_CHECK(led_strip_new_spi_device(&strip_config, &spi_config, &led_strip));
|
||||
#else
|
||||
#error "unsupported LED strip backend"
|
||||
#endif
|
||||
/* Set all LED off to clear all pixels */
|
||||
led_strip_clear(led_strip);
|
||||
}
|
||||
|
||||
#elif CONFIG_BLINK_LED_GPIO
|
||||
|
||||
static void blink_led(void)
|
||||
{
|
||||
/* Set the GPIO level according to the state (LOW or HIGH)*/
|
||||
gpio_set_level(BLINK_GPIO, s_led_state);
|
||||
}
|
||||
|
||||
static void configure_led(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
|
||||
gpio_reset_pin(BLINK_GPIO);
|
||||
/* Set the GPIO as a push/pull output */
|
||||
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "unsupported LED type"
|
||||
#endif
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
|
||||
/* Configure the peripheral according to the LED type */
|
||||
configure_led();
|
||||
|
||||
while (1) {
|
||||
ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF");
|
||||
blink_led();
|
||||
/* Toggle the LED state */
|
||||
s_led_state = !s_led_state;
|
||||
vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
@@ -5,21 +5,16 @@
|
||||
|
||||
void app_main(void) {
|
||||
scd30_data_t sensor_data;
|
||||
|
||||
// Initialize the SCD30 sensor
|
||||
scd30_init();
|
||||
scd30_start_measurement();
|
||||
|
||||
// Example: SDA = 21, SCL = 22 (change as needed)
|
||||
scd30_handle_t *scd30 = scd30_init(21, 22);
|
||||
scd30_start_measurement(scd30);
|
||||
while (1) {
|
||||
// Read data from the sensor
|
||||
if (scd30_read_data(&sensor_data) == 0) {
|
||||
if (scd30_read_data(scd30, &sensor_data) == 0) {
|
||||
printf("CO2: %.2f ppm, Temp: %.2f °C, Humidity: %.2f %%\n",
|
||||
sensor_data.co2, sensor_data.temp, sensor_data.humidity);
|
||||
} else {
|
||||
printf("Failed to read data from SCD30 sensor\n");
|
||||
}
|
||||
|
||||
// Wait for 2 seconds
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import logging
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from pytest_embedded_idf.dut import IdfDut
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.generic
|
||||
def test_blink(dut: IdfDut) -> None:
|
||||
# check and log bin size
|
||||
binary_file = os.path.join(dut.app.binary_path, 'blink.bin')
|
||||
bin_size = os.path.getsize(binary_file)
|
||||
logging.info('blink_bin_size : {}KB'.format(bin_size // 1024))
|
||||
Reference in New Issue
Block a user