Please note that the current firmware is designed for the BeeLight v1 PCB so the BME688 is not fully integrated and the software is built for an nRF5340. The BeeLight v2 will be supported as soon as the new boards were available.About
This project shows you how to build an open-source nRF54L-based environment and light sensor for your Home Automation installation. BeeLight allows you to measure all relevant information to control your radiators, lamps, windows, etc. by combining a light sensor with a state-of-the-art environment sensor. You can measure:
- Min. / Max. / Current Light
- Min. / Max. / Current Temperature
- Min. / Max. / Current Humidity
- Min. / Max. / Current Pressure
- IAQ
- VOC
- CO2
The circuit board is designed to be small and consume as little power as possible and contains the following sensors:
- APDS-9306: Used for the light measurement
- BME688: Used for the environment and IAQ, VOC, and CO2 measurement
- ADC: Used to measure the battery voltage
The board is designed with KiCad 8 and a CI/CD pipeline for KiBot is added into the repository to generate all necessary output data automatically:
- Gerber
- Pick & Place
- Documentation
- Rendering
- Step file
- BOM with costs
The housing is 40x42 mm in size and is designed with Fusion 360. It is separated into two parts with a simple press connection. The holes are needed for better airflow to improve the measurement results of the BME688. The light guide is used for the light sensor, which enables better measurement results.
The device firmware is built with Zephyr and the nRF Connect SDK (NCS) 2.8. To build the firmware, you can use VS Code with the nRF Connect plugin.
For the IAQ, VOC, and CO2 measurement, the optional BSEC2 library from Bosch is needed. This library can not be integrated into the main repository due to the license from Bosch. So you have to download it separately when you want to use these features.
The repository contains a custom board to describe the basic hardware and the revision-specific definitions were added as an overlay to the existing device tree.
/ {
leds {
status = "okay";
compatible = "gpio-leds";
led0: led_0 {
gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
label = "Identify LED";
};
};
buttons {
status = "okay";
compatible = "gpio-keys";
button0: button_0 {
gpios = <&gpio0 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Join button";
zephyr,code = <INPUT_KEY_3>;
};
};
vbatt {
status = "okay";
compatible = "voltage-divider";
io-channels = <&adc 0>;
output-ohms = <2200>;
full-ohms = <(8200 + 2200)>;
power-gpios = <&gpio1 6 0>;
};
};
&i2c1 {
apds9306: apds9306@52 {
status = "okay";
compatible = "avago,apds9306";
reg = <0x52>;
gain = <0>;
resolution = <0>;
frequency = <0>;
};
bme688: bme688@76 {
status = "okay";
compatible = "bosch,bme680";
reg = <0x76>;
};
};
The Zephyr OS (and so the firmware) uses the ZBOSS ZigBee stack and a custom device can be added by using the documentation from the ZigBee Cluster Library (ZCL) and the ZBOSS-API (see beelight.h for the full configuration):
/** @brief See https://zigbeealliance.org/wp-content/uploads/2021/10/07-5123-08-Zigbee-Cluster-Library.pdf for additional informations
* @details
* Server
* - @ref ZB_ZCL_BASIC \n
* - @ref ZB_ZCL_IDENTIFY \n
* - @ref ZB_ZCL_CLUSTER_ID_POWER_CONFIG \n
* - @ref ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT \n
*
* Client
* - @ref ZB_ZCL_IDENTIFY \n
*/
#define LIGHT_SENSOR_ENDPOINT 10
#define ZB_DEVICE_VER 1
#define ZB_PROFILE_ID ZB_AF_HA_PROFILE_ID
#define ZB_DEVICE_ID 0x106
#define ZB_DECLARE_LIGHT_SENSOR_CLUSTER_LIST( \
cluster_list_name, \
basic_attr_list, \
identify_client_attr_list, \
identify_server_attr_list, \
power_attr_list, \
measure_attr_list) \
zb_zcl_cluster_desc_t cluster_list_name[] = \
{ \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_BASIC, \
ZB_ZCL_ARRAY_SIZE(basic_attr_list, zb_zcl_attr_t), \
(basic_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_IDENTIFY, \
ZB_ZCL_ARRAY_SIZE(identify_server_attr_list, zb_zcl_attr_t), \
(identify_server_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_POWER_CONFIG, \
ZB_ZCL_ARRAY_SIZE(power_attr_list, zb_zcl_attr_t), \
(power_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT, \
ZB_ZCL_ARRAY_SIZE(measure_attr_list, zb_zcl_attr_t), \
(measure_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_IDENTIFY, \
ZB_ZCL_ARRAY_SIZE(identify_client_attr_list, zb_zcl_attr_t), \
(identify_client_attr_list), \
ZB_ZCL_CLUSTER_CLIENT_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
) \
}
ZigBee2MQTT integrationThe sensor can be used with ZigBee2MQTT to integrate it into Home Assistant or similar applications with ease. The repository contains an external converter to add support for ZigBee2MQTT.
const {} = require('zigbee-herdsman-converters/lib/modernExtend');
const fz = require('zigbee-herdsman-converters/converters/fromZigbee');
const tz = require('zigbee-herdsman-converters/converters/toZigbee');
const exposes = require('zigbee-herdsman-converters/lib/exposes');
const reporting = require('zigbee-herdsman-converters/lib/reporting');
const ota = require('zigbee-herdsman-converters/lib/ota');
const utils = require('zigbee-herdsman-converters/lib/utils');
const globalStore = require('zigbee-herdsman-converters/lib/store');
const e = exposes.presets;
const ea = exposes.access;
const definition = {
zigbeeModel: ["BeeLight_v1.0"],
model: "BeeLight_v2.0",
vendor: "Kampi",
description: "ZigBee based Light Sensor (https://github.com/Kampi/BeeLight)",
fromZigbee: [fz.identify, fz.battery, fz.illuminancey],
toZigbee: [],
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint10 = device.getEndpoint(10);
await reporting.bind(endpoint10, coordinatorEndpoint, ["genPowerCfg", "msIlluminanceMeasurement"]);
await reporting.batteryVoltage(endpoint10);
await reporting.illuminance(endpoint10, {min: 1, max: constants.repInterval.MINUTES_1, change: 10});
await reporting.batteryPercentageRemaining(endpoint10);
},
exposes: [e.identify(), e.battery(), e.illuminance()],
};
module.exports = definition;
The sensor is tested with the latest ZigBee2MQTT (2.0) version and a ZigBee dongle from Sonoff. You can check the sensor state and reporting in the ZigBee2MQTT web UI after the sensor joins the ZigBee network.
Comments