From 16b277ff998a7e5a12802bcf371b28c7941f9f38 Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 5 Sep 2025 17:44:33 +0200 Subject: [PATCH] ajout capteur luminosite --- components/espressif__bh1750/CMakeLists.txt | 5 + components/espressif__bh1750/README.md | 8 + components/espressif__bh1750/bh1750.c | 135 ++++++++++++ .../espressif__bh1750/idf_component.yml | 5 + components/espressif__bh1750/include/bh1750.h | 127 +++++++++++ components/espressif__bh1750/license.txt | 202 ++++++++++++++++++ .../espressif__bh1750/test/CMakeLists.txt | 3 + .../espressif__bh1750/test/bh1750_test.c | 85 ++++++++ main/communication.c | 4 + main/idf_component.yml | 3 +- main/include/communication.h | 2 +- main/main.c | 121 ++++++++++- 12 files changed, 691 insertions(+), 9 deletions(-) create mode 100644 components/espressif__bh1750/CMakeLists.txt create mode 100644 components/espressif__bh1750/README.md create mode 100644 components/espressif__bh1750/bh1750.c create mode 100644 components/espressif__bh1750/idf_component.yml create mode 100644 components/espressif__bh1750/include/bh1750.h create mode 100644 components/espressif__bh1750/license.txt create mode 100644 components/espressif__bh1750/test/CMakeLists.txt create mode 100644 components/espressif__bh1750/test/bh1750_test.c diff --git a/components/espressif__bh1750/CMakeLists.txt b/components/espressif__bh1750/CMakeLists.txt new file mode 100644 index 0000000..7a33264 --- /dev/null +++ b/components/espressif__bh1750/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + SRCS "bh1750.c" + INCLUDE_DIRS "include" + REQUIRES "driver" +) diff --git a/components/espressif__bh1750/README.md b/components/espressif__bh1750/README.md new file mode 100644 index 0000000..0352cb4 --- /dev/null +++ b/components/espressif__bh1750/README.md @@ -0,0 +1,8 @@ +# Component: BH1750 + +* This component will show you how to use I2C module read external i2c sensor data, here we use BH1750 light sensor(GY-30 module). +* BH1750 measurement mode: + * one-time mode: bh1750 just measure only one time when receieved the one time measurement command, so you need to send this command when you want to get intensity value every time + * continuous mode: bh1750 will measure continuously when receieved the continuously measurement command, so you just need to send this command once, and than call `bh1750_get_data()` to get intensity value repeatedly. +## Notice: +* Bh1750 has different measurement time in different measurement mode, and also, measurement time can be changed by call `bh1750_change_measure_time()` diff --git a/components/espressif__bh1750/bh1750.c b/components/espressif__bh1750/bh1750.c new file mode 100644 index 0000000..7364301 --- /dev/null +++ b/components/espressif__bh1750/bh1750.c @@ -0,0 +1,135 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "driver/i2c_master.h" +#include "bh1750.h" +#include "esp_log.h" + + +#define BH_1750_MEASUREMENT_ACCURACY 1.2 /*!< the typical measurement accuracy of BH1750 sensor */ + +#define BH1750_POWER_DOWN 0x00 /*!< Command to set Power Down*/ +#define BH1750_POWER_ON 0x01 /*!< Command to set Power On*/ + +typedef struct { + i2c_port_t bus; + uint16_t dev_addr; + i2c_master_dev_handle_t dev_handle; +} bh1750_dev_t; + +static esp_err_t bh1750_write_byte(const bh1750_dev_t *const sens, const uint8_t byte) +{ + esp_err_t ret; + ESP_ERROR_CHECK(i2c_master_transmit(sens->dev_handle, &byte, 1, -1)); + + /*i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + ret = i2c_master_start(cmd); + assert(ESP_OK == ret); + ret = i2c_master_write_byte(cmd, sens->dev_addr | I2C_MASTER_WRITE, true); + assert(ESP_OK == ret); + ret = i2c_master_write_byte(cmd, byte, true); + assert(ESP_OK == ret); + ret = i2c_master_stop(cmd); + assert(ESP_OK == ret); + ret = i2c_master_cmd_begin(sens->bus, cmd, 1000 / portTICK_PERIOD_MS); + i2c_cmd_link_delete(cmd); + return ret; + */ + return 0; +} + +bh1750_handle_t bh1750_create(i2c_port_t port, const uint16_t dev_addr, i2c_master_bus_handle_t bus_handle) +{ + bh1750_dev_t *sensor = (bh1750_dev_t *) calloc(1, sizeof(bh1750_dev_t)); + sensor->bus = port; + sensor->dev_addr = dev_addr << 1; + + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = dev_addr, + .scl_speed_hz = 100000, + }; + i2c_master_dev_handle_t dev_handle; + ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &(sensor->dev_handle))); + return (bh1750_handle_t) sensor; + +} + +esp_err_t bh1750_delete(bh1750_handle_t sensor) +{ + bh1750_dev_t *sens = (bh1750_dev_t *) sensor; + free(sens); + return ESP_OK; +} + +esp_err_t bh1750_power_down(bh1750_handle_t sensor) +{ + bh1750_dev_t *sens = (bh1750_dev_t *) sensor; + return bh1750_write_byte(sens, BH1750_POWER_DOWN); +} + +esp_err_t bh1750_power_on(bh1750_handle_t sensor) +{ + bh1750_dev_t *sens = (bh1750_dev_t *) sensor; + return bh1750_write_byte(sens, BH1750_POWER_ON); +} + +esp_err_t bh1750_set_measure_time(bh1750_handle_t sensor, const uint8_t measure_time) +{ + bh1750_dev_t *sens = (bh1750_dev_t *) sensor; + uint32_t i = 0; + uint8_t buf[2] = {0x40, 0x60}; // constant part of the the MTreg + buf[0] |= measure_time >> 5; + buf[1] |= measure_time & 0x1F; + for (i = 0; i < 2; i++) { + esp_err_t ret = bh1750_write_byte(sens, buf[i]); + if (ESP_OK != ret) { + return ret; + } + } + return ESP_OK; +} + +esp_err_t bh1750_set_measure_mode(bh1750_handle_t sensor, const bh1750_measure_mode_t cmd_measure) +{ + bh1750_dev_t *sens = (bh1750_dev_t *) sensor; + return bh1750_write_byte(sens, (uint8_t)cmd_measure); +} + +esp_err_t bh1750_get_data(bh1750_handle_t sensor, float *const data) +{ + esp_err_t ret; + uint8_t bh1750_data_h, bh1750_data_l; + bh1750_dev_t *sens = (bh1750_dev_t *) sensor; + uint8_t datas[2] = {0}; + esp_err_t err = i2c_master_receive(sens->dev_handle, datas, 2, -1); + if (err != ESP_OK) { + ESP_LOGE("bh1750", "Erreur lecture BH1750 : %s", esp_err_to_name(err)); + return 0; + } + *data = ((datas[0] << 8) | datas[1])/ BH_1750_MEASUREMENT_ACCURACY; // En lux (si mode H-resolution) + /* + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + ret = i2c_master_start(cmd); + assert(ESP_OK == ret); + ret = i2c_master_write_byte(cmd, sens->dev_addr | I2C_MASTER_READ, true); + assert(ESP_OK == ret); + ret = i2c_master_read_byte(cmd, &bh1750_data_h, I2C_MASTER_ACK); + assert(ESP_OK == ret); + ret = i2c_master_read_byte(cmd, &bh1750_data_l, I2C_MASTER_NACK); + assert(ESP_OK == ret); + ret = i2c_master_stop(cmd); + assert(ESP_OK == ret); + ret = i2c_master_cmd_begin(sens->bus, cmd, 1000 / portTICK_PERIOD_MS); + i2c_cmd_link_delete(cmd); + if (ESP_OK != ret) { + return ret; + } + *data = (( bh1750_data_h << 8 | bh1750_data_l ) / BH_1750_MEASUREMENT_ACCURACY); + */ + return ESP_OK; +} diff --git a/components/espressif__bh1750/idf_component.yml b/components/espressif__bh1750/idf_component.yml new file mode 100644 index 0000000..30975cb --- /dev/null +++ b/components/espressif__bh1750/idf_component.yml @@ -0,0 +1,5 @@ +dependencies: + idf: '>=4.0' +description: I2C driver for BH1750 light sensor +url: https://github.com/espressif/esp-bsp/tree/master/components/bh1750 +version: 1.0.3 diff --git a/components/espressif__bh1750/include/bh1750.h b/components/espressif__bh1750/include/bh1750.h new file mode 100644 index 0000000..2cbda8d --- /dev/null +++ b/components/espressif__bh1750/include/bh1750.h @@ -0,0 +1,127 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "driver/i2c_master.h" + +typedef enum { + BH1750_CONTINUE_1LX_RES = 0x10, /*!< Command to set measure mode as Continuously H-Resolution mode*/ + BH1750_CONTINUE_HALFLX_RES = 0x11, /*!< Command to set measure mode as Continuously H-Resolution mode2*/ + BH1750_CONTINUE_4LX_RES = 0x13, /*!< Command to set measure mode as Continuously L-Resolution mode*/ + BH1750_ONETIME_1LX_RES = 0x20, /*!< Command to set measure mode as One Time H-Resolution mode*/ + BH1750_ONETIME_HALFLX_RES = 0x21, /*!< Command to set measure mode as One Time H-Resolution mode2*/ + BH1750_ONETIME_4LX_RES = 0x23, /*!< Command to set measure mode as One Time L-Resolution mode*/ +} bh1750_measure_mode_t; + +#define BH1750_I2C_ADDRESS_DEFAULT (0x23) +typedef void *bh1750_handle_t; + +/** + * @brief Set bh1750 as power down mode (low current) + * + * @param sensor object handle of bh1750 + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t bh1750_power_down(bh1750_handle_t sensor); + +/** + * @brief Set bh1750 as power on mode + * + * @param sensor object handle of bh1750 + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t bh1750_power_on(bh1750_handle_t sensor); + +/** + * @brief Get light intensity from bh1750 + * + * @param sensor object handle of bh1750 + * @param[in] cmd_measure the instruction to set measurement mode + * + * @note + * You should call this funtion to set measurement mode before call bh1750_get_data() to acquire data. + * If you set onetime mode, you just can get one measurement result. + * If you set continuous mode, you can call bh1750_get_data() to acquire data repeatedly. + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t bh1750_set_measure_mode(bh1750_handle_t sensor, const bh1750_measure_mode_t cmd_measure); + +/** + * @brief Get light intensity from BH1750 + * + * Returns light intensity in [lx] corrected by typical BH1750 Measurement Accuracy (= 1.2). + * + * @see BH1750 datasheet Rev. D page 2 + * + * @note + * You should acquire data from the sensor after the measurement time is over, + * so take care of measurement time in different modes. + * + * @param sensor object handle of bh1750 + * @param[out] data light intensity value got from bh1750 in [lx] + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t bh1750_get_data(bh1750_handle_t sensor, float *const data); + +/** + * @brief Set measurement time + * + * This function is used to adjust BH1750 sensitivity, i.e. compensating influence from optical window. + * + * @see BH1750 datasheet Rev. D page 11 + * + * @param sensor object handle of bh1750 + * @param[in] measure_time measurement time + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t bh1750_set_measure_time(bh1750_handle_t sensor, const uint8_t measure_time); + +/** + * @brief Create and init sensor object and return a sensor handle + * + * @param port I2C port number + * @param[in] dev_addr I2C device address of sensor + * + * @return + * - NULL Fail + * - Others Success + */ +bh1750_handle_t bh1750_create(i2c_port_t port, const uint16_t dev_addr, i2c_master_bus_handle_t bus_handle); + +/** + * @brief Delete and release a sensor object + * + * @param sensor object handle of bh1750 + * + * @return + * - ESP_OK Success + * - ESP_FAIL Fail + */ +esp_err_t bh1750_delete(bh1750_handle_t sensor); + +#ifdef __cplusplus +} +#endif diff --git a/components/espressif__bh1750/license.txt b/components/espressif__bh1750/license.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/components/espressif__bh1750/license.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/components/espressif__bh1750/test/CMakeLists.txt b/components/espressif__bh1750/test/CMakeLists.txt new file mode 100644 index 0000000..a1caed2 --- /dev/null +++ b/components/espressif__bh1750/test/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "bh1750_test.c" + INCLUDE_DIRS "." + REQUIRES "bh1750" "unity") diff --git a/components/espressif__bh1750/test/bh1750_test.c b/components/espressif__bh1750/test/bh1750_test.c new file mode 100644 index 0000000..59dd812 --- /dev/null +++ b/components/espressif__bh1750/test/bh1750_test.c @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "unity.h" +#include "driver/i2c.h" +#include "bh1750.h" +#include "esp_log.h" + +#define I2C_MASTER_SCL_IO 26 /*!< gpio number for I2C master clock */ +#define I2C_MASTER_SDA_IO 25 /*!< gpio number for I2C master data */ +#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */ +#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */ + +static const char *TAG = "bh1750 test"; +static bh1750_handle_t bh1750 = NULL; + +/** + * @brief i2c master initialization + */ +static void i2c_bus_init(void) +{ + i2c_config_t conf; + conf.mode = I2C_MODE_MASTER; + conf.sda_io_num = (gpio_num_t)I2C_MASTER_SDA_IO; + conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf.scl_io_num = (gpio_num_t)I2C_MASTER_SCL_IO; + conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf.master.clk_speed = I2C_MASTER_FREQ_HZ; + conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL; + + esp_err_t ret = i2c_param_config(I2C_MASTER_NUM, &conf); + TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, ret, "I2C config returned error"); + + ret = i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0); + TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, ret, "I2C install returned error"); +} + +void bh1750_init(void) +{ + i2c_bus_init(); + bh1750 = bh1750_create(I2C_MASTER_NUM, BH1750_I2C_ADDRESS_DEFAULT); + TEST_ASSERT_NOT_NULL_MESSAGE(bh1750, "BH1750 create returned NULL"); +} + +TEST_CASE("Sensor BH1750 test", "[bh1750][iot][sensor]") +{ + esp_err_t ret; + bh1750_measure_mode_t cmd_measure; + float bh1750_data; + + bh1750_init(); + + ret = bh1750_power_on(bh1750); + TEST_ASSERT_EQUAL(ESP_OK, ret); + + // one-shot mode + cmd_measure = BH1750_ONETIME_4LX_RES; + ret = bh1750_set_measure_mode(bh1750, cmd_measure); + TEST_ASSERT_EQUAL(ESP_OK, ret); + vTaskDelay(30 / portTICK_PERIOD_MS); + + ret = bh1750_get_data(bh1750, &bh1750_data); + TEST_ASSERT_EQUAL(ESP_OK, ret); + ESP_LOGI(TAG, "bh1750 val(one time mode): %f\n", bh1750_data); + + // continous mode + cmd_measure = BH1750_CONTINUE_4LX_RES; + ret = bh1750_set_measure_mode(bh1750, cmd_measure); + TEST_ASSERT_EQUAL(ESP_OK, ret); + vTaskDelay(30 / portTICK_PERIOD_MS); + + ret = bh1750_get_data(bh1750, &bh1750_data); + TEST_ASSERT_EQUAL(ESP_OK, ret); + ESP_LOGI(TAG, "bh1750 val(continuously mode): %f\n", bh1750_data); + + // clean-up + ret = bh1750_delete(bh1750); + TEST_ASSERT_EQUAL(ESP_OK, ret); + ret = i2c_driver_delete(I2C_MASTER_NUM); + TEST_ASSERT_EQUAL(ESP_OK, ret); +} diff --git a/main/communication.c b/main/communication.c index d578886..c7c077a 100644 --- a/main/communication.c +++ b/main/communication.c @@ -44,6 +44,10 @@ void splitIt(char *payload, unsigned int length, float *datas) mqtt_callback mqttcb; +void mqtt_publish(const char *topic, const char *datas){ + esp_mqtt_client_publish(client, topic, datas, 0, 1, 0); +} + /* * @brief Event handler registered to receive MQTT events * diff --git a/main/idf_component.yml b/main/idf_component.yml index 482d45a..80f1758 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -1,8 +1,9 @@ dependencies: + espressif/bh1750: "^1.0.3" espressif/esp_wifi_remote: rules: - if: target in ["esp32p4"] - version: "0.9.2" + version: "0.14.4" suda-morris/am2302_rmt: version: "^1.0.0" diff --git a/main/include/communication.h b/main/include/communication.h index 88f8ce5..29fc02f 100644 --- a/main/include/communication.h +++ b/main/include/communication.h @@ -16,7 +16,7 @@ typedef void (*wifi_callback)(wifi_evt evt); typedef void (*mqtt_callback)(mqtt_evt evt, esp_mqtt_event_handle_t evt_data); void wifi_init_sta(wifi_callback cb); void mqtt_app_start(mqtt_callback cb, EventGroupHandle_t evtGroup); - +void mqtt_publish(const char *topic, const char *datas); #define topicTempExt "house/temp/282A802600008059" #define topicHauteurCuve "house/cuve/hauteur" diff --git a/main/main.c b/main/main.c index 66d20f0..6c82fff 100644 --- a/main/main.c +++ b/main/main.c @@ -5,13 +5,15 @@ #include "esp_err.h" #include "esp_log.h" #include "esp_check.h" -#include "driver/i2c.h" #include "esp_event.h" #include "nvs_flash.h" #include #include "esp_vfs_fat.h" #include "sdmmc_cmd.h" #include +#include "bh1750.h" +#include + #include "esp_http_server.h" @@ -52,6 +54,12 @@ #define PIN_NUM_CLK 12 #define PIN_NUM_CS 10 +#define I2C_MASTER_SCL_IO 32 /*!< gpio number for I2C master clock */ +#define I2C_MASTER_SDA_IO 36 /*!< gpio number for I2C master data */ +#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */ +#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */ + +static bh1750_handle_t bh1750 = NULL; static const char *TAG = "domoTic"; @@ -74,6 +82,29 @@ extern lv_subject_t tempExtSubj; extern lv_subject_t hauteurCuveSubj; extern lv_subject_t hauteurCuveEvolSubj; +/** + * @brief i2c master initialization + */ +static void i2c_bus_init(i2c_master_bus_handle_t *bus_handle) +{ + i2c_master_bus_config_t conf; + conf.sda_io_num = (gpio_num_t)I2C_MASTER_SDA_IO; + conf.flags.enable_internal_pullup=true; + conf.scl_io_num = (gpio_num_t)I2C_MASTER_SCL_IO; + conf.i2c_port=I2C_NUM_0; + conf.clk_source = I2C_CLK_SRC_DEFAULT; + conf.glitch_ignore_cnt = 7; + ESP_ERROR_CHECK(i2c_new_master_bus(&conf, bus_handle)); +} + +void bh1750_init(void) +{ + i2c_master_bus_handle_t bus_handle; + i2c_bus_init(&bus_handle); + bh1750 = bh1750_create(I2C_MASTER_NUM, BH1750_I2C_ADDRESS_DEFAULT, bus_handle); +} + + void mqtt_cb(mqtt_evt evt, esp_mqtt_event_handle_t event){ switch (evt) { @@ -375,7 +406,8 @@ void simple_ota_example_task(void *pvParameter) #endif esp_https_ota_config_t ota_config = { .http_config = &config, - .buffer_caps = MALLOC_CAP_INTERNAL + .buffer_caps = MALLOC_CAP_INTERNAL, + .bulk_flash_erase =true }; ESP_LOGI(TAG, "Attempting to download update from %s", config.url); esp_https_ota_handle_t https_ota_handle = NULL; @@ -488,6 +520,9 @@ static void IRAM_ATTR gpio_isr_handler(void* arg) xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); } + +float maxBrightness = 100; + static void gpio_task_example(void* arg) { uint32_t io_num; @@ -496,7 +531,7 @@ static void gpio_task_example(void* arg) if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { ESP_LOGE(TAG,"Got it !"); if(ecranEteint){ - for (int i = 0; i < 100; i+=2) + for (int i = 0; i < maxBrightness; i+=2) { if(bsp_display_lock(0)){ bsp_display_brightness_set(i); @@ -539,7 +574,7 @@ void initPirSensor(){ static void presence_timer_callback(void* arg) { int64_t time_since_boot = esp_timer_get_time(); - for (int i = 100; i >= 0; i-=2) + for (int i = maxBrightness; i >= 0; i-=2) { if(bsp_display_lock(0)){ bsp_display_brightness_set(i); @@ -768,11 +803,83 @@ static void mqttStatus_obs_cb(lv_observer_t * observer, lv_subject_t * subject) } +typedef struct { + float Lmin; // lux min (ex. 1) + float Lmax; // lux max (ex. 10000) + float gamma; // 0.6 typique + float pwm_min; // 0.05 => 5% + float pwm_max; // 1.0 => 100% + float tau_rise; // s, ex. 1.5 + float tau_fall; // s, ex. 4.0 + float deadband; // 0.01 => 1% + float y; // état filtré [0..1] + bool init; +} auto_bright_t; + +static float clampf(float v, float a, float b){ return v < a ? a : (v > b ? b : v); } + +float auto_brightness_step(auto_bright_t *ab, float lux, float dt_s) +{ + // 1) lux -> cible en PWM normalisé [0..1] + lux = fmaxf(lux, ab->Lmin); + float x = (logf(lux) - logf(ab->Lmin)) / (logf(ab->Lmax) - logf(ab->Lmin)); + x = clampf(x, 0.f, 1.f); + float b_target = powf(x, ab->gamma); + float pwm_target = ab->pwm_min + b_target * (ab->pwm_max - ab->pwm_min); + pwm_target = clampf(pwm_target, ab->pwm_min, ab->pwm_max); + + // init + if(!ab->init){ ab->y = pwm_target; ab->init = true; return ab->y; } + + // deadband + //if (fabsf(pwm_target - ab->y) < ab->deadband) return ab->y; + + // 2) EMA avec constante de temps asymétrique + float tau = (pwm_target > ab->y) ? ab->tau_rise : ab->tau_fall; + float alpha = dt_s / (tau + dt_s); + ab->y = (1.f - alpha) * ab->y + alpha * pwm_target; + + return ab->y; // valeur à appliquer (0..1) +} + +auto_bright_t ab = { + .Lmin=0.1f, .Lmax=600.f, .gamma=2.f, + .pwm_min=0.00062f, .pwm_max=1.0f, + .tau_rise=1.5f, .tau_fall=4.0f, + .deadband=0.01f, .init=false +}; + +int32_t map_value(int32_t x, int32_t in_min, int32_t in_max, int32_t out_min, int32_t out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +void lightSensorTask(void *pvParameter){ + float bh1750_data; + while(1){ + ESP_ERROR_CHECK(bh1750_get_data(bh1750, &bh1750_data)); + //maxBrightness = map_value(bh1750_data, 0,300,0, 100); + maxBrightness = auto_brightness_step(&ab, bh1750_data, 0.1)*100; + //ESP_LOGI(TAG, "bh1750 val(continuously mode): %f --> %f\n", bh1750_data, maxBrightness); + + int len = snprintf(NULL, 0, "%f", bh1750_data); + char *result = malloc(len + 1); + snprintf(result, len + 1, "%f", bh1750_data); + //mqtt_publish("/domotic/sensor/light", result); + free(result); + bsp_display_brightness_set(maxBrightness); + vTaskDelay(pdMS_TO_TICKS(100)); + } + +} + void app_main(void) { esp_task_wdt_deinit(); // désactive le task watchdog vTaskDelay(pdMS_TO_TICKS(10000)); // laisse le temps d'attacher GDB + bh1750_measure_mode_t cmd_measure; + + startEvtManager(); //init_display(); const esp_timer_create_args_t periodic_timer_args = { @@ -838,6 +945,8 @@ void app_main(void) // ESP_ERROR_CHECK(esp_lcd_panel_mirror(lcd_panel,true,true)); xTaskCreatePinnedToCore(&drawIhm,"ihm_task",10000,getIHMQueueHandle(),10,NULL,0); + + // Initialize NVS esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) @@ -860,7 +969,7 @@ void app_main(void) * and hence timings for overall OTA operation. */ esp_wifi_set_ps(WIFI_PS_NONE); - xTaskCreatePinnedToCore(&simple_ota_example_task, "ota__task", 8192, NULL, 1, NULL,0); + xTaskCreatePinnedToCore(&simple_ota_example_task, "ota__task", 8192, NULL, 6, NULL,0); on_weather_data_retrieval(weather_data_retreived); on_weather_data_retrieval_start(weather_data_retreived_start); @@ -905,6 +1014,4 @@ void app_main(void) ESP_ERROR_CHECK(am2302_new_sensor_rmt(&am2302_config, &rmt_config, &sensor)); xTaskCreate(&readTempHumid, "read_temp_task", 8192, NULL, 5, NULL); - - }